Files
new-api/.trae/documents/tech-architecture.md
T
admin e83ec743c8
Docker Build / Build and Push Docker Image (push) Failing after 1m35s
feat: add DaisyUI frontend theme and document management system
2026-06-13 01:36:06 +08:00

13 KiB
Raw Blame History

ModelsToken 管理平台 - 技术架构文档

1. 架构设计

flowchart TB
    subgraph "前端 (React + DaisyUI 5)"
        A["React 18"] --> B["React Router v6"]
        B --> C["页面组件"]
        C --> D["DaisyUI 5 组件"]
        D --> E["Tailwind CSS 4"]
        A --> F["Zustand 状态管理"]
        A --> G["React Query 数据请求"]
        A --> H["i18next 国际化"]
        A --> I["React Markdown 渲染"]
    end
    subgraph "后端 (Go + Gin)"
        J["Gin HTTP Server"]
        J --> K["API 路由"]
        J --> L["Relay 代理"]
        K --> M["控制器"]
        M --> N["模型层"]
        N --> O["数据库 (SQLite/MySQL/PostgreSQL)"]
    end
    C -->|"Axios HTTP"| K

2. 技术说明

  • 前端框架React 18 + TypeScript
  • UI 库DaisyUI 5 + Tailwind CSS 4
  • 构建工具Vite 6
  • 路由React Router v6(懒加载)
  • 状态管理Zustand(轻量级,替代 Redux
  • 数据请求TanStack React Query v5 + Axios
  • 国际化i18next + react-i18next
  • 图表Recharts
  • Markdownreact-markdown + remark-gfm + rehype-highlight
  • 图标Lucide React
  • 代码高亮highlight.js
  • 表单验证React Hook Form + Zod
  • 通知react-hot-toast
  • 项目目录web/daisy/

3. 路由定义

3.1 公共路由

路由 用途
/ 首页
/login 登录
/register 注册
/forgot-password 忘记密码
/reset-password 密码重置确认
/setup 初始化向导
/pricing 模型定价
/about 关于
/user-agreement 用户协议
/privacy-policy 隐私政策
/oauth/callback/:provider OAuth 回调

3.2 认证后路由

路由 用途
/dashboard 仪表盘
/tokens API 密钥管理
/wallet 钱包/充值
/subscriptions 订阅管理
/logs 使用日志
/logs/midjourney MJ 日志
/logs/tasks 任务日志
/profile 个人设置
/playground Playground
/docs 文档中心(新增)
/docs/:slug 文档详情(新增)

3.3 管理员路由

路由 用途
/admin/channels 渠道管理
/admin/users 用户管理
/admin/redemptions 兑换码管理
/admin/models 模型管理
/admin/vendors 供应商管理
/admin/deployments 部署管理
/admin/subscriptions 订阅计划管理

3.4 超级管理员路由

路由 用途
/settings/site 站点设置
/settings/auth 认证设置
/settings/billing 计费设置
/settings/content 内容设置
/settings/models 模型设置
/settings/operations 运维设置
/settings/security 安全设置
/settings/docs 文档管理(新增)

4. API 定义

4.1 核心类型

// 用户
interface User {
  id: number;
  username: string;
  display_name: string;
  email: string;
  role: number; // 1=user, 10=admin, 100=root
  status: number;
  quota: number;
  used_quota: number;
  request_count: number;
  group: string;
  aff_code: string;
  inviter_id: number;
  language: string;
  access_token: string;
  created_time: number;
}

// 渠道
interface Channel {
  id: number;
  type: number;
  key: string;
  openai_organization?: string;
  base_url: string;
  models: string;
  model_mapping?: string;
  group: string;
  groups: string[];
  name: string;
  priority: number;
  weight: number;
  status: number;
  tag?: string;
  setting?: string;
  test_time: number;
  response_time: number;
  balance: number;
  balance_updated_time: number;
  created_time: number;
}

// 令牌
interface Token {
  id: number;
  user_id: number;
  key: string;
  status: number;
  name: string;
  created_time: number;
  accessed_time: number;
  expired_time: number;
  remain_quota: number;
  unlimited_quota: boolean;
  used_quota: number;
  models: string;
  subnet: string;
  group: string;
}

// 日志
interface Log {
  id: number;
  user_id: number;
  created_at: number;
  type: number;
  content: string;
  username: string;
  token_name: string;
  model_name: string;
  quota: number;
  prompt_tokens: number;
  completion_tokens: number;
  channel_id: number;
  token_id: number;
  group: string;
  request_id: string;
  ip: string;
  detail: string;
}

// 订阅计划
interface SubscriptionPlan {
  id: number;
  name: string;
  description: string;
  price: number;
  currency: string;
  duration_days: number;
  quota: number;
  models: string;
  enabled: boolean;
  sort_order: number;
  created_time: number;
}

// 文档(新增)
interface Document {
  id: number;
  title: string;
  slug: string;
  content: string; // Markdown
  category_id: number;
  category?: DocumentCategory;
  visibility: 'public' | 'auth' | 'admin';
  sort_order: number;
  created_at: string;
  updated_at: string;
  author_id: number;
  author?: User;
  versions?: DocumentVersion[];
}

interface DocumentCategory {
  id: number;
  name: string;
  slug: string;
  parent_id: number | null;
  children?: DocumentCategory[];
  sort_order: number;
}

interface DocumentVersion {
  id: number;
  document_id: number;
  content: string;
  created_at: string;
  author_id: number;
}

4.2 新增文档管理 API

端点 方法 权限 说明
/api/docs/categories GET 公开 获取分类树
/api/docs/categories POST Admin 创建分类
/api/docs/categories/:id PUT Admin 更新分类
/api/docs/categories/:id DELETE Admin 删除分类
/api/docs/ GET 按可见性 文档列表(支持搜索)
/api/docs/:slug GET 按可见性 获取文档详情
/api/docs/ POST Admin 创建文档
/api/docs/:id PUT Admin 更新文档
/api/docs/:id DELETE Admin 删除文档
/api/docs/:id/versions GET Admin 文档版本历史

5. 项目目录结构

web/daisy/
├── index.html
├── package.json
├── tsconfig.json
├── vite.config.ts
├── tailwind.config.ts
├── public/
│   └── manifest.json
└── src/
    ├── main.tsx                    # 入口
    ├── App.tsx                     # 根组件 + 路由
    ├── vite-env.d.ts
    ├── api/                        # API 请求层
    │   ├── client.ts               # Axios 实例 + 拦截器
    │   ├── auth.ts                 # 认证 API
    │   ├── channel.ts              # 渠道 API
    │   ├── token.ts                # 令牌 API
    │   ├── user.ts                 # 用户 API
    │   ├── log.ts                  # 日志 API
    │   ├── subscription.ts         # 订阅 API
    │   ├── redemption.ts           # 兑换码 API
    │   ├── model.ts                # 模型 API
    │   ├── vendor.ts               # 供应商 API
    │   ├── deployment.ts           # 部署 API
    │   ├── option.ts               # 系统设置 API
    │   ├── payment.ts              # 支付 API
    │   └── doc.ts                  # 文档 API(新增)
    ├── stores/                     # Zustand 状态
    │   ├── auth.ts                 # 认证状态
    │   └── ui.ts                   # UI 状态(侧边栏/主题)
    ├── hooks/                      # 自定义 Hooks
    │   ├── useAuth.ts
    │   ├── usePermission.ts
    │   └── useQuota.ts
    ├── components/                 # 通用组件
    │   ├── layout/
    │   │   ├── AppLayout.tsx       # 主布局
    │   │   ├── Sidebar.tsx         # 侧边导航
    │   │   ├── Navbar.tsx          # 顶部导航
    │   │   └── Breadcrumb.tsx      # 面包屑
    │   ├── common/
    │   │   ├── QuotaDisplay.tsx    # 额度显示
    │   │   ├── ModelBadge.tsx      # 模型标签
    │   │   ├── StatusBadge.tsx     # 状态标签
    │   │   ├── SearchInput.tsx     # 搜索框
    │   │   ├── DataTable.tsx       # 数据表格
    │   │   ├── ConfirmDialog.tsx   # 确认对话框
    │   │   └── LoadingSpinner.tsx  # 加载动画
    │   └── charts/
    │       ├── QuotaChart.tsx      # 额度趋势图
    │       └── StatsChart.tsx      # 统计图表
    ├── pages/                      # 页面组件
    │   ├── public/
    │   │   ├── Home.tsx
    │   │   ├── Login.tsx
    │   │   ├── Register.tsx
    │   │   ├── ForgotPassword.tsx
    │   │   ├── Pricing.tsx
    │   │   ├── About.tsx
    │   │   └── Setup.tsx
    │   ├── dashboard/
    │   │   └── Dashboard.tsx
    │   ├── tokens/
    │   │   ├── TokenList.tsx
    │   │   └── TokenForm.tsx
    │   ├── channels/
    │   │   ├── ChannelList.tsx
    │   │   └── ChannelForm.tsx
    │   ├── users/
    │   │   ├── UserList.tsx
    │   │   └── UserForm.tsx
    │   ├── logs/
    │   │   ├── LogList.tsx
    │   │   ├── MidjourneyLog.tsx
    │   │   └── TaskLog.tsx
    │   ├── wallet/
    │   │   └── Wallet.tsx
    │   ├── subscriptions/
    │   │   ├── PlanList.tsx
    │   │   └── MySubscription.tsx
    │   ├── redemptions/
    │   │   └── RedemptionList.tsx
    │   ├── models/
    │   │   └── ModelList.tsx
    │   ├── vendors/
    │   │   └── VendorList.tsx
    │   ├── deployments/
    │   │   └── DeploymentList.tsx
    │   ├── playground/
    │   │   └── Playground.tsx
    │   ├── profile/
    │   │   └── Profile.tsx
    │   ├── docs/                   # 文档中心(新增)
    │   │   ├── DocCenter.tsx       # 文档浏览主页
    │   │   ├── DocViewer.tsx       # 文档阅读页
    │   │   ├── DocEditor.tsx       # 文档编辑页(管理员)
    │   │   └── DocCategoryManager.tsx # 分类管理(管理员)
    │   └── settings/
    │       ├── SiteSettings.tsx
    │       ├── AuthSettings.tsx
    │       ├── BillingSettings.tsx
    │       ├── ContentSettings.tsx
    │       ├── ModelSettings.tsx
    │       ├── OperationsSettings.tsx
    │       ├── SecuritySettings.tsx
    │       └── DocSettings.tsx     # 文档设置(新增)
    ├── i18n/                       # 国际化
    │   ├── index.ts
    │   └── locales/
    │       ├── en.json
    │       └── zh.json
    ├── lib/                        # 工具函数
    │   ├── constants.ts
    │   ├── utils.ts
    │   ├── quota.ts
    │   └── channel-types.ts
    └── types/                      # TypeScript 类型
        ├── api.ts
        ├── channel.ts
        ├── token.ts
        ├── user.ts
        ├── log.ts
        ├── subscription.ts
        ├── doc.ts
        └── option.ts

6. 数据模型(新增文档管理)

erDiagram
    "document_categories" {
        int id PK
        string name
        string slug UK
        int parent_id FK
        int sort_order
        timestamp created_at
    }
    "documents" {
        int id PK
        string title
        string slug UK
        text content
        int category_id FK
        string visibility
        int sort_order
        int author_id FK
        timestamp created_at
        timestamp updated_at
    }
    "document_versions" {
        int id PK
        int document_id FK
        text content
        int author_id FK
        timestamp created_at
    }
    "document_categories" ||--o{ "document_categories" : "parent"
    "document_categories" ||--o{ "documents" : "has"
    "documents" ||--o{ "document_versions" : "has"

DDL

CREATE TABLE document_categories (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    name VARCHAR(100) NOT NULL,
    slug VARCHAR(100) NOT NULL UNIQUE,
    parent_id INTEGER REFERENCES document_categories(id) ON DELETE SET NULL,
    sort_order INTEGER DEFAULT 0,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE documents (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    title VARCHAR(200) NOT NULL,
    slug VARCHAR(200) NOT NULL UNIQUE,
    content TEXT NOT NULL,
    category_id INTEGER REFERENCES document_categories(id) ON DELETE SET NULL,
    visibility VARCHAR(20) DEFAULT 'public' CHECK (visibility IN ('public', 'auth', 'admin')),
    sort_order INTEGER DEFAULT 0,
    author_id INTEGER NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE document_versions (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    document_id INTEGER NOT NULL REFERENCES documents(id) ON DELETE CASCADE,
    content TEXT NOT NULL,
    author_id INTEGER NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

CREATE INDEX idx_documents_slug ON documents(slug);
CREATE INDEX idx_documents_category ON documents(category_id);
CREATE INDEX idx_documents_visibility ON documents(visibility);
CREATE INDEX idx_document_versions_doc ON document_versions(document_id);