feat(shopro): 完善首页商品列表装修逻辑,支持hidden商品展示

- 在Goods控制器中添加normalizeHomeGoodsListParams方法调用,
  用于处理首页商品列表参数规范化
- 重构Decorate模型,移除未使用的DecorateContent引用
- 新增resolveHomeGoodsListContext方法,解析首页商品列表上下文
- 实现normalizeHomeGoodsListParams方法,确保关键词搜索为空时
 使用装修配置的商品ID
- 添加enrichHomeGoodsBlocks方法,丰富首页商品区块数据
- 优化extractHomeGoodsContextFromBlocks方法,从装修区块中提取
  商品上下文信息
- 修改Goods模型,在指定goods_ids时允许查询status为hidden的商品,
  确保装修中设置的隐藏商品能够正常展示
```
这个提交包含在:
可乐加冰
2026-10-02 15:14:55 +08:00
父节点 80844ae1a0
当前提交 5b2d85af5f
共有 3 个文件被更改,包括 180 次插入 和 1 次删除

查看文件

@@ -82,6 +82,10 @@ class Goods extends Base
{ {
$params = $this->request->get(); $params = $this->request->get();
$params['platform'] = $this->request->header('platform'); $params['platform'] = $this->request->header('platform');
$params = \addons\shopro\model\Decorate::normalizeHomeGoodsListParams(
$params,
$params['platform'] ?? ''
);
$data = \addons\shopro\model\Goods::getGoodsList($params)->toArray(); $data = \addons\shopro\model\Goods::getGoodsList($params)->toArray();
// 获取vip价格 // 获取vip价格

查看文件

@@ -2,7 +2,6 @@
namespace addons\shopro\model; namespace addons\shopro\model;
use addons\shopro\model\DecorateContent;
use think\Model; use think\Model;
use addons\shopro\exception\Exception; use addons\shopro\exception\Exception;
@@ -81,9 +80,183 @@ class Decorate extends Model
$v['content'] = self::getDecorateContentByType($v); $v['content'] = self::getDecorateContentByType($v);
$template[$v->category][] = $v; $template[$v->category][] = $v;
} }
if (!empty($template['home'])) {
$template['home'] = self::enrichHomeGoodsBlocks($template['home']);
}
return $template; return $template;
} }
/**
* 首页「精选好酒」模块:API 侧补齐 goods_ids,避免小程序仅带 category_id 时少显示装修选中的 hidden 商品。
*
* @return array<int, string> [category_id => goods_ids]
*/
public static function resolveHomeGoodsListContext($platform = '')
{
try {
$template = self::getCurrentPlatformDecorate($platform ?: 'wxMiniProgram');
} catch (\Throwable $e) {
return ['category_id' => 0, 'goods_ids' => ''];
}
$home = $template['home'] ?? [];
if (!$home) {
return ['category_id' => 0, 'goods_ids' => ''];
}
$ctx = self::extractHomeGoodsContextFromBlocks($home);
return [
'category_id' => (int) ($ctx['category_id'] ?? 0),
'goods_ids' => (string) ($ctx['goods_ids'] ?? ''),
];
}
/**
* 与首页 sh-hot-goods 请求对齐:无筛选时用装修商品;首页分类与全部分类列表一致。
*/
public static function normalizeHomeGoodsListParams(array $params, $platform = '')
{
$keywords = trim((string) ($params['keywords'] ?? ''));
if ($keywords !== '') {
return $params;
}
if (!empty($params['goods_ids'])) {
return $params;
}
$ctx = self::resolveHomeGoodsListContext($platform);
$homeIds = trim((string) ($ctx['goods_ids'] ?? ''));
$homeCat = (int) ($ctx['category_id'] ?? 0);
if ($homeIds === '') {
return $params;
}
$categoryId = isset($params['category_id']) ? (int) $params['category_id'] : 0;
$scoped = $categoryId > 0;
if (!$scoped) {
$params['goods_ids'] = $homeIds;
unset($params['category_id']);
return $params;
}
if ($homeCat > 0 && $categoryId === $homeCat) {
$params['goods_ids'] = $homeIds;
unset($params['category_id']);
}
return $params;
}
protected static function enrichHomeGoodsBlocks(array $home)
{
$ctx = self::extractHomeGoodsContextFromBlocks($home);
if (($ctx['goods_ids'] ?? '') === '') {
return $home;
}
$targetIdx = null;
foreach ($home as $idx => $block) {
if (in_array($block['type'] ?? '', ['goods-list', 'goods-group'], true)) {
$targetIdx = $idx;
break;
}
}
if ($targetIdx === null) {
$targetIdx = self::findLastCategoryTabsIndex($home);
}
if ($targetIdx === null || $targetIdx < 0) {
return $home;
}
$content = $home[$targetIdx]['content'] ?? [];
$content['ids'] = $ctx['goods_ids'];
unset($content['id']);
$home[$targetIdx]['content'] = $content;
return $home;
}
protected static function findLastCategoryTabsIndex(array $home)
{
for ($i = count($home) - 1; $i >= 0; $i--) {
if (($home[$i]['type'] ?? '') === 'category-tabs') {
return $i;
}
}
return -1;
}
protected static function extractHomeGoodsContextFromBlocks(array $home)
{
$categoryId = 0;
foreach ($home as $block) {
$type = $block['type'] ?? '';
if (!in_array($type, ['goods-list', 'goods-group'], true)) {
continue;
}
$content = $block['content'] ?? [];
if (!empty($content['ids'])) {
return [
'category_id' => (int) ($content['id'] ?? 0),
'goods_ids' => self::normalizeGoodsIdsString($content['ids']),
];
}
if (!empty($content['id'])) {
$categoryId = (int) $content['id'];
return [
'category_id' => $categoryId,
'goods_ids' => self::goodsIdsFromCategoryId($categoryId),
];
}
}
for ($i = count($home) - 1; $i >= 0; $i--) {
if (($home[$i]['type'] ?? '') !== 'category-tabs') {
continue;
}
$content = $home[$i]['content'] ?? [];
if (!empty($content['ids'])) {
return [
'category_id' => (int) ($content['id'] ?? ($content['category_arr'][0]['id'] ?? 0)),
'goods_ids' => self::normalizeGoodsIdsString($content['ids']),
];
}
$categoryId = (int) ($content['id'] ?? ($content['category_arr'][0]['id'] ?? 0));
if ($categoryId > 0) {
return [
'category_id' => $categoryId,
'goods_ids' => self::goodsIdsFromCategoryId($categoryId),
];
}
break;
}
return ['category_id' => 0, 'goods_ids' => ''];
}
protected static function normalizeGoodsIdsString($ids)
{
$ids = is_array($ids) ? implode(',', $ids) : (string) $ids;
$parts = array_filter(array_map('intval', explode(',', $ids)));
return implode(',', array_unique($parts));
}
protected static function goodsIdsFromCategoryId($categoryId)
{
$categoryId = (int) $categoryId;
if ($categoryId <= 0) {
return '';
}
$categoryIds = Category::getCategoryIds($categoryId);
if (!$categoryIds) {
return '';
}
$query = Goods::where('status', 'in', ['up', 'hidden']);
$query->where(function ($q) use ($categoryIds) {
foreach ($categoryIds as $cid) {
$q->whereOrRaw("find_in_set($cid, category_ids)");
}
});
$ids = $query->order('weigh asc, id desc')->column('id');
return self::normalizeGoodsIdsString(implode(',', $ids));
}
public static function getDecorateContentByType($templateValue) public static function getDecorateContentByType($templateValue)
{ {
$content = json_decode($templateValue->content, true); $content = json_decode($templateValue->content, true);

查看文件

@@ -60,6 +60,8 @@ class Goods extends Model
$order = 'field(id, ' . $goods_ids . ')'; // 如果传了 goods_ids 就按照里面的 id 进行排序 $order = 'field(id, ' . $goods_ids . ')'; // 如果传了 goods_ids 就按照里面的 id 进行排序
$goodsIdsArray = explode(',', $goods_ids); $goodsIdsArray = explode(',', $goods_ids);
$where['id'] = ['in', $goodsIdsArray]; $where['id'] = ['in', $goodsIdsArray];
// 装修/首页指定 id 时允许 hidden(如招商礼盒),仍不展示 down
$where['status'] = ['in', ['up', 'hidden']];
} }
$category_ids = []; $category_ids = [];