|
@@ -171,6 +171,10 @@ class HomePageModuleClass
|
|
|
$data = self::normalizeActivityBase($saved);
|
|
$data = self::normalizeActivityBase($saved);
|
|
|
$data['enabled'] = HomePageConfigClass::getModuleEnabled($mainId, 'seckill');
|
|
$data['enabled'] = HomePageConfigClass::getModuleEnabled($mainId, 'seckill');
|
|
|
$data['goods'] = self::normalizeSeckillGoods($saved['goods'] ?? [], $mainId, $refreshStock);
|
|
$data['goods'] = self::normalizeSeckillGoods($saved['goods'] ?? [], $mainId, $refreshStock);
|
|
|
|
|
+ // 按已添加商品数量 + 展开开关动态推导列数与展示数量(不依赖商家手动配置)
|
|
|
|
|
+ $layout = self::resolveActivityLayout(count($data['goods']), $data['expand']);
|
|
|
|
|
+ $data['layoutCols'] = $layout['layoutCols'];
|
|
|
|
|
+ $data['displayCount'] = $layout['displayCount'];
|
|
|
$data['status'] = self::calcActivityStatus($data['startTime'], $data['endTime'], $data['enabled']);
|
|
$data['status'] = self::calcActivityStatus($data['startTime'], $data['endTime'], $data['enabled']);
|
|
|
return $data;
|
|
return $data;
|
|
|
}
|
|
}
|
|
@@ -314,6 +318,10 @@ class HomePageModuleClass
|
|
|
$data = self::normalizeActivityBase($saved);
|
|
$data = self::normalizeActivityBase($saved);
|
|
|
$data['enabled'] = HomePageConfigClass::getModuleEnabled($mainId, 'groupBuy');
|
|
$data['enabled'] = HomePageConfigClass::getModuleEnabled($mainId, 'groupBuy');
|
|
|
$data['goods'] = self::normalizeGroupBuyGoods($saved['goods'] ?? [], $mainId, $refreshStock);
|
|
$data['goods'] = self::normalizeGroupBuyGoods($saved['goods'] ?? [], $mainId, $refreshStock);
|
|
|
|
|
+ // 按已添加商品数量 + 展开开关动态推导列数与展示数量(不依赖商家手动配置)
|
|
|
|
|
+ $layout = self::resolveActivityLayout(count($data['goods']), $data['expand']);
|
|
|
|
|
+ $data['layoutCols'] = $layout['layoutCols'];
|
|
|
|
|
+ $data['displayCount'] = $layout['displayCount'];
|
|
|
$data['status'] = self::calcActivityStatus($data['startTime'], $data['endTime'], $data['enabled']);
|
|
$data['status'] = self::calcActivityStatus($data['startTime'], $data['endTime'], $data['enabled']);
|
|
|
return $data;
|
|
return $data;
|
|
|
}
|
|
}
|
|
@@ -451,8 +459,6 @@ class HomePageModuleClass
|
|
|
'type' => intval($saved['type'] ?? self::LINK_GOODS),
|
|
'type' => intval($saved['type'] ?? self::LINK_GOODS),
|
|
|
'value' => strval($saved['value'] ?? ''),
|
|
'value' => strval($saved['value'] ?? ''),
|
|
|
'sort' => intval($saved['sort'] ?? self::SORT_PRODUCT),
|
|
'sort' => intval($saved['sort'] ?? self::SORT_PRODUCT),
|
|
|
- 'layoutCols' => self::normalizeLayoutCols($saved['layoutCols'] ?? null),
|
|
|
|
|
- 'displayCount' => intval($saved['displayCount'] ?? 0),
|
|
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -464,8 +470,7 @@ class HomePageModuleClass
|
|
|
$type = intval($data['type'] ?? 0);
|
|
$type = intval($data['type'] ?? 0);
|
|
|
$value = trim(strval($data['value'] ?? ''));
|
|
$value = trim(strval($data['value'] ?? ''));
|
|
|
$sort = intval($data['sort'] ?? self::SORT_PRODUCT);
|
|
$sort = intval($data['sort'] ?? self::SORT_PRODUCT);
|
|
|
- $layoutCols = intval($data['layoutCols'] ?? self::DEFAULT_LAYOUT_COLS);
|
|
|
|
|
- $displayCount = self::normalizeDisplayCount($data['displayCount'] ?? 0);
|
|
|
|
|
|
|
+ // layoutCols/displayCount 由读取时按真实商品数量自动推导,保存时不再接收商家手动配置
|
|
|
if ($name === '') {
|
|
if ($name === '') {
|
|
|
util::fail('请输入首页展示名称');
|
|
util::fail('请输入首页展示名称');
|
|
|
}
|
|
}
|
|
@@ -481,21 +486,41 @@ class HomePageModuleClass
|
|
|
if (!in_array($sort, [self::SORT_PRODUCT, self::SORT_SALES, self::SORT_NEW], true)) {
|
|
if (!in_array($sort, [self::SORT_PRODUCT, self::SORT_SALES, self::SORT_NEW], true)) {
|
|
|
util::fail('排序规则无效');
|
|
util::fail('排序规则无效');
|
|
|
}
|
|
}
|
|
|
- if (!in_array($layoutCols, self::LAYOUT_COLS_OPTIONS, true)) {
|
|
|
|
|
- util::fail('排列规则无效');
|
|
|
|
|
- }
|
|
|
|
|
self::setJson($mainId, $suffix, [
|
|
self::setJson($mainId, $suffix, [
|
|
|
'name' => $name,
|
|
'name' => $name,
|
|
|
'type' => $type,
|
|
'type' => $type,
|
|
|
'value' => $value,
|
|
'value' => $value,
|
|
|
'sort' => $sort,
|
|
'sort' => $sort,
|
|
|
- 'layoutCols' => $layoutCols,
|
|
|
|
|
- 'displayCount' => $displayCount,
|
|
|
|
|
]);
|
|
]);
|
|
|
HomePageConfigClass::updateModuleEnabled($mainId, $moduleKey, !empty($data['enabled']) ? 1 : 0);
|
|
HomePageConfigClass::updateModuleEnabled($mainId, $moduleKey, !empty($data['enabled']) ? 1 : 0);
|
|
|
return true;
|
|
return true;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按真实商品总数与模块类型自动推导首页列数与展示数量
|
|
|
|
|
+ * - 1个商品:1排1列,展示全部
|
|
|
|
|
+ * - 2个商品:1排2列,展示全部
|
|
|
|
|
+ * - ≥3个:hot/new 按1排3列且只展示3个;pullGoods 按1排2列且展示全部
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $goodsTotal 关联配置解析出的真实商品总数
|
|
|
|
|
+ * @param string $moduleKey hot|new|pullGoods
|
|
|
|
|
+ * @return array{layoutCols:int,displayCount:int}
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function resolveGoodsSectionLayout($goodsTotal, $moduleKey)
|
|
|
|
|
+ {
|
|
|
|
|
+ $goodsTotal = intval($goodsTotal);
|
|
|
|
|
+ if ($goodsTotal <= 1) {
|
|
|
|
|
+ return ['layoutCols' => 1, 'displayCount' => 0];
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($goodsTotal === 2) {
|
|
|
|
|
+ return ['layoutCols' => 2, 'displayCount' => 0];
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($moduleKey === 'pullGoods') {
|
|
|
|
|
+ return ['layoutCols' => 2, 'displayCount' => 0];
|
|
|
|
|
+ }
|
|
|
|
|
+ return ['layoutCols' => 3, 'displayCount' => 3];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 规范化排列规则取值,非法/缺省时回退默认值
|
|
* 规范化排列规则取值,非法/缺省时回退默认值
|
|
|
*/
|
|
*/
|
|
@@ -667,26 +692,9 @@ class HomePageModuleClass
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 规范化首页商品展示数量:0=全部,1-10=具体数量
|
|
|
|
|
- *
|
|
|
|
|
- * @param mixed $value
|
|
|
|
|
- * @return int
|
|
|
|
|
- */
|
|
|
|
|
- public static function normalizeDisplayCount($value)
|
|
|
|
|
- {
|
|
|
|
|
- if ($value === '' || $value === null || intval($value) === 0) {
|
|
|
|
|
- return 0;
|
|
|
|
|
- }
|
|
|
|
|
- $count = intval($value);
|
|
|
|
|
- if ($count < 1 || $count > 10) {
|
|
|
|
|
- util::fail('商品展示数量范围为1-10,留空表示全部');
|
|
|
|
|
- }
|
|
|
|
|
- return $count;
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* 根据 displayCount 计算首页实际截断条数:1-10 用配置值,0(全部)回退默认上限
|
|
* 根据 displayCount 计算首页实际截断条数:1-10 用配置值,0(全部)回退默认上限
|
|
|
|
|
+ * 供秒杀/团购等活动模块使用
|
|
|
*
|
|
*
|
|
|
* @param mixed $displayCount
|
|
* @param mixed $displayCount
|
|
|
* @return int
|
|
* @return int
|
|
@@ -721,14 +729,38 @@ class HomePageModuleClass
|
|
|
'title' => strval($saved['title'] ?? ''),
|
|
'title' => strval($saved['title'] ?? ''),
|
|
|
'subtitle' => strval($saved['subtitle'] ?? ''),
|
|
'subtitle' => strval($saved['subtitle'] ?? ''),
|
|
|
'showCountdown' => !empty($saved['showCountdown']) ? 1 : 0,
|
|
'showCountdown' => !empty($saved['showCountdown']) ? 1 : 0,
|
|
|
- 'displayCount' => intval($saved['displayCount'] ?? 0),
|
|
|
|
|
|
|
+ // 商品展开:开启后首页按1排1列展示全部商品,默认关闭
|
|
|
|
|
+ 'expand' => !empty($saved['expand']) ? 1 : 0,
|
|
|
'startTime' => intval($saved['startTime'] ?? 0),
|
|
'startTime' => intval($saved['startTime'] ?? 0),
|
|
|
'endTime' => intval($saved['endTime'] ?? 0),
|
|
'endTime' => intval($saved['endTime'] ?? 0),
|
|
|
'desc' => strval($saved['desc'] ?? ''),
|
|
'desc' => strval($saved['desc'] ?? ''),
|
|
|
- 'layoutCols' => self::normalizeLayoutCols($saved['layoutCols'] ?? null),
|
|
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 按已添加商品数量与「商品展开」开关自动推导首页列数与展示数量
|
|
|
|
|
+ * - expand 开启:1排1列,展示全部
|
|
|
|
|
+ * - 1个商品:1排1列;2个:1排2列;≥3个:1排3列且只展示3个
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param int $goodsCount 已添加商品总数(含未上架)
|
|
|
|
|
+ * @param int $expand 商品展开开关 0/1
|
|
|
|
|
+ * @return array{layoutCols:int,displayCount:int}
|
|
|
|
|
+ */
|
|
|
|
|
+ public static function resolveActivityLayout($goodsCount, $expand)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!empty($expand)) {
|
|
|
|
|
+ return ['layoutCols' => 1, 'displayCount' => 0];
|
|
|
|
|
+ }
|
|
|
|
|
+ $goodsCount = intval($goodsCount);
|
|
|
|
|
+ if ($goodsCount <= 1) {
|
|
|
|
|
+ return ['layoutCols' => 1, 'displayCount' => 0];
|
|
|
|
|
+ }
|
|
|
|
|
+ if ($goodsCount === 2) {
|
|
|
|
|
+ return ['layoutCols' => 2, 'displayCount' => 0];
|
|
|
|
|
+ }
|
|
|
|
|
+ return ['layoutCols' => 3, 'displayCount' => 3];
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public static function validateActivityBase($data)
|
|
public static function validateActivityBase($data)
|
|
|
{
|
|
{
|
|
|
$title = trim(strval($data['title'] ?? ''));
|
|
$title = trim(strval($data['title'] ?? ''));
|
|
@@ -736,8 +768,7 @@ class HomePageModuleClass
|
|
|
$desc = trim(strval($data['desc'] ?? ''));
|
|
$desc = trim(strval($data['desc'] ?? ''));
|
|
|
$startTime = intval($data['startTime'] ?? 0);
|
|
$startTime = intval($data['startTime'] ?? 0);
|
|
|
$endTime = intval($data['endTime'] ?? 0);
|
|
$endTime = intval($data['endTime'] ?? 0);
|
|
|
- $layoutCols = intval($data['layoutCols'] ?? self::DEFAULT_LAYOUT_COLS);
|
|
|
|
|
- $displayCount = self::normalizeDisplayCount($data['displayCount'] ?? 0);
|
|
|
|
|
|
|
+ // layoutCols/displayCount 由读取时按商品数量自动推导,保存时不再接收商家手动配置
|
|
|
if ($title === '') {
|
|
if ($title === '') {
|
|
|
util::fail('请输入活动标题');
|
|
util::fail('请输入活动标题');
|
|
|
}
|
|
}
|
|
@@ -762,18 +793,14 @@ class HomePageModuleClass
|
|
|
if (mb_strlen($desc) > 500) {
|
|
if (mb_strlen($desc) > 500) {
|
|
|
util::fail('活动说明不能超过500字');
|
|
util::fail('活动说明不能超过500字');
|
|
|
}
|
|
}
|
|
|
- if (!in_array($layoutCols, self::LAYOUT_COLS_OPTIONS, true)) {
|
|
|
|
|
- util::fail('排列规则无效');
|
|
|
|
|
- }
|
|
|
|
|
return [
|
|
return [
|
|
|
'title' => $title,
|
|
'title' => $title,
|
|
|
'subtitle' => $subtitle,
|
|
'subtitle' => $subtitle,
|
|
|
'showCountdown' => !empty($data['showCountdown']) ? 1 : 0,
|
|
'showCountdown' => !empty($data['showCountdown']) ? 1 : 0,
|
|
|
- 'displayCount' => $displayCount,
|
|
|
|
|
|
|
+ 'expand' => !empty($data['expand']) ? 1 : 0,
|
|
|
'startTime' => $startTime,
|
|
'startTime' => $startTime,
|
|
|
'endTime' => $endTime,
|
|
'endTime' => $endTime,
|
|
|
'desc' => $desc,
|
|
'desc' => $desc,
|
|
|
- 'layoutCols' => $layoutCols,
|
|
|
|
|
];
|
|
];
|
|
|
}
|
|
}
|
|
|
|
|
|