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
+53 -11
View File
@@ -1,3 +1,11 @@
// Package handler 将 service 层的能力暴露为 Wails 绑定方法。
//
// Handler 层的职责非常单一:
// 1. 调用 Wails runtime API(文件对话框、事件等);
// 2. 将 service 返回值转换为前端友好的格式(string 错误消息等);
// 3. 不包含任何业务逻辑,所有逻辑都在 service 层。
//
// 此文件专门处理"知识库 CRUD + 文件导入"的 Wails 绑定。
package handler
import (
@@ -9,13 +17,15 @@ import (
"github.com/wailsapp/wails/v2/pkg/runtime"
)
// LibraryHandler exposes library management and CSV import via Wails bindings.
// LibraryHandler 是知识库管理功能的 Wails 绑定集合。
// ctx 在 startup 时由 Wails 注入,用于调用 runtime API(如文件对话框)。
type LibraryHandler struct{ ctx context.Context }
func NewLibraryHandler() *LibraryHandler { return &LibraryHandler{} }
func (h *LibraryHandler) SetContext(ctx context.Context) { h.ctx = ctx }
// ListLibraries returns all registered knowledge libraries.
// ListLibraries 返回所有已注册知识库的列表,含实时条目数和"是否活跃"标志。
// is_active 由当前活跃库名称与各库名称对比判断(在 handler 层计算,service 层不感知"活跃"概念)。
func (h *LibraryHandler) ListLibraries() []LibraryInfo {
libs, err := service.ListLibraries()
if err != nil {
@@ -25,32 +35,38 @@ func (h *LibraryHandler) ListLibraries() []LibraryInfo {
for i, l := range libs {
out[i] = LibraryInfo{
ID: l.ID, Name: l.Name, Description: l.Description,
EntryCount: l.EntryCount, IsActive: l.Name == database.GetActiveLibName(),
EntryCount: l.EntryCount,
IsActive: l.Name == database.GetActiveLibName(),
}
}
return out
}
// GetActiveLibrary returns the name of the currently active library.
// GetActiveLibrary 返回当前活跃知识库的名称,用于前端 LibraryBar 标题显示。
func (h *LibraryHandler) GetActiveLibrary() string {
return database.GetActiveLibName()
}
// CreateLibrary registers a new knowledge library.
// CreateLibrary 创建新知识库,并自动切换到它。
//
// 创建后立即切换的原因:用户刚创建的库通常就是下一步要操作的目标,
// 省去一次额外的"切换"操作。
// 返回空字符串表示成功,否则返回中文错误信息供前端 Toast 显示。
func (h *LibraryHandler) CreateLibrary(name, description string) string {
if name == "" {
return "名称不能为空"
return "知识库名称不能为空"
}
lib, err := service.CreateLibrary(name, description)
if err != nil {
return err.Error()
}
// Auto-switch to newly created library
// 忽略切换错误(文件刚创建,极少失败),用户可手动重新切换
service.SwitchLibrary(lib.Name) //nolint
return ""
}
// SwitchLibrary makes the named library active.
// SwitchLibrary 将指定名称的知识库激活为当前工作库。
// 返回空字符串表示成功,否则返回错误信息。
func (h *LibraryHandler) SwitchLibrary(name string) string {
if err := service.SwitchLibrary(name); err != nil {
return err.Error()
@@ -58,7 +74,10 @@ func (h *LibraryHandler) SwitchLibrary(name string) string {
return ""
}
// DeleteLibrary removes a library from the registry (file is kept).
// DeleteLibrary 从注册表中移除知识库(不删除 .db 文件)。
//
// 在删除前强制检查:不能删除当前正在使用的库,
// 因为删除后活跃连接会变成悬空引用,后续写入会 panic。
func (h *LibraryHandler) DeleteLibrary(name string) string {
if name == database.GetActiveLibName() {
return "不能删除当前使用中的知识库,请先切换到其他库"
@@ -69,7 +88,13 @@ func (h *LibraryHandler) DeleteLibrary(name string) string {
return ""
}
// ImportCSV opens a native file dialog then imports CSV data into the active library.
// ImportCSV 调起系统原生文件选择对话框,让用户选取 CSV 文件后导入。
//
// 使用 Wails runtime.OpenFileDialog 而非让前端传入路径的原因:
// 1. 安全性:前端(WebView)无法直接访问本地文件系统,
// 必须通过 Wails 桥接调用原生对话框;
// 2. 体验:原生对话框支持文件类型过滤(*.csv),
// 比任何 HTML <input type="file"> 都更流畅。
func (h *LibraryHandler) ImportCSV() service.ImportResult {
filePath, err := runtime.OpenFileDialog(h.ctx, runtime.OpenDialogOptions{
Title: "选择 CSV 文件",
@@ -84,7 +109,24 @@ func (h *LibraryHandler) ImportCSV() service.ImportResult {
return service.ImportCSV(filePath)
}
// LibraryInfo is the frontend-facing representation of a library.
// ImportExcel 调起原生文件对话框,让用户选取 .xlsx 文件后导入。
// 逻辑与 ImportCSV 完全对称,仅文件过滤器和 service 调用不同。
func (h *LibraryHandler) ImportExcel() service.ImportResult {
filePath, err := runtime.OpenFileDialog(h.ctx, runtime.OpenDialogOptions{
Title: "选择 Excel 文件",
Filters: []runtime.FileFilter{
{DisplayName: "Excel 文件", Pattern: "*.xlsx"},
{DisplayName: "所有文件", Pattern: "*"},
},
})
if err != nil || filePath == "" {
return service.ImportResult{Error: "已取消"}
}
return service.ImportExcel(filePath)
}
// LibraryInfo 是 LibraryHandler 向前端暴露的知识库信息 DTO。
// 相比 models.Library,额外计算了 IsActive 字段,并去掉了 FilePath(不暴露内部路径)。
type LibraryInfo struct {
ID uint `json:"id"`
Name string `json:"name"`