Переглянути джерело

1.进入聊天室(room)清空未读消息数 2.优化代码

shizhongqi 11 місяців тому
батько
коміт
6067579990
3 змінених файлів з 90 додано та 49 видалено
  1. 1 18
      main.go
  2. 87 31
      wsClient/redis.go
  3. 2 0
      wsClient/room.go

+ 1 - 18
main.go

@@ -10,7 +10,6 @@ import (
 	"log"
 	"net/http"
 	"os"
-	"strconv"
 
 	"github.com/joho/godotenv"
 )
@@ -30,23 +29,7 @@ func main() {
 	}
 
 	// 初始化Redis连接
-	// 从环境变量获取Redis配置,如果没有设置则使用默认值
-	redisAddr := os.Getenv("REDIS_ADDR")
-	if redisAddr == "" {
-		redisAddr = "localhost:6379" // 默认Redis地址
-	}
-	
-	redisPassword := os.Getenv("REDIS_PASSWORD") // 默认为空
-	
-	redisDB := 0 // 默认数据库
-	if dbStr := os.Getenv("REDIS_DB"); dbStr != "" {
-		if db, err := strconv.Atoi(dbStr); err == nil {
-			redisDB = db
-		}
-	}
-
-	// 初始化Redis连接
-	if err := wsClient.InitRedis(redisAddr, redisPassword, redisDB); err != nil {
+	if err := wsClient.InitializeRedisFromEnv(); err != nil {
 		log.Printf("Redis初始化失败: %v", err)
 		log.Println("将继续运行,但不会存储消息到Redis")
 	} else {

+ 87 - 31
wsClient/redis.go

@@ -6,6 +6,7 @@ import (
 	"encoding/json"
 	"fmt"
 	"log"
+	"os"
 	"strconv"
 	"time"
 
@@ -22,6 +23,11 @@ var ctx = context.Background()
 const (
 	UnreadMultiplier = 10000.0 // 未读消息数乘数,用于小数部分存储(增大乘数以提高精度)
 	ContactTTL       = 7 * 24 * time.Hour // 最近联系人过期时间(7天)
+
+	// 门店用户类型
+	UserTypeShop = "shop"
+	// 顾客用户类型
+	UserTypeCustomer = "customer"
 )
 
 // ContactInfo 表示联系人信息
@@ -32,6 +38,26 @@ type ContactInfo struct {
 	ContactType  string    `json:"contact_type"`  // 联系人类型(shop/customer)
 }
 
+// 从环境变量初始化Redis连接
+func InitializeRedisFromEnv() error {
+	// 从环境变量获取Redis配置,如果没有设置则使用默认值
+	redisAddr := os.Getenv("REDIS_ADDR")
+	if redisAddr == "" {
+		redisAddr = "localhost:6379" // 默认Redis地址
+	}
+	
+	redisPassword := os.Getenv("REDIS_PASSWORD") // 默认为空
+	
+	redisDB := 0 // 默认数据库
+	if dbStr := os.Getenv("REDIS_DB"); dbStr != "" {
+		if db, err := strconv.Atoi(dbStr); err == nil {
+			redisDB = db
+		}
+	}
+
+	return InitRedis(redisAddr, redisPassword, redisDB)
+}
+
 // ChatMessage 表示存储在Redis中的聊天消息结构
 type ChatMessage struct {
 	Content   string    `json:"content"`   // 原始消息内容(JSON字符串)
@@ -123,9 +149,9 @@ func UpdateRecentContacts(client *Client) error {
 
 	currentTime := time.Now().Unix()
 
-	if client.userInfo.Type == "shop" {
+	if client.userInfo.Type == UserTypeShop {
 		// 更新门店的联系人列表(客户)
-		key := getContactKey("shop", client.userInfo.ShopId) // shop_chats:{ShopId}
+		key := getContactKey(UserTypeShop, client.userInfo.ShopId) // shop_chats:{ShopId}
 		if key != "" {
 			// 先获取当前未读消息数
 			// currentScore, err := redisClient.ZScore(ctx, key, strconv.Itoa(int(client.userInfo.CustomId))).Result()
@@ -145,7 +171,7 @@ func UpdateRecentContacts(client *Client) error {
 		}
 
 		// 更新客户的联系人列表(门店)
-		key = getContactKey("customer", client.userInfo.UserId) // customer_chats:{UserId}
+		key = getContactKey(UserTypeCustomer, client.userInfo.UserId) // customer_chats:{UserId}
 		if key != "" {
 			// 先获取当前未读消息数
 			currentScore, err := redisClient.ZScore(ctx, key, strconv.Itoa(int(client.userInfo.ShopId))).Result()
@@ -165,9 +191,9 @@ func UpdateRecentContacts(client *Client) error {
 		}
 	}
 
-	if client.userInfo.Type == "customer" {
+	if client.userInfo.Type == UserTypeCustomer {
 		// 更新客户的联系人列表(门店)
-		key := getContactKey("customer", client.userInfo.UserId) // customer_chats:{UserId}
+		key := getContactKey(UserTypeCustomer, client.userInfo.UserId) // customer_chats:{UserId}
 		if key != "" {
 			// 先获取当前未读消息数
 			// currentScore, err := redisClient.ZScore(ctx, key, strconv.Itoa(int(client.userInfo.ShopId))).Result()
@@ -187,7 +213,7 @@ func UpdateRecentContacts(client *Client) error {
 		}
 
 		// 更新门店的联系人列表(客户)
-		key = getContactKey("shop", client.userInfo.ShopId) // shop_chats:{ShopId}
+		key = getContactKey(UserTypeShop, client.userInfo.ShopId) // shop_chats:{ShopId}
 		if key != "" {
 			// 先获取当前未读消息数
 			currentScore, err := redisClient.ZScore(ctx, key, strconv.Itoa(int(client.userInfo.CustomId))).Result()
@@ -224,14 +250,14 @@ func IncrementUnreadCount(sender *Client, count int) error {
 	var receiverID int32
 	var senderMember string
 
-	if sender.userInfo.Type == "shop" {
+	if sender.userInfo.Type == UserTypeShop {
 		// 门店发送消息给客户,接收者是客户
-		receiverType = "customer"
+		receiverType = UserTypeCustomer
 		receiverID = sender.userInfo.UserId
 		senderMember = strconv.Itoa(int(sender.userInfo.ShopId))
-	} else if sender.userInfo.Type == "customer" {
+	} else if sender.userInfo.Type == UserTypeCustomer {
 		// 客户发送消息给门店,接收者是门店
-		receiverType = "shop"
+		receiverType = UserTypeShop
 		receiverID = sender.userInfo.ShopId
 		senderMember = strconv.Itoa(int(sender.userInfo.CustomId))
 	} else {
@@ -339,12 +365,17 @@ func parseScore(score float64) (timestamp int64, unreadCount int) {
 	return
 }
 
-// getContactKey 生成联系人的Redis键
-func getContactKey(userType string, userID int32) string {
-	if userType == "shop" {
-		return "shop_chats:" + strconv.Itoa(int(userID))
-	} else if userType == "customer" {
-		return "customer_chats:" + strconv.Itoa(int(userID))
+/**
+* 生成联系人的Redis键
+* @param userType 用户类型
+* @param id 用户ID -- shopId 或 userId
+* @return 联系人的Redis键
+*/
+func getContactKey(userType string, id int32) string {
+	if userType == UserTypeShop {
+		return "shop_chats:" + strconv.Itoa(int(id))
+	} else if userType == UserTypeCustomer {
+		return "customer_chats:" + strconv.Itoa(int(id))
 	}
 	return ""
 }
@@ -380,9 +411,9 @@ func GetRecentContacts(userType string, userID int32, limit int64) ([]ContactInf
 		timestamp, unreadCount := parseScore(item.Score)
 
 		// 确定联系人的类型
-		contactType := "customer"
-		if userType == "customer" {
-			contactType = "shop"
+		contactType := UserTypeCustomer
+		if userType == UserTypeCustomer {
+			contactType = UserTypeShop
 		}
 
 		contact := ContactInfo{
@@ -425,23 +456,44 @@ func GetTotalUnreadCount(userType string, userID int32) (int, error) {
 	return totalUnread, nil
 }
 
-// ClearUnreadCount 清除指定联系人的未读消息数
-func ClearUnreadCount(userType string, userID int32, contactID int32) error {
+/**
+* 清除指定联系人的未读消息数
+* @param client 客户端
+* @return 错误
+*/
+func ClearUnreadCount(client *Client) error {
+	id := client.userInfo.ShopId
+	contactID := client.userInfo.UserId
+	if client.userInfo.Type == UserTypeCustomer {
+		id = client.userInfo.UserId
+		contactID = client.userInfo.ShopId
+	}
+
 	if redisClient == nil {
 		log.Println("Redis客户端未初始化")
-		return nil
+		return fmt.Errorf("redis client is not initialized")
 	}
 
-	key := getContactKey(userType, userID)
+	key := getContactKey(client.userInfo.Type, id)
 	if key == "" {
-		return fmt.Errorf("无效的用户类型: %s", userType)
+		log.Printf("无效的用户类型: %s", client.userInfo.Type)
+		return fmt.Errorf("invalid user type: %s", client.userInfo.Type)
 	}
 
+	contactIDStr := strconv.Itoa(int(contactID))
 	// 获取当前分数
-	currentScore, err := redisClient.ZScore(ctx, key, strconv.Itoa(int(contactID))).Result()
+	currentScore, err := redisClient.ZScore(ctx, key, contactIDStr).Result()
 	if err != nil {
-		// 如果联系人不存在,不需要清理
-		return nil
+		if err == redis.Nil {
+			// 如果联系人不存在,这并非一个错误,只是无需清理。
+			log.Printf("Contact not found, no unread count to clear - UserType: %s, UserID: %d, ContactID: %d",
+				client.userInfo.Type, id, contactID)
+			return nil
+		}
+		// 对于其他类型的错误(如连接问题),则返回错误。
+		log.Printf("failed to get score for contact - UserType: %s, UserID: %d, ContactID: %d, Error: %v",
+			client.userInfo.Type, id, contactID, err)
+		return err
 	}
 
 	// 解析当前分数,保留时间戳,清除未读消息数
@@ -449,12 +501,16 @@ func ClearUnreadCount(userType string, userID int32, contactID int32) error {
 	newScore := calculateScore(timestamp, 0)
 
 	// 更新分数
-	redisClient.ZAdd(ctx, key, redis.Z{
+	if err := redisClient.ZAdd(ctx, key, redis.Z{
 		Score:  newScore,
-		Member: strconv.Itoa(int(contactID)),
-	})
+		Member: contactIDStr,
+	}).Err(); err != nil {
+		log.Printf("failed to clear unread count - UserType: %s, UserID: %d, ContactID: %d, Error: %v",
+			client.userInfo.Type, id, contactID, err)
+		return err
+	}
 
 	log.Printf("未读消息数已清除 - 用户类型: %s, 用户ID: %d, 联系人ID: %d",
-		userType, userID, contactID)
+		client.userInfo.Type, id, contactID)
 	return nil
 }

+ 2 - 0
wsClient/room.go

@@ -106,6 +106,8 @@ func (r *Room) run() {
 			// 将新客户端添加到房间的客户端集合中
 			r.clientConns[client] = true // 使用 true 作为值,实际上只使用 key(client 指针)
 			log.Printf("客户端 %v 加入房间 %v", client.name, r.name)
+			// 清空未读消息数
+			go ClearUnreadCount(client)
 
 		// 处理客户端离开事件
 		case client := <-r.leave: