Browse Source

Merge branch 'redesign‌-260706' of git.huaml.com:zhh/huahuibao into redesign‌-260706

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

+ 131 - 0
app-ghs/controllers/AuthController.php

@@ -30,6 +30,137 @@ use yii\helpers\Json;
 class AuthController extends PublicController
 {
 
+    //小程序获取手机号并登录 (新接口) ssh 20250728
+    public function actionGetMiniMobile()
+    {
+        $post = Yii::$app->request->post();
+        $code = $post['code'] ?? '';
+        $miniOpenId = $post['miniOpenId'] ?? '';
+        if (empty($code)) {
+            util::fail('参数错误:缺少code');
+        }
+
+        // 使用 miniUtil 封装好的方法获取手机号 (ptStyle=2 表示供货商端)
+        $merchant = WxOpenClass::getGhsWxInfo();
+        $res = \common\components\miniUtil::getPhoneNumber($merchant, $code, 2);
+
+        if (isset($res['errcode']) && $res['errcode'] == 0) {
+            $phoneNumber = $res['phone_info']['purePhoneNumber'] ?? '';
+            if (empty($phoneNumber)) {
+                util::fail('获取手机号内容为空');
+            }
+
+            // 登录逻辑 (同步自 actionWxMobileLogin)
+            $admin = AdminClass::getByCondition(['mobile' => $phoneNumber]);
+            if (empty($admin)) {
+                util::fail('请先注册或请店长添加自己为员工');
+            }
+            $currentShopId = $admin['currentGhsShopId'] ?? 0;
+            $openShop = $admin['openGhsShop'] ?? 1;
+            if (empty($currentShopId)) {
+                if ($openShop == 2) {
+                    util::fail('审核中');
+                }
+                util::fail('请先注册..');
+            }
+            $currentShop = ShopClass::getById($currentShopId, true);
+            if (empty($currentShop)) {
+                util::fail('没有找到门店69');
+            }
+            $mainId = $currentShop->mainId ?? 0;
+            $adminId = $admin['id'] ?? 0;
+            if (isset($admin['ghsMiniOpenId']) && empty($admin['ghsMiniOpenId'])) {
+                AdminClass::updateById($adminId, ['ghsMiniOpenId' => $miniOpenId]);
+            }
+            $admin['miniOpenId'] = $miniOpenId;
+            //1没有开店 2已申请待审核 3已开店
+            $openShop = $admin['openGhsShop'] ?? 1;
+            if ($openShop == 2) {
+                util::fail('帐号审核中');
+            }
+            $shopAdmin = ShopAdminClass::getByCondition(['adminId' => $adminId, 'mainId' => $mainId], true);
+            if (empty($shopAdmin)) {
+                util::fail('请先注册...');
+            }
+            $shopAdmin->lastLogin = date("Y-m-d H:i:s");
+            $shopAdmin->save();
+            $shopAdminId = $shopAdmin->id ?? 0;
+            //是否有切换门店的权限
+            $switchShop = \biz\shop\classes\ShopAdminClass::hasSwitchShopRight($shopAdmin);
+
+            $admin['avatar'] = imgUtil::getPrefix() . '/retail/default-img.png';
+            $token = jwt::getNewToken($adminId);
+            $showDemo = 1;
+            $remind = getenv('GHS_UPDATE_REMIND') == false ? 0 : getenv('GHS_UPDATE_REMIND');
+            $shop = ShopClass::getById($currentShopId, true);
+            $skCustomId = $shop->skCustomId ?? 0;
+            $apiHost = Yii::$app->params['ghsHost'];
+            $imgUploadApi = $apiHost . '/upload/save-file';
+
+            //使用手册
+            $cacheKey = 'close_book_' . $shopAdminId;
+            $hasClose = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+            $showBook = !empty($hasClose) ? 0 : 1;
+
+            $cacheKey = 'has_hit_navigate_' . $shopAdminId;
+            $hasHit = Yii::$app->redis->executeCommand('GET', [$cacheKey]);
+            $hasHitNavigate = !empty($hasHit) ? 1 : 0;
+
+            $ghsUpgrading = getenv('GHS_UPGRADING') == false ? 0 : getenv('GHS_UPGRADING');
+            if ($ghsUpgrading == 1) {
+                $allowShopAdminIdsStr = getenv('GHS_UPGRADE_ALLOW_SHOP_ADMIN_IDS') ?: '';
+                $allowShopAdminIds = !empty($allowShopAdminIdsStr) ? explode(',', $allowShopAdminIdsStr) : [];
+                if (!in_array($shopAdminId, $allowShopAdminIds)) {
+                    util::fail('系统升级中,稍后再试');
+                }
+            }
+
+            $lookAllShop = 0;
+            if (getenv('YII_ENV') == 'production') {
+                $couldLookAllShop = dict::getDict('couldLookAllShop');
+                if (in_array($adminId, $couldLookAllShop)) {
+                    $lookAllShop = 1;
+                }
+            } else {
+                $lookAllShop = 1;
+            }
+
+            //惠雅鲜花员工不能看收入情况
+            if (in_array($adminId, [2366, 2812, 4004])) {
+                $shopAdmin->super = 0;
+            }
+
+            $labelList = LabelClass::getMyUnUseLabelList($mainId);
+
+            //注意这里的输出内容有多个地方一样,要修改需要同步修改,请搜索关键词loginOK!!!!!!!!
+            util::success([
+                'token' => $token,
+                'admin' => $admin,
+                'shopAdminId' => $shopAdminId,
+                'shopId' => $currentShopId,
+                'switchShop' => $switchShop,
+                'openShop' => $openShop,
+                'showDemo' => $showDemo,
+                //有小程序新版本提示更新
+                'update' => $remind,
+                'skCustomId' => $skCustomId,
+                'apiHost' => $apiHost,
+                'imgUploadApi' => $imgUploadApi,
+                'showBook' => $showBook,
+                'hasHitNavigate' => $hasHitNavigate,
+                'staff' => $shopAdmin,
+                'lookAllShop' => $lookAllShop,
+                'labelList' => $labelList,
+            ]);
+        } else {
+            $errMsg = $res['errmsg'] ?? '获取手机号失败';
+            $errCode = $res['errcode'] ?? -1;
+            Yii::info("小程序新接口获取手机号失败 (GHS):code={$errCode}, msg={$errMsg}");
+            noticeUtil::push("供货商小程序新接口获取手机号失败:code={$errCode}, msg={$errMsg}", '15280215347');
+            util::fail("获取手机号失败:{$errMsg}({$errCode})");
+        }
+    }
+
     //获取手机号
     public function actionGetMobile()
     {

+ 1 - 0
app-ghs/controllers/ShMethodController.php

@@ -62,6 +62,7 @@ class ShMethodController extends BaseController
      * - id: 配置ID(可选)
      * - style: 配送类型 (0: 送货, 1: 自取, 2: 跑腿, 3: 快递, 4: 物流)
      * - name: 名称
+     * - calcType: 算运费方式 (0: 用跑腿, 1: 用自定义)
      * - status: 状态 (0: 禁用, 1: 启用)
      * - sort: 排序
      * - minAmount: 最低消费金额

+ 2 - 17
app-ghs/controllers/TestController.php

@@ -47,22 +47,6 @@ class TestController extends BaseController
 
     public $guestAccess = ['rabbit', 'recharge', 'fx', 'on', 'in', 'clear-query', 'ip', 'html', 'debt', 'apply', 'clear', 'ls-trade-query', 'ls-trade-refund', 'refund-query', 'inform', 'notice', 'order-query', 'add-order', 'index', 'get', 'trade-query', 'query', 'balance-query', 'refund', 'recharge-query', 'sim', 'push', 'code'];
 
-    // ./yii test/rabbit 0
-    public function actionRabbit()
-    {
-//        $data = [
-//            "type" => 'limit_buy_clear',
-//            "ptType" => 'ghs',
-//            "productId" => 27285,
-//            "clearAt" => 1778126400,
-//            "recurring" => 1,
-//            "intervalDays" => 1,
-//            "clearHour" => 12
-//        ];
-//        stockConsumer::clearOrderItemLimitBuy($data);
-    }
-
-
     public function actionFx()
     {
         $ghsShopId = 7855;
@@ -510,7 +494,8 @@ class TestController extends BaseController
             //['name' => '亳州花鲜谷', 'merchantNo' => '82238105992004A', 'wx' => [908947821, 908946480], 'zfb' => '2088780700742980'],
             //['name' => '福建清流美朵花业', 'merchantNo' => '82239505992002F', 'wx' => [909185571, 2000017120], 'zfb' => '2088780716665741'],
             //['name' => '东莞丰行', 'merchantNo' => '8226020599200RW', 'wx' => [909917474, 909917851], 'zfb' => '2088780774491467'],
-            ['name' => '重庆大金地2', 'merchantNo' => '8226900599201GA', 'wx' => [910648990, 910644127], 'zfb' => '2088780830897617'],
+            ['name' => '中山淘花里小榄店', 'merchantNo' => '8226030599200D5', 'wx' => [911061554, 911061963], 'zfb' => '2088780851935068'],
+            ['name' => '重庆大金地', 'merchantNo' => '8226900599201GA', 'wx' => [910648990, 910644127], 'zfb' => '2088780830897617'],
             ['name' => '云南珑松珠海店', 'merchantNo' => '82258505992009Q', 'wx' => [910384498, 910385532], 'zfb' => '2088780804010303'],
             //['name' => '义乌我要花', 'merchantNo' => '82239505992002H', 'wx' => [910330169, 910330807], 'zfb' => '2088780802113602'],
             //['name' => '仁寿花鲜谷', 'merchantNo' => '82266705992003V', 'wx' => [910335651, 910335572], 'zfb' => '2088780803109765'],

+ 116 - 0
app-hd/controllers/AuthController.php

@@ -33,6 +33,122 @@ use yii\helpers\Json;
 class AuthController extends PublicController
 {
 
+    //小程序获取手机号并登录 (新接口) ssh 20250728
+    public function actionGetMiniMobile()
+    {
+        $post = Yii::$app->request->post();
+        $code = $post['code'] ?? '';
+        $miniOpenId = $post['miniOpenId'] ?? '';
+        if (empty($code)) {
+            util::fail('参数错误:缺少code');
+        }
+
+        // 使用 miniUtil 封装好的方法获取手机号 (ptStyle=1 表示花店端)
+        $merchant = WxOpenService::getWxMiniBase();
+        $res = \common\components\miniUtil::getPhoneNumber($merchant, $code, 1);
+
+        if (isset($res['errcode']) && $res['errcode'] == 0) {
+            $phoneNumber = $res['phone_info']['purePhoneNumber'] ?? '';
+            if (empty($phoneNumber)) {
+                util::fail('获取手机号内容为空');
+            }
+
+            // 登录逻辑 (同步自 actionWxMobileLogin)
+            $admin = AdminService::getByCondition(['mobile' => $phoneNumber]);
+            if (empty($admin)) {
+                util::fail('请先注册');
+            }
+            $adminId = $admin['id'];
+            AdminClass::updateById($adminId, ['miniOpenId' => $miniOpenId]);
+            $admin['miniOpenId'] = $miniOpenId;
+            $openShop = $admin['openShop'] ?? 1;
+            $currentShopId = $admin['currentShopId'] ?? 0;
+            if (empty($currentShopId)) {
+                if ($openShop == 2) {
+                    util::fail('审核中');
+                }
+                util::fail('请先注册');
+            }
+            $currentShop = ShopClass::getById($currentShopId, true);
+            if (empty($currentShop)) {
+                util::fail('没有找到门店36');
+            }
+            $pfShopId = $currentShop->pfShopId ?? 0;
+            $onlyCg = $currentShop->onlyCg ?? 1;
+            $mainId = $currentShop->mainId ?? 0;
+
+            $shareLogo = imgUtil::groupImg('buy_logo.jpg');
+            if (isset($currentShop->shareLogo) && !empty($currentShop->shareLogo)) {
+                $shareLogo = imgUtil::groupImg($currentShop->shareLogo);
+            }
+
+            $shopAdmin = ShopAdminService::getByCondition(['adminId' => $adminId, 'mainId' => $mainId], true);
+            if (empty($shopAdmin)) {
+                util::fail('无法操作');
+            }
+            if ($shopAdmin->status == 0) {
+                util::fail("您的账号已被冻结");
+            }
+            $token = jwt::getNewToken($adminId);
+            $shopAdmin->lastLogin = date("Y-m-d H:i:s");
+            $shopAdmin->save();
+            $shopAdminId = $shopAdmin->id ?? 0;
+
+            //是否有切换门店的权限
+            $switchShop = \biz\shop\classes\ShopAdminClass::hasSwitchShopRight($shopAdmin);
+            $prefix = imgUtil::getPrefix();
+            $avatar = isset($admin['avatar']) && !empty($admin['avatar']) ? $prefix . $admin['avatar'] : $prefix . '/retail/default-img.png';
+            $admin['avatar'] = $avatar;
+            $showDemo = 1;
+            $remind = getenv('HD_UPDATE_REMIND') == false ? 0 : getenv('HD_UPDATE_REMIND');
+
+            $hdUpgrading = getenv('HD_UPGRADING') == false ? 0 : getenv('HD_UPGRADING');
+            if ($hdUpgrading == 1) {
+                $allowShopAdminIdsStr = getenv('HD_UPGRADE_ALLOW_SHOP_ADMIN_IDS') ?: '';
+                $allowShopAdminIds = !empty($allowShopAdminIdsStr) ? explode(',', $allowShopAdminIdsStr) : [];
+                if (!in_array($shopAdminId, $allowShopAdminIds)) {
+                    util::fail('系统升级中,稍后再试');
+                }
+            }
+
+            $apiHost = Yii::$app->params['hdHost'];
+            $imgUploadApi = $apiHost . '/upload/save-file';
+
+            //惠雅鲜花员工不能看收入情况
+            if (in_array($adminId, [2366, 2812, 4004])) {
+                $shopAdmin->super = 0;
+            }
+
+            //充值送钱有没设置,没有设置则进行设置,临时方法,后面需要去掉,有多处,关键词recharge_sq_init ssh 20251229
+            RechargeSqClass::initData($currentShop);
+            //会员等级有没设置,没有设置则进行设置,临时方法,后面需要去掉,有多处,关键词member_level_init ssh 20251229
+            MemberLevelClass::initData($currentShop);
+
+            //涉及几个登录的地方,需要同步修改,请搜索关键词uni_login_info
+            util::success([
+                'token' => $token,
+                'admin' => $admin,
+                'shopId' => $currentShopId,
+                'shopAdminId' => $shopAdminId,
+                'switchShop' => $switchShop,
+                'pfShopId' => $pfShopId,
+                'onlyCg' => $onlyCg,
+                'shareLogo' => $shareLogo,
+                'showDemo' => $showDemo,
+                'imgUploadApi' => $imgUploadApi,
+                //有小程序新版本提示更新
+                'update' => $remind,
+                'staff' => $shopAdmin,
+            ]);
+        } else {
+            $errMsg = $res['errmsg'] ?? '获取手机号失败';
+            $errCode = $res['errcode'] ?? -1;
+            Yii::info("小程序新接口获取手机号失败 (HD):code={$errCode}, msg={$errMsg}");
+            noticeUtil::push("花店小程序新接口获取手机号失败:code={$errCode}, msg={$errMsg}", '15280215347');
+            util::fail("获取手机号失败:{$errMsg}({$errCode})");
+        }
+    }
+
     //获取手机号 ssh 20250217
     public function actionGetMobile()
     {

+ 58 - 2
app-hd/controllers/GhsController.php

@@ -8,6 +8,7 @@ use bizGhs\custom\classes\AccountMoneyClass;
 use bizGhs\custom\classes\CustomClass;
 use bizGhs\custom\classes\CustomLevelClass;
 use bizGhs\merchant\classes\WlClass;
+use bizGhs\order\classes\ShMethodClass;
 use bizGhs\shop\classes\GhsNoticeClass;
 use bizHd\purchase\classes\PurchaseClass;
 use bizHd\shop\classes\ShopExtClass;
@@ -26,6 +27,61 @@ class GhsController extends BaseController
 
     public $guestAccess = ['info', 'get-ghs-data', 'detail', 'common-info', 'ghs-notice-detail'];
 
+    //根据自定义价格,计算跑腿费用 ssh 20270730
+    public function actionCalcCustomPtFee()
+    {
+        $get = Yii::$app->request->get();
+        $id = $get['id'] ?? 0;
+        $sendType = $get['sendType'] ?? 2;
+        $ghs = GhsClass::getById($id, true);
+        if (empty($ghs)) {
+            util::fail('没有找到批发店');
+        }
+        if (!isset($ghs->ownShopId) || $ghs->ownShopId != $this->shopId) {
+            util::fail('不是你的批发店');
+        }
+        $customId = $ghs->customId ?? 0;
+        $custom = CustomClass::getById($customId, true);
+        if (empty($custom)) {
+            util::success(['sendCost' => 0, 'sendDistance' => 0]);
+        }
+        $ghsShopId = $ghs->shopId ?? 0;
+        $ghsMainId = $ghs->mainId ?? 0;
+        $shCurrentConfig = shMethodClass::getConfig($ghsShopId, $ghsMainId, $sendType);
+
+        //使用自定义计算费用
+        $startKm = $shCurrentConfig['startKm'] ?? 0;
+        $startPrice = $shCurrentConfig['startPrice'] ?? 0;
+        $perKmPrice = $shCurrentConfig['perKmPrice'] ?? 0;//超出起步,每公里加收金额
+        $changeRate = $shCurrentConfig['changeRate'] ?? 0;//负值时为降价百分比,正值时为涨价百分比
+        if ($startKm <= 0 || $startPrice <= 0 || $perKmPrice <= 0) {
+            util::success(['sendCost' => 0, 'distanceKm' => 0,'distance'=>0]);
+        }
+        //计算客户到店的距离,骑电动车
+        $distanceRespond = mapUtil::calcShopDistanceByEleBike($custom, $ghs, 0);
+        $sendDistance = $distanceRespond['distanceKm'] ?? 0;
+        $distance = $distanceRespond['distance'] ?? 0;
+        $distance = floatval($distance);
+        $sendDistance = floatval($sendDistance);
+        if ($sendDistance <= 0) {
+            util::success(['sendCost' => 0, 'distanceKm' => 0,'distance'=>0]);
+        }
+        // 计算运费逻辑
+        $sendCost = $startPrice;
+        if ($sendDistance > $startKm) {
+            $extraDistance = bcsub($sendDistance, $startKm, 2);
+            $extraCost = bcmul($extraDistance, $perKmPrice, 2);
+            $sendCost = bcadd($sendCost, $extraCost, 2);
+        }
+        if ($changeRate != 0) {
+            // 临时涨价/降价百分比
+            $rate = bcadd(1, bcdiv($changeRate, 100, 4), 4);
+            $sendCost = bcmul($sendCost, $rate, 2);
+        }
+        $sendCost = floatval($sendCost);
+        util::success(['sendCost' => $sendCost, 'distanceKm' => $sendDistance,'distance'=>$distance]);
+    }
+
     //提示花店有多个供货商
     public function actionRemindMoreGhs()
     {
@@ -303,15 +359,14 @@ class GhsController extends BaseController
             }
         }
 
+        /*****此区域部分可以考虑删除******/
         $shopExt = ShopExtClass::getByCondition(['shopId' => $ghsShopId], false, false, 'purchaseGuide,purchaseGuideText,hcFreeKm,hcMap');
         $ghsInfo['buyNotice'] = $ghsShop->buyNotice ?? 0;
         $ghsInfo['buyNoticeText'] = $shopExt['purchaseGuideText'] ?? '';
-
         //判断是否开启同城配送功能
         $intraCityRet = ShopClass::hasIntraCity($ghsShop);
         $openIntraCity = $intraCityRet['openIntraCity'];
         $ghsInfo['openIntraCity'] = $openIntraCity;
-
         //花材的免费配送设置
         $hcFreeKm = $shopExt['hcFreeKm'] ?? 0;
         $ghsInfo['hcFreeKm'] = $hcFreeKm;
@@ -321,6 +376,7 @@ class GhsController extends BaseController
             $hcMap = json_decode($hcMapString, true);
         }
         $ghsInfo['hcMap'] = $hcMap;
+        /*****此区域部分可以考虑删除******/
 
         //是否使用新的配送方式,关键词 sh_method_area
         $newShMethod = dict::getNewMethodShop();

+ 110 - 37
app-hd/controllers/PurchaseController.php

@@ -22,6 +22,7 @@ use common\components\dateUtil;
 use common\components\delivery\util\DeliveryQuoteUtil;
 use common\components\dict;
 use common\components\imgUtil;
+use common\components\mapUtil;
 use common\components\noticeUtil;
 use common\components\orderSn;
 use Yii;
@@ -497,19 +498,6 @@ class PurchaseController extends BaseController
                         }
                     }
                 }
-// 已经有了 -- 在 replaceItem()
-//                foreach ($productList as $itemData) {
-//                    $productId = $itemData['productId'] ?? 0;
-//                    $product = $productInfoList[$productId] ?? [];
-//                    if (empty($product)) {
-//                        util::fail('有商品信息没有找到');
-//                    }
-//                    $bigNum = $itemData['bigNum'] ?? 0;
-//                    if (($product['limitBuy'] ?? 0) > 0) {
-//                        $product['productId'] = $productId;
-//                        ProductClass::handleLimitBuy($product, $customId, floatval($bigNum));
-//                    }
-//                }
 
             } else {
                 util::fail('花材不存在');
@@ -635,30 +623,114 @@ class PurchaseController extends BaseController
                 // xhShMethod 门店:下单前按配置写入不满最低消费时的附加包装费/运费,关键词 sh_method_area
                 $newShMethod = dict::getNewMethodShop();
                 if (in_array($ghsShopId, $newShMethod)) {
-                    $shMethodBigNum = 0;
-                    foreach ($productList as $itemData) {
-                        $shMethodBigNum += floatval($itemData['bigNum'] ?? 0);
-                    }
-                    $additionalCosts = ShMethodClass::calcFee(
-                        $ghsShopId,
-                        $ghsMainId,
-                        $sendType,
-                        $shMethodItemAmount,
-                        $shMethodBigNum,
-                        $customId,
-                        $ghsInfo
-                    );
-
-                    // 如果产生了附加运费,与前面可能产生的 sendCost 进行累加或覆盖
-                    if ($additionalCosts['sendCost'] > 0) {
-                        $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $additionalCosts['sendCost'], 2);
+
+                    $shCurrentConfig = shMethodClass::getConfig($ghsShopId, $ghsMainId, $sendType);
+                    $shCurrentName = $shCurrentConfig['name'] ?? '';
+                    if (isset($shCurrentConfig['status']) && $shCurrentConfig['status'] == 0) {
+                        util::fail($shCurrentName . '已停用');
                     }
 
-                    // 如果产生了附加包装费,覆盖前面赋值的 packCost
-                    if ($additionalCosts['packCost'] > 0) {
-                        $post['packCost'] = $additionalCosts['packCost'];
+                    if ($sendType == dict::getDict('sendType', 'thirdSend')) {
+                        //如果是发跑腿
+
+                        // 生成随机订单号,不要跟原来的订单号混起来,跑腿-销售单-
+                        $prefix = 'PT-XSD-' . $this->mainId . '-';
+                        $orderSn = $prefix . round(microtime(true) * 1000);
+
+                        $calcType = $shCurrentConfig['calcType'] ?? 0;
+                        if ($calcType == 1) {
+                            //使用自定义计算费用
+                            $startKm = $shCurrentConfig['startKm'] ?? 0;
+                            $startPrice = $shCurrentConfig['startPrice'] ?? 0;
+                            $perKmPrice = $shCurrentConfig['perKmPrice'] ?? 0;//超出起步,每公里加收金额
+                            $changeRate = $shCurrentConfig['changeRate'] ?? 0;//负值时为降价百分比,正值时为涨价百分比
+                            if ($startKm <= 0 || $startPrice <= 0 || $perKmPrice <= 0) {
+                                util::fail('算运费失败,请更换配送方式');
+                            }
+                            //计算客户到店的距离,骑电动车
+                            $distanceRespond = mapUtil::calcShopDistanceByEleBike($custom, $ghsShopInfo);
+                            $sendDistance = $distanceRespond['distanceKm'] ?? 0;
+                            if ($sendDistance <= 0) {
+                                util::fail('算运费失败,距离是0,请选到店自取');
+                            }
+                            // 计算运费逻辑
+                            $sendCost = $startPrice;
+                            if ($sendDistance > $startKm) {
+                                $extraDistance = bcsub($sendDistance, $startKm, 2);
+                                $extraCost = bcmul($extraDistance, $perKmPrice, 2);
+                                $sendCost = bcadd($sendCost, $extraCost, 2);
+                            }
+                            if ($changeRate != 0) {
+                                // 临时涨价/降价百分比
+                                $rate = bcadd(1, bcdiv($changeRate, 100, 4), 4);
+                                $sendCost = bcmul($sendCost, $rate, 2);
+                            }
+
+                            $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $sendCost, 2);
+                            $post['sendDistance'] = $sendDistance;
+
+                        } else {
+                            // 使用 DeliveryQuoteUtil 获取配送报价
+                            try {
+                                $quoteResult = DeliveryQuoteUtil::getDeliveryQuote([
+                                    'productList' => $productList,
+                                    'deliveryPlatform' => $post['deliveryPlatform'],
+                                    'deliveryBracketContent' => $post['deliveryBracketContent'], // 平台多报价识别id
+                                    'ghsInfo' => $ghsInfo,
+                                    'custom' => $custom,
+                                    'order' => [
+                                        'orderSn' => $orderSn,
+                                        'goodsType' => 1, //商品类型:0 花束 1 花材
+                                        'itemTotalAmount' => $post['itemTotalAmount'] ?? 0,
+                                        'remark' => $post['remark'] ?? '',
+                                    ],
+                                    'mainId' => $this->mainId,
+                                    'productCount' => $productCount,
+                                    //当前配送方式
+                                    'shConfig' => $shCurrentConfig,
+                                ]);
+
+                                $sendCost = $quoteResult['sendCost'];
+                                $sendDistance = $quoteResult['sendDistance'];
+
+                                $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $sendCost, 2);
+                                $post['sendDistance'] = $sendDistance;
+
+                            } catch (\Exception $e) {
+                                noticeUtil::push("计算跑腿费用出错了:" . $e->getMessage(), '15280215347');
+                                util::fail('下单失败,请选其他配送方式');
+                            }
+                        }
+
+                    } else {
+                        //如果是不是发跑腿,比如送货上门和发快递,则可能要收运费或打包费任一
+
+                        $shMethodBigNum = 0;
+                        foreach ($productList as $itemData) {
+                            $shMethodBigNum += floatval($itemData['bigNum'] ?? 0);
+                        }
+
+                        $additionalCosts = ShMethodClass::calcFee(
+                            $shCurrentConfig,
+                            $sendType,
+                            $shMethodItemAmount,
+                            $shMethodBigNum,
+                            $customId,
+                            $ghsInfo
+                        );
+
+                        // 如果产生了附加运费,与前面可能产生的 sendCost 进行累加或覆盖
+                        if ($additionalCosts['sendCost'] > 0) {
+                            $post['sendCost'] = bcadd($post['sendCost'] ?? 0, $additionalCosts['sendCost'], 2);
+                        }
+                        // 如果产生了附加包装费,覆盖前面赋值的 packCost。
+                        if ($additionalCosts['packCost'] > 0) {
+                            $post['packCost'] = $additionalCosts['packCost'];
+                        }
+
                     }
-                }else{
+
+                } else {
 
                     //同城发货包装费和运费的计算
                     $sendCost = 0;
@@ -671,7 +743,7 @@ class PurchaseController extends BaseController
                             util::fail('不能使用跑腿');
                         }
                         if ($openIntraCity == 1) {
-                            // 生成随机订单号,不要跟原来的混起来,跑腿-销售单-
+                            // 生成随机订单号,不要跟原来的单号混起来,跑腿-销售单-
                             $prefix = 'PT-XSD-' . $this->mainId . '-';
                             $orderSn = $prefix . round(microtime(true) * 1000);
 
@@ -701,7 +773,8 @@ class PurchaseController extends BaseController
                                 $sendCost = $quoteResult['sendCost'];
                                 $sendDistance = $quoteResult['sendDistance'];
                             } catch (\Exception $e) {
-                                util::fail($e->getMessage());
+                                noticeUtil::push("计算跑腿费用出错了:" . $e->getMessage(), '15280215347');
+                                util::fail('下单失败,请选其他配送方式');
                             }
                         }
                     }
@@ -783,7 +856,7 @@ class PurchaseController extends BaseController
 
                         //情意花卉,必选品
                         if ($ghsShopId == 100883) {
-                            $hasMust = array_intersect($ids, [5017957,5036067,5036089,5036099,5017958,5036063,5017948,5035980,5036073,5036075,5036076,5036117,5036118,5017949,5035979,5035976,5035928,5035930,5036061,5035879]);
+                            $hasMust = array_intersect($ids, [5017957, 5036067, 5036089, 5036099, 5017958, 5036063, 5017948, 5035980, 5036073, 5036075, 5036076, 5036117, 5036118, 5017949, 5035979, 5035976, 5035928, 5035930, 5036061, 5035879]);
                             if (empty($hasMust)) {
                                 util::fail('请返回选择 必选商品');
                             }

+ 40 - 5
app-mall/controllers/UserController.php

@@ -16,6 +16,8 @@ use common\components\dict;
 use common\components\errCode;
 use common\components\imgUtil;
 use common\components\jwt;
+use common\components\miniUtil;
+use common\components\noticeUtil;
 use common\components\stringUtil;
 use Yii;
 use common\components\util;
@@ -26,7 +28,7 @@ class UserController extends BaseController
 {
 
     //二维码收款使用 ssh
-    public $guestAccess = ['discount', 'mini-mobile', 'create', 'account-login', 'current-info'];
+    public $guestAccess = ['discount', 'mini-mobile', 'get-mini-mobile', 'create', 'account-login', 'current-info'];
 
     //清空登录信息 ssh 20250215
     public function actionClearLogin()
@@ -270,10 +272,11 @@ class UserController extends BaseController
         $pc = new \WXBizDataCrypt($appId, $sessionKey);
         $errCode = $pc->decryptData($encryptedData, $iv, $result);
         if ($errCode != 0) {
-            Yii::info($result . ' ' . $errCode);
-            util::fail('获取用户信息失败');
+            // 记录详细日志以便排查。常见错误:-41003(AES解密失败/sessionKey过期)
+            Yii::info("小程序获取用户信息解密失败:errCode={$errCode}, miniOpenId={$miniOpenId}, appId={$appId}");
+            util::fail("获取用户信息失败(code:{$errCode})");
         }
-        Yii::info('小程序获取用户信息:' . $result);
+        Yii::info('小程序获取用户信息成功:' . $result);
         $originalInfo = Json::decode($result);
         util::success($originalInfo);
     }
@@ -300,7 +303,10 @@ class UserController extends BaseController
         $pc = new \WXBizDataCrypt($appId, $sessionKey);
         $errCode = $pc->decryptData($encryptedData, $iv, $result);
         if ($errCode != 0) {
-            util::fail('解密失败');
+            // 记录详细日志以便排查。常见错误:-41003(AES解密失败/sessionKey过期)
+            Yii::info("小程序手机号解密失败:errCode={$errCode}, miniOpenId={$miniOpenId}, appId={$appId}");
+            noticeUtil::push("小程序手机号解密失败:errCode={$errCode}, miniOpenId={$miniOpenId}, appId={$appId}", '15280215347');
+            util::fail("解密失败(code:{$errCode}),请尝试重新登录或重试");
         }
         $arr = Json::decode($result);
         $mobile = $arr['purePhoneNumber'] ?? '';
@@ -310,6 +316,35 @@ class UserController extends BaseController
         util::success(['mobile' => $mobile]);
     }
 
+    //小程序获取手机号新接口 ssh 2025.07.28
+    //接口文档:https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/user-info/phone-number/getPhoneNumber.html
+    public function actionGetMiniMobile()
+    {
+        $post = Yii::$app->request->post();
+        $code = $post['code'] ?? '';
+        if (empty($code)) {
+            util::fail('参数错误:缺少code');
+        }
+
+        // 使用 miniUtil 封装好的方法获取手机号 (ptStyle=3 表示商城端)
+        $merchant = WxOpenClass::getMallWxMiniBase();
+        $res = miniUtil::getPhoneNumber($merchant, $code, 3);
+
+        if (isset($res['errcode']) && $res['errcode'] == 0) {
+            $mobile = $res['phone_info']['purePhoneNumber'] ?? '';
+            if (empty($mobile)) {
+                util::fail('获取手机号内容为空');
+            }
+            util::success(['mobile' => $mobile]);
+        } else {
+            $errMsg = $res['errmsg'] ?? '获取手机号失败';
+            $errCode = $res['errcode'] ?? -1;
+            Yii::info("小程序新接口获取手机号失败:code={$errCode}, msg={$errMsg}");
+            noticeUtil::push("小程序新接口获取手机号失败:code={$errCode}, msg={$errMsg}", '15280215347');
+            util::fail("获取手机号失败:{$errMsg}({$errCode})");
+        }
+    }
+
     //密码修改
     public function actionPassword()
     {

+ 11 - 8
biz-ghs/order/classes/OrderClass.php

@@ -2025,7 +2025,7 @@ class OrderClass extends BaseClass
             //东莞我要花不要自动打印标准,mainId=2644,已经去掉了
             $map = [65726, 58, 25119, 28500, 1294, 12925, 83694];
         } else {
-            $map = [828];
+            $map = [828,644];
         }
         if (in_array($orderMainId, $map)) {
             self::printLogisticsLabel($orderInfo, $shop, $ext);
@@ -3083,7 +3083,7 @@ XL;
         if (getenv('YII_ENV') == 'production') {
             $map = [65726, 58, 25119, 28500, 1294, 12925, 2644, 10652, 2084, 89473, 83694];
         } else {
-            $map = [828];
+            $map = [828,644];
         }
         /**************************如果是好多花的云仓还要再打一下标签纸,多处要同步修改,关键词 hdh_yc *****************************/
         $customId = $order->customId ?? 0;
@@ -3124,6 +3124,7 @@ XL;
         $address = $order->address ?? '';
         $floor = $order->floor ?? '';
         $fullAddress = $address . $floor;
+        $showAddress = $order->showAddress ?? '';
 
         $shopName = $shop->shopName ?? '';
         $sjName = $shop->merchantName;
@@ -3177,15 +3178,17 @@ XL;
             $itemNum = floatval($itemNum);
             $payTime = $order->payTime ?? '';
             $payDate = date('m-d H:i', strtotime($payTime));
-            $content = '<TEXT x="400" y="30" font="12" w="3" h="3" r="90">' . $customName . '</TEXT>';
+            $content = '<TEXT x="400" y="45" font="12" w="3" h="3" r="90">' . $customName . '</TEXT>';
 
             // 地址超过15个字,字体大小(w和h)变小一级(由 w="2" h="2" 变为 w="1" h="1")
             $addressLen = mb_strlen($fullAddress, 'UTF-8');
-            $fontScale = $addressLen > 16 ? '1' : '2';
-            $content .= '<TEXT x="280" y="30" font="12" w="' . $fontScale . '" h="' . $fontScale . '" r="90">' . $fullAddress . '</TEXT>';
-
-            $content .= '<TEXT x="180" y="30" font="12" w="2" h="2" r="90">' . $customMobile . '  ' . $itemNum . '扎</TEXT>';
-            $content .= '<TEXT x="86" y="30" font="12" w="2" h="2" r="90">' . $distName . ' ' . $payDate . '</TEXT>';
+            $fontScale = '2';
+            $content .= '<TEXT x="290" y="45" font="12" w="' . $fontScale . '" h="' . $fontScale . '" r="90">' . $fullAddress . '</TEXT>';
+            if(!empty($showAddress)){
+                $content .= '<TEXT x="230" y="45" font="12" w="1" h="2" r="90">' . $showAddress . '</TEXT>';
+            }
+            $content .= '<TEXT x="140" y="45" font="12" w="2" h="2" r="90">' . $customMobile . '  ' . $itemNum . '扎</TEXT>';
+            $content .= '<TEXT x="66" y="45" font="12" w="2" h="2" r="90">' . $distName . ' ' . $payDate . '</TEXT>';
             /**************************如果是好多花的云仓还要再打一下标签纸,多处要同步修改,关键词 hdh_yc *****************************/
         }
         $p->printLabelMsg($content);

+ 2 - 3
biz-ghs/order/classes/ShMethodClass.php

@@ -334,7 +334,7 @@ class ShMethodClass extends BaseClass
      * @param array|object $ghsInfo 客户与该供货商的关系信息(xhGhs)
      * @return array ['sendCost' => 运费, 'packCost' => 包装费]
      */
-    public static function calcFee($shopId, $mainId, $sendType, $itemTotalAmount, $bigNum, $customId = 0, $ghsInfo = [])
+    public static function calcFee($config, $sendType, $itemTotalAmount, $bigNum, $customId = 0, $ghsInfo = [])
     {
         $costs = ['sendCost' => 0, 'packCost' => 0];
         
@@ -343,8 +343,6 @@ class ShMethodClass extends BaseClass
             return $costs;
         }
 
-        $config = self::getConfig($shopId, $mainId, $style);
-
         if (empty($config)) {
             return $costs;
         }
@@ -421,6 +419,7 @@ class ShMethodClass extends BaseClass
 
         $saveData = [
             'name' => $data['name'] ?? '',
+            'calcType' => isset($data['calcType']) ? (int)$data['calcType'] : 0, // 算运费方式 (0: 用跑腿, 1: 用自定义)
             'status' => isset($data['status']) ? (int)$data['status'] : 1,
             'sort' => isset($data['sort']) ? (int)$data['sort'] : 0,
             'minAmount' => isset($data['minAmount']) ? (float)$data['minAmount'] : 0.00,

+ 69 - 14
common/components/delivery/util/DeliveryQuoteUtil.php

@@ -115,20 +115,42 @@ class DeliveryQuoteUtil
         $sendCost = ($result['price'] ?? 0) / 100;
         $sendDistance = $result['distance'] ?? 0;
 
-        // 11. 应用免费配送规则
-        if(isset($params['order']['freightType']) && $params['order']['freightType'] == 0) { //用于处理及区分花束订单是否部分免跑腿费,还是完全收取跑腿费
-            $finalSendCost= $sendCost;
-        }else{
-            $finalSendCost = self::applyFreeDeliveryRules(
-                $sendCost,
-                $sendDistance,
-                $params['ghsInfo']['shopId'],
-                $params['productCount'],
-                $params['order']['itemTotalAmount'],
-                $params['ghsInfo']['mainId'],
-                $order['orderSn'],
-                $order['goodsType']
-            );
+        if (empty($params['shConfig'])) {
+            //旧的规则走这个
+
+            // 11. 应用免费配送规则
+            if (isset($params['order']['freightType']) && $params['order']['freightType'] == 0) { //用于处理及区分花束订单是否部分免跑腿费,还是完全收取跑腿费
+                $finalSendCost = $sendCost;
+            } else {
+                $finalSendCost = self::applyFreeDeliveryRules(
+                    $sendCost,
+                    $sendDistance,
+                    $params['ghsInfo']['shopId'],
+                    $params['productCount'],
+                    $params['order']['itemTotalAmount'],
+                    $params['ghsInfo']['mainId'],
+                    $order['orderSn'],
+                    $order['goodsType']
+                );
+            }
+        } else {
+            //新免费规则走这里,欧阳写到这里有问题沟通 ssh 20260730
+
+            $freightType = $params['order']['freightType'] ?? 0; //运费计算方式,0 按距离计算 1 免运费,包运费
+            $property = $order['goodsType'] ?? 1;//订单是什么类型订单 0 花束订单 1 花材订单,多种商品,只要含一把花束,就是花束订单
+            $totalPrice = $params['order']['itemTotalAmount'] ?? 0;
+            $totalNum = $params['productCount'] ?? 0;
+            $element = [
+                'shConfig' => $params['shConfig'],
+                'sendCost' => $sendCost,
+                'sendDistance' => $sendDistance,
+                'freightType' => $freightType,
+                'property' => $property,
+                'totalPrice' => $totalPrice,
+                'totalNum' => $totalNum,
+            ];
+            $discountRespond = self::discountSearch($element);
+            $finalSendCost = $discountRespond['sendCost'] ?? 0;
         }
 
         return [
@@ -139,6 +161,39 @@ class DeliveryQuoteUtil
         ];
     }
 
+    //查询是否符合跑腿的满减规则
+    private static function discountSearch($params)
+    {
+        $shConfig = $params['shConfig'] ?? [];
+        $sendCost = $params['sendCost'] ?? 0;
+        $sendDistance = $params['sendDistance'] ?? 0;
+        $freightType = $params['freightType'] ?? 0;
+        $property = $params['property'] ?? 1;
+        $totalPrice = $params['totalPrice'] ?? 0;
+        $totalNum = $params['totalNum'] ?? 0;
+
+        //免运费的情况 (配置本身设为包邮)
+        if ($freightType == 1) {
+            return ['sendCost' => 0];
+        }
+
+        // 遍历满减规则,判断是否符合免邮条件
+        if (!empty($shConfig['reduceRules']) && is_array($shConfig['reduceRules'])) {
+            foreach ($shConfig['reduceRules'] as $rule) {
+                $meetNum = (float)($rule['meetNum'] ?? 0);
+                $meetAmount = (float)($rule['meetAmount'] ?? 0);
+                $freeKm = (float)($rule['freeKm'] ?? 0);
+
+                // 校验规则:金额满 meetAmount 且 数量满 meetNum 且 距离在 freeKm 以内
+                if ($totalPrice >= $meetAmount && $totalNum >= $meetNum && $sendDistance <= $freeKm) {
+                    return ['sendCost' => 0];
+                }
+            }
+        }
+
+        return ['sendCost' => $sendCost];
+    }
+
     /**
      * 计算商品总重量
      *

+ 5 - 0
common/components/dict.php

@@ -13,6 +13,7 @@ class dict
             0 => [
                 'name' => '送货',
                 'originName' => '送货',
+                'calcType' => 0,
                 'status' => 1,
                 'sort' => 1,
                 'minAmount' => 0.00,
@@ -27,6 +28,7 @@ class dict
             1 => [
                 'name' => '自取',
                 'originName' => '自取',
+                'calcType' => 0,
                 'status' => 1,
                 'sort' => 2,
                 'minAmount' => 0.00,
@@ -41,6 +43,7 @@ class dict
             2 => [
                 'name' => '跑腿',
                 'originName' => '跑腿',
+                'calcType' => 0,
                 'status' => 1,
                 'sort' => 3,
                 'minAmount' => 0.00,
@@ -55,6 +58,7 @@ class dict
             4 => [
                 'name' => '快递',
                 'originName' => '快递',
+                'calcType' => 0,
                 'status' => 1,
                 'sort' => 4,
                 'minAmount' => 0.00,
@@ -69,6 +73,7 @@ class dict
             3 => [
                 'name' => '物流',
                 'originName' => '物流',
+                'calcType' => 0,
                 'status' => 1,
                 'sort' => 5,
                 'minAmount' => 0.00,

+ 43 - 5
common/components/mapUtil.php

@@ -47,6 +47,44 @@ class mapUtil
         return $distance;
     }
 
+    //计算客户到店距离,骑电动车 ssh 2026.7.30
+    public static function calcShopDistanceByEleBike($beginPlace, $toPlace, $report = 1)
+    {
+        $beginLnt = $beginPlace->long ?? '';
+        $beginLat = $beginPlace->lat ?? '';
+        $toLnt = $toPlace->long ?? '';
+        $toLat = $toPlace->lat ?? '';
+
+        // 校验经纬度参数格式
+        if (empty($beginLnt) || empty($beginLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,请完善地址');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        if (!is_numeric($beginLnt) || !is_numeric($beginLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,请完善地址');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        if (empty($toLnt) || empty($toLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,商家地址没有完善');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        if (!is_numeric($toLnt) || !is_numeric($toLat)) {
+            if ($report == 1) {
+                util::fail('计算距离失败,商家地址没有完善');
+            }
+            return ['distance' => 0, 'distanceKm' => 0];
+        }
+        $distance = self::calculateDistance($beginLnt, $beginLat, $toLnt, $toLat);
+        $distanceKm = bcdiv($distance, 1000, 2);
+        return ['distance' => $distance, 'distanceKm' => $distanceKm];
+    }
+
     /**
      * 批量计算多个起点到一个终点的距离 (高德 V3 距离测量接口)
      * @param array $origins 起点坐标数组,例如:[['lng' => '116.481028', 'lat' => '39.989643'], ...]
@@ -79,12 +117,12 @@ class mapUtil
         if (!empty($result['status']) && $result['status'] == 1 && !empty($result['results'])) {
             foreach ($result['results'] as $index => $res) {
                 // 返回的结果顺序与传入的 origins 顺序一致
-                $distances[$index] = $res['distance'] ?? 0; 
+                $distances[$index] = $res['distance'] ?? 0;
             }
-        }else{
-            noticeUtil::push("高德批量测距接口返回失败:".json_encode($result)." url:".$url);
+        } else {
+            noticeUtil::push("高德批量测距接口返回失败:" . json_encode($result) . " url:" . $url);
         }
-        
+
         return $distances;
     }
 
@@ -316,4 +354,4 @@ class mapUtil
         }
         return false;
     }
-}
+}

+ 24 - 0
common/components/miniUtil.php

@@ -1689,6 +1689,30 @@ class miniUtil
         return $behind . $fileName;
     }
 
+    /**
+     * 获取小程序手机号 (新接口) ssh 2025.07.28
+     * @param $merchant
+     * @param $code
+     * @param int $ptStyle
+     * @return mixed
+     */
+    public static function getPhoneNumber($merchant, $code, $ptStyle = 3)
+    {
+        $accessToken = self::getMiniProgramAccessToken($merchant, $ptStyle);
+        if (empty($accessToken)) {
+            return ['errcode' => -1, 'errmsg' => '获取微信令牌失败'];
+        }
+
+        $url = "https://api.weixin.qq.com/wxa/business/getuserphonenumber?access_token={$accessToken}";
+        $data = ['code' => $code];
+
+        $curl = new curl\Curl();
+        $curl->setOption(CURLOPT_SSL_VERIFYPEER, false);
+        $result = $curl->setOption(CURLOPT_POSTFIELDS, Json::encode($data))->post($url);
+
+        return Json::decode($result);
+    }
+
     //微信开放平台获取component_access_token
     public static function getComponentAccessToken($open)
     {