统一 skill 与 specialist 清单,移除旧的 office 执行包与下线对象,并补入 text_to_speech、customer_followup 等当前目录定义与种子数据。
91 lines
2.9 KiB
Go
91 lines
2.9 KiB
Go
package api
|
||
|
||
import (
|
||
"time"
|
||
|
||
"github.com/gin-gonic/gin"
|
||
"gorm.io/gorm"
|
||
|
||
"eai_agentplatform/backend/internal/middleware"
|
||
"eai_agentplatform/backend/internal/model"
|
||
"eai_agentplatform/backend/internal/store"
|
||
"eai_agentplatform/backend/internal/web"
|
||
)
|
||
|
||
// —— 积分规则(游戏化成长值,集中一处便于调整,见 docs/01_System_Overall/变更日志.md 待确认项)——
|
||
const (
|
||
ptFirstCompany = 10 // 首次浏览公司介绍
|
||
ptFirstProduct = 2 // 首次浏览单个产品
|
||
ptFirstCourse = 5 // 首次浏览单门课程
|
||
ptSelfTestSubmit = 5 // 自测提交一次
|
||
ptFormalPass = 50 // 正式考试通过
|
||
ptMistakeResolved = 3 // 错题标记已掌握
|
||
)
|
||
|
||
// awardPoints 记录积分流水并累加到 user.learning_points(points<=0 直接忽略,避免负分刷分)。
|
||
func awardPoints(userID uint, eventType string, points int, refType string, refID uint) {
|
||
if userID == 0 || points <= 0 {
|
||
return
|
||
}
|
||
store.DB.Create(&model.PointEvent{
|
||
UserID: userID,
|
||
EventType: eventType,
|
||
Points: points,
|
||
RefType: refType,
|
||
RefID: refID,
|
||
})
|
||
store.DB.Model(&model.User{}).Where("id = ?", userID).
|
||
UpdateColumn("learning_points", gorm.Expr("learning_points + ?", points))
|
||
}
|
||
|
||
// awardFirstView 首次浏览公司/产品/课程加分(由 RecordLearningProgress 幂等触发)。
|
||
func awardFirstView(userID uint, itemType string, itemID uint) {
|
||
switch itemType {
|
||
case "company":
|
||
awardPoints(userID, "first_company", ptFirstCompany, itemType, itemID)
|
||
case "product":
|
||
awardPoints(userID, "first_product", ptFirstProduct, itemType, itemID)
|
||
case "course":
|
||
awardPoints(userID, "first_course", ptFirstCourse, itemType, itemID)
|
||
}
|
||
}
|
||
|
||
// MyPoints GET /api/points/me —— 我的积分 + 最近积分流水
|
||
func MyPoints(c *gin.Context) {
|
||
u := middleware.CurrentUser(c)
|
||
if u == nil {
|
||
web.Fail(c, web.NewAuthError("未登录"))
|
||
return
|
||
}
|
||
var total int
|
||
store.DB.Raw(`SELECT COALESCE(SUM(points), 0) FROM point_event WHERE user_id = ?`, u.ID).Scan(&total)
|
||
var events []model.PointEvent
|
||
store.DB.Where("user_id = ?", u.ID).Order("created_at DESC, id DESC").Limit(50).Find(&events)
|
||
web.OK(c, gin.H{"total": total, "events": events})
|
||
}
|
||
|
||
// Leaderboard GET /api/points/leaderboard —— 学习积分排行榜(全员,含我的名次)
|
||
func Leaderboard(c *gin.Context) {
|
||
u := middleware.CurrentUser(c)
|
||
var users []model.User
|
||
store.DB.Where("role = ? AND status = ?", "employee", "active").
|
||
Order("learning_points DESC, id ASC").Find(&users)
|
||
|
||
out := make([]gin.H, 0, len(users))
|
||
myRank := 0
|
||
for i, usr := range users {
|
||
out = append(out, gin.H{
|
||
"rank": i + 1,
|
||
"user_id": usr.ID,
|
||
"full_name": usr.FullName,
|
||
"department": usr.Department,
|
||
"learning_points": usr.LearningPoints,
|
||
"is_me": u != nil && usr.ID == u.ID,
|
||
})
|
||
if u != nil && usr.ID == u.ID {
|
||
myRank = i + 1
|
||
}
|
||
}
|
||
web.OK(c, gin.H{"items": out, "my_rank": myRank, "total": len(out), "updated_at": time.Now()})
|
||
}
|