二维码自动补发
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/clause"
|
||||
"hfb_sys/backend/internal/model"
|
||||
"hfb_sys/backend/internal/modules/chathub"
|
||||
)
|
||||
|
||||
// QrCodeStatus 二维码状态常量
|
||||
@@ -83,24 +84,35 @@ type QrCodeOCRConfig struct {
|
||||
|
||||
// CreateQrCode 创建二维码
|
||||
func (r *Repository) CreateQrCode(ctx context.Context, adminID uint64, req CreateQrCodeRequest) (*model.ChatQrCode, error) {
|
||||
qrcode := model.ChatQrCode{
|
||||
ImageURL: req.ImageURL,
|
||||
GroupName: req.GroupName,
|
||||
Status: QrCodeStatusUnused,
|
||||
CreatedBy: adminID,
|
||||
Note: req.Note,
|
||||
ExpiresAt: req.ExpiresAt,
|
||||
}
|
||||
var qrcode model.ChatQrCode
|
||||
var deliveredMessages []model.ChatMessage
|
||||
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
qrcode = model.ChatQrCode{
|
||||
ImageURL: req.ImageURL,
|
||||
GroupName: req.GroupName,
|
||||
Status: QrCodeStatusUnused,
|
||||
CreatedBy: adminID,
|
||||
Note: req.Note,
|
||||
ExpiresAt: req.ExpiresAt,
|
||||
}
|
||||
|
||||
// 如果未指定过期时间,默认7天后过期
|
||||
if qrcode.ExpiresAt == nil {
|
||||
expires := time.Now().Add(7 * 24 * time.Hour)
|
||||
qrcode.ExpiresAt = &expires
|
||||
}
|
||||
// 如果未指定过期时间,默认7天后过期
|
||||
if qrcode.ExpiresAt == nil {
|
||||
expires := time.Now().Add(7 * 24 * time.Hour)
|
||||
qrcode.ExpiresAt = &expires
|
||||
}
|
||||
|
||||
if err := r.db.WithContext(ctx).Create(&qrcode).Error; err != nil {
|
||||
if err := tx.Create(&qrcode).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
deliveredMessages, err = deliverPendingQrCodes(tx)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.notifyDeliveredQrCodeMessages(deliveredMessages)
|
||||
|
||||
return &qrcode, nil
|
||||
}
|
||||
@@ -108,26 +120,36 @@ func (r *Repository) CreateQrCode(ctx context.Context, adminID uint64, req Creat
|
||||
// BatchCreateQrCode 批量创建二维码
|
||||
func (r *Repository) BatchCreateQrCode(ctx context.Context, adminID uint64, req BatchCreateQrCodeRequest) ([]model.ChatQrCode, error) {
|
||||
var qrcodes []model.ChatQrCode
|
||||
var deliveredMessages []model.ChatMessage
|
||||
defaultExpires := time.Now().Add(7 * 24 * time.Hour)
|
||||
|
||||
for _, item := range req.Items {
|
||||
qr := model.ChatQrCode{
|
||||
ImageURL: item.ImageURL,
|
||||
GroupName: item.GroupName,
|
||||
Status: QrCodeStatusUnused,
|
||||
CreatedBy: adminID,
|
||||
Note: item.Note,
|
||||
ExpiresAt: item.ExpiresAt,
|
||||
err := r.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
|
||||
for _, item := range req.Items {
|
||||
qr := model.ChatQrCode{
|
||||
ImageURL: item.ImageURL,
|
||||
GroupName: item.GroupName,
|
||||
Status: QrCodeStatusUnused,
|
||||
CreatedBy: adminID,
|
||||
Note: item.Note,
|
||||
ExpiresAt: item.ExpiresAt,
|
||||
}
|
||||
if qr.ExpiresAt == nil {
|
||||
qr.ExpiresAt = &defaultExpires
|
||||
}
|
||||
qrcodes = append(qrcodes, qr)
|
||||
}
|
||||
if qr.ExpiresAt == nil {
|
||||
qr.ExpiresAt = &defaultExpires
|
||||
}
|
||||
qrcodes = append(qrcodes, qr)
|
||||
}
|
||||
|
||||
if err := r.db.WithContext(ctx).Create(&qrcodes).Error; err != nil {
|
||||
if err := tx.Create(&qrcodes).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
deliveredMessages, err = deliverPendingQrCodes(tx)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r.notifyDeliveredQrCodeMessages(deliveredMessages)
|
||||
|
||||
return qrcodes, nil
|
||||
}
|
||||
@@ -342,3 +364,82 @@ func (r *Repository) markQrCodeAsUsed(tx *gorm.DB, qrcodeID uint64, conversation
|
||||
"used_at": now,
|
||||
}).Error
|
||||
}
|
||||
|
||||
func deliverPendingQrCodes(tx *gorm.DB) ([]model.ChatMessage, error) {
|
||||
deliveredMessages := make([]model.ChatMessage, 0)
|
||||
for {
|
||||
var task model.ChatQrCodeDeliveryTask
|
||||
if err := tx.Clauses(clause.Locking{Strength: "UPDATE"}).
|
||||
Where("status = ?", "pending").
|
||||
Order("created_at ASC, id ASC").
|
||||
First(&task).Error; err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return deliveredMessages, nil
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
qrcode, err := fetchUnusedQrCode(tx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if qrcode == nil {
|
||||
return deliveredMessages, nil
|
||||
}
|
||||
|
||||
if err := markQrCodeAsUsed(tx, qrcode.ID, task.ConversationID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
message, err := sendQrCodeImage(tx, task.ConversationID, qrcode.ImageURL)
|
||||
if err != nil {
|
||||
now := time.Now()
|
||||
if updateErr := tx.Model(&task).Updates(map[string]interface{}{
|
||||
"status": "failed",
|
||||
"qrcode_id": qrcode.ID,
|
||||
"error_message": err.Error(),
|
||||
"updated_at": now,
|
||||
}).Error; updateErr != nil {
|
||||
return nil, updateErr
|
||||
}
|
||||
continue
|
||||
}
|
||||
deliveredMessages = append(deliveredMessages, *message)
|
||||
|
||||
now := time.Now()
|
||||
if err := tx.Model(&task).Updates(map[string]interface{}{
|
||||
"status": "sent",
|
||||
"qrcode_id": qrcode.ID,
|
||||
"error_message": "",
|
||||
"sent_at": now,
|
||||
"updated_at": now,
|
||||
}).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Repository) notifyDeliveredQrCodeMessages(messages []model.ChatMessage) {
|
||||
if r.hub == nil {
|
||||
return
|
||||
}
|
||||
for _, msg := range messages {
|
||||
event := &chathub.ChatEvent{
|
||||
Type: "new_message",
|
||||
ConversationID: msg.ConversationID,
|
||||
Message: &chathub.MessageData{
|
||||
ID: msg.ID,
|
||||
ConversationID: msg.ConversationID,
|
||||
SenderType: msg.SenderType,
|
||||
SenderID: msg.SenderID,
|
||||
SenderRole: msg.SenderRole,
|
||||
SenderName: "系统",
|
||||
ContentType: msg.ContentType,
|
||||
Content: msg.Content,
|
||||
AttachmentURLS: decodeStringList(msg.AttachmentURLS),
|
||||
CreatedAt: msg.CreatedAt.Format(time.RFC3339),
|
||||
},
|
||||
}
|
||||
r.hub.NotifyConversation(msg.ConversationID, event)
|
||||
r.hub.NotifyAllAdmins(event)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user