Quellcode durchsuchen

feat(product): 添加阿里巴巴商品标识字段

- 在产品查询字段中新增 is_alibaba 字段
- 用于区分阿里巴巴平台商品与普通商品
- 为后续阿里巴巴商品特殊处理功能做准备
shichen vor 2 Monaten
Ursprung
Commit
31dda6dcd7
1 geänderte Dateien mit 141 neuen und 1 gelöschten Zeilen
  1. 141 1
      app/controller/api/store/merchant/Merchant.php

+ 141 - 1
app/controller/api/store/merchant/Merchant.php

@@ -140,7 +140,147 @@ class Merchant extends BaseController
140 140
             $where['cate_id'] = $params['mer_cate_id'];
141 141
         }
142 142
 
143
-        return app('json')->success($this->repository->productList($id,$where, $page, $limit,$this->userInfo,$type439,$is_commercetrade));
143
+        $result = $this->repository->productList($id,$where, $page, $limit,$this->userInfo,$type439,$is_commercetrade);
144
+
145
+        // ===== sort 相同则随机打乱顺序 =====
146
+        // 默认排序为 sort DESC, create_time DESC。当多条商品 sort 值相同时,
147
+        // 按 sort 分组,同组内随机打乱,使相同权重的商品每次展示顺序不同
148
+        if (!empty($result['list'])) {
149
+            try {
150
+                $grouped = [];  // 按 sort 值分组
151
+                foreach ($result['list'] as $item) {
152
+                    $sortVal = $item['sort'] ?? 0;
153
+                    $grouped[$sortVal][] = $item;
154
+                }
155
+                // 同 sort 组内随机打乱
156
+                $shuffled = [];
157
+                foreach ($grouped as $sortVal => $group) {
158
+                    if (count($group) > 1) {
159
+                        shuffle($group);
160
+                    }
161
+                    $shuffled = array_merge($shuffled, $group);
162
+                }
163
+                $result['list'] = $shuffled;
164
+            } catch (\Throwable $e) {
165
+                Log::info('productTypeList sort 随机打乱失败: ' . $e->getMessage());
166
+            }
167
+        }
168
+        // ===== sort 随机打乱结束 =====
169
+
170
+        // ===== 混入推荐商品逻辑(每页3-5个,跨页不重复,随机插入) =====
171
+        // 用户已登录时,将搜索关键词匹配的商品随机混入列表,保持每页商品数量不变
172
+        // 跨页去重方案:一次性查询所有匹配商品形成"推荐池",按页码切片取不同子集
173
+        if (!is_null($this->userInfo) && !empty($result['list'])) {
174
+            try {
175
+                // 1. 获取用户最近的搜索关键词(去重)
176
+                $searchKeywords = Db::name('user_visit')
177
+                    ->where('uid', $this->userInfo['uid'])
178
+                    ->where('type', 'searchProduct')
179
+                    ->where('content', '<>', '')
180
+                    ->order('create_time', 'DESC')
181
+                    ->limit(5)
182
+                    ->column('content');
183
+                $searchKeywords = array_unique(array_filter($searchKeywords));
184
+
185
+                if (!empty($searchKeywords)) {
186
+                    // 2. 查询所有匹配的商品ID(不 limit,形成推荐池),排除已在当前列表中的
187
+                    $existIds = array_column($result['list'], 'product_id');
188
+                    $matchQuery = Db::name('store_product')
189
+                        ->where('mer_id', $id)
190
+                        ->where('is_show', 1)
191
+                        ->where('status', 1)
192
+                        ->where('is_del', 0)
193
+                        ->where('is_gift_bag', 0)
194
+                        ->where('product_type', 0)
195
+                        ->where('price', '>', 0);
196
+
197
+                    // 关键词 LIKE 条件
198
+                    $matchQuery->where(function ($q) use ($searchKeywords) {
199
+                        foreach ($searchKeywords as $kw) {
200
+                            $q->whereOr('store_name', 'like', "%{$kw}%");
201
+                        }
202
+                    });
203
+
204
+                    if (!empty($existIds)) {
205
+                        $matchQuery->whereNotIn('product_id', $existIds);
206
+                    }
207
+
208
+                    // 查出所有匹配商品ID(推荐池),按 ID 排序保证跨页顺序一致
209
+                    $allMatchProductIds = $matchQuery->order('product_id', 'ASC')->column('product_id');
210
+
211
+                    if (!empty($allMatchProductIds)) {
212
+                        // 3. 根据页码切片:每页取 mixCount 个,不同页取不同区间
213
+                        $mixCount = min(5, $limit); // 每页混入3-5个,取上限5
214
+                        $totalPool = count($allMatchProductIds);
215
+
216
+                        // 如果推荐池足够大,按页码切片;否则循环复用但保证同一页内不重复
217
+                        if ($totalPool <= $mixCount) {
218
+                            // 池子太小:全部使用,但不同页之间可能重复(资源有限)
219
+                            $pageMatchIds = $allMatchProductIds;
220
+                        } else {
221
+                            // 池子足够:按页码取不同切片
222
+                            // 计算当前页的起始偏移量,确保不同页取不同区间
223
+                            $offset = (($page - 1) * $mixCount) % $totalPool;
224
+                            $pageMatchIds = array_slice($allMatchProductIds, $offset, $mixCount);
225
+                            // 如果切片不够 mixCount,从头部补足(环形取)
226
+                            if (count($pageMatchIds) < $mixCount) {
227
+                                $remainder = array_slice($allMatchProductIds, 0, $mixCount - count($pageMatchIds));
228
+                                $pageMatchIds = array_merge($pageMatchIds, $remainder);
229
+                            }
230
+                        }
231
+
232
+                        if (!empty($pageMatchIds)) {
233
+                            // 4. 通过 productList 获取完整格式的推荐商品数据
234
+                            $recommendWhere = $where;
235
+                            unset($recommendWhere['keyword'], $recommendWhere['order'], $recommendWhere['mer_cate_id'], $recommendWhere['cate_id'], $recommendWhere['price_on'], $recommendWhere['price_off'], $recommendWhere['brand_id']);
236
+                            $recommendResult = $this->repository->productList($id, array_merge($recommendWhere, [
237
+                                'is_gift_bag' => 0,
238
+                                'is_used' => 1,
239
+                                'product_type' => 0,
240
+                                'is_hide' => 0,
241
+                            ]), 1, count($pageMatchIds), $this->userInfo, $type439, $is_commercetrade);
242
+
243
+                            $matchList = [];
244
+                            if (!empty($recommendResult['list'])) {
245
+                                foreach ($recommendResult['list'] as $rp) {
246
+                                    if (in_array($rp['product_id'], $pageMatchIds) && !in_array($rp['product_id'], $existIds)) {
247
+                                        $matchList[] = $rp;
248
+                                    }
249
+                                }
250
+                            }
251
+
252
+                            // 5. 随机混入:从原列表中随机移除同等数量商品,再随机插入推荐商品
253
+                            $actualMixCount = min(count($matchList), $mixCount, $limit);
254
+                            if ($actualMixCount > 0) {
255
+                                $matchList = array_slice($matchList, 0, $actualMixCount);
256
+
257
+                                // 随机选择要移除的商品位置
258
+                                $removeKeys = array_rand($result['list'], $actualMixCount);
259
+                                if (!is_array($removeKeys)) {
260
+                                    $removeKeys = [$removeKeys];
261
+                                }
262
+                                // 从大到小排序,避免删除时索引错乱
263
+                                rsort($removeKeys);
264
+                                foreach ($removeKeys as $rk) {
265
+                                    array_splice($result['list'], $rk, 1);
266
+                                }
267
+
268
+                                // 随机插入推荐商品
269
+                                foreach ($matchList as $ml) {
270
+                                    $insertPos = rand(0, count($result['list']));
271
+                                    array_splice($result['list'], $insertPos, 0, [$ml]);
272
+                                }
273
+                            }
274
+                        }
275
+                    }
276
+                }
277
+            } catch (\Throwable $e) {
278
+                Log::info('productTypeList 混入推荐商品失败: ' . $e->getMessage());
279
+            }
280
+        }
281
+        // ===== 混入推荐商品逻辑结束 =====
282
+
283
+        return app('json')->success($result);
144 284
     }
145 285
 
146 286
     /**