Files
pj0235-eai_agentplatform/eai_agentplatform/backend-go/internal/api/notification.go
T
eaiadminandClaude Code 0455f064ac feat: 新增语音转文字(ASR)功能
- 后端:新增 /api/audio/transcribe 接口,调用 Ollama whisper 进行语音识别
- 前端:新增 AudioTranscribePage.vue 页面,支持 MP3/WAV/M4A/OGG/FLAC 等格式
- 注册路由、工具卡片、智能助手欢迎语更新

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-09-14 00:53:36 +08:00

111 lines
3.2 KiB
Go

package api
import (
"strings"
"github.com/gin-gonic/gin"
"eai_agentplatform/backend/internal/middleware"
"eai_agentplatform/backend/internal/model"
"eai_agentplatform/backend/internal/store"
"eai_agentplatform/backend/internal/web"
)
// notifyUser 给单个用户发站内通知(userID=0 忽略)。
func notifyUser(userID uint, ntype, title, content, link string) {
if userID == 0 {
return
}
store.DB.Create(&model.Notification{
UserID: userID, Type: ntype, Title: title, Content: content, Link: link,
})
}
// notifyAllEmployees 给所有启用员工发通知(如新正式考试发布)。
func notifyAllEmployees(ntype, title, content, link string) {
var users []model.User
store.DB.Where("role = ? AND status = ?", "employee", "active").Select("id").Find(&users)
for _, u := range users {
notifyUser(u.ID, ntype, title, content, link)
}
}
func notifyAdmins(ntype, title, content, link string) {
var users []model.User
store.DB.Where("role = ? AND status = ?", "admin", "active").Select("id").Find(&users)
for _, u := range users {
notifyUser(u.ID, ntype, title, content, link)
}
}
func notifyUsersByOwner(owner, ntype, title, content, link string) {
owner = strings.TrimSpace(owner)
if owner == "" || owner == "待指派" {
return
}
var users []model.User
store.DB.Where("status = ? AND (full_name = ? OR username = ?)", "active", owner, owner).Select("id").Find(&users)
for _, u := range users {
notifyUser(u.ID, ntype, title, content, link)
}
}
// MyNotifications GET /api/notifications?unread_only=true —— 我的通知列表
func MyNotifications(c *gin.Context) {
u := middleware.CurrentUser(c)
if u == nil {
web.Fail(c, web.NewAuthError("未登录"))
return
}
q := store.DB.Model(&model.Notification{}).Where("user_id = ?", u.ID)
if c.Query("unread_only") == "true" {
q = q.Where("read = ?", false)
}
var items []model.Notification
q.Order("created_at DESC, id DESC").Limit(100).Find(&items)
web.OK(c, items)
}
// UnreadNotificationCount GET /api/notifications/unread-count —— 未读数(铃铛角标)
func UnreadNotificationCount(c *gin.Context) {
u := middleware.CurrentUser(c)
if u == nil {
web.Fail(c, web.NewAuthError("未登录"))
return
}
var n int64
store.DB.Model(&model.Notification{}).Where("user_id = ? AND read = ?", u.ID, false).Count(&n)
web.OK(c, gin.H{"unread": n})
}
// MarkNotificationRead PUT /api/notifications/{id}/read —— 标记单条已读
func MarkNotificationRead(c *gin.Context) {
u := middleware.CurrentUser(c)
id, ok := parseID(c, "id")
if !ok {
return
}
var n model.Notification
if err := store.DB.First(&n, id).Error; err != nil {
web.Fail(c, web.NewNotFoundError("通知不存在"))
return
}
if n.UserID != u.ID {
web.Fail(c, web.NewForbiddenError("无权操作他人通知"))
return
}
store.DB.Model(&n).Update("read", true)
web.OK(c, gin.H{"id": n.ID, "read": true})
}
// MarkAllNotificationsRead PUT /api/notifications/read-all —— 全部标记已读
func MarkAllNotificationsRead(c *gin.Context) {
u := middleware.CurrentUser(c)
if u == nil {
web.Fail(c, web.NewAuthError("未登录"))
return
}
store.DB.Model(&model.Notification{}).Where("user_id = ? AND read = ?", u.ID, false).Update("read", true)
web.OK(c, gin.H{"read": true})
}