实现知识库页 UI 并对齐效果图
分类侧栏含条目计数、列表支持排序筛选与详情抽屉;列表接口补充分类名与使用次数排序。
This commit is contained in:
@@ -42,13 +42,40 @@ func hasKnowledgeCapacity(tenantID uint) (bool, error) {
|
||||
return count < int64(plan.KBLimit), nil
|
||||
}
|
||||
|
||||
type CategoryListItem struct {
|
||||
model.Category
|
||||
EntryCount int64 `json:"entry_count"`
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) ListCategories(c *gin.Context) {
|
||||
tenantID := middleware.GetTenantID(c)
|
||||
|
||||
var categories []model.Category
|
||||
model.DB.Where("tenant_id = ?", tenantID).Find(&categories)
|
||||
model.DB.Where("tenant_id = ?", tenantID).Order("id asc").Find(&categories)
|
||||
|
||||
middleware.JSON(c, categories)
|
||||
type countRow struct {
|
||||
CategoryID uint
|
||||
Cnt int64
|
||||
}
|
||||
var rows []countRow
|
||||
model.DB.Model(&model.KnowledgeEntry{}).
|
||||
Select("category_id, COUNT(*) as cnt").
|
||||
Where("tenant_id = ?", tenantID).
|
||||
Group("category_id").
|
||||
Scan(&rows)
|
||||
countMap := map[uint]int64{}
|
||||
var total int64
|
||||
for _, r := range rows {
|
||||
countMap[r.CategoryID] = r.Cnt
|
||||
total += r.Cnt
|
||||
}
|
||||
|
||||
items := make([]CategoryListItem, 0, len(categories))
|
||||
for _, cat := range categories {
|
||||
items = append(items, CategoryListItem{Category: cat, EntryCount: countMap[cat.ID]})
|
||||
}
|
||||
// total 放在额外字段便于侧栏「全部知识库」
|
||||
middleware.JSON(c, gin.H{"list": items, "total_entries": total})
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) CreateCategory(c *gin.Context) {
|
||||
@@ -70,12 +97,18 @@ func (h *KnowledgeHandler) CreateCategory(c *gin.Context) {
|
||||
middleware.JSON(c, category)
|
||||
}
|
||||
|
||||
type EntryListItem struct {
|
||||
model.KnowledgeEntry
|
||||
CategoryName string `json:"category_name"`
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) ListEntries(c *gin.Context) {
|
||||
tenantID := middleware.GetTenantID(c)
|
||||
page, pageSize := middleware.GetPageParams(c)
|
||||
categoryID := c.Query("category_id")
|
||||
search := c.Query("search")
|
||||
status := c.Query("status")
|
||||
sortBy := c.Query("sort") // usage | updated(default)
|
||||
|
||||
var entries []model.KnowledgeEntry
|
||||
var total int64
|
||||
@@ -92,9 +125,45 @@ func (h *KnowledgeHandler) ListEntries(c *gin.Context) {
|
||||
}
|
||||
|
||||
query.Model(&model.KnowledgeEntry{}).Count(&total)
|
||||
query.Order("updated_at desc").Offset((page - 1) * pageSize).Limit(pageSize).Find(&entries)
|
||||
order := "updated_at desc"
|
||||
if sortBy == "usage" {
|
||||
order = "usage_count desc, updated_at desc"
|
||||
} else if sortBy == "title" {
|
||||
order = "title asc"
|
||||
}
|
||||
query.Order(order).Offset((page - 1) * pageSize).Limit(pageSize).Find(&entries)
|
||||
|
||||
middleware.JSONList(c, entries, total, page, pageSize)
|
||||
catIDs := make([]uint, 0, len(entries))
|
||||
for _, e := range entries {
|
||||
catIDs = append(catIDs, e.CategoryID)
|
||||
}
|
||||
catMap := map[uint]string{}
|
||||
if len(catIDs) > 0 {
|
||||
seen := map[uint]struct{}{}
|
||||
unique := make([]uint, 0)
|
||||
for _, id := range catIDs {
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
unique = append(unique, id)
|
||||
}
|
||||
var cats []model.Category
|
||||
model.DB.Where("id IN ?", unique).Find(&cats)
|
||||
for _, cat := range cats {
|
||||
catMap[cat.ID] = cat.Name
|
||||
}
|
||||
}
|
||||
|
||||
items := make([]EntryListItem, 0, len(entries))
|
||||
for _, e := range entries {
|
||||
items = append(items, EntryListItem{
|
||||
KnowledgeEntry: e,
|
||||
CategoryName: catMap[e.CategoryID],
|
||||
})
|
||||
}
|
||||
|
||||
middleware.JSONList(c, items, total, page, pageSize)
|
||||
}
|
||||
|
||||
func (h *KnowledgeHandler) CreateEntry(c *gin.Context) {
|
||||
|
||||
Reference in New Issue
Block a user