feat: 添加注释

This commit is contained in:
Blizzard
2026-04-01 15:29:35 +08:00
parent aef2e152dc
commit 6162c9110c
28 changed files with 1293 additions and 298 deletions
+38 -6
View File
@@ -1,16 +1,48 @@
// Package models 定义知识库 .db 文件中的核心业务表。
package models
import "time"
// Entry is a single Q&A row in a knowledge library .db file.
// Entry 是知识库中的一条问答记录,存储于各知识库 .db 文件的 entries 表。
//
// # 设计说明
//
// Entry 不包含 user_id 字段——这是本架构与传统多用户方案的核心区别。
// 数据隔离通过"切换不同 .db 文件"实现(物理隔离),而非逻辑隔离。
// 这意味着:
// - 每个知识库文件就是一个完全独立的数据源;
// - 任何针对 Entry 的查询都自动限定在当前活跃的知识库内;
// - 不存在因遗漏 WHERE user_id = ? 而导致跨库数据泄露的风险。
//
// # 字段说明
//
// Keyword 是搜索的主要匹配目标(经过 INDEX 加速),
// Question 存放完整的问题文本(兼做二级匹配),
// Answer 存放答案全文(供 AI 润色时作为原始素材)。
type Entry struct {
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
Keyword string `gorm:"index;size:255;not null" json:"keyword"`
Question string `gorm:"type:text;not null" json:"question"`
Answer string `gorm:"type:text;not null" json:"answer"`
Category string `gorm:"size:100;default:'通用'" json:"category"`
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
// Keyword 是精简的检索关键词,例如 "退款政策"、"浇水频率"。
// 添加了 GORM 索引(B-Tree),使 LIKE '%keyword%' 查询更快。
// size:255 对应 TEXT NOT NULL,防止存入过长字符串或空值。
Keyword string `gorm:"index;size:255;not null" json:"keyword"`
// Question 是完整的问题描述,作为搜索的二级匹配字段。
// type:text 映射到 SQLite TEXT 类型,无长度限制。
Question string `gorm:"type:text;not null" json:"question"`
// Answer 是对应答案全文,也是传给 AI 做"润色"的原始素材。
Answer string `gorm:"type:text;not null" json:"answer"`
// Category 用于前端分类展示和颜色区分(例如 "浇水"、"病虫害")。
// default:'通用' 保证没填分类时有默认值,避免前端渲染空标签。
Category string `gorm:"size:100;default:'通用'" json:"category"`
// GORM 约定字段:自动维护创建时间和最后更新时间。
// UpdatedAt 用于在搜索无结果时排序返回"最近更新"的热门问答。
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
// TableName 显式指定表名为 "entries"(避免 GORM 默认复数化为 "entries" / "entris")。
func (Entry) TableName() string { return "entries" }
+44 -11
View File
@@ -1,25 +1,58 @@
// Package models 定义所有 GORM 数据模型(对应 SQLite 数据表)。
//
// 本文件包含两个存在于 settings.db 中的模型:
// - AppSetting: 简单的键值配置表,用于存 AI 参数和用户偏好。
// - Library: 知识库注册表,每行指向一个独立的 .db 文件。
package models
import "time"
// AppSetting is a key-value store for global application settings
// (AI provider, endpoint, API key, etc.) in settings.db.
// AppSetting 是存储于 settings.db 的全局键值对配置表。
//
// 选择键值对(而非定义强类型结构体)的原因:
// 1. 配置项未来可能扩展(新增 AI 提供商、新增偏好项),KV 表无需迁移。
// 2. 加密后的 API Key(二进制)和普通字符串值可以统一存储。
// 3. UPSERTINSERT ... ON CONFLICT DO UPDATE)操作极为简单。
//
// 典型键名:
// - "ai_provider" / "base_url" / "model"
// - "api_key_encrypted"AES-256-GCM 密文 base64
// - "system_prompt" / "max_tokens" / "use_public_key"
// - "active_library" (上次使用的知识库名,用于启动时恢复)
type AppSetting struct {
Key string `gorm:"primaryKey;size:100" json:"key"`
// Key 使用 primaryKey,保证同名键全局唯一,UPSERT 可直接依赖此约束。
Key string `gorm:"primaryKey;size:100" json:"key"`
// Value 使用 text 而非 varchar,支持存储较长内容(如系统提示词)。
Value string `gorm:"type:text" json:"value"`
}
// TableName 显式声明表名,避免 GORM 的复数化规则(AppSettings → app_settings
// 在不同 GORM 版本间产生歧义。
func (AppSetting) TableName() string { return "app_settings" }
// Library represents a registered knowledge library in settings.db.
// Each library is a separate SQLite file.
// Library 是知识库注册表,存储于 settings.db
//
// 每条 Library 记录描述一个独立的知识库 .db 文件。
//
// # 物理隔离设计
//
// 传统多租户方案在同一张表里用 user_id 或 namespace 做逻辑隔离,
// 一旦查询遗漏 WHERE 条件就会产生跨库数据泄露。
// 本项目改用"一个知识库 = 一个独立 .db 文件"的物理隔离方案:
// - 数据泄露风险从根本上消除;
// - 用户可以在 Finder 中直接拷贝/分享单个 .db 文件;
// - 切换知识库等同于更换数据库连接,极为清晰。
type Library struct {
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
Name string `gorm:"uniqueIndex;size:100;not null" json:"name"`
Description string `gorm:"size:255" json:"description"`
FilePath string `gorm:"size:1024;not null" json:"file_path"`
EntryCount int `gorm:"-" json:"entry_count"` // populated on read
CreatedAt time.Time `json:"created_at"`
ID uint `gorm:"primaryKey;autoIncrement" json:"id"`
// Name 添加 uniqueIndex 防止重复注册同名知识库。
Name string `gorm:"uniqueIndex;size:100;not null" json:"name"`
Description string `gorm:"size:255" json:"description"`
// FilePath 存储 .db 文件的绝对路径,程序通过此路径打开对应 SQLite 连接。
FilePath string `gorm:"size:1024;not null" json:"file_path"`
// EntryCount 使用 gorm:"-" 标签,表示此字段不映射到数据库列,
// 而是在 service 层查询后动态填充,供前端展示。
EntryCount int `gorm:"-" json:"entry_count"`
CreatedAt time.Time `json:"created_at"`
}
func (Library) TableName() string { return "libraries" }