Browse Source

fix:限时折扣的

super-yimizi 1 month ago
parent
commit
3513babc62

+ 186 - 10
application/admin/controller/marketing/Discount.php

@@ -286,20 +286,196 @@ class Discount extends Backend
                 $goodsIdArr = json_decode($row['goods_ids'], true);
                 $row['goods_ids'] = implode(',', $goodsIdArr);
                 
-                // 获取商品数据
+                // 获取商品数据,包含完整的SKU和规格信息
                 $goodsData = [];
                 if (!empty($goodsIdArr)) {
-                    $goodsData = Db::name('shop_goods')
-                        ->alias('g')
-                        ->field('g.*')
-                        ->where('g.id', 'in', $goodsIdArr)
+                    // 查询商品基础数据
+                    $goodsResult = Db::name('shop_goods')
+                        ->where('id', 'in', $goodsIdArr)
                         ->select();
+                    $goodsData = [];
+                    if ($goodsResult) {
+                        foreach ($goodsResult as $item) {
+                            $goodsData[] = is_array($item) ? $item : $item->toArray();
+                        }
+                    }
+                        
+                    // 一次性查询该活动的所有SKU折扣数据
+                    $activitySkus = Db::table('shop_activity_sku')
+                        ->where('activity_id', $ids)
+                        ->select();
+                    
+                    // 将活动SKU数据按照goods_id和sku_id进行索引
+                    $activitySkuMap = [];
+                    foreach ($activitySkus as $activitySku) {
+                        $key = $activitySku['goods_id'] . '_' . $activitySku['sku_id'];
+                        $activitySkuMap[$key] = $activitySku;
+                    }
+                    
+                    // 一次性查询所有商品的SKU信息
+                    $allSkusResult = Db::name('shop_goods_sku')
+                        ->where('goods_id', 'in', $goodsIdArr)
+                        ->order('is_default desc, id asc')
+                        ->select();
+                    
+                    // 转换SKU结果为数组并按商品ID分组
+                    $skusByGoods = [];
+                    foreach ($allSkusResult as $sku) {
+                        $skuArray = is_array($sku) ? $sku : $sku->toArray();
+                        $skusByGoods[$skuArray['goods_id']][] = $skuArray;
+                    }
+                    
+                    // 找出多规格商品ID
+                    $multiSpecGoodsIds = [];
+                    foreach ($goodsData as $item) {
+                        if ($item['spec_type'] == 1) {
+                            $multiSpecGoodsIds[] = $item['id'];
+                        }
+                    }
+                    
+                    // 一次性查询所有多规格商品的规格信息
+                    $specsByGoods = [];
+                    if (!empty($multiSpecGoodsIds)) {
+                        $allSpecsResult = Db::name('shop_goods_sku_spec')
+                            ->alias('gss')
+                            ->field('gss.goods_id, sp.id as spec_id, sp.name as spec_name, sp.type as spec_type, sv.id as spec_value_id, sv.value, sv.image, sv.desc')
+                            ->join('shop_spec sp', 'sp.id = gss.spec_id', 'LEFT')
+                            ->join('shop_spec_value sv', 'sv.id = gss.spec_value_id', 'LEFT')
+                            ->where('gss.goods_id', 'in', $multiSpecGoodsIds)
+                            ->order('gss.goods_id asc, sp.id asc, sv.id asc')
+                            ->select();
+                        
+                        // 按商品ID分组规格数据
+                        foreach ($allSpecsResult as $spec) {
+                            $specArray = is_array($spec) ? $spec : $spec->toArray();
+                            $specsByGoods[$specArray['goods_id']][] = $specArray;
+                        }
+                    }
+                    
+                    // 一次性查询所有SKU的规格属性文本
+                    $allSkuIds = [];
+                    foreach ($skusByGoods as $skus) {
+                        foreach ($skus as $sku) {
+                            $allSkuIds[] = $sku['id'];
+                        }
+                    }
+                    
+                    $skuSpecTexts = [];
+                    if (!empty($allSkuIds)) {
+                        $skuSpecResults = Db::name('shop_goods_sku')
+                            ->alias('sku')
+                            ->field('sku.id, GROUP_CONCAT(sp.name,":",sv.value ORDER BY sp.id asc) as specs_text')
+                            ->join('shop_goods_sku_spec gss', "FIND_IN_SET(gss.id, sku.spec_value_ids)", 'LEFT')
+                            ->join('shop_spec sp', 'sp.id = gss.spec_id', 'LEFT')
+                            ->join('shop_spec_value sv', 'sv.id = gss.spec_value_id', 'LEFT')
+                            ->where('sku.id', 'in', $allSkuIds)
+                            ->group('sku.id')
+                            ->select();
+                        
+                        foreach ($skuSpecResults as $result) {
+                            $resultArray = is_array($result) ? $result : $result->toArray();
+                            $skuSpecTexts[$resultArray['id']] = $resultArray['specs_text'] ?: '';
+                        }
+                    }
+                        
+                    // 为每个商品添加完整的SKU和规格信息(纯数据组装,无数据库查询)
+                    foreach ($goodsData as &$item) {
+                        if ($item['image']) {
+                            $item['image'] = cdnurl($item['image'], true);
+                        }
                         
-                    // 处理商品数据,添加category属性
-                    // foreach ($goodsData as &$goods) {
-                    //     $goods['category'] = ['name' => $goods['category_name']];
-                    //     unset($goods['category_name']);
-                    // }
+                        // 获取商品的SKU信息
+                        $skus = $skusByGoods[$item['id']] ?? [];
+                        
+                        if ($skus) {
+                            // 获取第一个SKU ID(单规格商品通常只有一个SKU)
+                            $item['sku_id'] = $skus[0]['id'];
+                            
+                            // 为每个SKU添加规格属性文本和活动折扣信息
+                            foreach ($skus as &$sku) {
+                                $sku['specs_text'] = $skuSpecTexts[$sku['id']] ?? '';
+                                
+                                // 查找该SKU是否有活动折扣数据
+                                $activityKey = $item['id'] . '_' . $sku['id'];
+                                if (isset($activitySkuMap[$activityKey])) {
+                                    $activitySku = $activitySkuMap[$activityKey];
+                                    $sku['activity_discount'] = $activitySku['discount'];
+                                    $sku['activity_discount_price'] = $activitySku['discount_price'];
+                                    $sku['activity_stocks'] = $activitySku['stocks'];
+                                }
+                            }
+                            $item['skus'] = $skus;
+                            
+                            // 如果是多规格商品,添加规格数据
+                            if ($item['spec_type'] == 1) {
+                                $specs = $specsByGoods[$item['id']] ?? [];
+                                
+                                // 按规格分组构建规格数据结构
+                                $spec_groups = [];
+                                foreach ($specs as $spec) {
+                                    if (!isset($spec_groups[$spec['spec_id']])) {
+                                        $spec_groups[$spec['spec_id']]['id'] = $spec['spec_id'];
+                                        $spec_groups[$spec['spec_id']]['name'] = $spec['spec_name'];
+                                        $spec_groups[$spec['spec_id']]['type'] = $spec['spec_type'] == 2 ? 'custom' : 'basic';
+                                        $spec_groups[$spec['spec_id']]['value'] = [];
+                                    }
+                                    $spec_groups[$spec['spec_id']]['value'][] = [
+                                        'id' => $spec['spec_value_id'],
+                                        'name' => $spec['value'],
+                                        'image' => $spec['image'] ?: '',
+                                        'description' => $spec['desc'] ?: ''
+                                    ];
+                                }
+                                
+                                // 转换为数组格式,与前端渲染一致
+                                $item['spec'] = array_values($spec_groups);
+                                
+                                // 构建已选择的规格折扣数据(用于前端回显)
+                                $selectedSpecs = [];
+                                $summary = [
+                                    'participate_count' => 0,
+                                    'avg_discount' => 0,
+                                    'total_stocks' => 0
+                                ];
+                                $totalDiscount = 0;
+                                
+                                foreach ($skus as $sku) {
+                                    $activityKey = $item['id'] . '_' . $sku['id'];
+                                    if (isset($activitySkuMap[$activityKey])) {
+                                        $activitySku = $activitySkuMap[$activityKey];
+                                        $selectedSpecs[] = [
+                                            'sku_id' => $sku['id'],
+                                            'discount' => $activitySku['discount'],
+                                            'discount_price' => $activitySku['discount_price'],
+                                            'discount_stocks' => $activitySku['stocks']
+                                        ];
+                                        
+                                        $summary['participate_count']++;
+                                        $totalDiscount += floatval($activitySku['discount']);
+                                        $summary['total_stocks'] += intval($activitySku['stocks']);
+                                    }
+                                }
+                                
+                                if ($summary['participate_count'] > 0) {
+                                    $summary['avg_discount'] = round($totalDiscount / $summary['participate_count'], 1);
+                                    
+                                    // 为前端JavaScript提供已选择的规格数据
+                                    $item['selected_discount_data'] = [
+                                        'goodsId' => $item['id'],
+                                        'spec' => $selectedSpecs,
+                                        'summary' => $summary
+                                    ];
+                                }
+                            } else {
+                                // 单规格商品,没有spec数据
+                                $item['spec'] = [];
+                            }
+                        } else {
+                            $item['sku_id'] = 0;
+                            $item['skus'] = [];
+                            $item['spec'] = [];
+                        }
+                    }
                 }
                 $this->view->assign('goodsData', $goodsData);
             }

+ 127 - 7
application/admin/controller/shop/Goods.php

@@ -807,22 +807,142 @@ class Goods extends Backend
         
         $ids = explode(',', $ids);
         $list = $this->model
-            ->with(['Category'])
             ->where('id', 'in', $ids)
             ->select();
             
-        // 处理图片URL和SKU信息
-        foreach ($list as &$item) {
+        // 转换商品结果为数组
+        $goodsData = [];
+        if ($list) {
+            foreach ($list as $item) {
+                $goodsData[] = is_array($item) ? $item : $item->toArray();
+            }
+        }
+        
+        // 如果没有商品数据,直接返回空数组
+        if (empty($goodsData)) {
+            return json([]);
+        }
+        
+        // 一次性查询所有商品的SKU信息
+        $allSkusResult = Db::name('shop_goods_sku')
+            ->where('goods_id', 'in', $ids)
+            ->order('is_default desc, id asc')
+            ->select();
+        
+        // 按商品ID分组SKU数据
+        $skusByGoods = [];
+        foreach ($allSkusResult as $sku) {
+            $skuArray = is_array($sku) ? $sku : $sku->toArray();
+            $skusByGoods[$skuArray['goods_id']][] = $skuArray;
+        }
+        
+        // 找出多规格商品ID
+        $multiSpecGoodsIds = [];
+        foreach ($goodsData as $item) {
+            if ($item['spec_type'] == 1) {
+                $multiSpecGoodsIds[] = $item['id'];
+            }
+        }
+        
+        // 一次性查询所有多规格商品的规格信息
+        $specsByGoods = [];
+        if (!empty($multiSpecGoodsIds)) {
+            $allSpecsResult = Db::name('shop_goods_sku_spec')
+                ->alias('gss')
+                ->field('sp.id as spec_id, sp.name as spec_name, sp.type as spec_type, sv.id as spec_value_id, sv.value, sv.image, sv.desc, gss.goods_id')
+                ->join('shop_spec sp', 'sp.id=gss.spec_id', 'LEFT')
+                ->join('shop_spec_value sv', 'sv.id=gss.spec_value_id', 'LEFT')
+                ->where('gss.goods_id', 'in', $multiSpecGoodsIds)
+                ->order('gss.goods_id asc, sp.id asc, sv.id asc')
+                ->select();
+            
+            // 按商品ID分组规格数据
+            foreach ($allSpecsResult as $spec) {
+                $specArray = is_array($spec) ? $spec : $spec->toArray();
+                $specsByGoods[$specArray['goods_id']][] = $specArray;
+            }
+        }
+        
+        // 一次性查询所有SKU的规格属性文本
+        $allSkuIds = [];
+        foreach ($skusByGoods as $skus) {
+            foreach ($skus as $sku) {
+                $allSkuIds[] = $sku['id'];
+            }
+        }
+        
+        $skuSpecTexts = [];
+        if (!empty($allSkuIds)) {
+            $skuSpecResults = Db::name('shop_goods_sku')
+                ->alias('sku')
+                ->field('sku.id, GROUP_CONCAT(sp.name,":",sv.value ORDER BY sp.id asc) as specs_text')
+                ->join('shop_goods_sku_spec gss', "FIND_IN_SET(gss.id, sku.spec_value_ids)", 'LEFT')
+                ->join('shop_spec sp', 'sp.id=gss.spec_id', 'LEFT')
+                ->join('shop_spec_value sv', 'sv.id=gss.spec_value_id', 'LEFT')
+                ->where('sku.id', 'in', $allSkuIds)
+                ->group('sku.id')
+                ->select();
+            
+            foreach ($skuSpecResults as $result) {
+                $resultArray = is_array($result) ? $result : $result->toArray();
+                $skuSpecTexts[$resultArray['id']] = $resultArray['specs_text'] ?: '';
+            }
+        }
+            
+        // 处理每个商品的详细信息(纯数据组装,无数据库查询)
+        foreach ($goodsData as &$item) {
             if ($item['image']) {
                 $item['image'] = cdnurl($item['image'], true);
             }
             
-            // 获取商品的第一个SKU ID(单规格商品通常只有一个SKU)
-            $sku = \app\common\model\Sku::where('goods_id', $item['id'])->find();
-            $item['sku_id'] = $sku ? $sku['id'] : 0;
+            // 获取商品的SKU信息
+            $skus = $skusByGoods[$item['id']] ?? [];
+            
+            if ($skus) {
+                // 获取第一个SKU ID(单规格商品通常只有一个SKU)
+                $item['sku_id'] = $skus[0]['id'];
+                
+                // 为每个SKU添加规格属性文本
+                foreach ($skus as &$sku) {
+                    $sku['specs_text'] = $skuSpecTexts[$sku['id']] ?? '';
+                }
+                $item['skus'] = $skus;
+                
+                // 如果是多规格商品,添加规格数据
+                if ($item['spec_type'] == 1) {
+                    $specs = $specsByGoods[$item['id']] ?? [];
+                    
+                    // 按规格分组构建规格数据结构
+                    $spec_groups = [];
+                    foreach ($specs as $spec) {
+                        if (!isset($spec_groups[$spec['spec_id']])) {
+                            $spec_groups[$spec['spec_id']]['id'] = $spec['spec_id'];
+                            $spec_groups[$spec['spec_id']]['name'] = $spec['spec_name'];
+                            $spec_groups[$spec['spec_id']]['type'] = $spec['spec_type'] == 2 ? 'custom' : 'basic';
+                            $spec_groups[$spec['spec_id']]['value'] = [];
+                        }
+                        $spec_groups[$spec['spec_id']]['value'][] = [
+                            'id' => $spec['spec_value_id'],
+                            'name' => $spec['value'],
+                            'image' => $spec['image'] ?: '',
+                            'description' => $spec['desc'] ?: ''
+                        ];
+                    }
+                    
+                    // 转换为数组格式,与前端渲染一致
+                    $item['spec'] = array_values($spec_groups);
+                } else {
+                    // 单规格商品,没有spec数据
+                    $item['spec'] = [];
+                }
+            } else {
+                $item['sku_id'] = 0;
+                $item['skus'] = [];
+                $item['spec'] = [];
+            }
         }
         
-        return json($list);
+        return json($goodsData);
     }
 
     /**

+ 11 - 339
application/common/Enum/ActivityEnum.php

@@ -6,343 +6,15 @@ namespace app\common\Enum;
  */
 class ActivityEnum
 {
-    // ============ 活动基础状态 ============
-    const ACTIVITY_STATUS_NOT_STARTED = 1;  // 未开始
-    const ACTIVITY_STATUS_ONGOING = 2;      // 进行中
-    const ACTIVITY_STATUS_ENDED = 3;        // 已结束
-    const ACTIVITY_STATUS_CANCELLED = 4;    // 已取消
-    const ACTIVITY_STATUS_SUSPENDED = 5;    // 已暂停
-    const ACTIVITY_STATUS_CLOSED = 6;       // 已关闭
-    const ACTIVITY_STATUS_DELETED = 7;      // 已删除
-    const ACTIVITY_STATUS_EXPIRED = 8;      // 已过期
-
-    // ============ 活动类型 ============
-    const ACTIVITY_TYPE_CONSUMPTION_LOTTERY = 1; // 消费抽奖
-
-    // ============ 开奖方式 ============
-    const LOTTERY_TYPE_INSTANT = 1;         // 即抽即中
-    const LOTTERY_TYPE_TIME = 2;            // 按时间开奖
-    const LOTTERY_TYPE_PEOPLE = 3;          // 按人数开奖
-
-    // ============ 用户群体类型 ============
-    const USER_LIMIT_ALL = 1;               // 全部会员
-    const USER_LIMIT_LEVEL = 2;             // 会员等级
-    const USER_LIMIT_TAG = 3;               // 会员标签
-
-    // ============ 引导样式 ============
-    const GUIDE_STYLE_DEFAULT = 1;          // 默认样式
-    const GUIDE_STYLE_CUSTOM = 2;           // 自定义
-
-    // ============ 奖品类型 ============
-    const PRIZE_TYPE_NO_PRIZE = 1;          // 未中奖
-    const PRIZE_TYPE_GOODS = 2;             // 实物奖品
-    const PRIZE_TYPE_POINTS = 3;            // 积分
-    const PRIZE_TYPE_BALANCE = 4;           // 余额
-    const PRIZE_TYPE_COUPON = 5;            // 优惠券
-    const PRIZE_TYPE_REDPACK = 6;           // 红包
-    const PRIZE_TYPE_CODE = 7;              // 兑换码
-    const PRIZE_TYPE_SHOP_GOODS = 8;        // 商城奖品
-
-    // ============ 奖品发放方式 ============
-    const DELIVER_TYPE_AUTO = 1;            // 自动发放
-    const DELIVER_TYPE_MANUAL = 2;          // 手动发放
-
-    // ============ 奖品发放状态 ============
-    const DELIVER_STATUS_PENDING = 0;       // 待发放
-    const DELIVER_STATUS_SUCCESS = 1;       // 已发放
-    const DELIVER_STATUS_FAILED = 2;        // 发放失败
-    const DELIVER_STATUS_CANCELLED = 3;     // 已取消
-
-    // ============ 参与条件类型 ============
-    const CONDITION_TYPE_BUY_GOODS = 1;     // 购买指定商品
-    const CONDITION_TYPE_ORDER_AMOUNT = 2;  // 单笔订单消费满额
-    const CONDITION_TYPE_RECHARGE_AMOUNT = 3; // 单次充值满额
-    const CONDITION_TYPE_TOTAL_AMOUNT = 4;  // 活动期间累计消费满额
-
-    // ============ 商品规则 ============
-    const GOODS_RULE_INCLUDE = 1;           // 指定商品参与
-    const GOODS_RULE_EXCLUDE = 2;           // 指定商品不可参与
-
-    // ============ 触发类型 ============
-    const TRIGGER_TYPE_BUY_GOODS = 1;       // 购买商品
-    const TRIGGER_TYPE_ORDER_CONSUME = 2;   // 订单消费
-    const TRIGGER_TYPE_RECHARGE = 3;        // 充值
-    const TRIGGER_TYPE_TOTAL_CONSUME = 4;   // 累计消费
-
-    // ============ 兑奖期限类型 ============
-    const REDEEM_EXPIRE_FOREVER = 1;        // 永久有效
-    const REDEEM_EXPIRE_FIXED = 2;          // 固定时长
-
-    /**
-     * 获取活动状态映射(页面显示用)
-     */
-    public static function getActivityStatusMap()
-    {
-        return [
-            self::ACTIVITY_STATUS_NOT_STARTED => '未开始',
-            self::ACTIVITY_STATUS_ONGOING => '进行中',
-            self::ACTIVITY_STATUS_ENDED => '已结束',
-            self::ACTIVITY_STATUS_CANCELLED => '已取消',
-            self::ACTIVITY_STATUS_SUSPENDED => '已暂停',
-        ];
-    }
-    
-    /**
-     * 获取全部活动状态映射(包含逻辑状态)
-     */
-    public static function getAllActivityStatusMap()
-    {
-        return [
-            self::ACTIVITY_STATUS_NOT_STARTED => '未开始',
-            self::ACTIVITY_STATUS_ONGOING => '进行中',
-            self::ACTIVITY_STATUS_ENDED => '已结束',
-            self::ACTIVITY_STATUS_CANCELLED => '已取消',
-            self::ACTIVITY_STATUS_SUSPENDED => '已暂停',
-            self::ACTIVITY_STATUS_CLOSED => '已关闭',
-            self::ACTIVITY_STATUS_DELETED => '已删除',
-            self::ACTIVITY_STATUS_EXPIRED => '已过期',
-        ];
-    }
-
-    /**
-     * 获取活动类型映射
-     */
-    public static function getActivityTypeMap()
-    {
-        return [
-            self::ACTIVITY_TYPE_CONSUMPTION_LOTTERY => '消费抽奖',
-        ];
-    }
-
-    /**
-     * 获取开奖方式映射
-     */
-    public static function getLotteryTypeMap()
-    {
-        return [
-            self::LOTTERY_TYPE_INSTANT => '即抽即中',
-            self::LOTTERY_TYPE_TIME => '按时间开奖',
-            self::LOTTERY_TYPE_PEOPLE => '按人数开奖',
-        ];
-    }
-
-    /**
-     * 获取用户群体类型映射
-     */
-    public static function getUserLimitTypeMap()
-    {
-        return [
-            self::USER_LIMIT_ALL => '全部会员',
-            self::USER_LIMIT_LEVEL => '会员等级',
-            self::USER_LIMIT_TAG => '会员标签',
-        ];
-    }
-
-    /**
-     * 获取引导样式映射
-     */
-    public static function getGuideStyleMap()
-    {
-        return [
-            self::GUIDE_STYLE_DEFAULT => '默认样式',
-            self::GUIDE_STYLE_CUSTOM => '自定义',
-        ];
-    }
-
-    /**
-     * 获取奖品类型映射
-     */
-    public static function getPrizeTypeMap()
-    {
-        return [
-            self::PRIZE_TYPE_NO_PRIZE => '未中奖',
-            self::PRIZE_TYPE_GOODS => '实物奖品',
-            self::PRIZE_TYPE_POINTS => '积分',
-            self::PRIZE_TYPE_BALANCE => '余额',
-            self::PRIZE_TYPE_COUPON => '优惠券',
-            self::PRIZE_TYPE_REDPACK => '红包',
-            self::PRIZE_TYPE_CODE => '兑换码',
-            self::PRIZE_TYPE_SHOP_GOODS => '商城奖品',
-        ];
-    }
-
-    /**
-     * 获取奖品默认图片映射
-     */
-    public static function getPrizeDefaultImageMap()
-    {
-        // 从配置文件获取图片路径
-        $config = config('site');
-        
-        return [
-            self::PRIZE_TYPE_NO_PRIZE => $config['prize_losing_lottery'] ?? '/assets/img/avatar.png',
-            self::PRIZE_TYPE_GOODS => $config['prize_goods'] ?? '/assets/img/package.png',
-            self::PRIZE_TYPE_POINTS => $config['prize_credit'] ?? '/assets/img/circle.png',
-            self::PRIZE_TYPE_BALANCE => $config['prize_balance'] ?? '/assets/img/circle.png',
-            self::PRIZE_TYPE_COUPON => $config['prize_coupon'] ?? '/assets/img/circle.png',
-            self::PRIZE_TYPE_REDPACK => $config['prize_redbag'] ?? '/assets/img/circle.png',
-            self::PRIZE_TYPE_CODE => $config['prize_code'] ?? '/assets/img/circle.png',
-            self::PRIZE_TYPE_SHOP_GOODS => $config['prize_shop_goods'] ?? '/assets/img/package.png',
-        ];
-    }
-
-    /**
-     * 获取奖品发放方式映射
-     */
-    public static function getDeliverTypeMap()
-    {
-        return [
-            self::DELIVER_TYPE_AUTO => '自动发放',
-            self::DELIVER_TYPE_MANUAL => '手动发放',
-        ];
-    }
-
-    /**
-     * 获取奖品发放状态映射
-     */
-    public static function getDeliverStatusMap()
-    {
-        return [
-            self::DELIVER_STATUS_PENDING => '待发放',
-            self::DELIVER_STATUS_SUCCESS => '已发放',
-            self::DELIVER_STATUS_FAILED => '发放失败',
-            self::DELIVER_STATUS_CANCELLED => '已取消',
-        ];
-    }
-
-    /**
-     * 获取参与条件类型映射
-     */
-    public static function getConditionTypeMap()
-    {
-        return [
-            self::CONDITION_TYPE_BUY_GOODS => '购买指定商品',
-            self::CONDITION_TYPE_ORDER_AMOUNT => '单笔订单消费满N元',
-            self::CONDITION_TYPE_RECHARGE_AMOUNT => '单次充值金额满N元',
-            self::CONDITION_TYPE_TOTAL_AMOUNT => '活动期间累计消费N元',
-        ];
-    }
-
-    /**
-     * 获取商品规则映射
-     */
-    public static function getGoodsRuleMap()
-    {
-        return [
-            self::GOODS_RULE_INCLUDE => '指定商品参与',
-            self::GOODS_RULE_EXCLUDE => '指定商品不可参与',
-        ];
-    }
-
-    /**
-     * 获取触发类型映射
-     */
-    public static function getTriggerTypeMap()
-    {
-        return [
-            self::TRIGGER_TYPE_BUY_GOODS => '购买商品',
-            self::TRIGGER_TYPE_ORDER_CONSUME => '订单消费',
-            self::TRIGGER_TYPE_RECHARGE => '充值',
-            self::TRIGGER_TYPE_TOTAL_CONSUME => '累计消费',
-        ];
-    }
-
-    /**
-     * 获取兑奖期限类型映射
-     */
-    public static function getRedeemExpireTypeMap()
-    {
-        return [
-            self::REDEEM_EXPIRE_FOREVER => '永久有效',
-            self::REDEEM_EXPIRE_FIXED => '固定时长',
-        ];
-    }
-
-    /**
-     * 获取活动状态文本
-     */
-    public static function getActivityStatusText($status)
-    {
-        $map = self::getAllActivityStatusMap();
-        return $map[$status] ?? '未知';
-    }
-
-    /**
-     * 获取奖品类型文本
-     */
-    public static function getPrizeTypeText($type)
-    {
-        $map = self::getPrizeTypeMap();
-        return $map[$type] ?? '未知';
-    }
-
-    /**
-     * 获取开奖方式文本
-     */
-    public static function getLotteryTypeText($type)
-    {
-        $map = self::getLotteryTypeMap();
-        return $map[$type] ?? '未知';
-    }
-
-    /**
-     * 获取条件类型文本
-     */
-    public static function getConditionTypeText($type)
-    {
-        $map = self::getConditionTypeMap();
-        return $map[$type] ?? '未知';
-    }
-
-    /**
-     * 验证活动状态是否有效(包含所有状态)
-     */
-    public static function isValidActivityStatus($status)
-    {
-        return array_key_exists($status, self::getAllActivityStatusMap());
-    }
-
-    /**
-     * 判断是否为可在页面显示的状态
-     */
-    public static function isDisplayableStatus($status)
-    {
-        return array_key_exists($status, self::getActivityStatusMap());
-    }
-
-    /**
-     * 判断是否为逻辑状态(不在页面显示)
-     */
-    public static function isLogicalStatus($status)
-    {
-        return in_array($status, [
-            self::ACTIVITY_STATUS_CLOSED,
-            self::ACTIVITY_STATUS_DELETED,
-            self::ACTIVITY_STATUS_EXPIRED
-        ]);
-    }
-
-    /**
-     * 验证奖品类型是否有效
-     */
-    public static function isValidPrizeType($type)
-    {
-        return array_key_exists($type, self::getPrizeTypeMap());
-    }
-
-    /**
-     * 验证开奖方式是否有效
-     */
-    public static function isValidLotteryType($type)
-    {
-        return array_key_exists($type, self::getLotteryTypeMap());
-    }
-
-    /**
-     * 验证条件类型是否有效
-     */
-    public static function isValidConditionType($type)
-    {
-        return array_key_exists($type, self::getConditionTypeMap());
-    }
+    // ============ 活动基础状态 活动状态:0=未开始,1=进行中,2=已结束,3=手动停止 ============
+    const ACTIVITY_STATUS_NOT_STARTED = 0;  // 未开始
+    const ACTIVITY_STATUS_ONGOING = 1;      // 进行中
+    const ACTIVITY_STATUS_ENDED = 2;        // 已结束
+    const ACTIVITY_STATUS_CANCELLED = 3;    // 手动停止/已取消
+    const ACTIVITY_STATUS_SUSPENDED = 4;    // 已暂停
+    const ACTIVITY_STATUS_CLOSED = 5;       // 已关闭
+    const ACTIVITY_STATUS_DELETED = 6;      // 已删除
+    const ACTIVITY_STATUS_EXPIRED = 7;      // 已过期
+
+ 
 } 

+ 228 - 176
public/assets/js/backend/marketing/discount.js

@@ -350,136 +350,140 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
             if(goodsIds) {
                 console.log('开始加载商品数据,商品IDs:', goodsIds);
                 
-                // 加载已选择的商品数据
-                                 $.ajax({
-                     url: Fast.api.fixurl('shop/goods/get_goods_by_ids'),
-                     type: 'POST',
-                     dataType: 'json',
-                     data: {ids: goodsIds},
-                     headers: {
-                         'X-Requested-With': 'XMLHttpRequest'
-                     },
-                                         success: function(ret, textStatus, jqXHR) {
-                         console.log('商品数据加载结果:', {
-                             ret: ret,
-                             retType: typeof ret,
-                             retIsArray: Array.isArray(ret),
-                             retCode: ret ? ret.code : null,
-                             retData: ret ? ret.data : null,
-                             retDataIsArray: ret && ret.data ? Array.isArray(ret.data) : false
-                         });
-                         
-                         // 根据实际返回的数据结构来处理
-                         var goodsData = [];
-                         
-                         // 情况1: 标准FastAdmin格式,数据在ret.data中
-                         if (ret && ret.code === 1 && ret.data && Array.isArray(ret.data)) {
-                             goodsData = ret.data;
-                             console.log('使用标准格式数据,数量:', goodsData.length);
-                         }
-                         // 情况2: 直接返回商品数组
-                         else if (Array.isArray(ret)) {
-                             goodsData = ret;
-                             console.log('使用直接数组数据,数量:', goodsData.length);
-                         }
-                         // 情况3: 如果ret.code不等于1,说明有错误
-                         else if (ret && ret.code !== undefined && ret.code !== 1) {
-                             console.error('接口返回错误:', ret.msg || '未知错误');
-                             Layer.msg(ret.msg || '加载商品数据失败', {icon: 2});
-                             return;
-                         }
-                         
-                         if(goodsData && goodsData.length > 0) {
-                             console.log('接口返回商品数据成功,商品数量:', goodsData.length);
-                             
-                             // 如果有goods_info数据,则合并折扣信息
-                             if (goodsInfo && goodsInfo.length > 0) {
-                                 console.log('合并goods_info中的折扣数据');
-                                 // 将goods_info中的折扣数据合并到接口返回的商品数据中
-                                 $.each(goodsData, function(index, goods) {
-                                     var matchedInfo = null;
-                                     $.each(goodsInfo, function(infoIndex, info) {
-                                         if (info.goods_id == goods.id) {
-                                             matchedInfo = info;
-                                             return false; // 跳出循环
-                                         }
-                                     });
-                                     
-                                     if (matchedInfo) {
-                                         // 合并折扣信息到商品数据
-                                         goods.discount_info = matchedInfo;
-                                         console.log('商品', goods.id, '合并折扣信息:', matchedInfo);
-                                     }
-                                 });
-                             }
-                             
-                             // 使用共享的商品渲染方法,传入编辑模式标识
-                             Controller.renderSelectedGoods(goodsData, true);
-                         } else {
-                             console.warn('没有获取到商品数据或数据为空');
-                             
-                             // 如果接口没有返回数据,但有goods_info,尝试直接渲染
-                             if (goodsInfo && goodsInfo.length > 0) {
-                                 console.log('尝试从goods_info构造商品数据进行渲染');
-                                 // 这里可以实现从goods_info重构商品数据的逻辑
-                                 // 不过通常情况下,如果有goods_ids,接口应该能返回商品基础数据
-                             }
-                         }
-                     },
-                     error: function(jqXHR, textStatus, errorThrown) {
-                         console.log('Ajax error回调触发,尝试解析响应:', {
-                             status: jqXHR.status,
-                             statusText: jqXHR.statusText,
-                             textStatus: textStatus,
-                             errorThrown: errorThrown,
-                             responseText: jqXHR.responseText
-                         });
-                         
-                         // 尝试解析响应文本,可能是有效的JSON但格式不符合预期
-                         try {
-                             var responseData = JSON.parse(jqXHR.responseText);
-                             console.log('解析响应数据成功:', responseData);
-                             
-                             if (Array.isArray(responseData)) {
-                                 console.log('响应是商品数组,尝试渲染:', responseData.length);
-                                 
-                                 // 如果有goods_info数据,则合并折扣信息
-                                 if (goodsInfo && goodsInfo.length > 0) {
-                                     console.log('合并goods_info中的折扣数据');
-                                     $.each(responseData, function(index, goods) {
-                                         var matchedInfo = null;
-                                         $.each(goodsInfo, function(infoIndex, info) {
-                                             if (info.goods_id == goods.id) {
-                                                 matchedInfo = info;
-                                                 return false;
-                                             }
-                                         });
-                                         
-                                         if (matchedInfo) {
-                                             goods.discount_info = matchedInfo;
-                                             console.log('商品', goods.id, '合并折扣信息:', matchedInfo);
-                                         }
-                                     });
-                                 }
-                                 
-                                 // 使用共享的商品渲染方法
-                                 Controller.renderSelectedGoods(responseData, true);
-                                 return; // 成功处理,不显示错误信息
-                             }
-                         } catch (e) {
-                             console.error('解析响应数据失败:', e);
-                         }
-                         
-                         // 真正的错误情况
-                         console.error('加载商品数据失败:', {
-                             status: jqXHR.status,
-                             statusText: jqXHR.statusText,
-                             textStatus: textStatus,
-                             errorThrown: errorThrown
-                         });
-                         Layer.msg('加载商品数据失败', {icon: 2});
-                     }
-                 });
+                // 检查是否有预设的goodsData(从服务器端传递)
+                if (typeof goodsData !== 'undefined' && goodsData && goodsData.length > 0) {
+                    console.log('使用服务器端预设的商品数据,数量:', goodsData.length);
+                    
+                    // 处理服务器端返回的活动折扣数据
+                    $.each(goodsData, function(index, goods) {
+                        // 处理SKU中的活动折扣数据
+                        if (goods.skus && goods.skus.length > 0) {
+                            $.each(goods.skus, function(skuIndex, sku) {
+                                // 如果SKU有活动折扣数据,构造discount_info
+                                if (sku.activity_discount !== undefined) {
+                                    if (!goods.discount_info) {
+                                        goods.discount_info = {
+                                            goods_id: goods.id,
+                                            spec_type: goods.spec_type
+                                        };
+                                    }
+                                    
+                                    if (goods.spec_type == 0) {
+                                        // 单规格商品
+                                        goods.discount_info.sku_id = sku.id;
+                                        goods.discount_info.discount = sku.activity_discount;
+                                        goods.discount_info.discount_price = sku.activity_discount_price;
+                                        goods.discount_info.discount_stocks = sku.activity_stocks;
+                                    } else if (goods.spec_type == 1) {
+                                        // 多规格商品
+                                        if (!goods.discount_info.spec) {
+                                            goods.discount_info.spec = [];
+                                        }
+                                        goods.discount_info.spec.push({
+                                            sku_id: sku.id,
+                                            discount: sku.activity_discount,
+                                            discount_price: sku.activity_discount_price,
+                                            discount_stocks: sku.activity_stocks
+                                        });
+                                    }
+                                }
+                            });
+                        }
+                        
+                        // 处理多规格商品的已选择规格数据
+                        if (goods.spec_type == 1 && goods.selected_discount_data) {
+                            console.log('商品', goods.id, '已选择的规格折扣数据:', goods.selected_discount_data);
+                            
+                            // 如果没有discount_info,从selected_discount_data构建
+                            if (!goods.discount_info) {
+                                goods.discount_info = {
+                                    goods_id: goods.id,
+                                    spec_type: goods.spec_type,
+                                    spec: goods.selected_discount_data.spec
+                                };
+                            }
+                        }
+                    });
+                    
+                    console.log('处理后的商品数据(包含活动折扣信息):', goodsData);
+                    
+                    // 使用共享的商品渲染方法,传入编辑模式标识
+                    Controller.renderSelectedGoods(goodsData, true);
+                } else {
+                    // 如果没有预设数据,则通过AJAX加载
+                    console.log('没有预设数据,通过AJAX加载商品数据');
+                    $.ajax({
+                        url: Fast.api.fixurl('shop/goods/get_goods_by_ids'),
+                        type: 'POST',
+                        dataType: 'json',
+                        data: {ids: goodsIds},
+                        headers: {
+                            'X-Requested-With': 'XMLHttpRequest'
+                        },
+                        success: function(ret, textStatus, jqXHR) {
+                            console.log('AJAX商品数据加载结果:', ret);
+                            
+                            // 根据实际返回的数据结构来处理
+                            var goodsData = [];
+                            
+                            // 情况1: 标准FastAdmin格式,数据在ret.data中
+                            if (ret && ret.code === 1 && ret.data && Array.isArray(ret.data)) {
+                                goodsData = ret.data;
+                                console.log('使用标准格式数据,数量:', goodsData.length);
+                            }
+                            // 情况2: 直接返回商品数组
+                            else if (Array.isArray(ret)) {
+                                goodsData = ret;
+                                console.log('使用直接数组数据,数量:', goodsData.length);
+                            }
+                            // 情况3: 如果ret.code不等于1,说明有错误
+                            else if (ret && ret.code !== undefined && ret.code !== 1) {
+                                console.error('接口返回错误:', ret.msg || '未知错误');
+                                Layer.msg(ret.msg || '加载商品数据失败', {icon: 2});
+                                return;
+                            }
+                            
+                            if(goodsData && goodsData.length > 0) {
+                                console.log('AJAX返回商品数据成功,商品数量:', goodsData.length);
+                                
+                                // 如果有goods_info数据,则合并折扣信息
+                                if (goodsInfo && goodsInfo.length > 0) {
+                                    console.log('合并goods_info中的折扣数据');
+                                    // 将goods_info中的折扣数据合并到接口返回的商品数据中
+                                    $.each(goodsData, function(index, goods) {
+                                        var matchedInfo = null;
+                                        $.each(goodsInfo, function(infoIndex, info) {
+                                            if (info.goods_id == goods.id) {
+                                                matchedInfo = info;
+                                                return false; // 跳出循环
+                                            }
+                                        });
+                                        
+                                        if (matchedInfo) {
+                                            // 合并折扣信息到商品数据
+                                            goods.discount_info = matchedInfo;
+                                            console.log('商品', goods.id, '合并折扣信息:', matchedInfo);
+                                        }
+                                    });
+                                }
+                                
+                                // 使用共享的商品渲染方法,传入编辑模式标识
+                                Controller.renderSelectedGoods(goodsData, true);
+                            } else {
+                                console.warn('没有获取到商品数据或数据为空');
+                            }
+                        },
+                        error: function(jqXHR, textStatus, errorThrown) {
+                            console.error('加载商品数据失败:', {
+                                status: jqXHR.status,
+                                statusText: jqXHR.statusText,
+                                textStatus: textStatus,
+                                errorThrown: errorThrown
+                            });
+                            Layer.msg('加载商品数据失败', {icon: 2});
+                        }
+                    });
+                }
             } else {
                 console.log('没有商品IDs,跳过商品数据加载');
             }
@@ -990,6 +994,8 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
             $.each(data, function(index, item) {
                 // 检查是否有合并的折扣信息
                 var hasDiscountInfo = item.discount_info;
+                // 检查是否有服务器端的已选择规格数据
+                var hasSelectedData = item.selected_discount_data;
                 
                 if (item.spec_type == 0) {
                     if (hasDiscountInfo) {
@@ -1016,40 +1022,63 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                         };
                         console.log('初始化单规格商品:', item.id, 'SKU ID:', skuId, '库存:', currentStocks);
                     }
-                } else if (item.spec_type == 1 && hasDiscountInfo && hasDiscountInfo.spec) {
-                    // 多规格商品,处理规格折扣信息
-                    var specs = {};
-                    var summary = {
-                        participate_count: 0,
-                        avg_discount: 0,
-                        total_stocks: 0
-                    };
-                    
-                    var totalDiscount = 0;
-                    $.each(hasDiscountInfo.spec, function(specIndex, spec) {
-                        specs[spec.sku_id] = {
-                            id: spec.sku_id,
-                            participate: true,
-                            discount: spec.discount,
-                            discount_price: spec.discount_price,
-                            stocks: spec.discount_stocks
+                } else if (item.spec_type == 1) {
+                    // 多规格商品处理
+                    if (hasSelectedData) {
+                        // 优先使用服务器端的已选择数据
+                        var specs = {};
+                        $.each(hasSelectedData.spec, function(specIndex, spec) {
+                            specs[spec.sku_id] = {
+                                id: spec.sku_id,
+                                participate: true,
+                                discount: spec.discount,
+                                discount_price: spec.discount_price,
+                                stocks: spec.discount_stocks
+                            };
+                        });
+                        
+                        discountData[item.id] = {
+                            id: item.id,
+                            specs: specs,
+                            summary: hasSelectedData.summary
                         };
                         
-                        summary.participate_count++;
-                        totalDiscount += parseFloat(spec.discount);
-                        summary.total_stocks += parseInt(spec.discount_stocks);
-                    });
-                    
-                    summary.avg_discount = summary.participate_count > 0 ? 
-                        (totalDiscount / summary.participate_count).toFixed(1) : '0';
-                    
-                    discountData[item.id] = {
-                        id: item.id,
-                        specs: specs,
-                        summary: summary
-                    };
-                    
-                    console.log('使用已保存的多规格商品折扣信息:', item.id, discountData[item.id]);
+                        console.log('使用服务器端已选择的多规格商品数据:', item.id, discountData[item.id]);
+                    } else if (hasDiscountInfo && hasDiscountInfo.spec) {
+                        // 使用合并的折扣信息
+                        var specs = {};
+                        var summary = {
+                            participate_count: 0,
+                            avg_discount: 0,
+                            total_stocks: 0
+                        };
+                        
+                        var totalDiscount = 0;
+                        $.each(hasDiscountInfo.spec, function(specIndex, spec) {
+                            specs[spec.sku_id] = {
+                                id: spec.sku_id,
+                                participate: true,
+                                discount: spec.discount,
+                                discount_price: spec.discount_price,
+                                stocks: spec.discount_stocks
+                            };
+                            
+                            summary.participate_count++;
+                            totalDiscount += parseFloat(spec.discount);
+                            summary.total_stocks += parseInt(spec.discount_stocks);
+                        });
+                        
+                        summary.avg_discount = summary.participate_count > 0 ? 
+                            (totalDiscount / summary.participate_count).toFixed(1) : '0';
+                        
+                        discountData[item.id] = {
+                            id: item.id,
+                            specs: specs,
+                            summary: summary
+                        };
+                        
+                        console.log('使用已保存的多规格商品折扣信息:', item.id, discountData[item.id]);
+                    }
                 }
             });
             
@@ -1070,7 +1099,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                     
                     if (goodsId && discountData[goodsId]) {
                         // 检查是否是多规格商品且有规格数据
-                        if (discountData[goodsId].specs) {
+                        if (discountData[goodsId].specs || discountData[goodsId].spec) {
                             console.log('回显多规格商品数据:', goodsId, discountData[goodsId]);
                             
                             // 设置多规格商品的数据属性
@@ -1082,19 +1111,42 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function
                             if ($btn.length > 0) {
                                 $btn.html('规格折扣设置 <span class="label label-success">已设置</span>');
                                 
-                                                                 // 显示汇总信息
-                                 if (discountData[goodsId].summary) {
-                                     var summary = discountData[goodsId].summary;
-                                     var infoText = '<i class="fa fa-check-circle text-success"></i> 已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件';
-                                     
-                                     // 检查是否已有汇总信息区域
-                                     var $infoArea = $row.find('.spec-discount-info');
-                                     if ($infoArea.length > 0) {
-                                         $infoArea.html(infoText);
-                                     } else {
-                                         $btn.parent().append('<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>');
-                                     }
-                                 }
+                                // 显示汇总信息
+                                var summary = discountData[goodsId].summary;
+                                if (summary) {
+                                    var infoText = '<i class="fa fa-check-circle text-success"></i> 已设置' + summary.participate_count + '个规格,平均' + summary.avg_discount + '折,共' + summary.total_stocks + '件';
+                                    
+                                    // 检查是否已有汇总信息区域
+                                    var $infoArea = $row.find('.spec-discount-info');
+                                    if ($infoArea.length > 0) {
+                                        $infoArea.html(infoText);
+                                    } else {
+                                        $btn.parent().append('<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>');
+                                    }
+                                } else {
+                                    // 如果没有summary,计算一个
+                                    var specs = discountData[goodsId].specs || discountData[goodsId].spec || [];
+                                    if (Array.isArray(specs) && specs.length > 0) {
+                                        var totalDiscount = 0;
+                                        var totalStocks = 0;
+                                        var count = specs.length;
+                                        
+                                        $.each(specs, function(i, spec) {
+                                            totalDiscount += parseFloat(spec.discount || 0);
+                                            totalStocks += parseInt(spec.discount_stocks || spec.stocks || 0);
+                                        });
+                                        
+                                        var avgDiscount = count > 0 ? (totalDiscount / count).toFixed(1) : '0';
+                                        var infoText = '<i class="fa fa-check-circle text-success"></i> 已设置' + count + '个规格,平均' + avgDiscount + '折,共' + totalStocks + '件';
+                                        
+                                        var $infoArea = $row.find('.spec-discount-info');
+                                        if ($infoArea.length > 0) {
+                                            $infoArea.html(infoText);
+                                        } else {
+                                            $btn.parent().append('<div class="spec-discount-info text-muted" style="margin-top:5px;">' + infoText + '</div>');
+                                        }
+                                    }
+                                }
                             }
                         }
                     }