Skip to content

管理员后台设计(Admin Dashboard)

1. 核心概念

管理员后台是"第二大脑"产品的 SaaS 运营中枢,面向平台管理员、运营人员、客服人员和系统管理员。它提供用户生命周期管理、数据监控、内容审核、系统配置、订阅计费、日志审计等全栈运营能力,支持多租户隔离和分级权限控制。


2. 权限模型(RBAC)

2.1 角色定义

typescript
enum AdminRole {
  SUPER_ADMIN = 'super_admin',      // 超级管理员:全部权限
  PLATFORM_ADMIN = 'platform_admin', // 平台管理员:用户/内容/系统管理
  OPERATOR = 'operator',             // 运营人员:数据/活动/用户支持
  FINANCE_ADMIN = 'finance_admin',   // 财务管理员:订阅/订单/退款
  SUPPORT = 'support',               // 客服人员:用户查询/工单处理
  AUDITOR = 'auditor',               // 审计人员:日志/安全/合规审查
  READONLY = 'readonly'             // 只读观察员:数据查看,无操作权限
}

interface Permission {
  resource: string;                  // 资源类型
  actions: ('create' | 'read' | 'update' | 'delete' | 'approve' | 'export' | 'manage')[];
  scope: 'own' | 'team' | 'all' | 'tenant';  // 数据范围
}

// 角色权限矩阵
const ROLE_PERMISSIONS: Record<AdminRole, Permission[]> = {
  SUPER_ADMIN: [
    { resource: '*', actions: ['create', 'read', 'update', 'delete', 'approve', 'export', 'manage'], scope: 'all' }
  ],
  PLATFORM_ADMIN: [
    { resource: 'users', actions: ['create', 'read', 'update', 'delete', 'manage'], scope: 'all' },
    { resource: 'content', actions: ['read', 'update', 'delete', 'approve'], scope: 'all' },
    { resource: 'system', actions: ['read', 'update', 'manage'], scope: 'all' },
    { resource: 'logs', actions: ['read', 'export'], scope: 'all' },
    { resource: 'stats', actions: ['read', 'export'], scope: 'all' },
    { resource: 'announcements', actions: ['create', 'read', 'update', 'delete'], scope: 'all' }
  ],
  OPERATOR: [
    { resource: 'users', actions: ['read', 'update'], scope: 'all' },
    { resource: 'content', actions: ['read', 'update', 'approve'], scope: 'all' },
    { resource: 'stats', actions: ['read', 'export'], scope: 'all' },
    { resource: 'announcements', actions: ['create', 'read', 'update'], scope: 'all' }
  ],
  FINANCE_ADMIN: [
    { resource: 'subscriptions', actions: ['read', 'update', 'manage'], scope: 'all' },
    { resource: 'orders', actions: ['read', 'update', 'export'], scope: 'all' },
    { resource: 'refunds', actions: ['read', 'approve', 'export'], scope: 'all' },
    { resource: 'stats', actions: ['read', 'export'], scope: 'all' },
    { resource: 'users', actions: ['read'], scope: 'all' }
  ],
  SUPPORT: [
    { resource: 'users', actions: ['read', 'update'], scope: 'all' },
    { resource: 'tickets', actions: ['create', 'read', 'update', 'manage'], scope: 'all' },
    { resource: 'content', actions: ['read'], scope: 'all' },
    { resource: 'logs', actions: ['read'], scope: 'all' }
  ],
  AUDITOR: [
    { resource: 'logs', actions: ['read', 'export'], scope: 'all' },
    { resource: 'users', actions: ['read'], scope: 'all' },
    { resource: 'content', actions: ['read'], scope: 'all' },
    { resource: 'stats', actions: ['read', 'export'], scope: 'all' }
  ],
  READONLY: [
    { resource: 'users', actions: ['read'], scope: 'all' },
    { resource: 'stats', actions: ['read'], scope: 'all' },
    { resource: 'content', actions: ['read'], scope: 'all' },
    { resource: 'logs', actions: ['read'], scope: 'all' }
  ]
};

2.2 管理员用户模型

typescript
interface AdminUser {
  id: string;
  email: string;                    // 登录邮箱
  name: string;                      // 显示名称
  avatar?: string;
  
  role: AdminRole;
  permissions: Permission[];        // 动态权限(可覆盖角色默认)
  
  // 状态
  status: 'active' | 'inactive' | 'suspended' | 'pending';
  lastLoginAt: Date;
  lastLoginIp: string;
  mfaEnabled: boolean;             // 是否启用 MFA
  
  // 审计
  createdAt: Date;
  createdBy: string;              // 谁创建的
  updatedAt: Date;
  
  // 数据范围(多租户场景)
  tenantId?: string;              // 所属租户
  managedTenants?: string[];      // 管理的租户列表(PLATFORM_ADMIN 可管理多个)
}

3. 数据库 Schema(Admin 专用表)

sql
-- ==================== 管理员用户表 ====================
CREATE TABLE admin_users (
    id TEXT PRIMARY KEY,
    email TEXT NOT NULL UNIQUE,
    name TEXT NOT NULL,
    avatar TEXT,
    
    -- 密码(bcrypt 哈希)
    password_hash TEXT NOT NULL,
    
    -- 角色和权限
    role TEXT NOT NULL CHECK(role IN ('super_admin', 'platform_admin', 'operator', 'finance_admin', 'support', 'auditor', 'readonly')),
    permissions TEXT,               -- JSON: Permission[] 动态覆盖
    
    -- 状态
    status TEXT DEFAULT 'pending' CHECK(status IN ('active', 'inactive', 'suspended', 'pending')),
    last_login_at TIMESTAMP,
    last_login_ip TEXT,
    mfa_enabled BOOLEAN DEFAULT false,
    mfa_secret TEXT,               -- 加密存储
    
    -- 审计
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    created_by TEXT,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    -- 多租户
    tenant_id TEXT,
    managed_tenants TEXT           -- JSON: string[]
);

CREATE INDEX idx_admin_users_role ON admin_users(role);
CREATE INDEX idx_admin_users_status ON admin_users(status);
CREATE INDEX idx_admin_users_tenant ON admin_users(tenant_id);

-- ==================== 管理员登录日志 ====================
CREATE TABLE admin_login_logs (
    id TEXT PRIMARY KEY,
    admin_id TEXT NOT NULL,
    ip_address TEXT,
    user_agent TEXT,
    login_method TEXT,             -- 'password' | 'mfa' | 'sso'
    status TEXT CHECK(status IN ('success', 'failed', 'mfa_required')),
    fail_reason TEXT,              -- 失败原因
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (admin_id) REFERENCES admin_users(id)
);

CREATE INDEX idx_admin_login_logs_admin ON admin_login_logs(admin_id);
CREATE INDEX idx_admin_login_logs_time ON admin_login_logs(created_at);

-- ==================== 管理员操作日志 ====================
CREATE TABLE admin_audit_logs (
    id TEXT PRIMARY KEY,
    admin_id TEXT NOT NULL,
    admin_name TEXT,
    admin_role TEXT,
    
    action TEXT NOT NULL,          -- 'create' | 'read' | 'update' | 'delete' | 'approve' | 'export' | 'login' | 'logout'
    resource_type TEXT NOT NULL, -- 'user' | 'content' | 'system' | 'subscription' | 'announcement' | 'config'
    resource_id TEXT,            -- 被操作资源的 ID
    
    before_state TEXT,           -- JSON: 操作前的状态
    after_state TEXT,            -- JSON: 操作后的状态
    changes TEXT,                -- JSON: 变更字段摘要
    
    ip_address TEXT,
    user_agent TEXT,
    request_id TEXT,             -- 关联请求 ID
    
    -- 风险标记
    risk_level TEXT DEFAULT 'low' CHECK(risk_level IN ('low', 'medium', 'high', 'critical')),
    risk_reason TEXT,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (admin_id) REFERENCES admin_users(id)
);

CREATE INDEX idx_admin_audit_logs_admin ON admin_audit_logs(admin_id);
CREATE INDEX idx_admin_audit_logs_action ON admin_audit_logs(action, resource_type);
CREATE INDEX idx_admin_audit_logs_time ON admin_audit_logs(created_at);
CREATE INDEX idx_admin_audit_logs_risk ON admin_audit_logs(risk_level);

-- ==================== 系统公告 ====================
CREATE TABLE announcements (
    id TEXT PRIMARY KEY,
    title TEXT NOT NULL,
    content TEXT NOT NULL,
    type TEXT DEFAULT 'info' CHECK(type IN ('info', 'warning', 'critical', 'feature', 'maintenance')),
    
    -- 目标受众
    target_roles TEXT,            -- JSON: AdminRole[] 或 null 表示全部
    target_tenants TEXT,          -- JSON: string[] 或 null 表示全部
    
    -- 发布控制
    status TEXT DEFAULT 'draft' CHECK(status IN ('draft', 'published', 'archived')),
    scheduled_at TIMESTAMP,       -- 计划发布时间
    published_at TIMESTAMP,
    expires_at TIMESTAMP,         -- 过期时间
    
    -- 统计
    view_count INTEGER DEFAULT 0,
    
    created_by TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (created_by) REFERENCES admin_users(id)
);

-- ==================== Feature Flags ====================
CREATE TABLE feature_flags (
    id TEXT PRIMARY KEY,
    key TEXT NOT NULL UNIQUE,     -- 功能标识符
    name TEXT NOT NULL,            -- 显示名称
    description TEXT,
    
    -- 状态
    enabled BOOLEAN DEFAULT false,
    
    -- 目标范围
    scope_type TEXT DEFAULT 'global' CHECK(scope_type IN ('global', 'tenant', 'user', 'percentage')),
    scope_value TEXT,             -- 具体值:租户 ID / 用户 ID / 百分比
    
    -- 灰度控制
    rollout_percentage INTEGER DEFAULT 0 CHECK(rollout_percentage BETWEEN 0 AND 100),
    
    -- 元数据
    category TEXT,                -- 'core' | 'experimental' | 'beta' | 'deprecated'
    depends_on TEXT,              -- JSON: string[] 依赖的其他 flag
    
    created_by TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (created_by) REFERENCES admin_users(id)
);

-- ==================== 系统配置 ====================
CREATE TABLE system_configs (
    id TEXT PRIMARY KEY,
    key TEXT NOT NULL UNIQUE,
    value TEXT NOT NULL,
    value_type TEXT DEFAULT 'string' CHECK(value_type IN ('string', 'number', 'boolean', 'json')),
    description TEXT,
    
    -- 可变性
    editable BOOLEAN DEFAULT true,
    requires_restart BOOLEAN DEFAULT false,
    
    -- 作用域
    scope TEXT DEFAULT 'global' CHECK(scope IN ('global', 'tenant', 'user')),
    tenant_id TEXT,
    
    -- 审计
    updated_by TEXT,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (updated_by) REFERENCES admin_users(id)
);

-- ==================== 用户举报 ====================
CREATE TABLE user_reports (
    id TEXT PRIMARY KEY,
    reporter_id TEXT,              -- 举报人(用户)
    reported_id TEXT,              -- 被举报对象 ID
    reported_type TEXT CHECK(reported_type IN ('user', 'content', 'comment', 'message')),
    
    reason TEXT NOT NULL,          -- 举报原因
    category TEXT CHECK(category IN ('spam', 'abuse', 'illegal', 'copyright', 'privacy', 'other')),
    evidence TEXT,                 -- JSON: 证据截图/链接
    
    -- 处理状态
    status TEXT DEFAULT 'pending' CHECK(status IN ('pending', 'investigating', 'resolved', 'dismissed')),
    resolution TEXT,              -- 处理结果
    resolved_by TEXT,             -- 处理人
    resolved_at TIMESTAMP,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (resolved_by) REFERENCES admin_users(id)
);

CREATE INDEX idx_user_reports_status ON user_reports(status);
CREATE INDEX idx_user_reports_type ON user_reports(reported_type);

-- ==================== 客服工单 ====================
CREATE TABLE support_tickets (
    id TEXT PRIMARY KEY,
    ticket_number TEXT NOT NULL UNIQUE,  -- 工单编号 TICKET-20260701-0001
    user_id TEXT NOT NULL,
    
    title TEXT NOT NULL,
    description TEXT,
    category TEXT CHECK(category IN ('billing', 'technical', 'feature_request', 'bug', 'account', 'other')),
    priority TEXT DEFAULT 'medium' CHECK(priority IN ('low', 'medium', 'high', 'critical')),
    
    -- 状态
    status TEXT DEFAULT 'open' CHECK(status IN ('open', 'in_progress', 'waiting_user', 'resolved', 'closed', 'escalated')),
    
    -- 分配
    assigned_to TEXT,              -- 分配的客服
    
    -- 时间戳
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    resolved_at TIMESTAMP,
    
    -- 满意度
    satisfaction_rating INTEGER,   -- 1-5
    satisfaction_comment TEXT,
    
    FOREIGN KEY (assigned_to) REFERENCES admin_users(id)
);

CREATE INDEX idx_support_tickets_status ON support_tickets(status);
CREATE INDEX idx_support_tickets_assigned ON support_tickets(assigned_to);
CREATE INDEX idx_support_tickets_user ON support_tickets(user_id);

-- ==================== 工单回复 ====================
CREATE TABLE ticket_replies (
    id TEXT PRIMARY KEY,
    ticket_id TEXT NOT NULL,
    author_id TEXT NOT NULL,       -- 可以是用户或管理员
    author_type TEXT CHECK(author_type IN ('user', 'admin')),
    content TEXT NOT NULL,
    is_internal BOOLEAN DEFAULT false,  -- 是否内部备注(用户不可见)
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    
    FOREIGN KEY (ticket_id) REFERENCES support_tickets(id)
);

-- ==================== 租户表(多租户) ====================
CREATE TABLE tenants (
    id TEXT PRIMARY KEY,
    name TEXT NOT NULL,
    slug TEXT NOT NULL UNIQUE,     -- 唯一标识
    
    -- 配置
    config TEXT,                   -- JSON: 租户级配置
    
    -- 资源配额
    max_users INTEGER,
    max_storage_gb INTEGER,
    max_api_calls_per_month INTEGER,
    
    -- 状态
    status TEXT DEFAULT 'active' CHECK(status IN ('active', 'suspended', 'trial', 'expired')),
    trial_ends_at TIMESTAMP,
    
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 用户表扩展:增加租户关联
ALTER TABLE users ADD COLUMN tenant_id TEXT;
ALTER TABLE users ADD COLUMN is_tenant_admin BOOLEAN DEFAULT false;
CREATE INDEX idx_users_tenant ON users(tenant_id);

4. Admin API 设计

4.1 认证与授权

typescript
// ==================== 管理员登录 ====================
POST /api/admin/auth/login
Request: {
  email: string;
  password: string;
  mfaCode?: string;          // 如果启用 MFA
}
Response: {
  accessToken: string;       // JWT,15 分钟
  refreshToken: string;      // 7 天
  admin: {
    id: string;
    name: string;
    email: string;
    role: string;
    permissions: Permission[];
  };
}

// ==================== 刷新 Token ====================
POST /api/admin/auth/refresh
Request: { refreshToken: string }
Response: { accessToken: string }

// ==================== 登出 ====================
POST /api/admin/auth/logout
Headers: Authorization: Bearer {accessToken}
Response: { success: true }

// ==================== 获取当前管理员信息 ====================
GET /api/admin/auth/me
Response: {
  id: string;
  name: string;
  email: string;
  role: string;
  permissions: Permission[];
  lastLoginAt: Date;
  mfaEnabled: boolean;
}

// ==================== 验证权限(中间件) ====================
// 使用方式:在路由前验证
// GET /api/admin/users 需要 admin:users:read 权限
// 如果没有权限,返回 403

4.2 用户管理

typescript
// ==================== 用户列表 ====================
GET /api/admin/users
Query: {
  page: number;              // 默认 1
  limit: number;            // 默认 20
  search?: string;          // 搜索邮箱/名称
  status?: 'active' | 'inactive' | 'suspended' | 'pending';
  role?: 'free' | 'pro' | 'team' | 'enterprise';
  tenantId?: string;        // 多租户筛选
  dateRange?: [string, string]; // 注册时间范围
  sortBy?: 'createdAt' | 'lastLoginAt' | 'subscriptionTier' | 'storageUsed';
  sortOrder?: 'asc' | 'desc';
}
Response: {
  users: AdminUserView[];
  pagination: { total: number; page: number; pages: number };
  summary: {
    totalUsers: number;
    activeUsers: number;
    newUsersToday: number;
    newUsersThisWeek: number;
    newUsersThisMonth: number;
    avgStorageUsed: number;
  };
}

interface AdminUserView {
  id: string;
  email: string;
  name: string;
  avatar?: string;
  status: string;
  role: string;
  subscriptionTier: string;
  subscriptionStatus: string;
  subscriptionExpiresAt: Date;
  storageUsed: number;          // 字节
  storageLimit: number;
  lastLoginAt: Date;
  lastLoginIp: string;
  createdAt: Date;
  tenantId?: string;
  
  // 统计
  stats: {
    totalNotes: number;
    totalClips: number;
    totalCapsules: number;
    totalKnowledgeUnits: number;
    apiCallsThisMonth: number;
  };
}

// ==================== 用户详情 ====================
GET /api/admin/users/:id
Response: {
  user: AdminUserView;
  loginHistory: LoginRecord[];
  activityTimeline: ActivityRecord[];
  subscriptionHistory: SubscriptionRecord[];
  supportTickets: TicketSummary[];
}

// ==================== 更新用户状态 ====================
PATCH /api/admin/users/:id
Request: {
  status?: 'active' | 'inactive' | 'suspended';
  subscriptionTier?: 'free' | 'pro' | 'team' | 'enterprise';
  storageLimit?: number;
  notes?: string;              // 管理员备注
}
Response: { user: AdminUserView }

// ==================== 批量操作用户 ====================
POST /api/admin/users/batch
Request: {
  action: 'suspend' | 'activate' | 'delete' | 'upgrade' | 'downgrade' | 'export';
  userIds: string[];
  reason: string;              // 操作原因(审计用)
  data?: any;                 // 额外参数
}
Response: {
  success: boolean;
  processed: number;
  failed: number;
  failures: { userId: string; reason: string }[];
}

// ==================== 用户登录历史 ====================
GET /api/admin/users/:id/login-history
Query: { page: number; limit: number; startDate?: string; endDate?: string }
Response: {
  records: LoginRecord[];
  pagination: Pagination;
  summary: {
    totalLogins: number;
    uniqueIps: number;
    failedAttempts: number;
  };
}

// ==================== 用户数据导出 ====================
POST /api/admin/users/:id/export
Request: {
  format: 'json' | 'csv' | 'pdf';
  dataTypes: ('profile' | 'notes' | 'clips' | 'capsules' | 'knowledge' | 'activity' | 'all')[];
  dateRange?: [string, string];
}
Response: {
  exportId: string;
  status: 'queued' | 'processing' | 'completed' | 'failed';
  downloadUrl?: string;       // 完成后提供
  expiresAt?: Date;
}

// SSE: GET /api/admin/users/:id/export/:exportId/progress

4.3 数据统计

typescript
// ==================== 全局仪表盘数据 ====================
GET /api/admin/stats/dashboard
Response: {
  // 用户指标
  users: {
    total: number;
    active: number;              // 30 天内有活跃
    newToday: number;
    newThisWeek: number;
    newThisMonth: number;
    churnRate: number;          // 月流失率
    retention: {                 // 留存率
      day1: number;
      day7: number;
      day30: number;
      day90: number;
    };
    byTier: Record<string, number>;  // 按套餐分布
    byCountry: Record<string, number>; // 按国家分布
  };
  
  // 活跃度指标
  activity: {
    dau: number;                 // 日活跃用户
    mau: number;                 // 月活跃用户
    avgSessionDuration: number;   // 平均会话时长(秒)
    avgSessionsPerDay: number;   // 日均会话数
    
    // 功能使用
    featureUsage: {
      notes: { users: number; count: number };
      clips: { users: number; count: number };
      capsules: { users: number; count: number };
      graph: { users: number; count: number };
      attention: { users: number; count: number };
      llm: { users: number; tokens: number };
    };
  };
  
  // 存储指标
  storage: {
    totalUsed: number;           // 总使用字节
    totalLimit: number;
    avgPerUser: number;
    byType: {
      notes: number;
      clips: number;
      attachments: number;
      vectors: number;
    };
  };
  
  // 收入指标
  revenue: {
    mrr: number;                 // 月度经常性收入
    arr: number;                 // 年度经常性收入
    thisMonth: number;
    lastMonth: number;
    growthRate: number;
    byTier: Record<string, number>;
    byPaymentMethod: Record<string, number>;
  };
  
  // 系统健康
  system: {
    apiUptime: number;           // API 可用率
    avgResponseTime: number;     // 平均响应时间
    errorRate: number;           // 错误率
    queueDepth: number;          // 任务队列深度
    activeSyncs: number;         // 活跃同步数
  };
}

// ==================== 时间序列数据 ====================
GET /api/admin/stats/timeseries
Query: {
  metric: 'dau' | 'mau' | 'new_users' | 'revenue' | 'api_calls' | 'storage' | 'retention';
  period: 'hour' | 'day' | 'week' | 'month';
  startDate: string;
  endDate: string;
  granularity?: 'hour' | 'day' | 'week' | 'month';
  tenantId?: string;
}
Response: {
  data: { timestamp: Date; value: number; label?: string }[];
  summary: {
    total: number;
    avg: number;
    max: number;
    min: number;
    change: number;              // 环比变化
  };
}

// ==================== 用户漏斗分析 ====================
GET /api/admin/stats/funnel
Query: {
  funnelType: 'onboarding' | 'subscription' | 'feature_adoption';
  dateRange: [string, string];
}
Response: {
  steps: {
    name: string;
    users: number;
    conversionRate: number;      // 到下一步的转化率
    dropOffRate: number;        // 流失率
    avgTime: number;            // 平均停留时间(秒)
  }[];
  totalConversion: number;      // 总转化率
}

// ==================== 热门内容/搜索 ====================
GET /api/admin/stats/popular
Query: {
  type: 'searches' | 'clips' | 'notes' | 'tags' | 'domains' | 'llm_queries';
  period: 'day' | 'week' | 'month';
  limit: number;
}
Response: {
  items: { name: string; count: number; trend: 'up' | 'down' | 'stable' }[];
}

4.4 内容管理

typescript
// ==================== 内容审核列表 ====================
GET /api/admin/content
Query: {
  page: number;
  limit: number;
  type?: 'note' | 'clip' | 'rss_item' | 'knowledge_unit' | 'capsule';
  status?: 'active' | 'flagged' | 'under_review' | 'removed' | 'appealed';
  brainSide?: 'personal' | 'network';
  flagReason?: 'spam' | 'abuse' | 'illegal' | 'copyright' | 'privacy' | 'ai_generated' | 'user_reported';
  dateRange?: [string, string];
  search?: string;
  sortBy?: 'flaggedAt' | 'createdAt' | 'reportCount';
}
Response: {
  items: ContentItem[];
  pagination: Pagination;
  summary: {
    totalFlagged: number;
    pendingReview: number;
    removedToday: number;
  };
}

interface ContentItem {
  id: string;
  type: string;
  brainSide: BrainSide;
  title: string;
  excerpt: string;
  
  author: {
    id: string;
    name: string;
    email: string;
    status: string;
  };
  
  status: string;
  flaggedAt: Date;
  flagReason: string;
  flagDetails: string;
  reportCount: number;
  
  // AI 检测
  aiDetected: {
    spamScore: number;
    toxicityScore: number;
    copyrightRisk: number;
    isAiGenerated: boolean;
  };
  
  createdAt: Date;
}

// ==================== 内容详情审核 ====================
GET /api/admin/content/:id
Response: {
  item: ContentItem;
  fullContent: string;
  reports: UserReport[];
  auditHistory: AuditAction[];
  similarContent: ContentItem[];  // AI 检测到的相似内容
}

// ==================== 审核操作 ====================
POST /api/admin/content/:id/audit
Request: {
  action: 'approve' | 'remove' | 'shadowban' | 'warn_author' | 'escalate';
  reason: string;              // 审核原因
  internalNotes?: string;     // 内部备注
  notifyUser?: boolean;       // 是否通知用户
}
Response: {
  success: boolean;
  item: ContentItem;
}

// ==================== 批量审核 ====================
POST /api/admin/content/batch-audit
Request: {
  contentIds: string[];
  action: 'approve' | 'remove' | 'shadowban';
  reason: string;
}

// ==================== 举报列表 ====================
GET /api/admin/reports
Query: {
  page: number;
  limit: number;
  status?: 'pending' | 'investigating' | 'resolved' | 'dismissed';
  category?: string;
  priority?: 'low' | 'medium' | 'high' | 'critical';
  assignedTo?: string;         // 分配给哪个管理员
}
Response: {
  reports: UserReport[];
  pagination: Pagination;
  summary: {
    pending: number;
    highPriority: number;
    avgResolutionTime: number;  // 平均处理时间(小时)
  };
}

// ==================== 处理举报 ====================
POST /api/admin/reports/:id/resolve
Request: {
  resolution: 'violation_found' | 'no_violation' | 'partial_violation' | 'needs_more_info';
  action: 'remove_content' | 'warn_user' | 'suspend_user' | 'dismiss' | 'escalate';
  reason: string;
  notifyReporter: boolean;
}

4.5 系统管理

typescript
// ==================== 系统配置列表 ====================
GET /api/admin/system/configs
Query: { category?: string; editable?: boolean }
Response: {
  configs: SystemConfig[];
}

interface SystemConfig {
  id: string;
  key: string;
  name: string;
  value: string;
  valueType: 'string' | 'number' | 'boolean' | 'json';
  description: string;
  editable: boolean;
  requiresRestart: boolean;
  scope: string;
  category: string;
  updatedBy: string;
  updatedAt: Date;
}

// ==================== 更新系统配置 ====================
PUT /api/admin/system/configs/:id
Request: {
  value: string;
  reason: string;              // 变更原因(审计)
}
Response: { config: SystemConfig }

// ==================== Feature Flags 列表 ====================
GET /api/admin/system/feature-flags
Response: {
  flags: FeatureFlag[];
}

interface FeatureFlag {
  id: string;
  key: string;
  name: string;
  description: string;
  enabled: boolean;
  scopeType: string;
  scopeValue?: string;
  rolloutPercentage: number;
  category: string;
  dependsOn: string[];
  createdBy: string;
  createdAt: Date;
}

// ==================== 创建/更新 Feature Flag ====================
POST /api/admin/system/feature-flags
Request: {
  key: string;
  name: string;
  description: string;
  enabled: boolean;
  scopeType: string;
  scopeValue?: string;
  rolloutPercentage: number;
  category: string;
}

// ==================== 系统健康检查 ====================
GET /api/admin/system/health
Response: {
  status: 'healthy' | 'degraded' | 'unhealthy';
  checks: {
    database: { status: string; latency: number };
    redis: { status: string; latency: number };
    chromadb: { status: string; latency: number };
    ollama: { status: string; latency: number; models: string[] };
    disk: { status: string; used: number; total: number };
    memory: { status: string; used: number; total: number };
  };
  uptime: number;                // 秒
  version: string;
  lastRestart: Date;
}

// ==================== 系统公告管理 ====================
GET /api/admin/system/announcements
Query: { status?: string; page: number; limit: number }
Response: { announcements: Announcement[]; pagination: Pagination }

POST /api/admin/system/announcements
Request: {
  title: string;
  content: string;
  type: 'info' | 'warning' | 'critical' | 'feature' | 'maintenance';
  targetRoles?: string[];
  targetTenants?: string[];
  scheduledAt?: string;
  expiresAt?: string;
}

PATCH /api/admin/system/announcements/:id
Request: { status: 'published' | 'draft' | 'archived' }

DELETE /api/admin/system/announcements/:id

4.6 订阅计费

typescript
// ==================== 订单列表 ====================
GET /api/admin/billing/orders
Query: {
  page: number;
  limit: number;
  status?: 'pending' | 'paid' | 'failed' | 'refunded' | 'disputed';
  paymentMethod?: 'stripe' | 'alipay' | 'wechat' | 'apple_pay' | 'bank_transfer';
  tier?: 'free' | 'pro' | 'team' | 'enterprise';
  dateRange?: [string, string];
  search?: string;               // 用户邮箱/订单号
}
Response: {
  orders: Order[];
  pagination: Pagination;
  summary: {
    totalRevenue: number;
    totalRefunds: number;
    netRevenue: number;
    totalOrders: number;
    avgOrderValue: number;
    byPaymentMethod: Record<string, number>;
    byTier: Record<string, number>;
  };
}

interface Order {
  id: string;
  orderNumber: string;          // ORD-20260701-0001
  userId: string;
  userName: string;
  userEmail: string;
  
  tier: string;
  period: 'monthly' | 'yearly' | 'lifetime';
  amount: number;
  currency: string;
  
  status: string;
  paymentMethod: string;
  paymentProvider: string;
  transactionId: string;
  
  paidAt: Date;
  expiresAt: Date;
  refundedAt: Date;
  refundAmount: number;
  
  createdAt: Date;
}

// ==================== 订单详情 ====================
GET /api/admin/billing/orders/:id
Response: {
  order: Order;
  invoiceUrl?: string;
  refundHistory: RefundRecord[];
  userSubscriptionHistory: Order[];
}

// ==================== 退款处理 ====================
POST /api/admin/billing/orders/:id/refund
Request: {
  amount: number;               // 退款金额(部分或全额)
  reason: string;
  category: 'customer_request' | 'billing_error' | 'fraud' | 'service_issue' | 'duplicate';
  notifyUser: boolean;
}
Response: {
  refundId: string;
  status: 'pending' | 'processing' | 'completed' | 'failed';
  estimatedCompletion: Date;
}

// ==================== 订阅管理 ====================
GET /api/admin/billing/subscriptions
Query: {
  page: number;
  limit: number;
  status?: 'active' | 'cancelled' | 'expired' | 'past_due' | 'trialing';
  tier?: string;
  autoRenew?: boolean;
  dateRange?: [string, string];
}
Response: {
  subscriptions: Subscription[];
  pagination: Pagination;
  summary: {
    active: number;
    trialing: number;
    pastDue: number;
    churning: number;            // 即将流失(7天内到期且不自动续费)
    mrr: number;
    arr: number;
  };
}

interface Subscription {
  id: string;
  userId: string;
  userName: string;
  userEmail: string;
  
  tier: string;
  status: string;
  period: string;
  
  currentPeriodStart: Date;
  currentPeriodEnd: Date;
  
  autoRenew: boolean;
  cancelAtPeriodEnd: boolean;
  
  paymentMethod: string;
  
  createdAt: Date;
  cancelledAt: Date;
}

// ==================== 更新订阅(手动干预) ====================
PATCH /api/admin/billing/subscriptions/:id
Request: {
  tier?: string;
  status?: 'active' | 'cancelled' | 'paused';
  extendDays?: number;          // 延长天数(补偿)
  reason: string;               // 操作原因
}

// ==================== 优惠券/促销码管理 ====================
GET /api/admin/billing/promotions
Query: { status?: string; page: number; limit: number }
Response: { promotions: Promotion[] }

POST /api/admin/billing/promotions
Request: {
  code: string;                 // 优惠码
  type: 'percentage' | 'fixed' | 'trial_extension';
  value: number;                // 折扣百分比或金额
  maxUses: number;              // 最大使用次数
  maxUsesPerUser: number;
  applicableTiers: string[];
  startDate: string;
  endDate: string;
  description: string;
}

// ==================== 收入报告 ====================
GET /api/admin/billing/revenue-report
Query: {
  period: 'daily' | 'weekly' | 'monthly' | 'yearly';
  startDate: string;
  endDate: string;
  groupBy?: 'tier' | 'payment_method' | 'country' | 'referral';
}
Response: {
  report: RevenueReport;
  downloadUrl: string;          // 可下载 CSV/PDF
}

4.7 日志审计

typescript
// ==================== 操作日志列表 ====================
GET /api/admin/logs/audit
Query: {
  page: number;
  limit: number;
  adminId?: string;             // 按管理员筛选
  action?: string;              // 'create' | 'read' | 'update' | 'delete' | 'approve'
  resourceType?: string;        // 'user' | 'content' | 'system' | 'subscription'
  riskLevel?: 'low' | 'medium' | 'high' | 'critical';
  dateRange?: [string, string];
  search?: string;
}
Response: {
  logs: AuditLog[];
  pagination: Pagination;
  summary: {
    totalActions: number;
    byAdmin: Record<string, number>;
    byAction: Record<string, number>;
    highRiskCount: number;
  };
}

interface AuditLog {
  id: string;
  adminId: string;
  adminName: string;
  adminRole: string;
  
  action: string;
  resourceType: string;
  resourceId: string;
  
  beforeState: any;
  afterState: any;
  changes: string[];
  
  ipAddress: string;
  userAgent: string;
  requestId: string;
  
  riskLevel: string;
  riskReason: string;
  
  createdAt: Date;
}

// ==================== 安全事件列表 ====================
GET /api/admin/logs/security
Query: {
  page: number;
  limit: number;
  severity?: 'info' | 'warning' | 'high' | 'critical';
  type?: 'failed_login' | 'mfa_bypass' | 'privilege_escalation' | 'unusual_access' | 'data_export' | 'config_change';
  dateRange?: [string, string];
}
Response: {
  events: SecurityEvent[];
  pagination: Pagination;
  summary: {
    totalEvents: number;
    criticalCount: number;
    unresolvedCount: number;
  };
}

interface SecurityEvent {
  id: string;
  type: string;
  severity: string;
  
  description: string;
  details: any;
  
  affectedResource: string;
  affectedUserId?: string;
  
  detectedAt: Date;
  resolvedAt: Date;
  resolvedBy: string;
  resolution: string;
  
  // 关联
  relatedLogs: string[];
  relatedAlerts: string[];
}

// ==================== 日志导出 ====================
POST /api/admin/logs/export
Request: {
  type: 'audit' | 'security' | 'login' | 'all';
  format: 'csv' | 'json' | 'ndjson';
  dateRange: [string, string];
  filters: any;
}
Response: {
  exportId: string;
  status: string;
  downloadUrl?: string;
  expiresAt: Date;
}

4.8 客服工单

typescript
// ==================== 工单列表 ====================
GET /api/admin/support/tickets
Query: {
  page: number;
  limit: number;
  status?: 'open' | 'in_progress' | 'waiting_user' | 'resolved' | 'closed' | 'escalated';
  priority?: 'low' | 'medium' | 'high' | 'critical';
  category?: string;
  assignedTo?: string;          // 分配给哪个管理员
  unassigned?: boolean;          // 只看未分配的
  search?: string;
}
Response: {
  tickets: SupportTicket[];
  pagination: Pagination;
  summary: {
    open: number;
    inProgress: number;
    waitingUser: number;
    resolvedToday: number;
    avgResolutionTime: number;    // 平均解决时间(小时)
    avgResponseTime: number;      // 平均首次响应时间(分钟)
  };
}

interface SupportTicket {
  id: string;
  ticketNumber: string;
  userId: string;
  userName: string;
  userEmail: string;
  
  title: string;
  description: string;
  category: string;
  priority: string;
  
  status: string;
  assignedTo: {
    id: string;
    name: string;
  };
  
  createdAt: Date;
  updatedAt: Date;
  
  replyCount: number;
  lastReplyAt: Date;
  lastReplyBy: string;
  
  satisfactionRating?: number;
}

// ==================== 工单详情 ====================
GET /api/admin/support/tickets/:id
Response: {
  ticket: SupportTicket;
  replies: TicketReply[];
  userHistory: SupportTicket[];
  relatedLogs: AdminAuditLog[];
}

// ==================== 回复工单 ====================
POST /api/admin/support/tickets/:id/replies
Request: {
  content: string;
  isInternal: boolean;           // 是否内部备注
  statusChange?: 'in_progress' | 'waiting_user' | 'resolved' | 'escalated';
  assignTo?: string;           // 转分配给
}
Response: { reply: TicketReply; ticket: SupportTicket }

// ==================== 工单统计 ====================
GET /api/admin/support/stats
Query: { dateRange: [string, string] }
Response: {
  overview: {
    totalTickets: number;
    resolved: number;
    resolutionRate: number;
    avgResponseTime: number;
    avgResolutionTime: number;
    customerSatisfaction: number;  // 平均满意度 1-5
  };
  byCategory: Record<string, number>;
  byPriority: Record<string, number>;
  byAgent: Record<string, { tickets: number; resolved: number; avgTime: number; satisfaction: number }>;
  dailyVolume: { date: string; created: number; resolved: number }[];
}

5. Admin Dashboard 前端设计

5.1 整体布局

┌─────────────────────────────────────────────────────────────────┐
│  🛡️ Admin Dashboard                    [🔔] [👤 Admin] [Logout]│
│  ═══════════════════════════════════════════════════════════════  │
│                                                                  │
│  ┌────────┬──────────────────────────────────────────────────┐ │
│  │        │  顶部面包屑 + 页面标题                              │ │
│  │  Admin │  Dashboard / Users / User Detail                   │ │
│  │  侧边栏 │                                                      │ │
│  │        │  ┌──────────────────────────────────────────────┐   │ │
│  │  📊    │  │                                              │   │ │
│  │  Dashboard│  │              主内容区域                        │   │ │
│  │        │  │                                              │   │ │
│  │  👤    │  │                                              │   │ │
│  │  Users │  │                                              │   │ │
│  │        │  │                                              │   │ │
│  │  📰    │  │                                              │   │ │
│  │  Content│  │                                              │   │ │
│  │        │  │                                              │   │ │
│  │  📊    │  │                                              │   │ │
│  │  Stats │  │                                              │   │ │
│  │        │  │                                              │   │ │
│  │  💰    │  │                                              │   │ │
│  │  Billing│  │                                              │   │ │
│  │        │  │                                              │   │ │
│  │  ⚙️    │  │                                              │   │ │
│  │  System│  │                                              │   │ │
│  │        │  │                                              │   │ │
│  │  📝    │  │                                              │   │ │
│  │  Logs  │  │                                              │   │ │
│  │        │  │                                              │   │ │
│  │  🎧    │  │                                              │   │ │
│  │  Support│  │                                              │   │ │
│  │        │  │                                              │   │ │
│  └────────┘  └──────────────────────────────────────────────┘   │ │
│                                                                  │
│  [⚙️ 设置]  [📖 文档]  [🐛 反馈]                                    │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

5.2 侧边栏菜单(权限感知)

typescript
const ADMIN_MENU_ITEMS = [
  {
    id: 'dashboard',
    icon: '📊',
    label: '仪表盘',
    path: '/admin',
    requiredPermission: { resource: 'stats', action: 'read' },
    badge: null
  },
  {
    id: 'users',
    icon: '👤',
    label: '用户管理',
    path: '/admin/users',
    requiredPermission: { resource: 'users', action: 'read' },
    badge: 'new_users_count',  // 动态徽章
    children: [
      { id: 'users-list', label: '用户列表', path: '/admin/users' },
      { id: 'users-activity', label: '活跃分析', path: '/admin/users/activity' },
      { id: 'users-segment', label: '用户分群', path: '/admin/users/segments' },
    ]
  },
  {
    id: 'content',
    icon: '📰',
    label: '内容管理',
    path: '/admin/content',
    requiredPermission: { resource: 'content', action: 'read' },
    badge: 'pending_reviews',
    children: [
      { id: 'content-review', label: '内容审核', path: '/admin/content' },
      { id: 'content-reports', label: '举报处理', path: '/admin/content/reports' },
      { id: 'content-stats', label: '内容统计', path: '/admin/content/stats' },
    ]
  },
  {
    id: 'stats',
    icon: '📈',
    label: '数据统计',
    path: '/admin/stats',
    requiredPermission: { resource: 'stats', action: 'read' },
    children: [
      { id: 'stats-overview', label: '概览', path: '/admin/stats' },
      { id: 'stats-engagement', label: '活跃度', path: '/admin/stats/engagement' },
      { id: 'stats-retention', label: '留存', path: '/admin/stats/retention' },
      { id: 'stats-revenue', label: '收入', path: '/admin/stats/revenue' },
      { id: 'stats-llm', label: 'LLM 用量', path: '/admin/stats/llm' },
    ]
  },
  {
    id: 'billing',
    icon: '💰',
    label: '订阅计费',
    path: '/admin/billing',
    requiredPermission: { resource: 'subscriptions', action: 'read' },
    children: [
      { id: 'billing-orders', label: '订单', path: '/admin/billing/orders' },
      { id: 'billing-subscriptions', label: '订阅', path: '/admin/billing/subscriptions' },
      { id: 'billing-refunds', label: '退款', path: '/admin/billing/refunds' },
      { id: 'billing-promotions', label: '促销', path: '/admin/billing/promotions' },
      { id: 'billing-revenue', label: '收入报告', path: '/admin/billing/revenue' },
    ]
  },
  {
    id: 'system',
    icon: '⚙️',
    label: '系统管理',
    path: '/admin/system',
    requiredPermission: { resource: 'system', action: 'read' },
    children: [
      { id: 'system-config', label: '系统配置', path: '/admin/system/config' },
      { id: 'system-flags', label: 'Feature Flags', path: '/admin/system/flags' },
      { id: 'system-announcements', label: '公告', path: '/admin/system/announcements' },
      { id: 'system-health', label: '健康监控', path: '/admin/system/health' },
      { id: 'system-admins', label: '管理员', path: '/admin/system/admins' },
    ]
  },
  {
    id: 'logs',
    icon: '📝',
    label: '日志审计',
    path: '/admin/logs',
    requiredPermission: { resource: 'logs', action: 'read' },
    children: [
      { id: 'logs-audit', label: '操作日志', path: '/admin/logs/audit' },
      { id: 'logs-security', label: '安全事件', path: '/admin/logs/security' },
      { id: 'logs-login', label: '登录日志', path: '/admin/logs/login' },
    ]
  },
  {
    id: 'support',
    icon: '🎧',
    label: '客服工单',
    path: '/admin/support',
    requiredPermission: { resource: 'tickets', action: 'read' },
    badge: 'open_tickets',
    children: [
      { id: 'support-tickets', label: '工单列表', path: '/admin/support' },
      { id: 'support-stats', label: '客服统计', path: '/admin/support/stats' },
    ]
  }
];

// 权限过滤
function filterMenuByPermissions(menuItems: MenuItem[], permissions: Permission[]): MenuItem[] {
  return menuItems.filter(item => {
    const hasPermission = checkPermission(permissions, item.requiredPermission);
    if (!hasPermission) return false;
    
    if (item.children) {
      item.children = filterMenuByPermissions(item.children, permissions);
    }
    return true;
  });
}

5.3 Dashboard 页面

┌─────────────────────────────────────────────────────────────────┐
│  📊 仪表盘                                                        │
│  ═══════════════════════════════════════════════════════════════  │
│                                                                  │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────┐│
│  │  👤 总用户   │ │  📈 日活跃   │ │  💰 月收入   │ │  🟢 系统  ││
│  │              │ │              │ │              │ │          ││
│  │  12,456      │ │  3,892      │ │  ¥45,678    │ │  健康    ││
│  │  ↑ 12%      │ │  ↑ 5%       │ │  ↑ 8%       │ │  99.9%  ││
│  │  vs 上月    │ │  vs 昨日    │ │  vs 上月    │ │          ││
│  │ [查看详情]  │ │ [查看详情]  │ │ [查看详情]  │ │ [查看]  ││
│  └──────────────┘ └──────────────┘ └──────────────┘ └──────────┘│
│                                                                  │
│  ┌──────────────────────────────────────────────────────────────┐│
│  │  📈 用户增长趋势(近30天)                                     ││
│  │  [折线图:DAU + 新用户 + 活跃用户]                           ││
│  │                                                              ││
│  │  今日: DAU 3,892 | 新用户 156 | 活跃用户 67%                  ││
│  │  本周: 平均 DAU 3,654 | 周留存 45%                            ││
│  │  本月: 目标 4,000 DAU | 当前进度 97%                         ││
│  └──────────────────────────────────────────────────────────────┘│
│                                                                  │
│  ┌──────────────────────────┐ ┌──────────────────────────────┐  │
│  │  📊 套餐分布               │ │  🌍 地域分布                  │  │
│  │  [饼图]                   │ │  [地图热力图]                 │  │
│  │                          │ │                              │  │
│  │  Free: 8,234 (66%)        │ │  中国: 45%                   │  │
│  │  Pro: 3,456 (28%)         │ │  美国: 23%                   │  │
│  │  Team: 567 (4%)           │ │  日本: 8%                    │  │
│  │  Enterprise: 199 (2%)     │ │  其他: 24%                   │  │
│  │  [查看详情]               │ │  [查看详情]                  │  │
│  └──────────────────────────┘ └──────────────────────────────┘  │
│                                                                  │
│  ┌──────────────────────────────────────────────────────────────┐│
│  │  ⚠️ 需要关注                                                  ││
│  │                                                              ││
│  │  • 3 个用户待审核(注册超过24小时未激活)                      ││
│  │  • 7 条内容举报待处理(其中 2 条高优先级)                     ││
│  │  • 5 个订阅即将到期(3天内)且未开启自动续费                  ││
│  │  • 1 个安全事件:异常登录尝试(IP: 192.168.x.x)               ││
│  │  • 系统磁盘使用率达到 85%(建议扩容)                         ││
│  │                                                              ││
│  │  [处理全部] [查看详情]                                        ││
│  └──────────────────────────────────────────────────────────────┘│
│                                                                  │
│  ┌──────────────────────────────────────────────────────────────┐│
│  │  📈 功能使用排行(近7天)                                     ││
│  │                                                              ││
│  │  1. 笔记管理    ████████████████████████████████  78%      ││
│  │  2. 浏览器剪藏  ██████████████████████████        65%      ││
│  │  3. LLM 对话    ██████████████████████            52%      ││
│  │  4. 知识图谱    ████████████████                  41%      ││
│  │  5. 时间胶囊    ████████████                      32%      ││
│  │  6. 注意力管家  █████████                         25%      ││
│  │  7. RSS 聚合    ██████                            18%      ││
│  │  8. 反脆弱库    ████                              15%      ││
│  │                                                              ││
│  └──────────────────────────────────────────────────────────────┘│
│                                                                  │
│  ┌──────────────────────────────────────────────────────────────┐│
│  │  💰 收入趋势(近6个月)                                       ││
│  │  [柱状图:MRR + 新订 + 续订 + 退款]                           ││
│  │                                                              ││
│  │  MRR: ¥45,678 | ARR: ¥548,136 | 目标达成率: 87%              ││
│  │  本月新订: 156 | 续订: 89% | 退款: 3 | 退款率: 0.8%          ││
│  └──────────────────────────────────────────────────────────────┘│
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

5.4 用户管理页面

┌─────────────────────────────────────────────────────────────────┐
│  👤 用户管理                                                      │
│  ═══════════════════════════════════════════════════════════════  │
│                                                                  │
│  筛选: [搜索邮箱/名称] [状态 ▼] [套餐 ▼] [注册时间 ▼] [导出]     │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐│
│  │  [☑] 用户ID    邮箱              名称    套餐    状态    注册   操作 ││
│  │  ───────────────────────────────────────────────────────────  ││
│  │  ☑  u_001    zhang@example.com  张三   Pro    ✓ 激活  2026-06 │ [查看] [编辑] ││
│  │  ☑  u_002    li@example.com     李四   Free   ✓ 激活  2026-06 │ [查看] [编辑] ││
│  │  ☑  u_003    wang@example.com   王五   Team   ⚠ 欠费  2026-05 │ [查看] [编辑] ││
│  │  ☑  u_004    zhao@example.com   赵六   Pro    🚫 封禁 2026-04 │ [查看] [编辑] ││
│  │  ☑  u_005    sun@example.com    孙七   Free   ⏳ 待审  2026-07 │ [查看] [编辑] ││
│  │  ───────────────────────────────────────────────────────────  ││
│  │  全选 [批量激活] [批量封禁] [批量升级] [导出选中]             ││
│  │  共 12,456 用户 | 第 1/623 页                                  ││
│  └────────────────────────────────────────────────────────────┘│
│                                                                  │
│  用户详情弹窗(点击"查看"):                                     │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  👤 张三 (zhang@example.com)                              │   │
│  │  ─────────────────────────────────────────────────────────  │   │
│  │  状态: ✓ 激活    套餐: Pro    到期: 2027-07-01           │   │
│  │  注册: 2026-06-15    最后登录: 2小时前 (IP: 123.45.x.x)   │   │
│  │  MFA: 已启用    存储: 1.2GB / 5GB                          │   │
│  │  ─────────────────────────────────────────────────────────  │   │
│  │  统计: 笔记 245 | 胶囊 12 | 剪藏 89 | 知识单元 456          │   │
│  │  API 调用: 本月 12,345 次 (限额 50,000)                     │   │
│  │  ─────────────────────────────────────────────────────────  │   │
│  │  [编辑套餐] [重置密码] [发送通知] [导出数据] [封禁账户]      │   │
│  │  [查看登录历史] [查看工单] [查看操作日志]                    │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

5.5 内容审核页面

┌─────────────────────────────────────────────────────────────────┐
│  📰 内容审核                                                      │
│  ═══════════════════════════════════════════════════════════════  │
│                                                                  │
│  筛选: [状态 ▼] [类型 ▼] [标记原因 ▼] [AI风险 ▼] [日期 ▼] [搜索]  │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐│
│  │  [☑] 内容ID  类型    标题/摘要        用户     状态   标记   操作 ││
│  │  ───────────────────────────────────────────────────────────  ││
│  │  ☑  c_001   剪藏    "Rust 内存安全..."  张三    ⚠ 待审  用户举报  │ [审核] ││
│  │  ☑  c_002   笔记    "个人日记..."      李四    ⚠ 待审  AI检测   │ [审核] ││
│  │  ☑  c_003   剪藏    "某框架性能..."    王五    🚫 已移除 虚假  │ [审核] ││
│  │  ☑  c_004   知识    "投资建议..."      赵六    ⚠ 待审  用户举报  │ [审核] ││
│  │  ───────────────────────────────────────────────────────────  ││
│  │  全选 [批量通过] [批量移除] [批量标记]                        ││
│  └────────────────────────────────────────────────────────────┘│
│                                                                  │
│  审核弹窗:                                                       │
│  ┌──────────────────────────────────────────────────────────┐   │
│  │  📰 内容审核: 剪藏 #c_001                                │   │
│  │  ───────────────────────────────────────────────────────  │   │
│  │  来源: https://example.com/blog/rust-memory              │   │
│  │  用户: 张三 (zhang@example.com)                          │   │
│  │  标记: 用户举报 (原因: "内容不准确")                      │   │
│  │  ───────────────────────────────────────────────────────  │   │
│  │  AI 检测:                                                 │   │
│  │  • 垃圾信息: 0.12 (低)                                   │   │
│  │  • 毒性内容: 0.05 (低)                                   │   │
│  │  • 版权风险: 0.34 (中)                                   │   │
│  │  • AI生成: 否                                             │   │
│  │  ───────────────────────────────────────────────────────  │   │
│  │  内容预览:                                                │   │
│  │  [内容预览区域...]                                        │   │
│  │  ───────────────────────────────────────────────────────  │   │
│  │  操作:                                                    │   │
│  │  [✅ 通过 - 内容正常] [🚫 移除 - 违规] [⚠️ 警告 - 边缘]      │   │
│  │  [👤 警告用户] [📝 内部备注] [⬆️ 升级处理]                   │   │
│  │  原因: [输入审核原因...]                                  │   │
│  │  通知用户: ☑ 发送通知                                     │   │
│  └──────────────────────────────────────────────────────────┘   │
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

5.6 系统健康监控页面

┌─────────────────────────────────────────────────────────────────┐
│  🖥️ 系统健康监控                                                  │
│  ═══════════════════════════════════════════════════════════════  │
│                                                                  │
│  ┌────────────────┐ ┌────────────────┐ ┌────────────────┐      │
│  │  🟢 API 服务    │ │  🟢 数据库      │ │  🟢 向量数据库   │      │
│  │  可用率: 99.9% │ │  延迟: 12ms     │ │  ChromaDB     │      │
│  │  平均响应: 45ms│ │  连接池: 8/20   │ │  延迟: 23ms    │      │
│  │  [查看详情]    │ │  [查看详情]     │ │  [查看详情]    │      │
│  └────────────────┘ └────────────────┘ └────────────────┘      │
│                                                                  │
│  ┌────────────────┐ ┌────────────────┐ ┌────────────────┐      │
│  │  🟢 Redis      │ │  🟡 Ollama      │ │  🟢 磁盘存储    │      │
│  │  内存: 45%     │ │  模型加载: 3/5  │ │  使用: 67%     │      │
│  │  键数: 1.2M   │ │  显存: 78%     │ │  可用: 156GB   │      │
│  │  [查看详情]    │ │  [查看详情]     │ │  [清理缓存]    │      │
│  └────────────────┘ └────────────────┘ └────────────────┘      │
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐│
│  │  📈 实时指标(近1小时)                                        ││
│  │  [多线图:API QPS + 延迟 + 错误率 + 队列深度]                   ││
│  │                                                              ││
│  │  当前 QPS: 234 | 平均延迟: 45ms | 错误率: 0.02% | 队列: 3   ││
│  └────────────────────────────────────────────────────────────┘│
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐│
│  │  ⚠️ 告警事件(最近24小时)                                     ││
│  │                                                              ││
│  │  14:32  🟡 磁盘使用 85% → 已自动清理缓存 → 当前 67%          ││
│  │  12:15  🟡 Ollama 模型 llama3.1:8b 加载失败 → 已重启 → 恢复   ││
│  │  09:45  🔴 API 延迟峰值 2.3s → 已自动扩容 → 恢复              ││
│  │  08:20  🟡 异常登录: IP 192.168.x.x 失败 5 次 → 已临时封禁   ││
│  │                                                              ││
│  │  [查看全部告警] [配置告警规则]                                 ││
│  └────────────────────────────────────────────────────────────┘│
│                                                                  │
│  ┌────────────────────────────────────────────────────────────┐│
│  │  📋 系统信息                                                  ││
│  │  版本: v1.2.3 (Build 20260701)                               ││
│  │  运行时间: 45 天 12 小时                                     ││
│  │  上次重启: 2026-05-17 02:00                                  ││
│  │  部署环境: production / Docker Compose / 4 vCPU / 16GB RAM  ││
│  │  [重启服务] [查看日志] [备份数据] [系统升级]                 ││
│  └────────────────────────────────────────────────────────────┘│
│                                                                  │
└─────────────────────────────────────────────────────────────────┘

6. 安全与合规

6.1 管理员认证安全

typescript
// MFA 实现
interface MFAConfig {
  enabled: boolean;
  method: 'totp' | 'sms' | 'email' | 'hardware_key';
  secret: string;              // TOTP 密钥(加密存储)
  backupCodes: string[];        // 备用码(一次性)
}

// 登录安全策略
interface LoginSecurityPolicy {
  maxFailedAttempts: number;     // 5 次失败锁定
  lockoutDuration: number;      // 30 分钟
  passwordMinLength: number;     // 12 位
  passwordComplexity: 'medium' | 'high';
  sessionTimeout: number;       // 30 分钟无操作登出
  requireMfa: boolean;          // 是否强制 MFA
  ipWhitelist: string[];       // 允许的管理 IP
  geoRestriction: string[];    // 允许的国家
}

// 敏感操作二次确认
interface SensitiveAction {
  action: 'delete_user' | 'refund_order' | 'change_config' | 'feature_flag_toggle';
  requireMfa: boolean;
  requireConfirmation: boolean;  // 需要二次确认弹窗
  requireReason: boolean;       // 需要填写原因
  auditLevel: 'standard' | 'high' | 'critical';
}

6.2 数据脱敏

typescript
// 用户数据脱敏策略
interface DataMaskingPolicy {
  // 默认脱敏规则
  rules: {
    email: 'partial';           // z***@example.com
    phone: 'partial';           // 138****5678
    password: 'hidden';         // ********
    ipAddress: 'partial';         // 192.168.x.x
    content: 'truncated';       // 内容截断显示
    paymentInfo: 'hidden';     // 支付信息完全隐藏
  };
  
  // 按角色覆盖
  roleOverrides: {
    'super_admin': { email: 'full', phone: 'full' },
    'support': { email: 'partial', content: 'full' },
    'finance_admin': { paymentInfo: 'full' },
  };
}

6.3 GDPR/数据合规

typescript
// 数据合规接口
interface ComplianceAPI {
  // 用户数据导出(GDPR 数据可携带权)
  exportUserData(userId: string): Promise<ExportResult>;
  
  // 用户数据删除(GDPR 被遗忘权)
  deleteUserData(userId: string, reason: string): Promise<DeleteResult>;
  
  // 数据匿名化
  anonymizeUserData(userId: string): Promise<void>;
  
  // 数据保留策略
  dataRetentionPolicy: {
    auditLogs: '1year';         // 审计日志保留1年
    loginLogs: '6months';       // 登录日志保留6个月
    deletedContent: '30days';  // 已删除内容保留30天(用于恢复)
    inactiveUsers: '2years'; // 不活跃用户数据保留2年后匿名化
  };
}

7. 实现优先级

优先级模块功能预估时间
P0认证管理员登录、RBAC 权限中间件2天
P0仪表盘全局统计数据、KPI 卡片2天
P0用户管理用户列表、详情、状态管理2天
P1内容审核内容列表、审核操作、举报处理2天
P1数据统计时间序列、留存、漏斗、图表3天
P1日志审计操作日志、安全事件、导出2天
P2订阅计费订单、订阅、退款、促销3天
P2系统管理配置、Feature Flags、公告、健康监控2天
P2客服工单工单列表、回复、统计2天
P3多租户租户管理、隔离、配额3天
P3高级安全MFA、IP 白名单、数据脱敏、GDPR2天
P3自动化告警、自动封禁、邮件通知2天

8. Admin 路由配置

typescript
// frontend/src/admin/AdminApp.tsx
import { Routes, Route, Navigate } from 'react-router-dom';
import AdminLayout from './layouts/AdminLayout';
import AdminLogin from './pages/AdminLogin';
import AdminDashboard from './pages/AdminDashboard';
import AdminUsers from './pages/users/AdminUsers';
import AdminUserDetail from './pages/users/AdminUserDetail';
import AdminContent from './pages/content/AdminContent';
import AdminStats from './pages/stats/AdminStats';
import AdminBilling from './pages/billing/AdminBilling';
import AdminSystem from './pages/system/AdminSystem';
import AdminLogs from './pages/logs/AdminLogs';
import AdminSupport from './pages/support/AdminSupport';
import { RequireAdminAuth } from './components/RequireAdminAuth';
import { RequirePermission } from './components/RequirePermission';

function AdminApp() {
  return (
    <Routes>
      {/* 登录页(公开) */}
      <Route path="/login" element={<AdminLogin />} />
      
      {/* 需要认证的路由 */}
      <Route element={<RequireAdminAuth />}>
        <Route element={<AdminLayout />}>
          {/* Dashboard - 所有管理员可见 */}
          <Route path="/" element={<AdminDashboard />} />
          
          {/* 用户管理 - 需要 users:read */}
          <Route element={<RequirePermission resource="users" action="read" />}>
            <Route path="/users" element={<AdminUsers />} />
            <Route path="/users/:id" element={<AdminUserDetail />} />
          </Route>
          
          {/* 内容管理 - 需要 content:read */}
          <Route element={<RequirePermission resource="content" action="read" />}>
            <Route path="/content" element={<AdminContent />} />
          </Route>
          
          {/* 数据统计 - 需要 stats:read */}
          <Route element={<RequirePermission resource="stats" action="read" />}>
            <Route path="/stats" element={<AdminStats />} />
            <Route path="/stats/:metric" element={<AdminStats />} />
          </Route>
          
          {/* 订阅计费 - 需要 subscriptions:read */}
          <Route element={<RequirePermission resource="subscriptions" action="read" />}>
            <Route path="/billing" element={<AdminBilling />} />
          </Route>
          
          {/* 系统管理 - 需要 system:read */}
          <Route element={<RequirePermission resource="system" action="read" />}>
            <Route path="/system" element={<AdminSystem />} />
          </Route>
          
          {/* 日志审计 - 需要 logs:read */}
          <Route element={<RequirePermission resource="logs" action="read" />}>
            <Route path="/logs" element={<AdminLogs />} />
          </Route>
          
          {/* 客服工单 - 需要 tickets:read */}
          <Route element={<RequirePermission resource="tickets" action="read" />}>
            <Route path="/support" element={<AdminSupport />} />
          </Route>
        </Route>
      </Route>
      
      {/* 未匹配路由 */}
      <Route path="*" element={<Navigate to="/admin" />} />
    </Routes>
  );
}

export default AdminApp;

9. 前后端整合要点

9.1 API 路由隔离

python
# backend/app/main.py
from fastapi import FastAPI
from app.api.admin.router import admin_router
from app.api.v1.router import api_router

app = FastAPI()

# 普通用户 API
app.include_router(api_router, prefix="/api/v1")

# 管理员 API(独立前缀 + 严格认证)
app.include_router(admin_router, prefix="/api/admin")

9.2 管理员认证中间件

python
# backend/app/api/admin/middleware.py
from fastapi import Request, HTTPException, Depends
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
from jose import jwt, JWTError
from datetime import datetime

security = HTTPBearer()

async def require_admin_auth(
    credentials: HTTPAuthorizationCredentials = Depends(security)
) -> AdminUser:
    """验证管理员 JWT Token"""
    try:
        payload = jwt.decode(
            credentials.credentials,
            SECRET_KEY,
            algorithms=[ALGORITHM]
        )
        
        admin_id = payload.get("sub")
        if not admin_id:
            raise HTTPException(status_code=401, detail="Invalid token")
        
        # 检查 Token 类型(必须是 admin)
        token_type = payload.get("type")
        if token_type != "admin":
            raise HTTPException(status_code=403, detail="Admin access required")
        
        # 获取管理员信息
        admin = await get_admin_user(admin_id)
        if not admin:
            raise HTTPException(status_code=401, detail="Admin not found")
        
        if admin.status != "active":
            raise HTTPException(status_code=403, detail="Admin account inactive")
        
        return admin
        
    except JWTError:
        raise HTTPException(status_code=401, detail="Invalid token")

async def require_permission(
    resource: str,
    action: str
):
    """权限检查装饰器"""
    async def checker(admin: AdminUser = Depends(require_admin_auth)):
        if not has_permission(admin, resource, action):
            raise HTTPException(
                status_code=403,
                detail=f"Permission denied: {resource}:{action}"
            )
        return admin
    return checker

# 使用方式
@router.get("/users", dependencies=[Depends(require_permission("users", "read"))])
async def list_users(admin: AdminUser = Depends(require_admin_auth)):
    pass

9.3 审计日志自动记录

python
# backend/app/api/admin/decorators.py
from functools import wraps
import json
from datetime import datetime

class AuditLogMiddleware:
    """自动记录管理操作的装饰器"""
    
    def __init__(self, resource_type: str, action: str, risk_level: str = "low"):
        self.resource_type = resource_type
        self.action = action
        self.risk_level = risk_level
    
    def __call__(self, func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            # 获取管理员信息(从依赖注入)
            admin = kwargs.get("admin")
            request = kwargs.get("request")
            
            # 记录操作前状态(如果是更新/删除)
            before_state = None
            if self.action in ["update", "delete"]:
                resource_id = kwargs.get("id")
                if resource_id:
                    before_state = await get_resource_state(self.resource_type, resource_id)
            
            # 执行操作
            result = await func(*args, **kwargs)
            
            # 记录操作后状态
            after_state = None
            if self.action in ["create", "update"] and result:
                after_state = json.loads(result.json()) if hasattr(result, "json") else result
            
            # 计算变更
            changes = []
            if before_state and after_state:
                changes = calculate_diff(before_state, after_state)
            
            # 写入审计日志
            await create_audit_log({
                "admin_id": admin.id,
                "admin_name": admin.name,
                "admin_role": admin.role,
                "action": self.action,
                "resource_type": self.resource_type,
                "resource_id": kwargs.get("id"),
                "before_state": json.dumps(before_state) if before_state else None,
                "after_state": json.dumps(after_state) if after_state else None,
                "changes": json.dumps(changes),
                "ip_address": request.client.host if request else None,
                "user_agent": request.headers.get("user-agent") if request else None,
                "risk_level": self.risk_level,
                "created_at": datetime.utcnow()
            })
            
            return result
        return wrapper

# 使用方式
@router.patch("/users/{id}")
@AuditLogMiddleware(resource_type="users", action="update", risk_level="medium")
async def update_user(
    id: str,
    data: UserUpdate,
    admin: AdminUser = Depends(require_admin_auth),
    request: Request = None
):
    pass

基于 AGPL-3.0 协议发布。