```
feat(shopro): 完善首页商品列表装修逻辑,支持hidden商品展示 - 在Goods控制器中添加normalizeHomeGoodsListParams方法调用, 用于处理首页商品列表参数规范化 - 重构Decorate模型,移除未使用的DecorateContent引用 - 新增resolveHomeGoodsListContext方法,解析首页商品列表上下文 - 实现normalizeHomeGoodsListParams方法,确保关键词搜索为空时 使用装修配置的商品ID - 添加enrichHomeGoodsBlocks方法,丰富首页商品区块数据 - 优化extractHomeGoodsContextFromBlocks方法,从装修区块中提取 商品上下文信息 - 修改Goods模型,在指定goods_ids时允许查询status为hidden的商品, 确保装修中设置的隐藏商品能够正常展示 ```
这个提交包含在:
@@ -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 = [];
|
||||||
|
|||||||
在新工单中引用
屏蔽一个用户