Files
pj0235-eai_agentplatform/eai_ap_app/backend-go/internal/api/points.go
T
eaiadmin 4e8817d768 init: 数字员工平台初始代码
包含前端(Vue3 + VueFlow 画布)、后端(Go)、文档体系。
- 工作台画布:节点拖放、连线模式、右键菜单、AI 助手
- 后端:连接器 API、专员种子数据
- 导航:左侧导航、工坊、市场、控制台
2026-08-18 20:19:58 +08:00

91 lines
2.9 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 api
import (
"time"
"github.com/gin-gonic/gin"
"gorm.io/gorm"
"eaisalestrain/backend/internal/middleware"
"eaisalestrain/backend/internal/model"
"eaisalestrain/backend/internal/store"
"eaisalestrain/backend/internal/web"
)
// —— 积分规则(游戏化成长值,集中一处便于调整,见 docs/changelog.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()})
}