- handler 只保留请求绑定、权限检查与响应映射;业务校验顺序、状态码与文案逐字保留 - 新增 service.Error 语义错误,由 handler 统一映射 HTTP 响应 - session 875→361 行、widget 745→321 行、settings 540→73 行 - 自动分配/租户设置(工作时间、欢迎语)/消息校验/黑名单检查/联系方式提取随迁 service 包 - 相关单元测试随迁 service 包,go test ./... 全部通过
60 lines
1.6 KiB
Go
60 lines
1.6 KiB
Go
package service
|
|
|
|
import (
|
|
"strings"
|
|
|
|
"kefu-cloud/server/internal/model"
|
|
"kefu-cloud/server/internal/ws"
|
|
)
|
|
|
|
// UniqueUint 去重并过滤零值。
|
|
func UniqueUint(ids []uint) []uint {
|
|
seen := make(map[uint]struct{}, len(ids))
|
|
out := make([]uint, 0, len(ids))
|
|
for _, id := range ids {
|
|
if id == 0 {
|
|
continue
|
|
}
|
|
if _, ok := seen[id]; ok {
|
|
continue
|
|
}
|
|
seen[id] = struct{}{}
|
|
out = append(out, id)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// UserDisplayName 坐席展示名(昵称优先,其次用户名)。
|
|
func UserDisplayName(userID uint) string {
|
|
var user model.User
|
|
if err := model.DB.Select("id", "nickname", "username").First(&user, userID).Error; err != nil {
|
|
return "未知坐席"
|
|
}
|
|
if strings.TrimSpace(user.Nickname) != "" {
|
|
return user.Nickname
|
|
}
|
|
if strings.TrimSpace(user.Username) != "" {
|
|
return user.Username
|
|
}
|
|
return "未知坐席"
|
|
}
|
|
|
|
// BroadcastSessionMessage 会话新消息广播(坐席 + 访客)。
|
|
func BroadcastSessionMessage(session *model.Session, message model.Message) {
|
|
payload, err := ws.NewEvent("message", session.ID, message)
|
|
if err == nil {
|
|
ws.DefaultHub.BroadcastToSession(session.TenantID, session.ID, session.AgentID, payload)
|
|
}
|
|
}
|
|
|
|
// BroadcastSessionUpdate 会话状态变更广播:坐席列表需要刷新;访客也必须收到
|
|
// ended/active,才能弹出评价或更新接待状态。
|
|
func BroadcastSessionUpdate(session *model.Session) {
|
|
payload, err := ws.NewEvent("session_updated", session.ID, map[string]interface{}{"status": session.Status})
|
|
if err != nil {
|
|
return
|
|
}
|
|
ws.DefaultHub.BroadcastToTenantStaff(session.TenantID, payload)
|
|
ws.DefaultHub.BroadcastToVisitor(session.TenantID, session.ID, payload)
|
|
}
|