- 后端:新增 /api/audio/transcribe 接口,调用 Ollama whisper 进行语音识别 - 前端:新增 AudioTranscribePage.vue 页面,支持 MP3/WAV/M4A/OGG/FLAC 等格式 - 注册路由、工具卡片、智能助手欢迎语更新 Co-Authored-By: Claude Code <noreply@anthropic.com>
111 lines
3.2 KiB
Go
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})
|
|
}
|