优化咨询客服

This commit is contained in:
yml2213
2026-05-29 10:15:21 +08:00
parent 2966b59c90
commit 2346f2e064
16 changed files with 202 additions and 32 deletions
+1 -1
View File
@@ -9,7 +9,7 @@ type Principal struct {
type ConversationDTO struct {
ID uint64 `json:"id"`
OrderID uint64 `json:"order_id"`
OrderID *uint64 `json:"order_id"`
Type string `json:"type"`
Title string `json:"title"`
Status string `json:"status"`
+14
View File
@@ -81,6 +81,20 @@ func (h *Handler) OrderConversation(c *gin.Context) {
response.OK(c, item)
}
func (h *Handler) EnsureSupportConversation(c *gin.Context) {
userID, ok := currentUserID(c)
if !ok {
response.Unauthorized(c, "缺少用户上下文")
return
}
item, err := h.service.EnsureSupportConversation(userID)
if err != nil {
writeChatError(c, err)
return
}
response.OK(c, item)
}
func (h *Handler) Messages(c *gin.Context) {
userID, ok := currentUserID(c)
if !ok {
+85 -2
View File
@@ -43,7 +43,7 @@ func EnsureOrderConversation(tx *gorm.DB, order model.RentalOrder) (*model.ChatC
now := time.Now()
conversation := model.ChatConversation{
OrderID: order.ID,
OrderID: &order.ID,
Type: "order_group",
Title: orderConversationTitle(order),
Status: "active",
@@ -182,6 +182,89 @@ func (r *Repository) FindOrderConversation(userID uint64, orderID uint64) (*Conv
return &dto, nil
}
func (r *Repository) EnsureSupportConversation(userID uint64) (*ConversationDTO, error) {
var conversationID uint64
err := r.db.Transaction(func(tx *gorm.DB) error {
var existing model.ChatConversation
err := tx.Table("chat_conversations AS c").
Select("c.*").
Joins("JOIN chat_participants AS cp ON cp.conversation_id = c.id").
Where("c.type = ? AND cp.participant_type = ? AND cp.participant_id = ?", "general_support", "user", userID).
Order("c.id ASC").
First(&existing).Error
if err == nil {
conversationID = existing.ID
return nil
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
return err
}
now := time.Now()
conversation := model.ChatConversation{
Type: "general_support",
Title: "平台客服",
Status: "active",
}
if err := tx.Create(&conversation).Error; err != nil {
return err
}
participants := []model.ChatParticipant{
{
ConversationID: conversation.ID,
ParticipantType: "user",
ParticipantID: userID,
Role: "customer",
JoinedAt: now,
},
}
if supportID := defaultSupportAdminID(tx); supportID > 0 {
participants = append(participants, model.ChatParticipant{
ConversationID: conversation.ID,
ParticipantType: "admin",
ParticipantID: supportID,
Role: "support",
JoinedAt: now,
})
}
for _, participant := range participants {
if err := tx.Clauses(clause.OnConflict{DoNothing: true}).Create(&participant).Error; err != nil {
return err
}
}
message := model.ChatMessage{
ConversationID: conversation.ID,
SenderType: "system",
SenderRole: "system",
ContentType: "system",
Content: "您好,客服会尽快回复,请直接描述您遇到的问题。",
AttachmentURLS: emptyJSONList(),
}
if err := tx.Create(&message).Error; err != nil {
return err
}
conversation.LastMessageID = &message.ID
conversation.LastMessagePreview = truncatePreview(message.Content)
conversation.LastMessageAt = &message.CreatedAt
if err := tx.Save(&conversation).Error; err != nil {
return err
}
conversationID = conversation.ID
return nil
})
if err != nil {
return nil, err
}
item, err := r.FindConversation(Principal{Type: "user", ID: userID}, conversationID)
if err != nil {
return nil, err
}
r.NotifyNewConversation(conversationID)
return item, nil
}
func (r *Repository) Messages(principal Principal, conversationID uint64, page, pageSize int) (*PaginatedResult, error) {
page, pageSize = normalizePagination(page, pageSize)
if _, err := r.findParticipant(r.db, principal, conversationID, false); err != nil {
@@ -473,7 +556,7 @@ func (r *Repository) adminNames(ids []uint64) (map[uint64]string, error) {
type conversationRow struct {
ID uint64
OrderID uint64
OrderID *uint64
Type string
Title string
Status string
+10
View File
@@ -41,6 +41,16 @@ func (s *Service) FindOrderConversation(userID uint64, orderID uint64) (*Convers
return s.repo.FindOrderConversation(userID, orderID)
}
func (s *Service) EnsureSupportConversation(userID uint64) (*ConversationDTO, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable
}
if userID == 0 {
return nil, ErrPermissionDenied
}
return s.repo.EnsureSupportConversation(userID)
}
func (s *Service) Messages(principal Principal, conversationID uint64, page, pageSize int) (*PaginatedResult, error) {
if s.repo == nil {
return nil, ErrDependencyUnavailable