yunzer_go/server/models/knowledge.go
2025-11-06 23:10:17 +08:00

456 lines
15 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package models
import (
"time"
"github.com/beego/beego/v2/client/orm"
)
// Knowledge 知识库模型
type Knowledge struct {
Id int `orm:"column(knowledge_id);pk;auto" json:"id"`
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
Title string `orm:"column(title);size(200)" json:"title"`
CategoryId int `orm:"column(category_id);default(0);null" json:"categoryId"`
CategoryName string `orm:"-" json:"categoryName"` // 不映射到数据库,从联查获取
Tags string `orm:"column(tags);type(text);null" json:"tags"`
Author string `orm:"column(author);size(50)" json:"author"`
Content string `orm:"column(content);type(longtext)" json:"content"`
Summary string `orm:"column(summary);size(500);null" json:"summary"`
CoverUrl string `orm:"column(cover_url);size(500);null" json:"coverUrl"`
Status int8 `orm:"column(status);default(0)" json:"status"`
Share int8 `orm:"column(share);default(0)" json:"share"`
ViewCount int `orm:"column(view_count);default(0)" json:"viewCount"`
LikeCount int `orm:"column(like_count);default(0)" json:"likeCount"`
IsRecommend int8 `orm:"column(is_recommend);default(0)" json:"isRecommend"`
IsTop int8 `orm:"column(is_top);default(0)" json:"isTop"`
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"`
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"updateTime"`
CreateBy string `orm:"column(create_by);size(50);null" json:"createBy"`
UpdateBy string `orm:"column(update_by);size(50);null" json:"updateBy"`
DeleteTime time.Time `orm:"column(delete_time);type(datetime);null" json:"deleteTime"`
DeleteBy string `orm:"column(delete_by);size(50);null" json:"deleteBy"`
}
// TableName 设置表名
func (k *Knowledge) TableName() string {
return "yz_knowledge"
}
// KnowledgeCategory 知识库分类模型
type KnowledgeCategory struct {
CategoryId int `orm:"column(category_id);pk;auto" json:"categoryId"`
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
CategoryName string `orm:"column(category_name);size(100)" json:"categoryName"`
CategoryDesc string `orm:"column(category_desc);size(500);null" json:"categoryDesc"`
ParentId int `orm:"column(parent_id);default(0)" json:"parentId"`
SortOrder int `orm:"column(sort_order);default(0)" json:"sortOrder"`
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"`
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"updateTime"`
}
// TableName 设置表名
func (kc *KnowledgeCategory) TableName() string {
return "yz_knowledge_category"
}
// KnowledgeTag 知识库标签模型
type KnowledgeTag struct {
TagId int `orm:"column(tag_id);pk;auto" json:"tagId"`
TenantId int `orm:"column(tenant_id);default(0)" json:"tenantId"`
TagName string `orm:"column(tag_name);size(50)" json:"tagName"`
TagColor string `orm:"column(tag_color);size(20);null" json:"tagColor"`
TagBackground string `orm:"column(tag_background);size(20);null" json:"tagBackground"`
UsageCount int `orm:"column(usage_count);default(0)" json:"usageCount"`
CreateTime time.Time `orm:"column(create_time);auto_now_add;type(datetime)" json:"createTime"`
UpdateTime time.Time `orm:"column(update_time);auto_now;type(datetime)" json:"updateTime"`
}
// TableName 设置表名
func (kt *KnowledgeTag) TableName() string {
return "yz_knowledge_tags"
}
// AddKnowledge 创建知识
func AddKnowledge(k *Knowledge) (int64, error) {
o := orm.NewOrm()
id, err := o.Insert(k)
return id, err
}
// GetKnowledgeById 根据ID获取知识详情使用联查获取分类名称
func GetKnowledgeById(id int, tenantId int) (*Knowledge, error) {
o := orm.NewOrm()
// 使用联查获取分类名称(只查询未删除的记录)
querySQL := `
SELECT k.*, c.category_name
FROM yz_knowledge k
LEFT JOIN yz_knowledge_category c ON k.category_id = c.category_id
WHERE k.knowledge_id = ? AND k.delete_time IS NULL
`
params := []interface{}{id}
// 如果tenantId > 0添加租户过滤
if tenantId > 0 {
querySQL += " AND k.tenant_id = ?"
params = append(params, tenantId)
}
var result struct {
Id int `orm:"column(knowledge_id)"`
Title string `orm:"column(title)"`
CategoryId int `orm:"column(category_id)"`
CategoryName string `orm:"column(category_name)"`
Tags string `orm:"column(tags)"`
Author string `orm:"column(author)"`
Content string `orm:"column(content)"`
Summary string `orm:"column(summary)"`
CoverUrl string `orm:"column(cover_url)"`
Status int8 `orm:"column(status)"`
ViewCount int `orm:"column(view_count)"`
LikeCount int `orm:"column(like_count)"`
IsRecommend int8 `orm:"column(is_recommend)"`
IsTop int8 `orm:"column(is_top)"`
CreateTime time.Time `orm:"column(create_time)"`
UpdateTime time.Time `orm:"column(update_time)"`
CreateBy string `orm:"column(create_by)"`
UpdateBy string `orm:"column(update_by)"`
}
err := o.Raw(querySQL, params...).QueryRow(&result)
if err != nil {
return nil, err
}
knowledge := &Knowledge{
Id: result.Id,
Title: result.Title,
CategoryId: result.CategoryId,
CategoryName: result.CategoryName,
Tags: result.Tags,
Author: result.Author,
Content: result.Content,
Summary: result.Summary,
CoverUrl: result.CoverUrl,
Status: result.Status,
ViewCount: result.ViewCount,
LikeCount: result.LikeCount,
IsRecommend: result.IsRecommend,
IsTop: result.IsTop,
CreateTime: result.CreateTime,
UpdateTime: result.UpdateTime,
CreateBy: result.CreateBy,
UpdateBy: result.UpdateBy,
}
// 增加查看次数
knowledge.ViewCount++
_, err = o.Raw("UPDATE yz_knowledge SET view_count = ? WHERE knowledge_id = ?", knowledge.ViewCount, id).Exec()
return knowledge, err
}
// LightKnowledge for limited fields (with orm and json tags for direct mapping)
type LightKnowledge struct {
Id int `orm:"column(knowledge_id)" json:"id"`
Title string `orm:"column(title)" json:"title"`
CategoryId int `orm:"column(category_id)" json:"categoryId"`
CategoryName string `orm:"column(category_name)" json:"categoryName"`
Tags string `orm:"column(tags)" json:"tags"`
Author string `orm:"column(author)" json:"author"`
Share int8 `orm:"column(share)" json:"share"`
ViewCount int `orm:"column(view_count)" json:"viewCount"`
LikeCount int `orm:"column(like_count)" json:"likeCount"`
CreateTime time.Time `orm:"column(create_time)" json:"createTime"`
UpdateTime time.Time `orm:"column(update_time)" json:"updateTime"`
}
// Helper to add conditions (reduces repetition)
func addCondition(where *string, params *[]interface{}, cond string, val interface{}) {
if val != nil {
*where += " AND " + cond
*params = append(*params, val)
}
}
// GetAllKnowledge (simplified: direct mapping to LightKnowledge, no separate struct or loop)
func GetAllKnowledge(page, pageSize int, status int8, categoryId int, share int8, keyword string, tenantId int) ([]*LightKnowledge, int64, error) {
o := orm.NewOrm()
whereSQL := "delete_time IS NULL"
params := []interface{}{}
// 如果tenantId > 0添加租户过滤
if tenantId > 0 {
whereSQL += " AND k.tenant_id = ?"
params = append(params, tenantId)
}
addCondition(&whereSQL, &params, "status = ?", func() interface{} {
if status >= 0 {
return status
}
return nil
}())
addCondition(&whereSQL, &params, "category_id = ?", func() interface{} {
if categoryId > 0 {
return categoryId
}
return nil
}())
addCondition(&whereSQL, &params, "share = ?", func() interface{} {
if share >= 0 {
return share
}
return nil
}())
addCondition(&whereSQL, &params, "title LIKE ?", func() interface{} {
if keyword != "" {
return "%" + keyword + "%"
}
return nil
}())
var total int64
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge k WHERE "+whereSQL, params).QueryRow(&total)
if err != nil {
return nil, 0, err
}
querySQL := `SELECT k.knowledge_id, k.title, k.category_id, c.category_name, k.tags, k.author, k.share, k.view_count, k.like_count, k.create_time, k.update_time
FROM yz_knowledge k LEFT JOIN yz_knowledge_category c ON k.category_id = c.category_id
WHERE ` + whereSQL + ` ORDER BY k.is_top DESC, k.create_time DESC LIMIT ? OFFSET ?`
params = append(params, pageSize, (page-1)*pageSize)
var knowledges []*LightKnowledge
_, err = o.Raw(querySQL, params).QueryRows(&knowledges)
if err != nil {
return nil, 0, err
}
return knowledges, total, nil
}
// GetKnowledgeCount 获取知识库数量(按租户)
func GetKnowledgeCount(tenantId int) (int64, error) {
o := orm.NewOrm()
whereSQL := "delete_time IS NULL"
params := []interface{}{}
// 如果tenantId > 0添加租户过滤
if tenantId > 0 {
whereSQL += " AND tenant_id = ?"
params = append(params, tenantId)
}
var count int64
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE "+whereSQL, params...).QueryRow(&count)
return count, err
}
// GetKnowledgeCountWithGrowth 获取知识库总数量及增长率(按租户)
// 返回:总数量、本月新增数量、上个月新增数量、增长率
func GetKnowledgeCountWithGrowth(tenantId int) (int64, int64, int64, float64, error) {
o := orm.NewOrm()
// 获取当前月份的开始和结束时间
now := time.Now()
currentYear := now.Year()
currentMonth := int(now.Month())
// 当前月的开始时间
currentMonthStart := time.Date(currentYear, time.Month(currentMonth), 1, 0, 0, 0, 0, time.Local)
// 当前月的结束时间(下个月的第一天)
nextMonth := currentMonth + 1
nextYear := currentYear
if nextMonth > 12 {
nextMonth = 1
nextYear++
}
currentMonthEnd := time.Date(nextYear, time.Month(nextMonth), 1, 0, 0, 0, 0, time.Local)
// 上个月的时间范围
lastMonth := currentMonth - 1
lastYear := currentYear
if lastMonth < 1 {
lastMonth = 12
lastYear--
}
lastMonthStart := time.Date(lastYear, time.Month(lastMonth), 1, 0, 0, 0, 0, time.Local)
lastMonthEnd := currentMonthStart
// 构建查询条件
baseWhere := "delete_time IS NULL"
tenantFilter := ""
params := []interface{}{}
if tenantId > 0 {
tenantFilter = " AND tenant_id = ?"
params = append(params, tenantId)
}
// 查询总数量(所有未删除的知识库)
totalWhere := baseWhere + tenantFilter
var totalCount int64
totalParams := params
if len(totalParams) == 0 {
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE " + totalWhere).QueryRow(&totalCount)
if err != nil {
return 0, 0, 0, 0, err
}
} else {
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE "+totalWhere, totalParams...).QueryRow(&totalCount)
if err != nil {
return 0, 0, 0, 0, err
}
}
// 查询本月新增数量(创建时间在当月范围内的)
currentWhere := baseWhere + " AND create_time >= ? AND create_time < ?" + tenantFilter
currentParams := append([]interface{}{currentMonthStart, currentMonthEnd}, params...)
var currentMonthCount int64
err := o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE "+currentWhere, currentParams...).QueryRow(&currentMonthCount)
if err != nil {
return 0, 0, 0, 0, err
}
// 查询上个月新增数量
lastWhere := baseWhere + " AND create_time >= ? AND create_time < ?" + tenantFilter
lastParams := append([]interface{}{lastMonthStart, lastMonthEnd}, params...)
var lastMonthCount int64
err = o.Raw("SELECT COUNT(*) FROM yz_knowledge WHERE "+lastWhere, lastParams...).QueryRow(&lastMonthCount)
if err != nil {
return 0, 0, 0, 0, err
}
// 计算增长率(本月新增相比上个月新增的增长率)
var growthRate float64
if lastMonthCount > 0 {
growthRate = float64(currentMonthCount-lastMonthCount) / float64(lastMonthCount) * 100
} else if currentMonthCount > 0 {
growthRate = 100.0 // 上个月为0这个月有数据增长100%
}
return totalCount, currentMonthCount, lastMonthCount, growthRate, nil
}
// UpdateKnowledge 更新知识
func UpdateKnowledge(id int, k *Knowledge, tenantId int) error {
o := orm.NewOrm()
knowledge := &Knowledge{Id: id}
err := o.Read(knowledge)
if err != nil {
return err
}
// 如果tenantId > 0验证租户ID是否匹配
if tenantId > 0 && knowledge.TenantId != tenantId {
return orm.ErrNoRows // 返回无记录错误,表示该知识不属于当前租户
}
// 更新字段
knowledge.Title = k.Title
knowledge.CategoryId = k.CategoryId
knowledge.Tags = k.Tags
knowledge.Author = k.Author
knowledge.Content = k.Content
knowledge.Summary = k.Summary
knowledge.CoverUrl = k.CoverUrl
knowledge.Status = k.Status
knowledge.Share = k.Share
knowledge.IsRecommend = k.IsRecommend
knowledge.IsTop = k.IsTop
knowledge.UpdateBy = k.UpdateBy
_, err = o.Update(knowledge, "title", "category_id", "tags", "author", "content", "summary", "cover_url", "status", "share", "is_recommend", "is_top", "update_by", "update_time")
return err
}
// DeleteKnowledge 软删除知识
func DeleteKnowledge(id int, deleteBy string, tenantId int) error {
o := orm.NewOrm()
knowledge := &Knowledge{Id: id}
err := o.Read(knowledge)
if err != nil {
return err
}
// 如果tenantId > 0验证租户ID是否匹配
if tenantId > 0 && knowledge.TenantId != tenantId {
return orm.ErrNoRows // 返回无记录错误,表示该知识不属于当前租户
}
// 执行软删除:设置 delete_time 和 delete_by
_, err = o.Raw("UPDATE yz_knowledge SET delete_time = ?, delete_by = ? WHERE knowledge_id = ?", time.Now(), deleteBy, id).Exec()
return err
}
// GetAllCategories 获取所有分类
func GetAllCategories(tenantId int) ([]*KnowledgeCategory, error) {
o := orm.NewOrm()
qs := o.QueryTable("yz_knowledge_category")
// 如果tenantId > 0添加租户过滤
if tenantId > 0 {
qs = qs.Filter("tenant_id", tenantId)
}
var categories []*KnowledgeCategory
_, err := qs.OrderBy("sort_order").All(&categories)
return categories, err
}
// GetCategoryById 根据ID获取分类
func GetCategoryById(id int) (*KnowledgeCategory, error) {
o := orm.NewOrm()
category := &KnowledgeCategory{CategoryId: id}
err := o.Read(category)
return category, err
}
// GetAllTags 获取所有标签
func GetAllTags(tenantId int) ([]*KnowledgeTag, error) {
o := orm.NewOrm()
qs := o.QueryTable("yz_knowledge_tags")
// 如果tenantId > 0添加租户过滤
if tenantId > 0 {
qs = qs.Filter("tenant_id", tenantId)
}
var tags []*KnowledgeTag
_, err := qs.All(&tags)
return tags, err
}
// AddCategory 添加分类
func AddCategory(category *KnowledgeCategory) (int64, error) {
o := orm.NewOrm()
id, err := o.Insert(category)
return id, err
}
// UpdateCategory 更新分类
func UpdateCategory(category *KnowledgeCategory) error {
o := orm.NewOrm()
_, err := o.Update(category, "CategoryName", "CategoryDesc", "ParentId", "SortOrder")
return err
}
// AddTag 添加标签
func AddTag(tag *KnowledgeTag) (int64, error) {
o := orm.NewOrm()
id, err := o.Insert(tag)
return id, err
}
// UpdateTag 更新标签
func UpdateTag(tag *KnowledgeTag) error {
o := orm.NewOrm()
_, err := o.Update(tag, "TagName", "TagColor", "TagBackground")
return err
}