Browse Source

Merge branch 'redesign‌-260706' into dev

shizhongqi 1 ngày trước cách đây
mục cha
commit
041fd3d84d

+ 4 - 3
app-ghs/controllers/ApplyController.php

@@ -3,9 +3,7 @@
 namespace ghs\controllers;
 
 use biz\shop\classes\ShopClass;
-use biz\sj\classes\SjClass;
 use bizGhs\admin\classes\AdminClass;
-use bizGhs\admin\services\AdminService;
 use bizHd\saas\services\ApplyService;
 use bizHd\wx\classes\WxOpenClass;
 use common\components\dict;
@@ -89,7 +87,7 @@ class ApplyController extends BaseController
         util::success($data);
     }
 
-    //申请试用,花店添加新客户 ssh 2021.1.8
+    //申请试用
     public function actionRegister()
     {
         $post = Yii::$app->request->post();
@@ -97,6 +95,8 @@ class ApplyController extends BaseController
         $mobile = $post['mobile'] ?? '';
         $fillMobile = $post['fillMobile'] ?? 1;
         $miniOpenId = $post['miniOpenId'] ?? '';
+        // 是否给同步创建的零售店复制样例模板,落库 xhApply.genTemplate 供审核通过后使用
+        $post['genTemplate'] = intval($post['genTemplate'] ?? 0) ? 1 : 0;
         if (empty($mobile)) {
             util::fail('请填写手机号');
         }
@@ -147,6 +147,7 @@ class ApplyController extends BaseController
                     $apply->name = $shopName;
                     $apply->style = 2;
                     $apply->status = 1;
+                    $apply->genTemplate = $post['genTemplate'];
                     $apply->save();
                     $transaction->commit();
                     noticeUtil::push("{$shopName} 手机号 {$mobile} 申请开通批发店", '15280215347');

+ 5 - 5
app-hd/controllers/ApplyController.php

@@ -228,10 +228,9 @@ class ApplyController extends BaseController
     //申请试用 ssh 2020.1.11
     public function actionRegister()
     {
-        $connection = Yii::$app->db;
-        $transaction = $connection->beginTransaction();
-
         $post = Yii::$app->request->post();
+        // 是否给新开零售店复制样例模板,落库后同请求内 pass 会带到 initHdBaseInfo
+        $post['genTemplate'] = intval($post['genTemplate'] ?? 0) ? 1 : 0;
 
         //前期限制只有批发店邀请了才能注册
         $ghsShopAdminId = $post['ghsShopAdminId'] ?? 0;
@@ -272,6 +271,8 @@ class ApplyController extends BaseController
             util::fail('手机号已经被使用');
         }
 
+        $connection = Yii::$app->db;
+        $transaction = $connection->beginTransaction();
         try {
             $post['adminId'] = $this->adminId;
             $authCode = $post['authCode'] ?? '';
@@ -328,7 +329,6 @@ class ApplyController extends BaseController
 
             //增加或更新申请
             $respond = ApplyService::replaceRetail($post);
-
             $id = $respond['id'] ?? 0;
             if (empty($id)) {
                 util::fail('申请失败');
@@ -430,7 +430,7 @@ class ApplyController extends BaseController
         } catch (\Exception $exception) {
             $transaction->rollBack();
             $message = $exception->getMessage() ?? '';
-            Yii::info("申请报错:" . $message);
+            Yii::error("申请报错:" . $message);
             noticeUtil::push("花店注册失败,手机号{$mobile},原因:" . $message, '15280215347');
             util::fail('提交失败');
         }

+ 2 - 3
biz-ghs/merchant/services/MerchantService.php

@@ -66,7 +66,7 @@ class MerchantService extends BaseService
         $sjId = $sj->id;
         $sjName = $sj->name ?? 0;
         $mobile = $applyData['mobile'] ?? '';
-        $ptStyle = $applyData['style'] ?? dict::getDict('ptStyle', 'hd');
+        $ptStyle = $applyData['style'] ?? dict::getDict('ptStyle', 'ghs');
 
         if (!empty($applyId) && $applyThis) {
             ApplyClass::updateById($applyId, ['sjId' => $sjId]);
@@ -111,10 +111,9 @@ class MerchantService extends BaseService
             'gradeList' => '1_2000_0.9I2_5000_0.88I3_10000_0.85I4_20000_0.8',//1 级会员需要满 2000 积分 购物享9折;2 级会员需要满 5000 积分 购物享88折
         ];
         MerchantExtendClass::add($extendData);
-
         MerchantInitClass::add(['sjId' => $sjId]);
 
-        //给10天时间
+        //给10天试用时间
         $deadTime = time()+864000;
         //创建门店
         $shopData = [

+ 28 - 4
biz-hd/merchant/services/SjService.php

@@ -14,17 +14,23 @@ use bizHd\merchant\classes\SjInitClass;
 use bizHd\recharge\classes\RechargeSqClass;
 use bizHd\saas\classes\ApplyClass;
 use bizHd\shop\classes\ShopClass;
+use bizHd\shop\classes\ShopTemplateClass;
 use bizHd\user\classes\UserClass;
 use common\components\dict;
-use common\components\noticeUtil;
 use common\components\stringUtil;
 use Yii;
 
 class SjService extends BaseService
 {
-
     public static $baseFile = '\bizHd\merchant\classes\SjClass';
 
+    /**
+     * 初始化零售商家基础信息
+     * @param array $applyData 申请数据(含 genTemplate:1 表示复制样例模板)
+     * @param object $main 主数据
+     * @param bool $applyOpen 是否开启申请:true 不需要申请,false 需要申请
+     * @return array 返回商家和店铺信息
+     */
     public static function initHdBaseInfo($applyData, $main, $applyOpen = false)
     {
         $applyId = $applyData['id'] ?? 0;
@@ -105,7 +111,6 @@ class SjService extends BaseService
             'gradeList' => '1_2000_0.9I2_5000_0.88I3_10000_0.85I4_20000_0.8',//1 级会员需要满 2000 积分 购物享9折;2 级会员需要满 5000 积分 购物享88折
         ];
         SjExtendClass::add($extendData);
-
         SjInitClass::add(['sjId' => $sjId]);
 
         $onlyCg = 1;
@@ -179,8 +184,27 @@ class SjService extends BaseService
         RechargeSqClass::initData($shopInfo);
         //会员等级初始化
         MemberLevelClass::initData($shopInfo);
+        //零售商店首页及商品数据初始化:勾选生成模板时,按环境写死的模板店复制样例数据
+        $isProduction = getenv('YII_ENV') == 'production';
+        if ($isProduction) {
+            // 生产环境下的模板店,此 mainId/shopId 写死,不考虑配置化
+            $tplMainId = 1;
+            $tplShopId = 1;
+        } else {
+            // 测试环境下的模板店,此 mainId/shopId 写死,不考虑配置化
+            $tplMainId = 1107;
+            $tplShopId = 37064;
+        }
+        if (intval($applyData['genTemplate'] ?? 0) === 1) {
+            try {
+                ShopTemplateClass::copyTemplateData($tplMainId, $tplShopId, $shopInfo);
+            } catch (\Throwable $e) {
+                // 模板复制失败不阻断开店主流程,新店仍可正常使用
+                Yii::error('复制零售店样例模板失败: ' . $e->getMessage());
+            }
+        }
 
         return ['sj' => $sj, 'shop' => $shopInfo];
     }
 
-}
+}

+ 0 - 8
biz-hd/saas/services/ApplyService.php

@@ -3,24 +3,16 @@
 namespace bizHd\saas\services;
 
 use biz\sj\classes\SjClass;
-use bizHd\ad\classes\AdClass;
-use bizHd\admin\classes\AdminClass;
 use bizHd\base\services\BaseService;
-use bizGhs\custom\classes\CustomClass;
 use biz\shop\classes\ShopAdminClass;
 use biz\sj\classes\MerchantClass;
-use bizHd\goods\classes\CategoryClass;
-use bizHd\goods\classes\GoodsSettingClass;
-use bizHd\item\services\ItemService;
 use bizHd\merchant\classes\ShopClass;
 use bizHd\merchant\services\SjService;
 use bizHd\saas\classes\ApplyClass;
 use bizHd\saas\classes\ApplyExtendClass;
-use biz\sj\services\MerchantService;
 use bizHd\shop\classes\MainClass;
 use common\components\dict;
 use common\components\imgUtil;
-use common\components\noticeUtil;
 use common\components\stringUtil;
 use common\components\util;
 

+ 493 - 0
biz-hd/shop/classes/ShopTemplateClass.php

@@ -0,0 +1,493 @@
+<?php
+
+/**
+ * 零售店开店样例模板复制
+ * 谁用:SjService::initHdBaseInfo 在申请勾选「生成样例模板」后调用
+ * 解决问题:把指定模板店的首页配置、分类、使用场景、商品、秒杀数据复制给新开零售店,并重写关联 ID
+ */
+
+namespace bizHd\shop\classes;
+
+use bizHd\base\classes\BaseClass;
+use bizHd\goods\classes\CategoryClass;
+use bizHd\goods\classes\GoodsCategoryClass;
+use bizHd\goods\classes\GoodsClass;
+use bizHd\goods\classes\GoodsUseCaseClass;
+use bizHd\goods\classes\KindClass;
+use bizHd\goods\classes\UseCaseClass;
+use bizHd\homePageConfig\classes\HomePageConfigClass;
+use bizHd\homePageConfig\classes\HomePageModuleConfigClass;
+use bizHd\seckill\classes\SeckillActivityClass;
+use bizHd\seckill\classes\SeckillGoodsClass;
+use Yii;
+
+class ShopTemplateClass extends BaseClass
+{
+    /**
+     * 从模板店复制零售店样例数据到新店
+     * @param int $tplMainId 模板店 mainId(按环境写死)
+     * @param int $tplShopId 模板店 shopId(按环境写死)
+     * @param object $shopInfo 新创建的门店对象,需含 id/mainId/sjId
+     * @return bool
+     */
+    public static function copyTemplateData($tplMainId, $tplShopId, $shopInfo)
+    {
+        $tplMainId = intval($tplMainId);
+        $tplShopId = intval($tplShopId);
+        $newMainId = intval($shopInfo->mainId ?? 0);
+        $newShopId = intval($shopInfo->id ?? 0);
+        $newSjId = intval($shopInfo->sjId ?? 0);
+        if ($tplMainId <= 0 || $tplShopId <= 0 || $newMainId <= 0 || $newShopId <= 0) {
+            Yii::error('复制零售店样例模板参数无效');
+            return false;
+        }
+
+        $newShop = [
+            'mainId' => $newMainId,
+            'shopId' => $newShopId,
+            'sjId' => $newSjId,
+        ];
+
+        // 已有开店事务时 Yii2 会创建保存点;独立调用时则开启新事务。
+        // 任一步骤失败都只回滚模板数据,避免外层继续提交残缺的分类、商品或首页配置。
+        $transaction = Yii::$app->db->beginTransaction();
+        try {
+            // 分类必须先复制:商品分类关联、首页金刚区/轮播都依赖分类 ID 映射
+            $categoryMap = self::copyCategories($tplMainId, $newShop);
+            $useCaseMap = self::copyUseCases($tplMainId, $tplShopId, $newShop);
+            $kindMap = self::buildKindMap($tplMainId, $newMainId);
+            $goodsMap = self::copyGoods($tplMainId, $tplShopId, $newShop, $kindMap);
+            self::copyGoodsCategories($tplMainId, $newShop, $goodsMap, $categoryMap);
+            self::copyUseCaseRelations($tplMainId, $newShop, $goodsMap, $useCaseMap);
+            $activityMap = self::copySeckillActivities($tplMainId, $tplShopId, $newShop);
+            self::copySeckillGoods($tplMainId, $tplShopId, $newShop, $activityMap, $goodsMap);
+            self::copyHomePageConfig($tplShopId, $newShop, $goodsMap, $categoryMap, $useCaseMap);
+            $transaction->commit();
+            return true;
+        } catch (\Throwable $e) {
+            $transaction->rollBack();
+            throw $e;
+        }
+    }
+
+    /**
+     * 删掉开店时初始化的默认分类,再整份复制模板店分类
+     * 为什么先删:ShopClass::addShop 已写入花束/花篮/永生花/绿植,勾选模板后以模板店分类为准
+     * @param int $tplMainId
+     * @param array $newShop
+     * @return array 旧分类id => 新分类id
+     */
+    protected static function copyCategories($tplMainId, $newShop)
+    {
+        $map = [];
+        CategoryClass::deleteByCondition(['mainId' => $newShop['mainId']]);
+        $list = CategoryClass::getAllByCondition(['mainId' => $tplMainId, 'delStatus' => 0], 'id ASC');
+        if (empty($list)) {
+            return $map;
+        }
+        foreach ($list as $row) {
+            $oldId = intval($row['id'] ?? 0);
+            $payload = self::prepareCopyRow($row, $newShop, ['goodsNum']);
+            $payload['goodsNum'] = 0;
+            $created = CategoryClass::add($payload, true);
+            $newId = intval($created->id ?? 0);
+            if ($oldId > 0 && $newId > 0) {
+                $map[$oldId] = $newId;
+            }
+        }
+        return $map;
+    }
+
+    /**
+     * 复制使用场景,建立旧 useCaseId => 新 useCaseId 映射
+     * @param int $tplMainId
+     * @param int $tplShopId
+     * @param array $newShop
+     * @return array
+     */
+    protected static function copyUseCases($tplMainId, $tplShopId, $newShop)
+    {
+        $map = [];
+        $list = UseCaseClass::getAllByCondition([
+            'mainId' => $tplMainId,
+            'shopId' => $tplShopId,
+            'delStatus' => 0,
+        ], 'inTurn DESC, id ASC');
+        if (empty($list)) {
+            return $map;
+        }
+        foreach ($list as $row) {
+            $oldId = intval($row['id'] ?? 0);
+            $payload = self::prepareCopyRow($row, $newShop);
+            $created = UseCaseClass::add($payload, true);
+            $newId = intval($created->id ?? 0);
+            if ($oldId > 0 && $newId > 0) {
+                $map[$oldId] = $newId;
+            }
+        }
+        return $map;
+    }
+
+    /**
+     * 按种类名称把模板店 kindId 映射到新店已初始化的种类
+     * 为什么按名称:开店时 KindClass::initKind 已给新店写过一套种类,不能直接复用模板店 kindId
+     * @param int $tplMainId
+     * @param int $newMainId
+     * @return array 旧kindId => 新kindId
+     */
+    protected static function buildKindMap($tplMainId, $newMainId)
+    {
+        $map = [];
+        $oldList = KindClass::getAllByCondition(['mainId' => $tplMainId, 'delStatus' => 0], null, 'id,name');
+        $newList = KindClass::getAllByCondition(['mainId' => $newMainId, 'delStatus' => 0], null, 'id,name');
+        $newByName = [];
+        foreach ($newList as $item) {
+            $name = strval($item['name'] ?? '');
+            if ($name !== '') {
+                $newByName[$name] = intval($item['id']);
+            }
+        }
+        foreach ($oldList as $item) {
+            $name = strval($item['name'] ?? '');
+            $oldId = intval($item['id'] ?? 0);
+            if ($oldId > 0 && isset($newByName[$name])) {
+                $map[$oldId] = $newByName[$name];
+            }
+        }
+        return $map;
+    }
+
+    /**
+     * 复制商品:先主记录再子规格,销量清零,masterId/kindId 按映射重写
+     * @param int $tplMainId
+     * @param int $tplShopId
+     * @param array $newShop
+     * @param array $kindMap
+     * @return array 旧goodsId => 新goodsId
+     */
+    protected static function copyGoods($tplMainId, $tplShopId, $newShop, $kindMap)
+    {
+        $map = [];
+        $list = GoodsClass::getAllByCondition([
+            'mainId' => $tplMainId,
+            'shopId' => $tplShopId,
+            'delStatus' => 0,
+        ], 'id ASC');
+        if (empty($list)) {
+            return $map;
+        }
+
+        $masters = [];
+        $children = [];
+        foreach ($list as $row) {
+            if (intval($row['masterId'] ?? 0) === 0) {
+                $masters[] = $row;
+            } else {
+                $children[] = $row;
+            }
+        }
+
+        foreach ($masters as $row) {
+            $oldId = intval($row['id'] ?? 0);
+            $payload = self::prepareGoodsRow($row, $newShop, $kindMap, 0);
+            $created = GoodsClass::add($payload, true);
+            $newId = intval($created->id ?? 0);
+            if ($oldId > 0 && $newId > 0) {
+                $map[$oldId] = $newId;
+            }
+        }
+        foreach ($children as $row) {
+            $oldId = intval($row['id'] ?? 0);
+            $oldMasterId = intval($row['masterId'] ?? 0);
+            if (!isset($map[$oldMasterId])) {
+                continue;
+            }
+            $payload = self::prepareGoodsRow($row, $newShop, $kindMap, $map[$oldMasterId]);
+            $created = GoodsClass::add($payload, true);
+            $newId = intval($created->id ?? 0);
+            if ($oldId > 0 && $newId > 0) {
+                $map[$oldId] = $newId;
+            }
+        }
+        return $map;
+    }
+
+    /**
+     * 整理商品复制字段:归属改到新店,销量清零,种类指向新店 kind
+     * @param array $row
+     * @param array $newShop
+     * @param array $kindMap
+     * @param int $newMasterId
+     * @return array
+     */
+    protected static function prepareGoodsRow($row, $newShop, $kindMap, $newMasterId)
+    {
+        $payload = self::prepareCopyRow($row, $newShop);
+        $payload['masterId'] = intval($newMasterId);
+        $payload['sold'] = 0;
+        $payload['actualSold'] = 0;
+        $payload['createTime'] = date('Y-m-d H:i:s');
+        $oldKindId = intval($row['kindId'] ?? 0);
+        if ($oldKindId > 0) {
+            $payload['kindId'] = $kindMap[$oldKindId] ?? 0;
+        }
+        return $payload;
+    }
+
+    /**
+     * 按商品/分类映射复制 xhGoodsCategory,并回写分类商品数量
+     * @param int $tplMainId
+     * @param array $newShop
+     * @param array $goodsMap
+     * @param array $categoryMap
+     * @return void
+     */
+    protected static function copyGoodsCategories($tplMainId, $newShop, $goodsMap, $categoryMap)
+    {
+        if (empty($goodsMap) || empty($categoryMap)) {
+            return;
+        }
+        $oldGoodsIds = array_keys($goodsMap);
+        $list = GoodsCategoryClass::getAllByCondition([
+            'mainId' => $tplMainId,
+            'gId' => ['in', $oldGoodsIds],
+        ], 'id ASC');
+        if (empty($list)) {
+            return;
+        }
+        $goodsNum = [];
+        foreach ($list as $row) {
+            $oldGoodsId = intval($row['gId'] ?? 0);
+            $oldCatId = intval($row['cId'] ?? 0);
+            if (!isset($goodsMap[$oldGoodsId]) || !isset($categoryMap[$oldCatId])) {
+                continue;
+            }
+            $newCatId = $categoryMap[$oldCatId];
+            $payload = self::prepareCopyRow($row, $newShop);
+            $payload['gId'] = $goodsMap[$oldGoodsId];
+            $payload['cId'] = $newCatId;
+            GoodsCategoryClass::add($payload);
+            $goodsNum[$newCatId] = ($goodsNum[$newCatId] ?? 0) + 1;
+        }
+        foreach ($goodsNum as $catId => $num) {
+            CategoryClass::updateById($catId, ['goodsNum' => $num]);
+        }
+    }
+
+    /**
+     * 按商品/场景映射复制 xhGoodsUseCaseRelation
+     * @param int $tplMainId
+     * @param array $newShop
+     * @param array $goodsMap
+     * @param array $useCaseMap
+     * @return void
+     */
+    protected static function copyUseCaseRelations($tplMainId, $newShop, $goodsMap, $useCaseMap)
+    {
+        if (empty($goodsMap) || empty($useCaseMap)) {
+            return;
+        }
+        $oldGoodsIds = array_keys($goodsMap);
+        $list = GoodsUseCaseClass::getAllByCondition([
+            'mainId' => $tplMainId,
+            'goodsId' => ['in', $oldGoodsIds],
+        ], 'id ASC');
+        if (empty($list)) {
+            return;
+        }
+        foreach ($list as $row) {
+            $oldGoodsId = intval($row['goodsId'] ?? 0);
+            $oldUseCaseId = intval($row['useCaseId'] ?? 0);
+            if (!isset($goodsMap[$oldGoodsId]) || !isset($useCaseMap[$oldUseCaseId])) {
+                continue;
+            }
+            GoodsUseCaseClass::add([
+                'mainId' => $newShop['mainId'],
+                'goodsId' => $goodsMap[$oldGoodsId],
+                'useCaseId' => $useCaseMap[$oldUseCaseId],
+            ]);
+        }
+    }
+
+    /**
+     * 复制模板店未删除的秒杀活动批次(秒杀按 mainId 共享,不按 shopId 过滤)
+     * @param int $tplMainId
+     * @param int $tplShopId
+     * @param array $newShop
+     * @return array 旧activityId => 新activityId
+     */
+    protected static function copySeckillActivities($tplMainId, $tplShopId, $newShop)
+    {
+        $map = [];
+        $list = SeckillActivityClass::getAllByCondition([
+            'mainId' => $tplMainId,
+            'delStatus' => 0,
+        ], 'id ASC');
+        if (empty($list)) {
+            return $map;
+        }
+        foreach ($list as $row) {
+            $oldId = intval($row['id'] ?? 0);
+            $payload = self::prepareCopyRow($row, $newShop);
+            $created = SeckillActivityClass::add($payload, true);
+            $newId = intval($created->id ?? 0);
+            if ($oldId > 0 && $newId > 0) {
+                $map[$oldId] = $newId;
+            }
+        }
+        return $map;
+    }
+
+    /**
+     * 复制秒杀商品版本,重写 activityId 与 goodsId
+     * @param int $tplMainId
+     * @param int $tplShopId
+     * @param array $newShop
+     * @param array $activityMap
+     * @param array $goodsMap
+     * @return void
+     */
+    protected static function copySeckillGoods($tplMainId, $tplShopId, $newShop, $activityMap, $goodsMap)
+    {
+        if (empty($activityMap) || empty($goodsMap)) {
+            return;
+        }
+        $list = SeckillGoodsClass::getAllByCondition([
+            'mainId' => $tplMainId,
+            'delStatus' => 0,
+        ], 'id ASC');
+        if (empty($list)) {
+            return;
+        }
+        foreach ($list as $row) {
+            $oldActivityId = intval($row['activityId'] ?? 0);
+            $oldGoodsId = intval($row['goodsId'] ?? 0);
+            if (!isset($activityMap[$oldActivityId]) || !isset($goodsMap[$oldGoodsId])) {
+                continue;
+            }
+            $payload = self::prepareCopyRow($row, $newShop);
+            $payload['activityId'] = $activityMap[$oldActivityId];
+            $payload['goodsId'] = $goodsMap[$oldGoodsId];
+            SeckillGoodsClass::add($payload);
+        }
+    }
+
+    /**
+     * 复制首页模块配置,并把 JSON 里引用的商品/分类/场景 ID 换成新店 ID
+     * @param int $tplShopId
+     * @param array $newShop
+     * @param array $goodsMap
+     * @param array $categoryMap
+     * @param array $useCaseMap
+     * @return void
+     */
+    protected static function copyHomePageConfig($tplShopId, $newShop, $goodsMap, $categoryMap, $useCaseMap)
+    {
+        $list = HomePageModuleConfigClass::getAllByCondition(['shopId' => $tplShopId], 'id ASC');
+        if (empty($list)) {
+            return;
+        }
+        foreach ($list as $row) {
+            $moduleKey = strval($row['moduleKey'] ?? '');
+            if ($moduleKey === '') {
+                continue;
+            }
+            $payload = json_decode($row['configValue'] ?? '', true);
+            if (!is_array($payload)) {
+                $payload = [];
+            }
+            $payload = self::remapHomePagePayload($moduleKey, $payload, $goodsMap, $categoryMap, $useCaseMap);
+            HomePageModuleConfigClass::saveConfigValue($newShop['mainId'], $newShop['shopId'], $moduleKey, $payload);
+        }
+    }
+
+    /**
+     * 按 moduleKey 把首页配置里的关联 ID 换成新店数据
+     * banner/navGrid 的 list[].type+value、hot/new/pullGoods 的 type+value 都可能指向商品/分类/场景
+     * @param string $moduleKey
+     * @param array $payload
+     * @param array $goodsMap
+     * @param array $categoryMap
+     * @param array $useCaseMap
+     * @return array
+     */
+    protected static function remapHomePagePayload($moduleKey, $payload, $goodsMap, $categoryMap, $useCaseMap)
+    {
+        if ($moduleKey === 'banner' || $moduleKey === 'navGrid') {
+            if (empty($payload['list']) || !is_array($payload['list'])) {
+                return $payload;
+            }
+            foreach ($payload['list'] as $index => $item) {
+                if (!is_array($item)) {
+                    continue;
+                }
+                $type = intval($item['type'] ?? 0);
+                $value = strval($item['value'] ?? '');
+                $payload['list'][$index]['value'] = self::remapLinkedValue($type, $value, $goodsMap, $categoryMap, $useCaseMap);
+            }
+            return $payload;
+        }
+        if (in_array($moduleKey, ['hot', 'new', 'pullGoods'], true)) {
+            $type = intval($payload['type'] ?? 0);
+            $value = strval($payload['value'] ?? '');
+            $payload['value'] = self::remapLinkedValue($type, $value, $goodsMap, $categoryMap, $useCaseMap);
+            return $payload;
+        }
+        return $payload;
+    }
+
+    /**
+     * 把关联配置的 value(单个 ID 或逗号拼接)按 type 映射到新店
+     * type:2 商品、3 分类、4 使用场景;未映射到的 ID 丢弃,避免新店引用模板店数据
+     * @param int $type
+     * @param string $value
+     * @param array $goodsMap
+     * @param array $categoryMap
+     * @param array $useCaseMap
+     * @return string
+     */
+    protected static function remapLinkedValue($type, $value, $goodsMap, $categoryMap, $useCaseMap)
+    {
+        $map = [];
+        if ($type === HomePageConfigClass::BANNER_TYPE_GOODS) {
+            $map = $goodsMap;
+        } elseif ($type === HomePageConfigClass::BANNER_TYPE_CATEGORY) {
+            $map = $categoryMap;
+        } elseif ($type === HomePageConfigClass::BANNER_TYPE_USE_CASE) {
+            $map = $useCaseMap;
+        } else {
+            return $value;
+        }
+        $ids = array_filter(array_map('intval', explode(',', strval($value))));
+        $mapped = [];
+        foreach ($ids as $id) {
+            if (isset($map[$id])) {
+                $mapped[] = $map[$id];
+            }
+        }
+        return implode(',', $mapped);
+    }
+
+    /**
+     * 去掉主键与时间戳,并把归属字段改成新店
+     * @param array $row
+     * @param array $newShop
+     * @param array $extraUnset 额外要丢掉的字段
+     * @return array
+     */
+    protected static function prepareCopyRow($row, $newShop, $extraUnset = [])
+    {
+        unset($row['id'], $row['addTime'], $row['updateTime']);
+        foreach ($extraUnset as $field) {
+            unset($row[$field]);
+        }
+        $row['mainId'] = $newShop['mainId'];
+        if (array_key_exists('shopId', $row)) {
+            $row['shopId'] = $newShop['shopId'];
+        }
+        if (array_key_exists('sjId', $row)) {
+            $row['sjId'] = $newShop['sjId'];
+        }
+        return $row;
+    }
+}

+ 6 - 6
common/components/delivery/platform/shunfeng/Shunfeng.php

@@ -30,12 +30,12 @@ class Shunfeng
             $this->devId = 1594082399;
             $this->appSecret = '9025c4f5ad93e8e08e947f02d0cde652';
         } else {
-//            $this->baseUrl = 'https://openic.sf-express.com/open/api/external/';
-//            $this->devId = 1741530942;
-//            $this->appSecret = '07b3f83d19a4a9f89322976c936faf92';
-            $this->baseUrl = 'https://openic.sf-express.com/open/api/external/';
-            $this->devId = 1594082399;
-            $this->appSecret = '9025c4f5ad93e8e08e947f02d0cde652';
+           $this->baseUrl = 'https://openic.sf-express.com/open/api/external/';
+           $this->devId = 1741530942;
+           $this->appSecret = '07b3f83d19a4a9f89322976c936faf92';
+            // $this->baseUrl = 'https://openic.sf-express.com/open/api/external/';
+            // $this->devId = 1594082399;
+            // $this->appSecret = '9025c4f5ad93e8e08e947f02d0cde652';
         }
         $this->shopId = $shopId;
 

+ 6 - 0
sql/20260828_apply_gen_template.sql

@@ -0,0 +1,6 @@
+-- 开店申请增加「是否给零售店生成样例模板」标记
+-- 用途:hdApp/ghsApp 申请开店勾选后写入 xhApply,审核/自动通过时按该字段决定是否复制模板店数据
+-- 执行前请确认 xhApply 尚无 genTemplate 字段
+
+ALTER TABLE `xhApply`
+  ADD COLUMN `genTemplate` tinyint(1) NOT NULL DEFAULT 0 COMMENT '是否给零售店生成样例模板 1是 0否' AFTER `inviteCommissionAmount`;