dong025 3 өдөр өмнө
parent
commit
245cafd63f

+ 2 - 0
.gitignore

@@ -4,3 +4,5 @@
 /.idea
 /.vscode
 vendor.zip
+public/.htaccess
+public/nginx.htaccess

+ 1 - 1
app/admin/command/FengSu.php

@@ -79,7 +79,7 @@ class FengSu extends Command
 
         $headers = [
             'Accept' => ' application/json, text/plain, */*',
-            'Authorization' => 'Bearer eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiIxODYwNTQ1MTExNSIsImRhdGFfcGVybWlzc2lvbiI6InByb2R1Y3RDb3N0IiwibmlrZSI6IjE4NjA1NDUxMTE1IiwiY3JlYXRlZCI6MTc2NDEyNTQwMzQ0OSwiZHBJZCI6MTAwNjczLCJleHAiOjE3NjQ3MzAyMDMsImVuYWJsZWQiOnRydWUsImF1dGhvcml0aWVzIjpbInpodXlvbmdodSJdLCJkcEFjY291bnRJZCI6MTAwNjczfQ.ihv6NRfD2hzU1NQoqttTaZ-mPxqAEXIUICM8MuxVx2tVLEPW9j-uPhHoFz4T3-lH07wTt2ORf1k_SPOQP4PuQg',
+            'Authorization' => site_config("addonsd.authorization_token"),
             'Host' => ' fsdy2.fengsutb.com',
             'platform' => $platform,
             'Content-Type' => ' application/json'

+ 56 - 190
app/admin/command/JuShuiTan.php

@@ -23,9 +23,9 @@ use app\common\model\ShopList;
 use app\common\model\ProductConfig;
 use app\common\model\ShopDelivery;
 use app\common\model\CustomerSpec;
-use app\admin\service\FengsuService;
+use app\admin\service\JuShuiTanService;
 use GuzzleHttp\Psr7\Request;
-
+use app\common\model\ImportList;
 //抖音
 class JuShuiTan extends Command
 {
@@ -39,9 +39,11 @@ class JuShuiTan extends Command
         'Accept' => 'application/json, text/plain, */*',
         'Authorization' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIyMTk0MzA5MSIsInJvbGVJZHMiOltdLCJ1c2VyX25hbWUiOiIxODE4MjY2OTkzNSIsImNvSWQiOiIxNDc5MjIyMiIsImV4cGlyYXRpb24iOjE3NjYyMTg0NDM1MzQsInVzZXIiOnsiY29JZCI6IjE0NzkyMjIyIiwiY29OYW1lIjoi5LqR5Y2X5LmQ55Wq55Sw5L6b5bqU6ZO-5pyJ6ZmQ5YWs5Y-4IiwibG9naW5OYW1lIjoiMTgxODI2Njk5MzUiLCJsb2dpbldheSI6IlVTRVJOQU1FIiwibmlja05hbWUiOiLmnY4iLCJyb2xlSWRzIjoiMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMjIsMjMsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzksNDAsNDEsNTIsNTMsNTQsNjEsNjIsNjMsNjQsNjUsNjYsNjcsNzAsNzEsNzIsNzMsNzYsOTAsMTAxLDEwMiwxMDMsMTA0LDEwNSwxMDYsMTA3LDEwOCwxMDkiLCJ1aWQiOiIyMTk0MzA5MSJ9LCJhdXRob3JpdGllcyI6WyJKU1QtY2hhbm5lbCIsIm11bHRpTG9naW4iLCJKU1Qtc3VwcGxpZXIiXSwiY2xpZW50X2lkIjoicGMiLCJqdGkiOiIxYjNhZjA4OC04ZDhiLTRhNzMtYjcwNC1lYzhhY2QwNzU1ODUiLCJleHAiOjE3NjYyMTg0NDN9.fXIP-yUlJDIfd49QgxjTQXUlRka2gpw0NrfY7lB50sU',
         'Content-Type' => 'application/json',
-        //'platform' => 'dy',
+        // 'platform' => 'dy',
     ];
 
+    // 打单平台 1:风速  2:聚水潭
+    protected $type_id=2;
     // 指令配置
     protected function configure()
     {
@@ -53,10 +55,11 @@ class JuShuiTan extends Command
     {
         $output->writeln('开始同步聚水潭订单');
         $resquet = $this->getOrderList('dy');
-        dump($resquet);
         if($resquet['success']){
-            if($resquet['data']['total'] > 0){
+            if(count($resquet['data']) > 0){
                 $list = $resquet['data'];
+                // dump($list);
+                // return;
                 $this->insertOrder($list);
                 //dump($resquet);
             }else{
@@ -79,12 +82,19 @@ class JuShuiTan extends Command
 
         $headers = [
             'Accept' => ' application/json, text/plain, */*',
-            'Authorization' => 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOiIyMTk0MzA5MSIsInJvbGVJZHMiOltdLCJ1c2VyX25hbWUiOiIxODE4MjY2OTkzNSIsImNvSWQiOiIxNDc5MjIyMiIsImV4cGlyYXRpb24iOjE3NjYyMTg0NDM1MzQsInVzZXIiOnsiY29JZCI6IjE0NzkyMjIyIiwiY29OYW1lIjoi5LqR5Y2X5LmQ55Wq55Sw5L6b5bqU6ZO-5pyJ6ZmQ5YWs5Y-4IiwibG9naW5OYW1lIjoiMTgxODI2Njk5MzUiLCJsb2dpbldheSI6IlVTRVJOQU1FIiwibmlja05hbWUiOiLmnY4iLCJyb2xlSWRzIjoiMTEsMTIsMTMsMTQsMTUsMTYsMTcsMTgsMjIsMjMsMjcsMjgsMjksMzAsMzEsMzIsMzMsMzQsMzUsMzYsMzksNDAsNDEsNTIsNTMsNTQsNjEsNjIsNjMsNjQsNjUsNjYsNjcsNzAsNzEsNzIsNzMsNzYsOTAsMTAxLDEwMiwxMDMsMTA0LDEwNSwxMDYsMTA3LDEwOCwxMDkiLCJ1aWQiOiIyMTk0MzA5MSJ9LCJhdXRob3JpdGllcyI6WyJKU1QtY2hhbm5lbCIsIm11bHRpTG9naW4iLCJKU1Qtc3VwcGxpZXIiXSwiY2xpZW50X2lkIjoicGMiLCJqdGkiOiIxYjNhZjA4OC04ZDhiLTRhNzMtYjcwNC1lYzhhY2QwNzU1ODUiLCJleHAiOjE3NjYyMTg0NDN9.fXIP-yUlJDIfd49QgxjTQXUlRka2gpw0NrfY7lB50sU',
+            'Authorization' =>site_config('addonsd.ju_shui_tan_authorization_toke'),
             'Content-Type' => ' application/json'
         ];
+        $todayTime=date("Y-m-d");
+        
+        $startTime = strtotime($todayTime . ' 00:00:00');
+        $startTime=date('Y-m-d H:i:s', $startTime);
+        // $startTime='2025-01-01 08:59:21';
+        $endTime = strtotime($todayTime . ' 23:59:59');
+        $endTime=date('Y-m-d H:i:s', $endTime);
         $body = '{
-            "startTime": "2025-11-28 00:00:00",
-            "endTime": "2025-11-28 23:59:59",
+            "startTime": "'.$startTime.'",
+            "endTime": "'.$endTime.'",
             "dateQueryType": "DeliveryDate",
             "coId": "14792222",
             "uid": "21943091",
@@ -97,6 +107,8 @@ class JuShuiTan extends Command
                 "Sent"
             ]
         }';
+        // "orderFrom":"PINDUODUO"
+        //"trackNo":"@SF3278427215674"
         $request = new Request('POST', 'https://innerapi.scm121.com/api/inner/supOrder/getErpNormalOrders', $headers, $body);
         $res = $client->sendAsync($request)->wait();
         $json = [];
@@ -118,197 +130,51 @@ class JuShuiTan extends Command
         $productConfig = new ProductConfig();
         $shopDelivery = new ShopDelivery();
         $customerSpec = new CustomerSpec();
+        
+        usort($order_list, function($a, $b) {
+            // 将create_time转换为时间戳比较(支持字符串时间戳)
+            $timeA = strtotime($a['deliveryDate']);
+            $timeB = strtotime($b['deliveryDate']);
+            
+            // 降序排序(从新到旧)
+            // return $timeB - $timeA;
+            
+            // 升序排序(从旧到新)可改为:
+            return $timeA - $timeB;
+        });
         foreach($order_list as $item) {
-            dump($item['shopId'], '店铺id');
-            $status = FengsuService::getAdditionalPrice( $shopList, $fengsuSku, $productConfig, $shopDelivery, $customerSpec, $item);
+            // dump($item['shopId'], '店铺id');
+            // 防止重复记录,订单号+快递单号
+            $goods_id=$item['disInnerOrderGoodsViewList'][0]['shopIid'];
+            $oid=$item['oid'];
+            $waybill_no=ltrim($item['trackNo'], '@');
+            $add_status = JuShuiTanService::prevent_duplicate_additions($oid,$waybill_no);
+            if($add_status) continue;
+            $status = JuShuiTanService::getAdditionalPrice( $shopList, $fengsuSku, $productConfig, $shopDelivery, $customerSpec, $item);
             $queue[] = [
+                'type_id'       => $this->type_id,
                 'shop_id'       => $item['shopId'],
-                'trade_from'    => $item['tradeFrom'],
-                'province'      => $item['receiverProvince'],
+                'order_id'       => $oid,
+                'trade_from'    => $item['orderFrom'],
+                'province'      => $item['receiverState'],
                 'city'          => $item['receiverCity'],
-                'company_name'  => $item['tradeOrderPrintVos'][0]['companyName'],
-                'waybill_no'    => $item['waybillNo'],
-                'consign_time'  => $item['consignTime'],
-                'goods_id'      => $item['tradeOrderPrintVos'][0]['goodsId'],
-                'sku_id'        => $item['tradeOrderPrintVos'][0]['skuId'],
-                'num'           => $item['tradeOrderPrintVos'][0]['total'],
-                'goods_title'   => $item['tradeOrderPrintVos'][0]['goodsTitle'],
-                'weigh'         => $item['tradeOrderPrintVos'][0]['weight'],
-                'price'         => bcdiv((string)$item['payment'], '100', 2),
+                'company_name'  => $item['expressCompany'],
+                'waybill_no'    => $waybill_no,
+                'consign_time'  => $item['deliveryDate'],
+                'goods_id'      => $goods_id,
+                'sku_id'        => $item['disInnerOrderGoodsViewList'][0]['shopSkuId'],
+                'num'           => $item['disInnerOrderGoodsViewList'][0]['itemCount'],
+                'goods_title'   => $item['disInnerOrderGoodsViewList'][0]['itemName'],
+                'goods_info'   => $item['disInnerOrderGoodsViewList'][0]['properties'],
+                'weigh'         => $item['weight'],
+                'price'         => bcdiv((string)$item['disInnerOrderGoodsViewList'][0]['price'], '1', 2),
                 'status'        => $status,
             ];
         }
 
         // 保存到数据库
-        (new FengsuShip())->saveAll($queue);
+        (new ImportList())->saveAll($queue);
         // 更新最后执行时间
         CrontabLog::create(['type_id' => 2,'last_time' => date('Y-m-d H:i:s')]);
     }
-}
-//风速接口返回格式
-//            {
-//                "shopId": "DY117939700",
-//                "sysNum": "3908161982177974",
-//                "groupId": "g3908162034664709",
-//                "tradeFrom": "dy",
-//                "tid": "6948414820472788426",
-//                "fromAccountId": 0,
-//                "createTime": "2025-11-26 21:27:53",
-//                "payTime": "2025-11-26 21:27:55",
-//                "inserTime": "2025-11-27 15:11:27",
-//                "inventoryPrintTime": null,
-//                "consignTime": "2025-11-27 15:11:27",
-//                "refunding": 0,
-//                "buyerId": "1@#MhctHqbGY6MptrPvaPcNSU6JEPT1RwM+zhPxvrsCvBSVf2u9/qsla+xb9Fu81aUBMmCH",
-//                "buyerNick": null,
-//                "buyerMessage": "",
-//                "sellerFlag": 0,
-//                "localFlag": 0,
-//                "sellerMemo": null,
-//                "localMemo": null,
-//                "offlineMemo": null,
-//                "offlineFlag": null,
-//                "receiverProvince": "黑龙江省",
-//                "receiverCity": "哈尔滨市",
-//                "receiverDistrict": "依兰县",
-//                "receiverTown": "依兰镇",
-//                "desensitizationName": "昕*",
-//                "desensitizationPhone": null,
-//                "desensitizationAddress": "*******",
-//                "desensitizationMobile": "1**********",
-//                "modifyAddr": 0,
-//                "invoiceType": null,
-//                "invoiceTitle": null,
-//                "invoiceTaxId": null,
-//                "promiseShipTime": "2025-12-01 21:27:56",
-//                "tradeStatus": "WAIT_CONFIRM",
-//                "payment": 9440,
-//                "receiptAmount": 9440,
-//                "postFee": 0,
-//                "splitType": 1,
-//                "packageNum": 1,
-//                "dpAccountId": 100673,
-//                "bizDpAccountId": 100673,
-//                "uid": "117939700",
-//                "bizShopId": "DY117939700",
-//                "companyName": "中通快递",
-//                "waybillNo": null,
-//                "companyId": 3,
-//                "templateId": 145375,
-//                "printSize": 1,
-//                "mergeHash": "6BC35CF08C74762098670BB71B38F77C387FB374",
-//                "mergeHash2": "AC9CEFB7FD89A32A1AA235A9E09BD69FE838D08D",
-//                "mergeable": 0,
-//                "handDeliverFlag": 0,
-//                "tradeAttr": "{\"promise_type\":1,\"recommend_logistics_list\":\"[]\"}",
-//                "localAttr": null,
-//                "senderAddressEntity": null,
-//                "outChannel": null,
-//                "tradeFlag": null,
-//                "link": "",
-//                "roleFlg": true,
-//                "shopFlg": true,
-//                "saleFlg": true,
-//                "picUrlFlag": true,
-//                "preSale": 1,
-//                "preSaleTime": null,
-//                "splitFailReason": null,
-//                "businessTag": 0,
-//                "locked": 0,
-//                "tradeOrderPrintVos": [
-//                    {
-//                        "distTime": null,
-//                        "orderStatus": "WAIT_CONFIRM",
-//                        "goodsTitle": "田与薯云南圆圆果·榴莲蜜薯软糯蜜甜新鲜高原黄心番薯地瓜粗粮",
-//                        "goodsId": "3665081518029678296",
-//                        "skuProp": "{\"65\":\"小糖豆(50g-150g)\",\"66\":\"5斤(精品装(带箱5斤))\",\"67\":\"5天内发货\"}",
-//                        "companyName": "中通快递",
-//                        "waybillNo": "76767227765924",
-//                        "outerId": null,
-//                        "refundStatus": null,
-//                        "picUrl": "https://p3-aio.ecombdimg.com/obj/ecom-shop-material/jpeg_m_e379a8d857f16246745a757892497184_sx_320989_www1668-1668",
-//                        "total": 1,
-//                        "price": 3980,
-//                        "payment": 3780,
-//                        "receiptAmount": null,
-//                        "orderType": 0,
-//                        "consignTime": "2025-11-27 15:11:27",
-//                        "signTime": null,
-//                        "weight": 0,
-//                        "goodShortName": null,
-//                        "skuShortName": null,
-//                        "oid": "6948414820472788426",
-//                        "packageNum": 1,
-//                        "splitType": 1,
-//                        "companyId": 3,
-//                        "templateId": 145375,
-//                        "outerSkuId": "LFT-LLSPK-4.5-SC-CX",
-//                        "skuId": "3617103894193922",
-//                        "printSize": 1,
-//                        "printTime": "2025-11-27 15:11:22",
-//                        "roleType": 1,
-//                        "roleName": "田与薯官方旗舰店",
-//                        "lastFactoryId": 100673,
-//                        "inventoryPrintSize": 0,
-//                        "inventoryPrintTime": null,
-//                        "platCode": "ZJ",
-//                        "purchaseAttr": null,
-//                        "shelfPosition": "",
-//                        "pushTime": null,
-//                        "orderAttr": "{\"author_name\":\"田与薯官方旗舰店\",\"order_goods_type\":0,\"order_biz\":2,\"pre_sale_label\":\"全款预售\",\"compensate_for_rotten_platform_guarantee\":\"坏了包退官方保障\",\"quick_refund_label\":\"极速退\",\"unsupport_7days_refund\":\"不支持7天\",\"c_biz_self_sell\":\"小店自卖\",\"compass_source_not_ad_mark\":\"非广告\",\"compass_source_content_type_live\":\"直播\",\"afterSaleType\":\"refund\",\"source_platform\":\"\",\"period_purchase_info\":{},\"pack_id\":\"147242304405974025\"}",
-//                        "freeze": 0,
-//                        "freezeReason": null,
-//                        "auditStatus": 2,
-//                        "payStatus": null,
-//                        "settleStatus": null,
-//                        "settleRefundStatus": null,
-//                        "settleAmount": null,
-//                        "templateType": "1",
-//                        "productSkuName": null,
-//                        "productSkuCode": null
-//                    }
-//                ],
-//                "tradePrintList": null,
-//                "platCode": "ZJ",
-//                "purchaseId": null,
-//                "purchaseStatus": null,
-//                "supplierName": null,
-//                "supplierId": null,
-//                "purchaseName": null,
-//                "offerId": null,
-//                "specId": null,
-//                "tradeClassify": "NORMAL",
-//                "payType": "NORMAL",
-//                "expressType": "NORMAL",
-//                "msgTradeAttr": null,
-//                "logisticsNames": null,
-//                "logisticsTag": 0,
-//                "tradeSource": null,
-//                "printBatch": null,
-//                "printBatchSn": 0,
-//                "assignDeliveryId": null,
-//                "factoryId": 100673,
-//                "prepareShipGroupId": null,
-//                "prepareShipDeliverStatus": null,
-//                "prepareShipErrorMsg": null,
-//                "prepareShipStatus": 0,
-//                "prepareShipCreateTime": null,
-//                "prepareShipUpdateTime": null,
-//                "waybillEntities": [
-//                    {
-//                        "id": 7671095,
-//                        "dpAccountId": 100673,
-//                        "relationId": 3909499998804122,
-//                        "deliveryId": 3,
-//                        "waybillNo": "76767227765924",
-//                        "createdTime": "2025-11-27 15:11:27",
-//                        "recycleFlag": 0
-//                    }
-//                ],
-//                "relationId": 3909499998804122,
-//                "optType": 0,
-//                "obsStatus": 0,
-//                "obsTime": null,
-//                "obsReason": null,
-//                "printFailReason": null
-//            },
+}

+ 213 - 0
app/admin/controller/goods/ImportList.php

@@ -0,0 +1,213 @@
+<?php
+
+declare(strict_types=1);
+
+namespace app\admin\controller\goods;
+
+use app\common\controller\Backend;
+use app\admin\traits\Actions;
+use think\annotation\route\Group;
+use think\annotation\route\Route;
+use think\facade\Db;
+use app\common\model\FengsuSku;
+use app\common\model\ShopList;
+use app\common\model\StockConfig;
+use app\common\model\ShopDelivery;
+use app\admin\service\JuShuiTanService;
+use app\common\model\CustomerSpec;
+use app\common\model\ProductConfig;
+use app\common\model\ImportList as ImportListModel;
+use app\common\model\ShopList as ShopListModel;
+#[Group("goods/import_list")]
+class ImportList extends Backend
+{
+    //app\admin\controller\goods\ImportList
+    use Actions {
+        index as private _index;
+        del as private _del;
+    }
+
+    protected function _initialize()
+    {
+        parent::_initialize();
+        $this->model = new ImportListModel();
+        $this->assign('shopList', ShopList::where('status', 1)->column('name', 'id'));
+        $this->assign('typeList',  StockConfig::where('type_id', 'variety_name')->order('sort desc')->column('title', 'id'));
+        $this->assign('packingList', StockConfig::where('type_id', 'packing_box')->column('title', 'id'));
+    }
+
+    /**
+     * 查看
+     */
+    #[Route('GET,JSON', 'index')]
+    public function index()
+    {
+        if (false === $this->request->isAjax()) {
+            return $this->fetch();
+        }
+        if ($this->request->post('selectpage')) {
+            return $this->selectpage();
+        }
+        [$where, $order, $limit, $with] = $this->buildparams();
+        
+        $list = $this->model
+            ->withJoin($with, 'left')
+            //如果没有使用operate filter过滤的情况下,推荐使用with关联,可以提高查询效率
+            //->with($with)
+            ->where($where)
+            ->order($order)
+            ->paginate($limit)
+            ->each(function ($item, $key) {
+                if(empty($item['type_id'])){
+                    $item['type_id']=0;
+
+                    
+                }
+                $trade_from_list=site_config("addonsd.ju_shui_tan_trade_from_list");
+                $trade_from=$item['trade_from'];
+                $item['trade_from']=empty($item['trade_from'])?'无':$trade_from_list[$trade_from];
+                
+                return $item;
+            });
+        $result = ['total' => $list->total(), 'rows' => $list->items()];
+        return json($result);
+    }
+
+    /**
+     * 关联店铺
+     */
+    #[Route('GET,POST', 'shops')]
+    public function shops()
+    {
+        if (false === $this->request->isPost()) {
+            $ids = $this->request->get('ids/s', '');
+            return $this->fetch();
+        }
+        $params = array_merge($this->request->post("row/a"), $this->postParams);
+        if (empty($params)) {
+            $this->error(__('提交的参数不能为空'));
+        }
+        if (!$this->request->checkToken('__token__', ['__token__' => $this->request->post('__token__')])) {
+            $this->error(__('token错误,请刷新页面重试'));
+        }
+        foreach ($params as &$value) {
+            if (is_array($value)) {
+                $value = implode(',', $value);
+            }
+            if ($value === '') {
+                $value = null;
+            }
+        }
+        $ids = $this->request->get('ids/s', '');
+        if (empty($params['shop_id'])) $this->error(__('请选择店铺'));
+        $result = false;
+        Db::startTrans();
+        try {
+            //更新店铺
+            ShopList::where('id', $params['shop_id'])->update(['shop_id' => $ids]);
+            //更新状态
+            $result = $this->model->where('shop_id', $ids)->update(['status' => 2]);
+            if ($this->callback) {
+                $callback = $this->callback;
+                $callback($this->model);
+            }
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+        if ($result === false) {
+            $this->error(__('没有新增任何数据'));
+        }
+        $this->success();
+    }
+
+    /**
+     * 关联规格
+     */
+    #[Route('GET,POST', 'specs')]
+    public function specs(mixed $row = null)
+    {
+        $ids = $this->request->param('ids');
+        if (!$row || is_array($row)) {
+            $row = $this->model->find($ids);
+        }
+        if (!$row) {
+            $this->error(__('没有找到记录'));
+        }
+        if (count($this->volidateFields) > 0) {
+            foreach ($this->volidateFields as $field => $value) {
+                if ($row[$field] != $value) {
+                    $this->error(__('没有操作权限'));
+                }
+            }
+        }
+        if (false === $this->request->isPost()) {
+            $shop_id=$row['shop_id'];
+            $shopListModel=new ShopListModel();
+            
+            $rows = $shopListModel::where('shop_id', $shop_id)->where('status', 1)->find();
+            $this->assign('rows', $rows->type_spec??'');
+            $this->assign('row', $row);
+            return $this->fetch();
+        }
+        $params = $this->request->post("");
+        if (empty($params['all_data'])) $this->error(__('请选择规格'));
+        $count = 0;
+        Db::startTrans();
+        try {
+
+            //插入规格
+            FengsuSku::insertSpecs($row['shop_id'], $row['sku_id'], (int)$params['all_data'][0]['type_id'], (int)$params['all_data'][0]['id']);
+
+            //查看有多少规格
+            $list = $this->model::where('shop_id', $row['shop_id'])->where('sku_id', $row['sku_id'])->where('status', 2)->select();
+            $shopList = new ShopList();
+            $productConfig = new ProductConfig();
+            $shopDelivery = new ShopDelivery();
+            $customerSpec = new CustomerSpec();
+            $fengsuSku = new FengsuSku();
+            foreach ($list as $item) {
+                //插入发货数据
+                JuShuiTanService::setAdditionalPrice(
+                    $fengsuSku,
+                    $shopList,
+                    $productConfig,
+                    $shopDelivery,
+                    $customerSpec,
+                    $row['shop_id'],
+                    $row['sku_id'],
+                    $params['all_data'][0]['type_id'],
+                    $params['all_data'][0]['id'],
+                    $params['all_data'][0]['name'],
+                    $row
+                );
+
+                $count += $item->save(['status' => 3]);
+            }
+            if ($this->callback) {
+                $callback = $this->callback;
+                $callback($ids);
+            }
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollback();
+            $this->error($e->getMessage());
+        }
+
+        if ($count) {
+            return resp_json(200, '操作成功');
+        }
+        $this->error(__('没有数据被更新'));
+    }
+
+
+    //删除
+    #[Route("GET,POST", "del")]
+    public function del()
+    {
+        //通过定义callback回调函数来执行删除后的操作
+        $this->callback = function ($ids) {};
+        return $this->_del();
+    }
+}

+ 1 - 1
app/admin/controller/shop/CustomerSpec.php

@@ -76,7 +76,7 @@ class CustomerSpec extends Backend
                         'product_id'  => $item['value'],
                         'box_id'      => $item['packet']??0,
                         'price'       => $item['price']??0,
-                        'fast_mail'   => $item['fast_mail']
+                        'fast_mail'   => $item['fast_mail']??0
 
                     ]);
                     $result++;

+ 147 - 0
app/admin/service/JuShuiTanService.php

@@ -0,0 +1,147 @@
+<?php
+/**
+ * ----------------------------------------------------------------------------
+ * 行到水穷处,坐看云起时
+ * 开发软件,找贵阳云起信息科技,官网地址:https://www.56q7.com/
+ * ----------------------------------------------------------------------------
+ * Author: 老成
+ * email:85556713@qq.com
+ */
+declare(strict_types=1);
+namespace app\admin\service;
+
+use app\common\model\ImportList;
+
+class JuShuiTanService {
+
+    /** 加收价格 
+     * 1.先判断店铺
+     * 2.在判断店铺下面的规格
+     * @param array $item
+     * @return int
+     */
+    public static function getAdditionalPrice(object $shopList, object $fengsuSku, object $productConfig, object $shopDelivery, object $customerSpec, array $item):int
+    {
+        $status = 1;
+        //判断是否存在店铺
+        $shops = $shopList::getSpecsIdByShopId($item['shopId']);
+        if(!$shops->isEmpty()){
+
+            //判断是否存在规格-获取重量
+            $specs = $fengsuSku::getSpecsIdByShopId($shops->shop_id, $item['disInnerOrderGoodsViewList'][0]['shopSkuId']);
+            
+            if(!$specs->isEmpty()) {
+
+                //根据规格重量获取,加收价格
+                $weight = $productConfig::getWeight($specs->spec_id);
+                $status = 3;
+                if($weight){
+                    $other_price = self::getRemoteAreaFee($item['expressCompany'],  $weight, $item['receiverState'], $item['receiverCity']);
+                    //获取包装箱
+                    $box = $customerSpec::getBoxId($shops->customer_id, $specs->variety_id, $specs->spec_id);
+                    $shopDelivery::create([
+                        'customer_id' => $shops->customer_id,
+                        'shop_id' => $shops->id,
+                        'plat_id' => $shops->platform,
+                        'variety_id'    => $specs->variety_id,
+                        'spec_id'       => $specs->spec_id,
+                        'spec_name'     => $specs->spec_name,
+                        'box_id'        => $specs->box_id??0,
+                        'box_name'      => $box->box_name??'',
+                        'variety_name'  => $box->variety_name,
+                        'num'           => $item['disInnerOrderGoodsViewList'][0]['itemCount'],
+                        'weigh'         => $weight,
+                        'price'         => $box->price??0,
+                        'total_price'   => bcmul($box->price, (string)$item['disInnerOrderGoodsViewList'][0]['itemCount'], 2),
+                        'company_name'  => $item['expressCompany'],
+                        'waybill_no'    => ltrim($item['trackNo'], '@'),
+                        'region'        => $item['receiverState'].' '.$item['receiverCity'],
+                        'other_price'   => $other_price,
+                        'ship_date'     => substr($item['deliveryDate'], 0, 10),
+                    ]);
+                }
+            }else{
+                $status = 2;
+            }
+        }
+        return $status;
+    }
+
+
+    /** 编辑规格-加收价格 
+     * @param array $item
+     * @return int
+     */
+    public static function setAdditionalPrice(object $fengsuSku,object $shopList, object $productConfig, object $shopDelivery, object $customerSpec, string $shop_id,$sku_id, $variety_id, $spec_id, string $spec_name, object $item):bool
+    {
+        //判断是否存在规格-获取重量
+        $specs = $fengsuSku::getSpecsIdByShopId($shop_id, $sku_id);
+        //判断是否存在店铺
+        $shops = $shopList::getSpecsIdByShopId($shop_id);
+     
+        //根据规格重量获取,加收价格
+        $weight = $productConfig::getWeight((int)$spec_id);
+    
+        $other_price = self::getRemoteAreaFee($item['company_name'],  $weight??0, $item['province'], $item['city']);
+        //获取包装箱
+        $box = $customerSpec::getBoxId($shops->customer_id, (int)$variety_id, (int)$spec_id);
+        
+        $shopDelivery::create([
+            'customer_id'   => $shops->customer_id,
+            'shop_id'       => $shops->id,
+            'plat_id'       => $shops->platform,
+            'variety_id'    => $variety_id,
+            'spec_id'       => $spec_id,
+            'spec_name'     => $specs->spec_name,
+            'box_id'        => $box->id??0,
+            'box_name'      => $box->box_name??'',
+            'variety_name'  => $box->variety_name,
+            'num'           => $item['num'],
+            'weigh'         => $weight??0,
+            'price'         => $box->price??0,
+            'total_price'   => bcmul((string)$box->price, (string)$item['num'], 2),
+            'company_name'  => $item['company_name'],
+            'waybill_no'    => $item['waybill_no'],
+            'region'        => $item['province'].' '.$item['city'],
+            'other_price'   => $other_price,
+            'ship_date'     => substr($item['consign_time'], 0, 10),
+        ]);
+        return true;
+    }
+
+    /**
+     * 获取偏远地区加收费用
+     * @param string $express 快递公司名称
+     * @param string $area 省份
+     * @param float $weight 重量
+     * @param string $city 城市
+     * @return float
+     */
+    protected static function getRemoteAreaFee(string $express, string $weight, string $area, string $city = ''){
+        $remote_area = config('app.remote_area');
+        $fee = 0;
+        if($express == '顺丰速运'){
+            if(in_array($area, $remote_area[1])) {
+                if($weight >= 3.5) $fee = 5;
+                if($weight >= 4.5) $fee = 6;
+            };
+        }else{
+            //普通(广东省-深圳) -浙江-舟山
+            if(in_array($area, $remote_area[0])) $fee = 1.5;
+            if($area == '广东省' && $city == '深圳市') $fee = 1.5;
+            if($area == '浙江省' && $city == '舟山市') $fee = 1.5;
+        }
+        return $fee;
+    }
+    //防止重复记录,订单号+快递单号
+    public static function prevent_duplicate_additions($oid,$waybill_no){
+        $importList=new ImportList();
+        $where = [
+            'order_id' => ['=', $oid],
+            'waybill_no' => ['=', $waybill_no]
+        ];
+        $result = $importList->where($where)->count();
+        return $result=$result>0?true:false;
+    }
+
+}

+ 129 - 0
app/admin/view/goods/import_list/index.html

@@ -0,0 +1,129 @@
+<template>
+    <el-card shadow="never">
+        <yun-table
+                :columns="columns"
+                ref="yuntable"
+                @render="onTableRender"
+                toolbar="refresh,del"
+                :auth="{
+               
+                    del:{:$auth->check('app\\admin\\controller\\goods\\ImportList','del')},
+         
+                }"
+                :extend="extend">
+        </yun-table>
+    </el-card>
+</template>
+<script>
+import table from "@components/Table.js";
+export default{
+    components:{
+        'YunTable':table
+    },
+    data:{
+        extend:{
+            index_url: 'goods/import_list/index',
+            del_url: 'goods/import_list/del',
+            multi_url: 'goods/import_list/multi',
+        },
+        columns:[
+            {checkbox: true,selectable:function (row,index){
+                //可以根据业务需求返回false让某些行不可选中
+                return true;
+            }},
+            {field:"id",title:"ID",operate:false},
+            {field:"shop_id",title:"店铺ID"},
+            {field: 'type_id', title:('打单平台'), operate: false,searchList: {1:'风速', 2:'聚水潭',0: '无'},formatter: function(data,row){
+                        let tag=Yunqi.formatter.tag;
+                        if(row.type_id==1){
+                            tag.value='风速';
+                            tag.type='success';
+                        }else if(row.type_id==2){
+                            tag.value='聚水潭';
+                            tag.type='primary';
+                        }else{
+                            tag.value='无';
+                            tag.type='info';
+                        }
+                        return tag;
+                    }},
+            {field:"trade_from",title:"平台"},
+            {field:"province",title:"省份",operate: false},
+            {field:"city",title:"城市",operate: false},
+            {field:"company_name",title:"快递名称"},
+            {field:"waybill_no",title:"快递单号"},
+            {field:"goods_title",title:"产品名称",width:300,align:'left'},
+            {field:"goods_info",title:"商品信息",width:300,align:'left'},
+            {field:"sku_id",title:"规格id"},
+            {field:"num",title:"件数",operate: false},
+            {field:"price",title:"实付价格",operate: false},
+            {field:"consign_time",title:"发货时间",operate:"daterange",formatter:Yunqi.formatter.datetime},
+            {field:"status",title:"状态",operate:"select",searchList:{1:"无店铺", 2:"无Sku", 3:"正常"},formatter:Yunqi.formatter.tags},
+            // {field:"user_id",title:"录入人",operate: false},
+            {field:"createtime",title:"创建时间",operate: false,formatter:Yunqi.formatter.datetime},
+            {field:"updatetime",title:"修改时间",visible:false,operate: false,formatter:Yunqi.formatter.datetime},
+            {
+                field: 'operate',
+                fixed: 'right',
+                title: __('操作'),
+                width:150,
+                      action:{
+                        shops:{
+                            tooltip:true,
+                            icon:'fa fa-certificate',
+                            type:'success',
+                            text:__('关联店铺'),
+                            method:'shops',
+                            visible:function(row,index){
+                                return row.status == 1;
+                            }
+                        },
+                        specs:{
+                            tooltip:true,
+                            icon:'fa fa-list',
+                            type:'info',
+                            text:__('关联规格'),
+                            method:'specs',
+                            visible:function(row,index){
+                                return row.status == 2;
+                            }
+                        },
+                        del:true
+                    }
+            }
+        ]
+    },
+    methods: {
+        shops:function (row){
+            let that=this;
+            Yunqi.api.open({
+                url:'goods/import_list/shops?ids='+row.shop_id,
+                width:1000,
+                title:__('关联店铺'),
+                icon:'fa fa-list',
+                close:function (r){
+                    that.$refs.yuntable.reload();
+                }
+            });
+        },
+        specs:function (row){
+            let that=this;
+            Yunqi.api.open({
+                url:'goods/import_list/specs?ids='+row.id,
+                width:1000,
+                title:__('关联规格'),
+                icon:'fa fa-list',
+                close:function (r){
+                    if(r){
+                        that.$refs.yuntable.reload();
+                    }
+                }
+            })
+            
+        },
+  
+    }
+}
+</script>
+<style>
+</style>

+ 76 - 0
app/admin/view/goods/import_list/shops.html

@@ -0,0 +1,76 @@
+<template>
+    <el-card shadow="never" style="border: 0;">
+        <yun-form
+            ref="yunform"
+            @render="onFormRender"
+            @submit="onSubmit"
+            @success="onSuccess"
+            @fail="onFail"
+            :data="row"
+            :columns="columns">
+            <template #default>
+                {:token_field()}
+            </template>
+    
+        </yun-form>
+    </el-card>
+</template>
+<script>
+import form from "@components/Form.js";
+export default{
+    components:{
+        'YunForm':form
+    },
+    data:{
+        columns:[
+            {field:"id",title:"ID",edit:"hidden"},
+            {field:"shop_id",title:"店铺名称",searchList:Yunqi.data.shopList,edit: 'select',rules:'required'},
+        ],
+        row:Yunqi.data.row || {}
+    },
+    //页面加载完成时执行
+    onLoad:function(query){
+        
+        
+    },
+    //页面初始显示或在框架内显示时执行
+    onShow:function(){
+
+    },
+    //页面在框架内隐藏时执行
+    onHide:function(){
+
+    },
+    //页面在框架内关闭时执行
+    onUnload:function(){
+
+    },
+    methods: {
+        onFormRender:function(rows){
+            //表单渲染完成后执行
+        },
+        onSubmit:function(rows){
+            //表单提交前执行,返回false可以阻止表单提交
+            /**
+             * form常用方法
+             * this.$refs.yunform.setError(field,message);//聚焦表单项并显示错误信息
+             * this.$refs.yunform.hideField(field);//隐藏表单项
+             * this.$refs.yunform.showField(field);//显示表单项
+             * this.$refs.yunform.setValue(field,value);//为表单项设置值
+             * this.$refs.yunform.getValue(field);//为获取表单项的值
+             * this.$refs.yunform.setField(field,key,value);//修改表单json的其他属性值,比如rules,title,searchList等
+             */
+            return true;
+        },
+        onSuccess:function(response){
+            //表单提交成功后执行
+            console.log(response)
+        },
+        onFail:function(err){
+            //表单提交失败后执行
+        }
+    }
+}
+</script>
+<style>
+</style>

+ 194 - 0
app/admin/view/goods/import_list/specs.html

@@ -0,0 +1,194 @@
+<template>
+    <el-card shadow="never" style="min-height: 450px; max-height: 450px; overflow: auto;">
+        <el-tabs tab-position="left" style="height: 100%; overflow: auto;" v-model="tabValue" @tab-click="handleClick">
+            <el-tab-pane v-for="(item,index) in tabData" :label="item.label" :name="item.value">
+            </el-tab-pane>
+            <el-table :data="tableData" style="width: 100%" border :ref="'multipleTable_' + tabValue" stripe
+                highlight-current-row @select="handleSelectionChange" @select-all="handleAllSelect"
+                @current-change="handleCurrentChange">
+                <el-table-column type="index" width="55">
+                </el-table-column>
+                <el-table-column prop="name" label="规格" align="center">
+                </el-table-column>
+                <!-- <el-table-column prop="packet" label="包装箱" align="center">
+                    <template #default="{row}">
+                        <span>{{options[row.box_id]}}</span>
+                    </template>
+                </el-table-column>
+                <el-table-column prop="price" label="发货价" align="center" ></el-table-column> -->
+
+            </el-table>
+        </el-tabs>
+    </el-card>
+    <div style="width: 100%;display: flex; align-items: center; justify-content: center; position: fixed; bottom: 6px;">
+        <el-button type="primary" @click="onSubmit">立即创建</el-button>
+        <el-button @click="cancelDialog">取消</el-button>
+    </div>
+</template>
+<script>
+    import table from "@components/Table.js";
+
+    export default {
+        components: { 'YunTable': table },
+        data: {
+            extend: {
+                index_url: 'general/category/index',
+            },
+            row: Yunqi.data.row,
+            tabData: Object.entries(Yunqi.data.typeList).map(([value, label]) => ({ label, value })),
+            tableData: [],
+            value: "",
+            form: {
+                nameValue: null,
+            },
+            options: Yunqi.data.packingList,//品种
+            tabValue: Object.entries(Yunqi.data.typeList).map(([value, label]) => ({ label, value }))[0].value, //选中的品种 获取到品种数据后要给他默认赋值第一个
+            chooseSpec: [], // 当前分类选中的规格  
+            allData: {},
+            type: 0, // 1编辑 0新增,
+            shop_allData: []
+        },
+        methods: {
+            onSubmit() {
+                if (this.allData == "") return;
+                let arr = Object.values(this.allData).flat(Infinity)
+                Yunqi.ajax.post('goods/import_list/specs', { ids: Yunqi.data.row.id, all_data: arr }, false, false, true).then(res => {
+                    console.log(res.data)
+                    if (res.code == 200) {
+                        this.$message.success(__('设置成功'));
+                        //倒计时刷新窗口
+                        setTimeout(() => {
+                            Yunqi.api.closelayer(Yunqi.app.window.id, true);
+                        }, 1000);
+
+                    } else {
+                        Yunqi.alert(__('请填写发货价格'), __('温馨提示'), { type: 'error' });
+                    }
+                });
+            },
+            handleAllSelect(e) {
+                this.allData[this.tabValue] = e || []
+            },
+            handleCurrentChange(e) {
+
+                this.allData[this.tabValue] = e || []
+            },
+            handleSelectionChange(e) {
+                console.log(this.allData, "=====this.allData")
+            },
+            handleClick(data, row) {
+                // 品种切换事件 可以在这里请求规格接口
+                this.tabValue = data.props.name
+                this.tabName = data.props.label
+                this.tableData = [];
+                this.getSpecData()
+            },
+            cancelDialog: function () {
+                Yunqi.api.closelayer(Yunqi.app.window.id, true);
+            },
+            getSpecData() {
+
+                //获取规格 ;
+                Yunqi.ajax.get('shop/customer_spec/get_box', { type_id: this.tabValue }, false, false, true).then(res => {
+                    //编辑数据
+                    if (res.length > 0) {
+                        for (var key in Object(res)) {
+                            let index = this.tableData.findIndex(item => item.id == res[key]['id']);
+                            const isExist = this.shop_allData.includes(res[key]['id'])
+                            if(isExist){
+                                if (index != -1) {
+                                    this.tableData.splice(index, 1)
+                                } else {
+                                    this.tableData.push({ name: res[key]['title'], id: res[key]['id'], type_id: this.tabValue });
+                                }
+                            }
+                            
+                        }
+                        this.$nextTick(() => {
+                            const tableRef = this.$refs['multipleTable_' + this.tabValue];
+                            if (this.type == 0 && this.allData[this.tabValue]?.length > 0 && tableRef) {
+                                this.tableData.forEach((item, index) => {
+                                    const matched = this.allData[this.tabValue].find(row => {
+                                        return row.id == item.id
+                                    });
+                                    if (matched) {
+                                        this.tableData[index] = matched
+                                    }
+                                })
+                                this.allData[this.tabValue].forEach(selected => {
+                                    const matched = this.tableData.find(row => row.id === selected.id);
+                                    if (matched) {
+                                        this.$refs['multipleTable_' + this.tabValue].toggleRowSelection(matched, true); // 勾选
+                                    }
+                                });
+                            }
+                            else if (this.type == 1 && this.allData[Number(this.tabValue)]) {
+                                this.tableData.forEach((item, index) => {
+                                    const matched = this.allData[Number(this.tabValue)].find(row => {
+                                        if (row.product_id) {
+                                            return row.product_id == item.value
+                                        } else {
+                                            return row.value == item.value
+                                        }
+                                    });
+                                    if (matched) {
+                                        // this.tableData[index] = { name: 'kam', value: 3, price: '111', type_id: '4', packet: '3' }
+                                        if (matched.product_id) {
+                                            this.tableData[index].name = matched.name
+                                            this.tableData[index].box_name = matched.box_name
+                                            this.tableData[index].type_name = matched.type_name
+                                            this.tableData[index].price = matched.price
+                                            this.tableData[index].packet = matched.box_id != 0 ? matched?.box_id.toString() : ""
+                                        } else {
+                                            this.tableData[index] = matched
+                                        }
+                                    }
+                                })
+                                this.allData[Number(this.tabValue)].forEach(selected => {
+                                    const matched = this.tableData.find(row => {
+                                        if (selected.product_id) {
+                                            return selected.product_id == row.value
+                                        } else {
+                                            return row.value === selected.value
+                                        }
+                                    });
+                                    if (matched) {
+                                        this.$refs['multipleTable_' + this.tabValue].toggleRowSelection(matched, true); // 勾选
+                                    }
+                                });
+                                console.log(this.allData)
+                            }
+                        });
+                    }
+                });
+            }
+
+        },
+        onLoad: function (query) {
+
+            let rows = Yunqi.data.rows;
+            if (rows) {
+                const grouped = JSON.parse(rows).reduce((acc, item) => {
+                    const key = item.type_id;
+                    if (!acc[key]) {
+                        acc[key] = [];
+                    }
+
+                    acc[key].push(item);
+                    return acc;
+                }, {});
+                this.shop_allData = JSON.parse(JSON.stringify(grouped))
+                let arr = Object.values(this.shop_allData).flat(Infinity)
+                let acc = [];
+                for (var key in Object(arr)) {
+                    acc[key] = Number(arr[key]['value']);
+                }
+                this.shop_allData=acc;
+            }
+            //你只需要保存规格是吧, 是你末尾加了个row
+            this.getSpecData()
+        },
+    }
+</script>
+<style>
+</style>

+ 14 - 1
app/common/model/FengsuSku.php

@@ -28,7 +28,20 @@ class FengsuSku Extends Model
     //获取店铺下规格
     public static function getSpecsIdByShopId(string $shop_id,  string $spec_id): object
     {
-        return self::where('shop_id', $shop_id)->where('sku_id', $spec_id)->findOrEmpty();
+        // return self::where('shop_id', $shop_id)->where('sku_id', $spec_id)->findOrEmpty();
+        $result = self::alias('f')
+                ->where(['f.shop_id'=>$shop_id,'f.sku_id'=>$spec_id])
+                ->join('yun_product_config p', 'f.variety_id = p.type_id AND f.spec_id = p.id', 'INNER')
+                ->field([
+                    'f.*',
+                    'p.type_id',
+                    'p.title as spec_name',
+                    'p.another_name as box_name',
+                    'p.weight',
+                    'p.box_id'
+                ])
+                ->findOrEmpty();
+        return $result;
     }
 
     //批量插入规格

+ 30 - 0
app/common/model/ImportList.php

@@ -0,0 +1,30 @@
+<?php
+declare(strict_types=1);
+
+namespace app\common\model;
+
+use think\Model;
+
+class ImportList Extends Model
+{
+    // 自动写入时间戳字段
+    protected $autoWriteTimestamp = true;
+    protected $createTime = 'createtime';
+    protected $updateTime = 'updatetime';
+
+    protected $type = [
+        'createtime'     =>  'timestamp:Y-m-d H:i',
+        'updatetime'     =>  'timestamp:Y-m-d H:i',
+    ];
+
+    public static function onAfterInsert($data)
+    {
+        $data->weigh=1000-$data->id;
+        $data->save();
+    }
+    //获取最后一条记录
+    public static function getLastRecord()
+    {
+        return self::order('id','desc')->getByName('createtime');
+    }
+}

+ 2 - 2
config/app.php

@@ -53,7 +53,7 @@ return [
     ],
     //偏远地区加收费用比例 other_price
     'remote_area' =>[
-        0 => ['黑龙江省', '吉林省', '辽宁省','青海省', '内蒙古自治区','甘肃省','宁夏回族自治区','海南省','北京市','上海市'], //普通(广东省-深圳) -浙江-舟山
+        0 => ['黑龙江省', '吉林省', '辽宁省','青海省', '内蒙古自治区','甘肃省','宁夏回族自治区','海南省'], //普通(广东省-深圳) -浙江-舟山
         1 => ['黑龙江省', '吉林省', '辽宁省','青海省', '内蒙古自治区','甘肃省','宁夏回族自治区'], //顺丰
     ],
     //用户登录
@@ -64,7 +64,7 @@ return [
        'keepalive'=>true,
         //保持登陆时间,单位秒
        'keepalive_time'=>24*3600,
-   ],
+   ]
 
 
 ];