// 功能描述:按购物车或收藏关联分类推荐真实在售商品;版本:1.0.0。 package user import ( "git.apinb.com/bsm-sdk/core/errcode" "git.apinb.com/bsm-sdk/core/infra" "git.apinb.com/heqiapp/platforms/backend/api/internal/impl" common "git.apinb.com/heqiapp/platforms/backend/api/internal/logic/common" "git.apinb.com/heqiapp/platforms/backend/api/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" "gorm.io/gorm/clause" ) // Recommendations 排除本人已入购物车商品,收藏场景另排除已收藏;相同分类优先,其余按最近更新排序。 func Recommendations(ctx *gin.Context) { account, ok := common.UserAccount(ctx) if !ok { return } var request struct { Source string `form:"source,default=cart" binding:"oneof=cart favorites"` Page int `form:"page,default=1" binding:"gte=1,lte=10000"` Size int `form:"page_size,default=2" binding:"gte=1,lte=20"` } if ctx.ShouldBindQuery(&request) != nil { infra.Response.Error(ctx, errcode.ErrInvalidArgument) return } query := impl.DBService.Where("status = ? AND stock_quantity > 0", common.StatusEnable). Where("NOT EXISTS (SELECT 1 FROM ec_cart c WHERE c.ec_product_id = ec_product.id AND c.user_account_id = ? AND c.status = ? AND c.deleted_at IS NULL)", account.ID, common.StatusEnable) table := "ec_cart" if request.Source == "favorites" { table = "ec_favorite" query = query.Where("NOT EXISTS (SELECT 1 FROM ec_favorite f WHERE f.ec_product_id = ec_product.id AND f.user_account_id = ? AND f.status = ? AND f.deleted_at IS NULL)", account.ID, common.StatusEnable) } // 表名来自固定枚举,用户输入不拼接进SQL;归属只使用JWT对应的内部账户键。 rank := "CASE WHEN EXISTS (SELECT 1 FROM " + table + " r JOIN ec_product p ON p.id = r.ec_product_id WHERE r.user_account_id = ? AND r.status = ? AND r.deleted_at IS NULL AND p.ec_category_id = ec_product.ec_category_id) THEN 0 ELSE 1 END" var products []models.EcProduct if err := query.Clauses(clause.OrderBy{Expression: gorm.Expr(rank+", ec_product.updated_at desc, ec_product.identity", account.ID, common.StatusEnable)}).Offset((request.Page - 1) * request.Size).Limit(request.Size + 1).Find(&products).Error; err != nil { infra.Response.Error(ctx, err) return } values, err := recommendationValues(impl.DBService, products) if err != nil { infra.Response.Error(ctx, err) return } respondClientPage(ctx, clientPage{Number: request.Page, Size: request.Size}, values) } // recommendationValues 批量读取主图和分类,公开结果只包含展示和下单所需字段。 func recommendationValues(db *gorm.DB, products []models.EcProduct) ([]gin.H, error) { result := make([]gin.H, 0, len(products)) if len(products) == 0 { return result, nil } ids := make([]uint64, 0, len(products)) categoryIDs := []uint64{} seen := map[uint64]bool{} for _, p := range products { ids = append(ids, p.ID) if !seen[p.EcCategoryID] { seen[p.EcCategoryID] = true categoryIDs = append(categoryIDs, p.EcCategoryID) } } var images []models.EcProductImage if err := db.Where("ec_product_id IN ? AND status = ?", ids, common.StatusEnable).Order("is_cover desc, sort_no, identity").Find(&images).Error; err != nil { return nil, err } imageMap := map[uint64]string{} for _, i := range images { if _, ok := imageMap[i.EcProductID]; !ok { imageMap[i.EcProductID] = i.ImageURI } } var categories []models.EcCategory if err := db.Where("id IN ? AND status = ?", categoryIDs, common.StatusEnable).Find(&categories).Error; err != nil { return nil, err } categoryMap := map[uint64]string{} for _, c := range categories { categoryMap[c.ID] = c.Name } for _, p := range products { result = append(result, gin.H{"identity": p.Identity, "name": p.Name, "price_amount": p.PriceAmount, "stock_quantity": p.StockQuantity, "image_url": imageMap[p.ID], "category_name": categoryMap[p.EcCategoryID]}) } return result, nil }