!277 京东云打印
Merge pull request !277 from 杨建炊/fix-release-1.0.0/yjc-migrate
This commit is contained in:
commit
7003cd9147
40
app/Events/CancelLogisticEvent.php
Normal file
40
app/Events/CancelLogisticEvent.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Events;
|
||||||
|
|
||||||
|
use Illuminate\Broadcasting\Channel;
|
||||||
|
use Illuminate\Broadcasting\InteractsWithSockets;
|
||||||
|
use Illuminate\Broadcasting\PresenceChannel;
|
||||||
|
use Illuminate\Broadcasting\PrivateChannel;
|
||||||
|
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
|
||||||
|
use Illuminate\Foundation\Events\Dispatchable;
|
||||||
|
use Illuminate\Queue\SerializesModels;
|
||||||
|
|
||||||
|
class CancelLogisticEvent
|
||||||
|
{
|
||||||
|
use Dispatchable, InteractsWithSockets, SerializesModels;
|
||||||
|
|
||||||
|
public $shopId;
|
||||||
|
public $orderSn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new event instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct($shopId, $orderSn)
|
||||||
|
{
|
||||||
|
$this->shopId = $shopId;
|
||||||
|
$this->orderSn = $orderSn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channels the event should broadcast on.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Broadcasting\Channel|array
|
||||||
|
*/
|
||||||
|
public function broadcastOn()
|
||||||
|
{
|
||||||
|
return new PrivateChannel('channel-name');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -10,6 +10,9 @@ class BusinessOrderFilter extends Filters
|
|||||||
{
|
{
|
||||||
protected function ids($value)
|
protected function ids($value)
|
||||||
{
|
{
|
||||||
|
if(is_string($value)){
|
||||||
|
$value = explode(",", $value);
|
||||||
|
}
|
||||||
return $this->builder->whereIn('id', $value);
|
return $this->builder->whereIn('id', $value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,12 +9,14 @@ use App\Models\BusinessOrder;
|
|||||||
use App\Models\BusinessOrderItem;
|
use App\Models\BusinessOrderItem;
|
||||||
use App\Models\GoodsSku;
|
use App\Models\GoodsSku;
|
||||||
use App\Models\Shop;
|
use App\Models\Shop;
|
||||||
use App\Services\Ship\WayBillService;
|
use App\Models\Waybill;
|
||||||
|
use App\Services\WayBill\JingDong\WayBillService;
|
||||||
use App\Utils\DateTimeUtils;
|
use App\Utils\DateTimeUtils;
|
||||||
use Carbon\Carbon;
|
use Carbon\Carbon;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Resources\BusinessOrderResource;
|
use App\Http\Resources\BusinessOrderResource;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
use Maatwebsite\Excel\Facades\Excel;
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
|
||||||
class BusinessOrderController extends Controller
|
class BusinessOrderController extends Controller
|
||||||
@ -27,17 +29,25 @@ class BusinessOrderController extends Controller
|
|||||||
$builder = BusinessOrder::query()
|
$builder = BusinessOrder::query()
|
||||||
->with([
|
->with([
|
||||||
'shop:id,name',
|
'shop:id,name',
|
||||||
'items:id,business_order_id,goods_name,goods_number,external_sku_id'
|
'items:id,business_order_id,goods_name,goods_number,external_sku_id',
|
||||||
|
"waybill"
|
||||||
])
|
])
|
||||||
->whereIn('shop_id', $shopIds)
|
->whereIn('shop_id', $shopIds)
|
||||||
->filter();
|
->filter();
|
||||||
$externalSkuIds = $request->get('external_sku_ids');
|
$externalSkuIds = $request->get('external_sku_ids');
|
||||||
|
$externalSkuId = $request->get('external_sku_id');
|
||||||
|
if (!empty($externalSkuId)) {
|
||||||
|
$externalSkuIds = $externalSkuId;
|
||||||
|
}
|
||||||
if ($externalSkuIds) {
|
if ($externalSkuIds) {
|
||||||
|
if (is_string($externalSkuIds)) {
|
||||||
|
$externalSkuIds = explode(",", $externalSkuIds);
|
||||||
|
}
|
||||||
$ids = BusinessOrderItem::query()->whereIn('external_sku_id', $externalSkuIds)->pluck('business_order_id');
|
$ids = BusinessOrderItem::query()->whereIn('external_sku_id', $externalSkuIds)->pluck('business_order_id');
|
||||||
$builder->whereIn('id', $ids);
|
$builder->whereIn('id', $ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
if($request->get("is_export")){
|
if ($request->get("is_export")) {
|
||||||
$params = $request->validate([
|
$params = $request->validate([
|
||||||
'confirm_at_start' => 'required',
|
'confirm_at_start' => 'required',
|
||||||
'confirm_at_end' => 'required',
|
'confirm_at_end' => 'required',
|
||||||
@ -52,7 +62,7 @@ class BusinessOrderController extends Controller
|
|||||||
throw new \Exception("导出时间超出一个月");
|
throw new \Exception("导出时间超出一个月");
|
||||||
}
|
}
|
||||||
|
|
||||||
return Excel::download(new BusinessOrderExport($builder->get()->toArray()), $startDate . '~' . $endDate."订单数据" . '.xlsx');
|
return Excel::download(new BusinessOrderExport($builder->get()->toArray()), $startDate . '~' . $endDate . "订单数据" . '.xlsx');
|
||||||
}
|
}
|
||||||
$businessOrders = $builder->orderByDesc('confirm_at')
|
$businessOrders = $builder->orderByDesc('confirm_at')
|
||||||
->paginate($request->get('per_page'));
|
->paginate($request->get('per_page'));
|
||||||
@ -177,24 +187,25 @@ class BusinessOrderController extends Controller
|
|||||||
->whereIn('shop_id', $shopIds)
|
->whereIn('shop_id', $shopIds)
|
||||||
->filter();
|
->filter();
|
||||||
$externalSkuIds = $request->get('external_sku_ids');
|
$externalSkuIds = $request->get('external_sku_ids');
|
||||||
|
|
||||||
if ($externalSkuIds) {
|
if ($externalSkuIds) {
|
||||||
$ids = BusinessOrderItem::query()->whereIn('external_sku_id', $externalSkuIds)->pluck('business_order_id');
|
$ids = BusinessOrderItem::query()->whereIn('external_sku_id', $externalSkuIds)->pluck('business_order_id');
|
||||||
$builder->whereIn('id', $ids);
|
$builder->whereIn('id', $ids);
|
||||||
}
|
}
|
||||||
if ($ids = $request->input('ids')) {
|
if ($ids = $request->input('ids')) {
|
||||||
|
if (is_string($ids)) {
|
||||||
|
$ids = explode(",", $ids);
|
||||||
|
}
|
||||||
$builder->whereIn('id', $ids);
|
$builder->whereIn('id', $ids);
|
||||||
}
|
}
|
||||||
$businessOrders = $builder->get();
|
$businessOrders = $builder->get();
|
||||||
|
|
||||||
$waybill = new WayBillService();
|
$waybill = new WayBillService();
|
||||||
$waybill->setOrders($businessOrders);
|
$waybill->setOrders($businessOrders);
|
||||||
$contents = $waybill->getContents();
|
$contents = $waybill->getWayBillContents();
|
||||||
// 待打印数据
|
|
||||||
[$documents, $orderIds] = $waybill->getDocumentsAndOrderIds($contents);
|
|
||||||
|
|
||||||
return response([
|
return response([
|
||||||
'documents' => $this->combinationPrintDocuments($documents),
|
'data' => $contents
|
||||||
'order_ids' => implode(',', $orderIds),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,9 +262,11 @@ class BusinessOrderController extends Controller
|
|||||||
$orderIds = $request->input('order_ids');
|
$orderIds = $request->input('order_ids');
|
||||||
$orderIds = explode(',', $orderIds);
|
$orderIds = explode(',', $orderIds);
|
||||||
BusinessOrder::query()
|
BusinessOrder::query()
|
||||||
->where('id', $orderIds)
|
->whereIn('id', $orderIds)
|
||||||
->increment('print_status');
|
->update(['print_status' => 1]);
|
||||||
|
Waybill::query()
|
||||||
|
->where('order_id', $orderIds)
|
||||||
|
->update(['status' => Waybill::$STATUS_PRINT_SUCCESS]);
|
||||||
return response(['message' => 'success']);
|
return response(['message' => 'success']);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
74
app/Http/Controllers/Business/WaybillController.php
Normal file
74
app/Http/Controllers/Business/WaybillController.php
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Business;
|
||||||
|
|
||||||
|
use App\Events\BusinessOrderCancelEvent;
|
||||||
|
use App\Events\CancelLogisticEvent;
|
||||||
|
use App\Exports\BusinessOrderExport;
|
||||||
|
use App\Exports\OrderBlankExport;
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\BusinessOrder;
|
||||||
|
use App\Models\BusinessOrderItem;
|
||||||
|
use App\Models\GoodsSku;
|
||||||
|
use App\Models\Shop;
|
||||||
|
use App\Models\Waybill;
|
||||||
|
use App\Services\Business\BusinessFactory;
|
||||||
|
use App\Services\WayBill\JingDong\JingDongService;
|
||||||
|
use App\Services\WayBill\JingDong\WayBillService;
|
||||||
|
use App\Utils\DateTimeUtils;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use App\Http\Resources\BusinessOrderResource;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Maatwebsite\Excel\Facades\Excel;
|
||||||
|
|
||||||
|
class WaybillController extends Controller
|
||||||
|
{
|
||||||
|
public function queryTrace(Request $request)
|
||||||
|
{
|
||||||
|
$params = $request->validate([
|
||||||
|
'order_id' => 'required',
|
||||||
|
], [
|
||||||
|
'order_id.required' => '订单id',
|
||||||
|
]);
|
||||||
|
$waybill = Waybill::query()->where("order_id", $params['order_id'])->firstOrFail();
|
||||||
|
$jingDongService = new JingDongService();
|
||||||
|
return $jingDongService->queryTrace($waybill);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function cancel(Request $request)
|
||||||
|
{
|
||||||
|
$params = $request->validate([
|
||||||
|
'order_id' => 'required',
|
||||||
|
], [
|
||||||
|
'order_id.required' => '订单id',
|
||||||
|
]);
|
||||||
|
$waybill = Waybill::query()->where("order_id", $params['order_id'])->firstOrFail();
|
||||||
|
if (empty($waybill->waybill_code)) {
|
||||||
|
throw new \Exception("无快递单号可取消");
|
||||||
|
}
|
||||||
|
try{
|
||||||
|
//取消快团团物流
|
||||||
|
$shop = Shop::query()->findOrFail($waybill->shop_id);
|
||||||
|
$client = BusinessFactory::init()->make($shop['plat_id'])->setShop($shop);
|
||||||
|
$client->cancelLogistic($waybill->order_sn, $waybill->waybill_code);
|
||||||
|
//取消京东物流
|
||||||
|
$jingDongService = new JingDongService();
|
||||||
|
$jingDongService->cancelOrder($waybill);
|
||||||
|
}catch(\Exception $exception) {
|
||||||
|
Log::error("取消快团团或者京东物流异常", ["error" => $exception->getMessage()]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$waybill->waybill_code = '';
|
||||||
|
$waybill->encryptedData = '';
|
||||||
|
$waybill->status = Waybill::$STATUS_INIT;
|
||||||
|
$waybill->cancel = 1;
|
||||||
|
$waybill->save();
|
||||||
|
BusinessOrder::query()->where("id", $params['order_id'])->update(['print_status' => 0]);
|
||||||
|
|
||||||
|
return response(['message' => 'success']);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
67
app/Http/Controllers/Shop/ShopSendsController.php
Normal file
67
app/Http/Controllers/Shop/ShopSendsController.php
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Shop;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\BusinessGoodsSku;
|
||||||
|
use App\Models\DeveloperConfig;
|
||||||
|
use App\Models\GoodsSku;
|
||||||
|
use App\Models\Shop;
|
||||||
|
use App\Http\Resources\ShopsResource;
|
||||||
|
use App\Models\ShopSender;
|
||||||
|
use App\Models\ShopShip;
|
||||||
|
use App\Services\Business\KuaiTuanTuan\FaceSheet;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Http\Resources\Json\JsonResource;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
use App\Services\Business\BusinessFactory;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
use App\Models\BusinessOrderItem;
|
||||||
|
|
||||||
|
class ShopSendsController extends Controller
|
||||||
|
{
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$shopSender = ShopSender::query()->filter()->paginate($request->get('per_page'));
|
||||||
|
|
||||||
|
return JsonResource::collection($shopSender);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
$params = $request->validate([
|
||||||
|
'id' => 'sometimes',
|
||||||
|
'shop_id' => 'required|int',
|
||||||
|
'province' => 'required',
|
||||||
|
'city' => 'required',
|
||||||
|
'district' => 'required',
|
||||||
|
'detail' => 'required',
|
||||||
|
'name' => 'required',
|
||||||
|
'mobile' => 'required',
|
||||||
|
'sort' => 'sometimes',
|
||||||
|
'wp_code' => 'sometimes',
|
||||||
|
], [
|
||||||
|
'shop_id.required' => '请选择店铺',
|
||||||
|
'province.required' => '请选择省份',
|
||||||
|
'city.required' => '请选择城市',
|
||||||
|
'district.required' => '请选择地区',
|
||||||
|
'detail.required' => '请填写详细地址',
|
||||||
|
]);
|
||||||
|
$params['wp_code'] = $params['wp_code'] ?? 'JD';
|
||||||
|
$params['country'] = $params['country'] ?? '中国';
|
||||||
|
if (empty($params['id'])) {
|
||||||
|
$shopSender = new ShopSender();
|
||||||
|
$shopSender->fill($params);
|
||||||
|
$shopSender->save();
|
||||||
|
} else {
|
||||||
|
ShopSender::query()->where('id', $params['id'])->update($params);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response($this->res, $this->res['httpCode']);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
|
use App\Events\CancelLogisticEvent;
|
||||||
use App\Events\CreateLogisticEvent;
|
use App\Events\CreateLogisticEvent;
|
||||||
use App\Models\Shop;
|
use App\Models\Shop;
|
||||||
use App\Models\Waybill;
|
use App\Models\Waybill;
|
||||||
@ -11,9 +12,6 @@ use Illuminate\Queue\InteractsWithQueue;
|
|||||||
|
|
||||||
class CancelLogisticListener implements ShouldQueue
|
class CancelLogisticListener implements ShouldQueue
|
||||||
{
|
{
|
||||||
public $connection = 'redis';
|
|
||||||
|
|
||||||
public $queue = 'listeners';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the event listener.
|
* Create the event listener.
|
||||||
@ -31,7 +29,7 @@ class CancelLogisticListener implements ShouldQueue
|
|||||||
* @param CreateLogisticEvent $event
|
* @param CreateLogisticEvent $event
|
||||||
* @return void
|
* @return void
|
||||||
*/
|
*/
|
||||||
public function handle(CreateLogisticEvent $event)
|
public function handle(CancelLogisticEvent $event)
|
||||||
{
|
{
|
||||||
$waybillNo = Waybill::query()
|
$waybillNo = Waybill::query()
|
||||||
->where('shop_id', $event->shopId)
|
->where('shop_id', $event->shopId)
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Listeners;
|
namespace App\Listeners;
|
||||||
|
|
||||||
use App\Events\CreateLogisticEvent;
|
use App\Events\CreateLogisticEvent;
|
||||||
|
use App\Models\BusinessOrder;
|
||||||
use App\Models\Shop;
|
use App\Models\Shop;
|
||||||
use App\Services\Business\BusinessFactory;
|
use App\Services\Business\BusinessFactory;
|
||||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||||
@ -10,10 +11,6 @@ use Illuminate\Queue\InteractsWithQueue;
|
|||||||
|
|
||||||
class CreateLogisticListener implements ShouldQueue
|
class CreateLogisticListener implements ShouldQueue
|
||||||
{
|
{
|
||||||
public $connection = 'redis';
|
|
||||||
|
|
||||||
public $queue = 'listeners';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the event listener.
|
* Create the event listener.
|
||||||
*
|
*
|
||||||
@ -32,7 +29,7 @@ class CreateLogisticListener implements ShouldQueue
|
|||||||
*/
|
*/
|
||||||
public function handle(CreateLogisticEvent $event)
|
public function handle(CreateLogisticEvent $event)
|
||||||
{
|
{
|
||||||
$shop = Shop::query()->findOrFail($event->shopId);
|
$shop = Shop::query()->findOrFail($event->shopId);;
|
||||||
$client = BusinessFactory::init()->make($shop['plat_id'])->setShop($shop);
|
$client = BusinessFactory::init()->make($shop['plat_id'])->setShop($shop);
|
||||||
$client->createLogistic($event->orderSn, $event->waybillNo);
|
$client->createLogistic($event->orderSn, $event->waybillNo);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -23,6 +23,8 @@ class BusinessOrder extends Model
|
|||||||
'print_status',
|
'print_status',
|
||||||
'ids',
|
'ids',
|
||||||
'pno',
|
'pno',
|
||||||
|
'order_sn',
|
||||||
|
'id',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@ -72,4 +74,9 @@ class BusinessOrder extends Model
|
|||||||
{
|
{
|
||||||
return $this->belongsTo(Shop::class, 'shop_id', 'id');
|
return $this->belongsTo(Shop::class, 'shop_id', 'id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function waybill()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Waybill::class, 'id', 'order_id');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,9 +2,16 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Models\traits\Filter;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
class ShopSender extends Model
|
class ShopSender extends Model
|
||||||
{
|
{
|
||||||
|
use Filter;
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
|
//查询字段
|
||||||
|
public $fieldSearchable = [
|
||||||
|
'shop_id',
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@ -10,4 +10,9 @@ class Waybill extends Model
|
|||||||
|
|
||||||
public static $BUSINESS_EXPRESS_CODE = 247;
|
public static $BUSINESS_EXPRESS_CODE = 247;
|
||||||
public static $AIR_FREIGHT_CODE = 266;
|
public static $AIR_FREIGHT_CODE = 266;
|
||||||
|
|
||||||
|
public static $STATUS_INIT = 0;
|
||||||
|
public static $STATUS_CREATE_WAYBILL_CODE = 1;
|
||||||
|
public static $STATUS_CREATE_WAYBILL_ENCRYPTED_DATA = 2;
|
||||||
|
public static $STATUS_PRINT_SUCCESS = 3;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@
|
|||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Events\BusinessOrdersUpdate;
|
use App\Events\BusinessOrdersUpdate;
|
||||||
|
use App\Events\CancelLogisticEvent;
|
||||||
use App\Events\StockUpdateEvent;
|
use App\Events\StockUpdateEvent;
|
||||||
use App\Events\GroupSetEvent;
|
use App\Events\GroupSetEvent;
|
||||||
use App\Events\BatchStockUpdateEvent;
|
use App\Events\BatchStockUpdateEvent;
|
||||||
@ -47,6 +48,9 @@ class EventServiceProvider extends ServiceProvider
|
|||||||
CreateLogisticEvent::class => [
|
CreateLogisticEvent::class => [
|
||||||
CreateLogisticListener::class
|
CreateLogisticListener::class
|
||||||
],
|
],
|
||||||
|
CancelLogisticEvent::class => [
|
||||||
|
CancelLogisticListener::class
|
||||||
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -4,6 +4,7 @@ namespace App\Services\Business;
|
|||||||
|
|
||||||
use App\Events\BusinessOrderCancelEvent;
|
use App\Events\BusinessOrderCancelEvent;
|
||||||
use App\Events\BusinessOrdersUpdate;
|
use App\Events\BusinessOrdersUpdate;
|
||||||
|
use App\Events\CancelLogisticEvent;
|
||||||
use App\Models\BusinessGoodsSku;
|
use App\Models\BusinessGoodsSku;
|
||||||
use App\Models\BusinessOrder;
|
use App\Models\BusinessOrder;
|
||||||
use App\Models\BusinessOrderItem;
|
use App\Models\BusinessOrderItem;
|
||||||
@ -55,7 +56,7 @@ abstract class BusinessClient
|
|||||||
$orderRecord->update($order);
|
$orderRecord->update($order);
|
||||||
}
|
}
|
||||||
if (!empty($order['cancel_status'])) {
|
if (!empty($order['cancel_status'])) {
|
||||||
event(new BusinessOrderCancelEvent($shopId, $order['order_sn']));
|
event(new CancelLogisticEvent($shopId, $order['order_sn']));
|
||||||
}
|
}
|
||||||
$goodsSkuNum = 0;
|
$goodsSkuNum = 0;
|
||||||
foreach ($order['sub_order_list'] as $item) {
|
foreach ($order['sub_order_list'] as $item) {
|
||||||
@ -154,7 +155,7 @@ abstract class BusinessClient
|
|||||||
'headers' => ['Content-type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
'headers' => ['Content-type' => 'application/x-www-form-urlencoded;charset=UTF-8'],
|
||||||
'form_params' => $params
|
'form_params' => $params
|
||||||
];
|
];
|
||||||
$res = (new Client())->request($method, $url, $headers);
|
$res = (new Client(['verify'=>false]))->request($method, $url, $headers);
|
||||||
$size = $res->getBody()->getSize();
|
$size = $res->getBody()->getSize();
|
||||||
$res = json_decode($res->getBody()->getContents(), true);
|
$res = json_decode($res->getBody()->getContents(), true);
|
||||||
$paramsJson = json_encode($params, 256);
|
$paramsJson = json_encode($params, 256);
|
||||||
|
|||||||
@ -374,7 +374,6 @@ class KuaiTuanTuan extends BusinessClient
|
|||||||
public function createLogistic($orderSn, $waybillNo)
|
public function createLogistic($orderSn, $waybillNo)
|
||||||
{
|
{
|
||||||
[$type, $appendParams] = Order::createOrderLogistic($orderSn, $waybillNo);
|
[$type, $appendParams] = Order::createOrderLogistic($orderSn, $waybillNo);
|
||||||
|
|
||||||
return $this->doRequest($type, $appendParams);
|
return $this->doRequest($type, $appendParams);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
244
app/Services/WayBill/JingDong/JingDongService.php
Normal file
244
app/Services/WayBill/JingDong/JingDongService.php
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\WayBill\JingDong;
|
||||||
|
|
||||||
|
use App\Enum\Pickup\ConsignType;
|
||||||
|
use App\Models\BusinessOrder;
|
||||||
|
use App\Models\OrderItem;
|
||||||
|
use App\Models\Pickup;
|
||||||
|
use App\Models\Waybill;
|
||||||
|
use App\Services\Pickup\Exceptions\KdNiaoException;
|
||||||
|
use App\Utils\Env\EnvUtils;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use Illuminate\Support\Facades\Log;
|
||||||
|
use Lop\LopOpensdkPhp\Filters\ErrorResponseFilter;
|
||||||
|
use Lop\LopOpensdkPhp\Filters\IsvFilter;
|
||||||
|
use Lop\LopOpensdkPhp\Options;
|
||||||
|
use Lop\LopOpensdkPhp\Support\DefaultClient;
|
||||||
|
use Lop\LopOpensdkPhp\Support\GenericRequest;
|
||||||
|
use Psr\Http\Message\ResponseInterface;
|
||||||
|
|
||||||
|
class JingDongService
|
||||||
|
{
|
||||||
|
public $baseUrl;
|
||||||
|
public $appKey;
|
||||||
|
public $appSecret;
|
||||||
|
public $accessToken;
|
||||||
|
public $customerCode;
|
||||||
|
public static $CANCEL_TYPE = [
|
||||||
|
1 => '预约信息有误',
|
||||||
|
2 => '快递员无法取件',
|
||||||
|
3 => '上门太慢',
|
||||||
|
4 => '运费太贵',
|
||||||
|
7 => '联系不上快递员',
|
||||||
|
8 => '快递员要求取消',
|
||||||
|
11 => '其他(如疫情管控,无法寄 件)',
|
||||||
|
9 => '预约信息有误',
|
||||||
|
];
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->baseUrl = "https://api.jdl.com";
|
||||||
|
$this->appKey = "5ee218f6619e438db8755ee560c3eaa7";
|
||||||
|
$this->appSecret = "7ffb176f75014ebbb37061f051024bf3";
|
||||||
|
$this->accessToken = "4e411a1d178147cdb58b5579a0df378d";//每年都会过期 https://oauth.jdl.com/oauth/authorize?client_id=YOUR_APP_KEY&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code
|
||||||
|
//生产环境域名:https://oauth.jdl.com 预发环境域名:https://uat-oauth.jdl.com
|
||||||
|
$this->domain = "FreshMedicineDelivery";//对接方案的编码 生鲜快递
|
||||||
|
$this->customerCode = "028K4188368";//月结编码
|
||||||
|
/*if (!EnvUtils::checkIsProduce()) {
|
||||||
|
//沙箱环境
|
||||||
|
$this->baseUrl = "https://test-api.jdl.com";
|
||||||
|
$this->appKey = "62d07644754843cc882fca7c01476c4f";
|
||||||
|
$this->appSecret = "0c2c8b6b7c10481ea639f6daa09ac02e";
|
||||||
|
$this->accessToken = "78c246c0ab564e67add6296a9eaf04a1";;//每年都会过期 https://oauth.jdl.com/oauth/authorize?client_id=YOUR_APP_KEY&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code
|
||||||
|
$this->customerCode = "27K1234912";//月结编码
|
||||||
|
}*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function request($body, $path)
|
||||||
|
{
|
||||||
|
// 生产环境: https://api.jdl.com
|
||||||
|
$client = new DefaultClient($this->baseUrl);
|
||||||
|
// 系统参数,应用的app_ley和app_secret,可从【控制台-应用管理-概览】中查看;access_token是用户授权时获取的令牌,用户授权相关说明请查看https://cloud.jdl.com/#/devSupport/53392
|
||||||
|
$isvFilter = new IsvFilter($this->appKey, $this->appSecret, $this->accessToken);
|
||||||
|
$errorResponseFilter = new ErrorResponseFilter();
|
||||||
|
|
||||||
|
$request = new GenericRequest();
|
||||||
|
$request->setDomain($this->domain);//对接方案的编码,应用订购对接方案后可在订阅记录查看
|
||||||
|
$request->setPath($path);//api的path,可在API文档查看
|
||||||
|
$request->setMethod("POST");//只支持POST
|
||||||
|
// 序列化后的JSON字符串
|
||||||
|
$request->setBody(json_encode([$body]));
|
||||||
|
|
||||||
|
// 为请求添加ISV模式过滤器,自动根据算法计算开放平台鉴权及签名信息
|
||||||
|
$request->addFilter($isvFilter);
|
||||||
|
// 为请求添加错误响应解析过滤器,如果不添加需要手动解析错误响应
|
||||||
|
$request->addFilter($errorResponseFilter);
|
||||||
|
|
||||||
|
$options = new Options();
|
||||||
|
|
||||||
|
$options->setAlgorithm(Options::MD5_SALT);
|
||||||
|
Log::info("京东请求body:{$path}", [$body]);
|
||||||
|
$response = $client->execute($request, $options);
|
||||||
|
$response = json_decode($response->getBody(), true);
|
||||||
|
Log::info("京东返回请求response", [$response]);
|
||||||
|
if (!isset($response['code']) || ($response['code'] != 0 && $response['code'] != 1 && $response['code'] != 1000)) {
|
||||||
|
throw new \Exception($response['message'] ?? "code异常");
|
||||||
|
}
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private function buildCargoes($extend)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
"quantity" => $extend["quantity"] ?? 1,
|
||||||
|
"goodsName" => "鲜花",
|
||||||
|
"volume" => ($extend['volume'] ?? 0) > 0 ? $extend['volume'] : 100,
|
||||||
|
"weight" => $extend['weight'] ?? 1,
|
||||||
|
"packageQty" => 1
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function buildContact($params)
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'senderName' => $params['name'] ?? '',
|
||||||
|
'senderPhone' => $params['mobile'] ?? '',
|
||||||
|
'senderAddress' => substr($params['province_name'] . $params['city_name'] . $params['area_name'] . $params['address_detail'], 0, 350),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createOrder(Waybill $pickup)
|
||||||
|
{
|
||||||
|
$path = "/freshmedicinedelivery/delivery/create/order/v1";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"orderId" => $pickupData['order_sn'],
|
||||||
|
"senderContactRequest" => [
|
||||||
|
'senderName' => $pickupData['sender_name'] ?? '',
|
||||||
|
'senderPhone' => $pickupData['sender_mobile'] ?? '',
|
||||||
|
'senderAddress' => substr($pickupData['sender_province'] . $pickupData['sender_city']
|
||||||
|
. $pickupData['sender_district'] . $pickupData['sender_detail'], 0, 350)
|
||||||
|
],
|
||||||
|
"customerCode" => $this->customerCode,
|
||||||
|
"remark" => $pickup['note'] ?? '',
|
||||||
|
"salePlatform" => '0030001',//其他平台
|
||||||
|
"cargoesRequest" => $this->buildCargoes($pickup),
|
||||||
|
"receiverContactRequest" => [
|
||||||
|
'receiverName' => $pickupData['recipient_name'] ?? '',
|
||||||
|
'receiverPhone' => $pickupData['recipient_mobile'] ?? '',
|
||||||
|
'receiverAddress' => substr($pickupData['recipient_province'] . $pickupData['recipient_city'] . $pickupData['recipient_district'] . $pickupData['recipient_detail'], 0, 350)
|
||||||
|
],
|
||||||
|
"channelOrderId" => $pickupData['order_sn'],
|
||||||
|
"promiseTimeType" => 26,//22:医药冷链 26:冷链专送,29医药专送
|
||||||
|
"goodsType" => 7,//1:普通,2:生鲜常温,5:鲜活,6:控温,7:冷藏,8:冷冻,9:深冷;21:医药冷藏,23:医药控温,24:医药常温,25:医药冷冻,27:医药深冷
|
||||||
|
//"pickUpStartTime" => Carbon::today()->startOfDay()->addDays(2)->addHours(19)->toDateTimeString(),
|
||||||
|
//"pickUpEndTime" => Carbon::today()->startOfDay()->addDays(2)->addHours(21)->toDateTimeString(),
|
||||||
|
];
|
||||||
|
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
return $response['data'];
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function cancelOrder(Waybill $pickup)
|
||||||
|
{
|
||||||
|
$path = "/freshmedicinedelivery/delivery/cancel/waybill/v1";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"waybillNo" => $pickupData['waybill_code'],
|
||||||
|
"customerCode" => $this->customerCode,
|
||||||
|
"interceptReason" => "订单信息有误",
|
||||||
|
];
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
|
||||||
|
return $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pullData(Waybill $pickup)
|
||||||
|
{
|
||||||
|
//云打印
|
||||||
|
$this->domain = "jdcloudprint";
|
||||||
|
$path = "/PullDataService/pullData";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"cpCode" => "JD",
|
||||||
|
"wayBillInfos" => [[
|
||||||
|
'orderNo' => $pickupData['order_sn'],
|
||||||
|
'jdWayBillCode' => $pickupData['waybill_code'],
|
||||||
|
]],
|
||||||
|
"parameters" => ["ewCustomerCode" => $this->customerCode],
|
||||||
|
"objectId" => $pickupData['object_id'],
|
||||||
|
];
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
|
||||||
|
return $response['prePrintDatas'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public function queryOrder(Waybill $pickup)
|
||||||
|
{
|
||||||
|
$path = "/ecap/v1/orders/details/query";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"waybillCode" => $pickupData['ship_sn'] ?? '',
|
||||||
|
"orderCode" => $pickupData['out_order_sn'] ?? "",
|
||||||
|
"customerCode" => $this->customerCode,
|
||||||
|
"orderOrigin" => 2,
|
||||||
|
];
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
|
||||||
|
return $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function subscribe(Waybill $pickup)
|
||||||
|
{
|
||||||
|
$path = "/jd/tracking/subscribe";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"referenceNumber" => $pickupData['ship_sn'] ?? '',
|
||||||
|
"referenceType" => 20000,
|
||||||
|
"customerCode" => $this->customerCode,
|
||||||
|
];
|
||||||
|
$this->domain = "Tracking_JD";//对接方案的编码
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
|
||||||
|
return $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function queryFee(Waybill $pickup)
|
||||||
|
{
|
||||||
|
$path = "/ecap/v1/orders/actualfee/query";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"waybillCode" => $pickupData['ship_sn'] ?? '',
|
||||||
|
"orderCode" => $pickupData['out_order_sn'] ?? "",
|
||||||
|
"customerCode" => $this->customerCode,
|
||||||
|
"orderOrigin" => 2,
|
||||||
|
];
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
|
||||||
|
return $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function queryTrace(Waybill $pickup)
|
||||||
|
{
|
||||||
|
$path = "/freshmedicinedelivery/delivery/query/waybill/gis/v1";
|
||||||
|
$pickupData = $pickup->toArray();
|
||||||
|
$body = [
|
||||||
|
"waybillNo" => $pickupData['waybill_code'] ?? '',
|
||||||
|
"customerCode" => $this->customerCode,
|
||||||
|
];
|
||||||
|
$response = $this->request($body, $path);
|
||||||
|
|
||||||
|
return $response['data'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
281
app/Services/WayBill/JingDong/WayBillService.php
Normal file
281
app/Services/WayBill/JingDong/WayBillService.php
Normal file
@ -0,0 +1,281 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Services\WayBill\JingDong;
|
||||||
|
|
||||||
|
use App\Events\CreateLogisticEvent;
|
||||||
|
use App\Http\Enum\BusinessOrderShippingStatus;
|
||||||
|
use App\Models\BusinessOrder;
|
||||||
|
use App\Models\GoodsSku;
|
||||||
|
use App\Models\ShopSender;
|
||||||
|
use App\Models\ShopShip;
|
||||||
|
use App\Models\Waybill;
|
||||||
|
use App\Services\Business\KuaiTuanTuan\FaceSheet;
|
||||||
|
|
||||||
|
class WayBillService
|
||||||
|
{
|
||||||
|
public $orders;
|
||||||
|
public $objectId;
|
||||||
|
public $adminUser;
|
||||||
|
// 标准模板
|
||||||
|
public $templateUrl = 'https://template-content.jd.com/template-oss?tempCode=jdkd76x130';
|
||||||
|
// 时效类型
|
||||||
|
public $timedDeliveryCode;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 新版京东打印-下单
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getWayBillContents()
|
||||||
|
{
|
||||||
|
// 已下单过的订单不再下单
|
||||||
|
$contents = [];
|
||||||
|
$this->adminUser = auth('api')->user();
|
||||||
|
$jingDongService = new JingDongService();
|
||||||
|
foreach ($this->orders as $shopId => $order) {
|
||||||
|
// 订单取消的情况暂不处理
|
||||||
|
$shopSend = $this->getShopSend($shopId);
|
||||||
|
foreach ($order as $item) {
|
||||||
|
[$sender, $orderInfo, $senderConfig] = $this->prepareRequest($item, $shopSend);
|
||||||
|
$waybill = $this->saveWayBill($item, $shopSend, $senderConfig);
|
||||||
|
if (empty($waybill->waybill_code)) {
|
||||||
|
$resp = $jingDongService->createOrder($waybill);
|
||||||
|
if (isset($resp['waybillNo'])) {
|
||||||
|
$waybill->status = Waybill::$STATUS_CREATE_WAYBILL_CODE;
|
||||||
|
$waybill->waybill_code = $resp['waybillNo'];
|
||||||
|
$waybill->save();
|
||||||
|
//物流发货
|
||||||
|
event(new CreateLogisticEvent($waybill->shop_id, $waybill->order_sn, $waybill->waybill_code));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//返回面单待打印数据
|
||||||
|
if (empty($waybill->encryptedData)) {
|
||||||
|
// 延时0.5秒 防止订单查询不到
|
||||||
|
usleep(0.5 * 1000000);
|
||||||
|
$resp = $jingDongService->pullData($waybill);
|
||||||
|
if (!empty($resp[0]['perPrintData'])) {
|
||||||
|
$waybill->status = Waybill::$STATUS_CREATE_WAYBILL_ENCRYPTED_DATA;
|
||||||
|
$waybill->templateUrl = $this->templateUrl;
|
||||||
|
$waybill->encryptedData = $resp[0]['perPrintData'];
|
||||||
|
$waybill->save();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$contents[$item['id']] = $waybill;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getDocumentsAndOrderIds($contents)
|
||||||
|
{
|
||||||
|
// 打印单,根据商品排序
|
||||||
|
$items = [];
|
||||||
|
foreach ($contents as $docId => $content) {
|
||||||
|
foreach ($content['items'] as $item) {
|
||||||
|
if ($item['is_single']) {
|
||||||
|
$items[$item['external_sku_id']][] = $docId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ksort($items);
|
||||||
|
$documents = $orderIds = $hasIds = [];
|
||||||
|
foreach ($items as $docIds) {
|
||||||
|
$docIds = array_unique($docIds);
|
||||||
|
$docIds = array_diff($docIds, $hasIds);
|
||||||
|
$hasIds = array_merge($hasIds, $docIds);
|
||||||
|
foreach ($docIds as $docId) {
|
||||||
|
$orderIds[] = $contents[$docId]['order_id'];
|
||||||
|
$documents[] = $contents[$docId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [$documents, $orderIds];
|
||||||
|
}
|
||||||
|
|
||||||
|
private function saveWayBill($order, $shopShip, $senderConfig)
|
||||||
|
{
|
||||||
|
$waybill = Waybill::query()->firstOrNew(
|
||||||
|
['order_sn' => $order['order_sn']]
|
||||||
|
);
|
||||||
|
|
||||||
|
$waybill->shop_id = $order['shop_id'];
|
||||||
|
$waybill->object_id = $this->objectId;
|
||||||
|
|
||||||
|
$waybill->sender_country = $senderConfig['country'];
|
||||||
|
$waybill->sender_province = $senderConfig['province'];
|
||||||
|
$waybill->sender_city = $senderConfig['city'];
|
||||||
|
$waybill->sender_district = $senderConfig['district'];
|
||||||
|
$waybill->sender_detail = $senderConfig['detail'];
|
||||||
|
$waybill->sender_name = $senderConfig['name'];
|
||||||
|
$waybill->sender_mobile = (int)$senderConfig['mobile'];
|
||||||
|
|
||||||
|
$waybill->recipient_province = $order['recipient_province'];
|
||||||
|
$waybill->recipient_city = $order['recipient_city'];
|
||||||
|
$waybill->recipient_district = $order['recipient_district'];
|
||||||
|
$waybill->recipient_detail = $order['recipient_detail'];
|
||||||
|
$waybill->recipient_name = $order['recipient_name'];
|
||||||
|
$waybill->recipient_mobile = $order['recipient_mobile'];
|
||||||
|
|
||||||
|
$waybill->user_id = $this->adminUser->id ?? 0;
|
||||||
|
$waybill->wp_code = $senderConfig['wp_code'];
|
||||||
|
$waybill->order_sn = $order['order_sn'];
|
||||||
|
$waybill->order_id = $order['id'];
|
||||||
|
$waybill->participate_no = $order['participate_no'];
|
||||||
|
$waybill->note = $order['note'];
|
||||||
|
$waybill->items = json_encode($order['items'], 256);
|
||||||
|
$waybill->save();
|
||||||
|
return $waybill;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTimedDelivery($order)
|
||||||
|
{
|
||||||
|
$this->timedDeliveryCode = Waybill::$BUSINESS_EXPRESS_CODE;
|
||||||
|
$address = [
|
||||||
|
'辽宁省' => [],
|
||||||
|
'吉林省' => [],
|
||||||
|
'黑龙江省' => [],
|
||||||
|
'甘肃省' => [],
|
||||||
|
'海南省' => [],
|
||||||
|
'宁夏回族自治区' => [
|
||||||
|
'银川市', '石嘴山市', '吴忠市', '固原市'
|
||||||
|
],
|
||||||
|
'青海省' => [
|
||||||
|
'西宁市', '海东市', '海北藏族自治州', '黄南藏族自治州', '海南藏族自治州', '玉树藏族自治州'
|
||||||
|
],
|
||||||
|
];
|
||||||
|
if (isset($address[$order['recipient_province']])) {
|
||||||
|
if (empty($address[$order['recipient_province']])) {
|
||||||
|
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
||||||
|
}
|
||||||
|
if ($address[$order['recipient_province']] && in_array($order['recipient_city'], $address[$order['recipient_province']], true)) {
|
||||||
|
$this->timedDeliveryCode = Waybill::$AIR_FREIGHT_CODE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function prepareRequest($order, $shopSend)
|
||||||
|
{
|
||||||
|
$this->setObjectId();
|
||||||
|
|
||||||
|
$items = [];
|
||||||
|
foreach ($order['items'] as $item) {
|
||||||
|
$items[] = [
|
||||||
|
'name' => $item['name'],
|
||||||
|
'count' => $item['count'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($shopSend)) {
|
||||||
|
abort(404, '发货人信息未匹配');
|
||||||
|
}
|
||||||
|
$senderConfig = $shopSend;
|
||||||
|
$sender = [
|
||||||
|
'address' => [
|
||||||
|
'city' => $senderConfig['city'],
|
||||||
|
'country' => $senderConfig['country'],
|
||||||
|
'detail' => $senderConfig['detail'],
|
||||||
|
'district' => $senderConfig['district'],
|
||||||
|
'province' => $senderConfig['province'],
|
||||||
|
],
|
||||||
|
'name' => $senderConfig['name'],
|
||||||
|
'mobile' => $senderConfig['mobile'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$orderInfo = [
|
||||||
|
'object_id' => $this->objectId,
|
||||||
|
'order_info' => [
|
||||||
|
'order_channels_type' => 'PDD',
|
||||||
|
'trade_order_list' => [$order['order_sn']],
|
||||||
|
],
|
||||||
|
'package_info' => [
|
||||||
|
'items' => $items,
|
||||||
|
],
|
||||||
|
'recipient' => [
|
||||||
|
'address' => [
|
||||||
|
'city' => $order['recipient_city'],
|
||||||
|
'detail' => $order['recipient_detail'],
|
||||||
|
'district' => $order['recipient_district'],
|
||||||
|
'province' => $order['recipient_province'],
|
||||||
|
],
|
||||||
|
'name' => $order['recipient_name'],
|
||||||
|
'mobile' => $order['recipient_mobile'],
|
||||||
|
],
|
||||||
|
'template_url' => $this->templateUrl,
|
||||||
|
];
|
||||||
|
|
||||||
|
return [$sender, $orderInfo, $senderConfig];
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setObjectId()
|
||||||
|
{
|
||||||
|
$this->objectId = date('YmdHis') . str_pad(mt_rand(1, 9999999), 7, '0', STR_PAD_LEFT);
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setOrders($orders)
|
||||||
|
{
|
||||||
|
$orders = $orders->toArray();
|
||||||
|
// 订单拆分组合
|
||||||
|
foreach ($orders as $order) {
|
||||||
|
if ($order['shipping_status'] != BusinessOrderShippingStatus::UNSHIP) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ($order['cancel_status'] == 1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$info = [
|
||||||
|
'id' => $order['id'],
|
||||||
|
'shop_id' => $order['shop_id'],
|
||||||
|
'order_sn' => $order['order_sn'],
|
||||||
|
'recipient_province' => $order['receiver_address_province'],
|
||||||
|
'recipient_city' => $order['receiver_address_city'],
|
||||||
|
'recipient_district' => $order['receiver_address_district'],
|
||||||
|
'recipient_detail' => $order['receiver_address_detail'],
|
||||||
|
'recipient_name' => $order['receiver_name'],
|
||||||
|
'recipient_mobile' => $order['receiver_mobile'],
|
||||||
|
'participate_no' => $order['is_supplier'] ? $order['participate_no'] : $order['supply_participate_no'],
|
||||||
|
'note' => $order['business_note'] ? $order['business_note'] . ',' . $order['buyer_memo'] : $order['buyer_memo'],
|
||||||
|
'items' => []
|
||||||
|
];
|
||||||
|
$note = "";
|
||||||
|
foreach ($order['items'] as $item) {
|
||||||
|
$count = $item['goods_number'] - $item['already_cancel_number'];
|
||||||
|
$info['items'][] = [
|
||||||
|
'is_single' => true,
|
||||||
|
'should_print' => true,
|
||||||
|
'name' => $item['goods_name'],
|
||||||
|
'count' => $count,
|
||||||
|
'external_sku_id' => $item['external_sku_id'],
|
||||||
|
];
|
||||||
|
$note .= $item['goods_name'] . " " . $count . "件,";
|
||||||
|
}
|
||||||
|
$note .= "[备注:" . $info['note'] . "]";
|
||||||
|
$info['note'] = $note;
|
||||||
|
$this->orders[$order['shop_id']][] = $info;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getShopSend($shopId)
|
||||||
|
{
|
||||||
|
return ShopSender::query()
|
||||||
|
->where('status', 1)->orderBy('sort')
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getShopShip($shopId)
|
||||||
|
{
|
||||||
|
return ShopShip::query()
|
||||||
|
->select(['id', 'shop_id', 'access_token', 'owner_id'])
|
||||||
|
->where('shop_id', $shopId)
|
||||||
|
->with([
|
||||||
|
'senders' => function ($query) {
|
||||||
|
$query->where('status', 1)->orderBy('sort');
|
||||||
|
}
|
||||||
|
])
|
||||||
|
->first();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -39,7 +39,8 @@
|
|||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"App\\": "app/"
|
"App\\": "app/",
|
||||||
|
"Lop\\LopOpensdkPhp\\" : "extend/lop-opensdk-php/src/"
|
||||||
},
|
},
|
||||||
"classmap": [
|
"classmap": [
|
||||||
"database/seeds",
|
"database/seeds",
|
||||||
|
|||||||
@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddFieldToWaybillsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
if (Schema::hasColumns('waybills', ["status"])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Schema::table('waybills', function (Blueprint $table) {
|
||||||
|
$table->integer('status')->default(0)->comment('状态 0待申请物流单 1已申请物流 2已申请面单 3已打印');
|
||||||
|
$table->index('order_id');
|
||||||
|
$table->index('order_sn');
|
||||||
|
$table->index('waybill_code');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('waybills', function (Blueprint $table) {
|
||||||
|
//
|
||||||
|
$table->dropColumn('status');
|
||||||
|
$table->dropIndex('order_id');
|
||||||
|
$table->dropIndex('order_sn');
|
||||||
|
$table->dropIndex('waybill_code');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
12
extend/lop-opensdk-php/.gitignore
vendored
Normal file
12
extend/lop-opensdk-php/.gitignore
vendored
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
# Created by https://www.toptal.com/developers/gitignore/api/composer
|
||||||
|
# Edit at https://www.toptal.com/developers/gitignore?templates=composer
|
||||||
|
|
||||||
|
### Composer ###
|
||||||
|
composer.phar
|
||||||
|
/vendor/
|
||||||
|
|
||||||
|
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
|
||||||
|
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
|
||||||
|
# composer.lock
|
||||||
|
|
||||||
|
# End of https://www.toptal.com/developers/gitignore/api/composer
|
||||||
0
extend/lop-opensdk-php/README.md
Normal file
0
extend/lop-opensdk-php/README.md
Normal file
18
extend/lop-opensdk-php/composer.json
Normal file
18
extend/lop-opensdk-php/composer.json
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"name": "lop/lop-opensdk-php",
|
||||||
|
"type": "library",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Lop\\LopOpensdkPhp\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.6",
|
||||||
|
"ext-json": "*",
|
||||||
|
"guzzlehttp/guzzle": "^6.5"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^5.7"
|
||||||
|
}
|
||||||
|
}
|
||||||
2284
extend/lop-opensdk-php/composer.lock
generated
Normal file
2284
extend/lop-opensdk-php/composer.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
extend/lop-opensdk-php/src/Client.php
Normal file
14
extend/lop-opensdk-php/src/Client.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface Client
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Options $options
|
||||||
|
* @return Response
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function execute($request, $options);
|
||||||
|
}
|
||||||
14
extend/lop-opensdk-php/src/Executor.php
Normal file
14
extend/lop-opensdk-php/src/Executor.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface Executor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Options $options
|
||||||
|
* @return Response
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function execute($request, $options);
|
||||||
|
}
|
||||||
13
extend/lop-opensdk-php/src/ExecutorFactory.php
Normal file
13
extend/lop-opensdk-php/src/ExecutorFactory.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface ExecutorFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param string $baseUri
|
||||||
|
* @return Executor
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function create($baseUri);
|
||||||
|
}
|
||||||
15
extend/lop-opensdk-php/src/Filter.php
Normal file
15
extend/lop-opensdk-php/src/Filter.php
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface Filter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Options $options
|
||||||
|
* @param FilterChain $chain
|
||||||
|
* @return Response
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function doFilter($request, $options, $chain);
|
||||||
|
}
|
||||||
14
extend/lop-opensdk-php/src/FilterChain.php
Normal file
14
extend/lop-opensdk-php/src/FilterChain.php
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface FilterChain
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param Request $request
|
||||||
|
* @param Options $options
|
||||||
|
* @return Response
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function doFilter($request, $options);
|
||||||
|
}
|
||||||
24
extend/lop-opensdk-php/src/Filters/ErrorResponseFilter.php
Normal file
24
extend/lop-opensdk-php/src/Filters/ErrorResponseFilter.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Filters;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Filter;
|
||||||
|
|
||||||
|
class ErrorResponseFilter implements Filter
|
||||||
|
{
|
||||||
|
|
||||||
|
const ERROR_RESPONSE_PATTERN = "/^{\"error_response\":{\"en_desc\":\"(.*)\",\"zh_desc\":\"(.*)\",\"code\":(.*)}}$/";
|
||||||
|
|
||||||
|
function doFilter($request, $options, $chain)
|
||||||
|
{
|
||||||
|
$response = $chain->doFilter($request, $options);
|
||||||
|
$matches = array();
|
||||||
|
if (preg_match(self::ERROR_RESPONSE_PATTERN, $response->getBody(), $matches) === 1) {
|
||||||
|
$response->setSucceed(false);
|
||||||
|
$response->setEnDesc($matches[1]);
|
||||||
|
$response->setZhDesc($matches[2]);
|
||||||
|
$response->setCode(intval($matches[3]));
|
||||||
|
}
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
66
extend/lop-opensdk-php/src/Filters/IsvFilter.php
Normal file
66
extend/lop-opensdk-php/src/Filters/IsvFilter.php
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Filters;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Filter;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
|
||||||
|
class IsvFilter implements Filter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $appKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $appSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $accessToken;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $appKey
|
||||||
|
* @param string $appSecret
|
||||||
|
* @param string $accessToken
|
||||||
|
*/
|
||||||
|
public function __construct($appKey, $appSecret, $accessToken)
|
||||||
|
{
|
||||||
|
$this->appKey = $appKey;
|
||||||
|
$this->appSecret = $appSecret;
|
||||||
|
$this->accessToken = $accessToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function doFilter($request, $options, $chain)
|
||||||
|
{
|
||||||
|
$request->setHeader("lop-tz", strval(date("Z") / 3600));
|
||||||
|
|
||||||
|
$timestamp = date("Y-m-d H:i:s");
|
||||||
|
$content = implode("", array(
|
||||||
|
$this->appSecret,
|
||||||
|
"access_token", $this->accessToken,
|
||||||
|
"app_key", $this->appKey,
|
||||||
|
"method", $request->getPath(),
|
||||||
|
"param_json", $request->getBody(),
|
||||||
|
"timestamp", $timestamp,
|
||||||
|
"v", "2.0",
|
||||||
|
$this->appSecret
|
||||||
|
));
|
||||||
|
$sign = Utils::sign($options->getAlgorithm(), $content, $this->appSecret);
|
||||||
|
|
||||||
|
$request->setQuery("app_key", $this->appKey);
|
||||||
|
$request->setQuery("access_token", $this->accessToken);
|
||||||
|
$request->setQuery("timestamp", $timestamp);
|
||||||
|
$request->setQuery("v", "2.0");
|
||||||
|
$request->setQuery("sign", $sign);
|
||||||
|
$request->setQuery("algorithm", $options->getAlgorithm());
|
||||||
|
|
||||||
|
return $chain->doFilter($request, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
59
extend/lop-opensdk-php/src/Filters/LoggerFilter.php
Normal file
59
extend/lop-opensdk-php/src/Filters/LoggerFilter.php
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Filters;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Filter;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
|
||||||
|
class LoggerFilter implements Filter
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var resource
|
||||||
|
*/
|
||||||
|
private $file;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param resource $file
|
||||||
|
*/
|
||||||
|
public function __construct($file)
|
||||||
|
{
|
||||||
|
$this->file = $file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function doFilter($request, $options, $chain)
|
||||||
|
{
|
||||||
|
$this->printf("[%s, Request ] Domain: %s, Path: %s, Method: %s", $request->getRequestId(),
|
||||||
|
$request->getDomain(), $request->getPath(), $request->getMethod());
|
||||||
|
$this->printf("[%s, Request ] Queries: %s", $request->getRequestId(), json_encode($request->getQueries()));
|
||||||
|
$this->printf("[%s, Request ] Headers: %s", $request->getRequestId(), json_encode($request->getHeaders()));
|
||||||
|
$this->printf("[%s, Request ] Body: %s", $request->getRequestId(), $request->getBody());
|
||||||
|
|
||||||
|
try {
|
||||||
|
$response = $chain->doFilter($request, $options);
|
||||||
|
} catch (SdkException $e) {
|
||||||
|
$this->printf("[%s, Response ] Error: %s", $e->getMessage());
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->printf("[%s, Response ] Succeed: %t, TraceId: %s, EnDesc: %s, ZhDesc: %s, Code: %d, Status: %d",
|
||||||
|
$request->getRequestId(), $response->isSucceed(), $response->getTraceId(),
|
||||||
|
$response->getEnDesc(), $response->getZhDesc(), $response->getCode(), $response->getStatus());
|
||||||
|
$this->printf("[%s, Response ] Body: %s", $request->getRequestId(), $response->getBody());
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $format
|
||||||
|
* @param mixed ...$values
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
private function printf($format, ...$values)
|
||||||
|
{
|
||||||
|
fwrite($this->file, date("Y/m/d H:i:s"));
|
||||||
|
fwrite($this->file, " ");
|
||||||
|
fwrite($this->file, sprintf($format, $values));
|
||||||
|
fwrite($this->file, "\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
58
extend/lop-opensdk-php/src/Filters/PartnerFilter.php
Normal file
58
extend/lop-opensdk-php/src/Filters/PartnerFilter.php
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Filters;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Filter;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
|
||||||
|
class PartnerFilter implements Filter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $appKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $appSecret;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $appKey
|
||||||
|
* @param string $appSecret
|
||||||
|
*/
|
||||||
|
public function __construct($appKey, $appSecret)
|
||||||
|
{
|
||||||
|
$this->appKey = $appKey;
|
||||||
|
$this->appSecret = $appSecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function doFilter($request, $options, $chain)
|
||||||
|
{
|
||||||
|
$request->setHeader("lop-tz", strval(date("Z") / 3600));
|
||||||
|
|
||||||
|
$timestamp = date("Y-m-d H:i:s");
|
||||||
|
$content = implode("", array(
|
||||||
|
$this->appSecret,
|
||||||
|
"access_token", "",
|
||||||
|
"app_key", $this->appKey,
|
||||||
|
"method", $request->getPath(),
|
||||||
|
"param_json", $request->getBody(),
|
||||||
|
"timestamp", $timestamp,
|
||||||
|
"v", "2.0",
|
||||||
|
$this->appSecret
|
||||||
|
));
|
||||||
|
$sign = Utils::sign($options->getAlgorithm(), $content, $this->appSecret);
|
||||||
|
|
||||||
|
$request->setQuery("app_key", $this->appKey);
|
||||||
|
$request->setQuery("timestamp", $timestamp);
|
||||||
|
$request->setQuery("v", "2.0");
|
||||||
|
$request->setQuery("sign", $sign);
|
||||||
|
$request->setQuery("algorithm", $options->getAlgorithm());
|
||||||
|
|
||||||
|
return $chain->doFilter($request, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
extend/lop-opensdk-php/src/Filters/Utils.php
Normal file
36
extend/lop-opensdk-php/src/Filters/Utils.php
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Filters;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Options;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
|
||||||
|
abstract class Utils
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Signature data with given algorithm and secret.
|
||||||
|
*
|
||||||
|
* @param string $algorithm
|
||||||
|
* @param string $secret
|
||||||
|
* @param string $data
|
||||||
|
* @return string
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
public static function sign($algorithm, $data, $secret)
|
||||||
|
{
|
||||||
|
if ($algorithm == Options::MD5_SALT) {
|
||||||
|
return md5($data);
|
||||||
|
} else if ($algorithm == Options::SM3_SALT) {
|
||||||
|
throw new SdkException("Algorithm sm3-salt not supported yet");
|
||||||
|
} else if ($algorithm == Options::HMAC_MD5) {
|
||||||
|
return base64_encode(hash_hmac("md5", $data, $secret, true));
|
||||||
|
} else if ($algorithm == Options::HMAC_SHA1) {
|
||||||
|
return base64_encode(hash_hmac("sha1", $data, $secret, true));
|
||||||
|
} else if ($algorithm == Options::HMAC_SHA256) {
|
||||||
|
return base64_encode(hash_hmac("sha256", $data, $secret, true));
|
||||||
|
} else if ($algorithm == Options::HMAC_SHA512) {
|
||||||
|
return base64_encode(hash_hmac("sha512", $data, $secret, true));
|
||||||
|
}
|
||||||
|
throw new SdkException("Algorithm " . $algorithm . " not supported yet");
|
||||||
|
}
|
||||||
|
}
|
||||||
40
extend/lop-opensdk-php/src/Options.php
Normal file
40
extend/lop-opensdk-php/src/Options.php
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
class Options
|
||||||
|
{
|
||||||
|
const MD5_SALT = "md5-salt";
|
||||||
|
const SM3_SALT = "sm3-salt";
|
||||||
|
const HMAC_MD5 = "HMacMD5";
|
||||||
|
const HMAC_SHA1 = "HMacSHA1";
|
||||||
|
const HMAC_SHA256 = "HMacSHA256";
|
||||||
|
const HMAC_SHA512 = "HMacSHA512";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $algorithm;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->algorithm = self::MD5_SALT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getAlgorithm()
|
||||||
|
{
|
||||||
|
return $this->algorithm;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $algorithm
|
||||||
|
*/
|
||||||
|
public function setAlgorithm($algorithm)
|
||||||
|
{
|
||||||
|
$this->algorithm = $algorithm;
|
||||||
|
}
|
||||||
|
}
|
||||||
137
extend/lop-opensdk-php/src/Request.php
Normal file
137
extend/lop-opensdk-php/src/Request.php
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface Request
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getDomain();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $domain
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setDomain($domain);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getPath();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $path
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setPath($path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getMethod();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $method
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setMethod($method);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function hasQuery($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getQuery($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setQuery($key, $value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
function getQueries();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function hasHeader($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getHeader($key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $key
|
||||||
|
* @param string $value
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setHeader($key, $value);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
function getHeaders();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Filter $filter
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function addFilter($filter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Filter[]
|
||||||
|
*/
|
||||||
|
function getFilters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function getEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getBody();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $body
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setBody($body);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getRequestId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $requestId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setRequestId($requestId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getResponseType();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $responseType
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setResponseType($responseType);
|
||||||
|
}
|
||||||
94
extend/lop-opensdk-php/src/Response.php
Normal file
94
extend/lop-opensdk-php/src/Response.php
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
interface Response
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
function isSucceed();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param bool $succeed
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setSucceed($succeed);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getTraceId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $traceId
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setTraceId($traceId);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getZhDesc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $zhDesc
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setZhDesc($zhDesc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getEnDesc();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $enDesc
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setEnDesc($enDesc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function getCode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $code
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setCode($code);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
function getStatus();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param int $status
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setStatus($status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getBody();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $body
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setBody($body);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
function getEntity();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param mixed $entity
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setEntity($entity);
|
||||||
|
}
|
||||||
27
extend/lop-opensdk-php/src/SdkException.php
Normal file
27
extend/lop-opensdk-php/src/SdkException.php
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class SdkException extends Exception
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Response $response
|
||||||
|
*/
|
||||||
|
private $response;
|
||||||
|
|
||||||
|
public function __construct($message = "", $code = 0, $response = null, $previous = null)
|
||||||
|
{
|
||||||
|
parent::__construct($message, $code, $previous);
|
||||||
|
$this->response = $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Response
|
||||||
|
*/
|
||||||
|
public function getResponse()
|
||||||
|
{
|
||||||
|
return $this->response;
|
||||||
|
}
|
||||||
|
}
|
||||||
79
extend/lop-opensdk-php/src/Support/DefaultClient.php
Normal file
79
extend/lop-opensdk-php/src/Support/DefaultClient.php
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Support;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Client;
|
||||||
|
use Lop\LopOpensdkPhp\ExecutorFactory;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
use Lop\LopOpensdkPhp\Version;
|
||||||
|
|
||||||
|
class DefaultClient implements Client
|
||||||
|
{
|
||||||
|
private $baseUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var ExecutorFactory
|
||||||
|
*/
|
||||||
|
private $executorFactory;
|
||||||
|
|
||||||
|
public function __construct($baseUri)
|
||||||
|
{
|
||||||
|
$this->baseUri = $baseUri;
|
||||||
|
$this->executorFactory = new DefaultExecutorFactory();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function execute($request, $options)
|
||||||
|
{
|
||||||
|
if (empty($request->getRequestId())) {
|
||||||
|
$request->setRequestId(uniqid());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($request->getBody())) {
|
||||||
|
$request->setBody(json_encode($request->getEntity()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$request->hasQuery("LOP-DN")) {
|
||||||
|
$request->setQuery("LOP-DN", $request->getDomain());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$request->hasHeader("User-Agent")) {
|
||||||
|
$request->setHeader("User-Agent", "lop-opensdk/php@" . Version::VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
$executor = $this->executorFactory->create($this->baseUri);
|
||||||
|
|
||||||
|
$chain = new DefaultFilterChain($executor, $request->getFilters());
|
||||||
|
$response = $chain->doFilter($request, $options);
|
||||||
|
|
||||||
|
if (!$response->isSucceed()) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($request->getResponseType())) {
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
$entity = json_decode($response->getBody());
|
||||||
|
if (json_last_error() != JSON_ERROR_NONE) {
|
||||||
|
throw new SdkException("json decode failed", 0, $response);
|
||||||
|
}
|
||||||
|
if (!settype($entity, $request->getResponseType())) {
|
||||||
|
throw new SdkException("set entity to response type failed", 0, $response);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response->setEntity($entity);
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ExecutorFactory $executorFactory
|
||||||
|
*/
|
||||||
|
public function setExecutorFactory($executorFactory)
|
||||||
|
{
|
||||||
|
$this->executorFactory = $executorFactory;
|
||||||
|
}
|
||||||
|
}
|
||||||
56
extend/lop-opensdk-php/src/Support/DefaultExecutor.php
Normal file
56
extend/lop-opensdk-php/src/Support/DefaultExecutor.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Support;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
|
use GuzzleHttp\Psr7\Request;
|
||||||
|
use Lop\LopOpensdkPhp\Executor;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
|
||||||
|
class DefaultExecutor implements Executor
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $baseUri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $baseUri
|
||||||
|
*/
|
||||||
|
public function __construct($baseUri)
|
||||||
|
{
|
||||||
|
$this->baseUri = $baseUri;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function execute($request, $options)
|
||||||
|
{
|
||||||
|
$uri = $this->baseUri . $request->getPath();
|
||||||
|
$httpRequest = new Request($request->getMethod(), $uri, $request->getHeaders(), $request->getBody());
|
||||||
|
|
||||||
|
$client = new Client(['verify' => false]);
|
||||||
|
try {
|
||||||
|
$httpResponse = $client->send($httpRequest, [
|
||||||
|
"query" => $request->getQueries(),
|
||||||
|
"http_errors" => false
|
||||||
|
]);
|
||||||
|
} catch (GuzzleException $e) {
|
||||||
|
throw new SdkException("", 0, null, $e);
|
||||||
|
}
|
||||||
|
|
||||||
|
$response = new GenericResponse();
|
||||||
|
$response->setSucceed($httpResponse->getStatusCode() == 200);
|
||||||
|
$response->setStatus($httpResponse->getStatusCode());
|
||||||
|
$response->setBody($httpResponse->getBody()->getContents());
|
||||||
|
|
||||||
|
$traceIds = $httpResponse->getHeader("Lop-Trace-Id");
|
||||||
|
if (count($traceIds) > 0) {
|
||||||
|
$response->setTraceId($traceIds[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $response;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Support;
|
||||||
|
|
||||||
|
use GuzzleHttp\Client;
|
||||||
|
use Lop\LopOpensdkPhp\ExecutorFactory;
|
||||||
|
|
||||||
|
class DefaultExecutorFactory implements ExecutorFactory
|
||||||
|
{
|
||||||
|
function create($baseUri)
|
||||||
|
{
|
||||||
|
return new DefaultExecutor($baseUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
51
extend/lop-opensdk-php/src/Support/DefaultFilterChain.php
Normal file
51
extend/lop-opensdk-php/src/Support/DefaultFilterChain.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Support;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Executor;
|
||||||
|
use Lop\LopOpensdkPhp\Filter;
|
||||||
|
use Lop\LopOpensdkPhp\FilterChain;
|
||||||
|
use Lop\LopOpensdkPhp\SdkException;
|
||||||
|
|
||||||
|
class DefaultFilterChain implements FilterChain
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var Executor
|
||||||
|
*/
|
||||||
|
private $executor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Filter[]
|
||||||
|
*/
|
||||||
|
private $filters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $position;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Executor $executor
|
||||||
|
* @param Filter[] $filters
|
||||||
|
*/
|
||||||
|
public function __construct($executor, $filters)
|
||||||
|
{
|
||||||
|
$this->executor = $executor;
|
||||||
|
$this->filters = $filters;
|
||||||
|
$this->position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws SdkException
|
||||||
|
*/
|
||||||
|
function doFilter($request, $options)
|
||||||
|
{
|
||||||
|
if ($this->position < count($this->filters)) {
|
||||||
|
$filter = $this->filters[$this->position];
|
||||||
|
$this->position++;
|
||||||
|
return $filter->doFilter($request, $options, $this);
|
||||||
|
} else {
|
||||||
|
return $this->executor->execute($request, $options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
184
extend/lop-opensdk-php/src/Support/GenericRequest.php
Normal file
184
extend/lop-opensdk-php/src/Support/GenericRequest.php
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Support;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Filter;
|
||||||
|
use Lop\LopOpensdkPhp\Request;
|
||||||
|
|
||||||
|
class GenericRequest implements Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $domain;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $path;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
private $queries;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string[]
|
||||||
|
*/
|
||||||
|
private $headers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var Filter[]
|
||||||
|
*/
|
||||||
|
private $filters;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $body;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $requestId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $responseType;
|
||||||
|
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
$this->queries = array();
|
||||||
|
$this->headers = array();
|
||||||
|
$this->filters = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function getDomain()
|
||||||
|
{
|
||||||
|
return $this->domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setDomain($domain)
|
||||||
|
{
|
||||||
|
$this->domain = $domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPath()
|
||||||
|
{
|
||||||
|
return $this->path;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPath($path)
|
||||||
|
{
|
||||||
|
$this->path = $path;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMethod()
|
||||||
|
{
|
||||||
|
return $this->method;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setMethod($method)
|
||||||
|
{
|
||||||
|
$this->method = $method;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasQuery($key)
|
||||||
|
{
|
||||||
|
return array_key_exists($key, $this->queries);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQuery($key)
|
||||||
|
{
|
||||||
|
return $this->queries[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
function setQuery($key, $value)
|
||||||
|
{
|
||||||
|
$this->queries[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getQueries()
|
||||||
|
{
|
||||||
|
return $this->queries;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasHeader($key)
|
||||||
|
{
|
||||||
|
return array_key_exists($key, $this->headers);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHeader($key)
|
||||||
|
{
|
||||||
|
return $this->headers[$key];
|
||||||
|
}
|
||||||
|
|
||||||
|
function setHeader($key, $value)
|
||||||
|
{
|
||||||
|
$this->headers[$key] = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getHeaders()
|
||||||
|
{
|
||||||
|
return $this->headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
function addFilter($filter)
|
||||||
|
{
|
||||||
|
$this->filters[] = $filter;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getFilters()
|
||||||
|
{
|
||||||
|
return $this->filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEntity()
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBody()
|
||||||
|
{
|
||||||
|
return $this->body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBody($body)
|
||||||
|
{
|
||||||
|
$this->body = $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getRequestId()
|
||||||
|
{
|
||||||
|
return $this->requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setRequestId($requestId)
|
||||||
|
{
|
||||||
|
$this->requestId = $requestId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
function getResponseType()
|
||||||
|
{
|
||||||
|
return $this->responseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param string $responseType
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
function setResponseType($responseType)
|
||||||
|
{
|
||||||
|
$this->responseType = $responseType;
|
||||||
|
}
|
||||||
|
}
|
||||||
129
extend/lop-opensdk-php/src/Support/GenericResponse.php
Normal file
129
extend/lop-opensdk-php/src/Support/GenericResponse.php
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp\Support;
|
||||||
|
|
||||||
|
use Lop\LopOpensdkPhp\Response;
|
||||||
|
|
||||||
|
class GenericResponse implements Response
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var bool
|
||||||
|
*/
|
||||||
|
private $succeed;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $traceId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $zhDesc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $enDesc;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
private $code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $status;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
private $body;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @var mixed
|
||||||
|
*/
|
||||||
|
private $entity;
|
||||||
|
|
||||||
|
function isSucceed()
|
||||||
|
{
|
||||||
|
return $this->succeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSucceed($succeed)
|
||||||
|
{
|
||||||
|
$this->succeed = $succeed;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTraceId()
|
||||||
|
{
|
||||||
|
return $this->traceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setTraceId($traceId)
|
||||||
|
{
|
||||||
|
$this->traceId = $traceId;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getZhDesc()
|
||||||
|
{
|
||||||
|
return $this->zhDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setZhDesc($zhDesc)
|
||||||
|
{
|
||||||
|
$this->zhDesc = $zhDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEnDesc()
|
||||||
|
{
|
||||||
|
return $this->enDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setEnDesc($enDesc)
|
||||||
|
{
|
||||||
|
$this->enDesc = $enDesc;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCode()
|
||||||
|
{
|
||||||
|
return $this->code;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setCode($code)
|
||||||
|
{
|
||||||
|
$this->code = $code;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStatus()
|
||||||
|
{
|
||||||
|
return $this->status;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setStatus($status)
|
||||||
|
{
|
||||||
|
$this->status = $status;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBody()
|
||||||
|
{
|
||||||
|
return $this->body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBody($body)
|
||||||
|
{
|
||||||
|
$this->body = $body;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getEntity()
|
||||||
|
{
|
||||||
|
return $this->entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setEntity($entity)
|
||||||
|
{
|
||||||
|
$this->entity = $entity;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
extend/lop-opensdk-php/src/Version.php
Normal file
8
extend/lop-opensdk-php/src/Version.php
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lop\LopOpensdkPhp;
|
||||||
|
|
||||||
|
class Version
|
||||||
|
{
|
||||||
|
const VERSION = "1.0.0";
|
||||||
|
}
|
||||||
@ -1 +1 @@
|
|||||||
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a[data-v-9f160e6c]{text-decoration:none;color:#fff}.opaBox[data-v-9f160e6c]{margin-bottom:15px}
|
#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@keyframes nprogress-spinner{0%{transform:rotate(0deg)}to{transform:rotate(1turn)}}a[data-v-d25d9320]{text-decoration:none;color:#fff}.opaBox[data-v-d25d9320]{margin-bottom:15px}
|
||||||
2
public/dist/index.html
vendored
2
public/dist/index.html
vendored
@ -1 +1 @@
|
|||||||
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>erp</title><script defer="defer" src="js/chunk-vendors.04652b46.js"></script><script defer="defer" src="js/app.f1ce3c3c.js"></script><link href="css/chunk-vendors.77489a8d.css" rel="stylesheet"><link href="css/app.7e37f273.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but erp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
<!doctype html><html lang=""><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="icon" href="favicon.ico"><title>erp</title><script defer="defer" src="js/chunk-vendors.04652b46.js"></script><script defer="defer" src="js/app.10acb235.js"></script><link href="css/chunk-vendors.77489a8d.css" rel="stylesheet"><link href="css/app.7e37f273.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but erp doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div></body></html>
|
||||||
File diff suppressed because one or more lines are too long
1
public/dist/js/147.34297e9a.js.map
vendored
Normal file
1
public/dist/js/147.34297e9a.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/dist/js/147.53e38aa6.js.map
vendored
1
public/dist/js/147.53e38aa6.js.map
vendored
File diff suppressed because one or more lines are too long
2
public/dist/js/19.39213a6d.js
vendored
Normal file
2
public/dist/js/19.39213a6d.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/dist/js/19.39213a6d.js.map
vendored
Normal file
1
public/dist/js/19.39213a6d.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/dist/js/298.143f4f4b.js.map
vendored
1
public/dist/js/298.143f4f4b.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/dist/js/298.c971cd33.js.map
vendored
Normal file
1
public/dist/js/298.c971cd33.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/dist/js/463.09656921.js
vendored
Normal file
2
public/dist/js/463.09656921.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/dist/js/463.09656921.js.map
vendored
Normal file
1
public/dist/js/463.09656921.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/dist/js/613.5a7f6161.js
vendored
2
public/dist/js/613.5a7f6161.js
vendored
File diff suppressed because one or more lines are too long
1
public/dist/js/613.5a7f6161.js.map
vendored
1
public/dist/js/613.5a7f6161.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/dist/js/64.2db5913e.js.map
vendored
Normal file
1
public/dist/js/64.2db5913e.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/dist/js/64.7efc004a.js.map
vendored
1
public/dist/js/64.7efc004a.js.map
vendored
File diff suppressed because one or more lines are too long
2
public/dist/js/808.eabeec45.js
vendored
2
public/dist/js/808.eabeec45.js
vendored
File diff suppressed because one or more lines are too long
1
public/dist/js/808.eabeec45.js.map
vendored
1
public/dist/js/808.eabeec45.js.map
vendored
File diff suppressed because one or more lines are too long
1
public/dist/js/999.1bc20d27.js.map
vendored
1
public/dist/js/999.1bc20d27.js.map
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
1
public/dist/js/999.7767bffa.js.map
vendored
Normal file
1
public/dist/js/999.7767bffa.js.map
vendored
Normal file
File diff suppressed because one or more lines are too long
2
public/dist/js/app.10acb235.js
vendored
Normal file
2
public/dist/js/app.10acb235.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
public/dist/js/app.f1ce3c3c.js
vendored
2
public/dist/js/app.f1ce3c3c.js
vendored
File diff suppressed because one or more lines are too long
8
resources/frontend/src/api/plat.js
vendored
8
resources/frontend/src/api/plat.js
vendored
@ -96,3 +96,11 @@ export function exportAfterOrder(params) {
|
|||||||
responseType: 'blob'
|
responseType: 'blob'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getPrintInfo(params) {
|
||||||
|
return http({
|
||||||
|
url: "/api/print/orders",
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
16
resources/frontend/src/api/shop.js
vendored
16
resources/frontend/src/api/shop.js
vendored
@ -82,3 +82,19 @@ export function orderRest(params) {
|
|||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function shopAddress(params) {
|
||||||
|
return http({
|
||||||
|
url: "/api/shop_sends",
|
||||||
|
method: "get",
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function updateShopAddress(params) {
|
||||||
|
return http({
|
||||||
|
url: '/api/shop_sends',
|
||||||
|
method: 'post',
|
||||||
|
params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
174
resources/frontend/src/components/shop/address.vue
Normal file
174
resources/frontend/src/components/shop/address.vue
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-dialog :visible.sync="showVisible" title="地址管理" width="900px" @close="closeDialog">
|
||||||
|
<div style="margin-bottom: 20px;"><el-button type="primary" @click="addPrintAddr()">添加地址</el-button></div>
|
||||||
|
<div>
|
||||||
|
<el-table :data="addrList" border style="width: 100%;height: auto;" v-loading="loading">
|
||||||
|
<el-table-column prop="id" label="ID" align="center" width="70"/>
|
||||||
|
<el-table-column prop="name" label="姓名" align="center" width="100"/>
|
||||||
|
<el-table-column prop="mobile" label="联系方式" align="center" width="120"/>
|
||||||
|
<el-table-column label="详细地址">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span>{{ scope.row.province }}{{ scope.row.city }}{{ scope.row.district }}{{ scope.row.detail }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" align="center" width="100">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="primary" size="mini" @click="editPrintAddr(scope.row)">编辑</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<el-dialog :visible.sync="printVisible" :title="curAddrId ? '编辑地址' : '新增地址'" width="500px">
|
||||||
|
<el-form label-width="100px">
|
||||||
|
<el-form-item label="姓名:">
|
||||||
|
<el-input v-model="printForm.name" type="input" placeholder="请输入姓名" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="联系电话:">
|
||||||
|
<el-input v-model="printForm.mobile" type="input" placeholder="请输入联系电话" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="省:">
|
||||||
|
<el-input v-model="printForm.province" type="input" placeholder="请输入" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="市:">
|
||||||
|
<el-input v-model="printForm.city" type="input" placeholder="请输入号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="区:">
|
||||||
|
<el-input v-model="printForm.district" type="input" placeholder="请输入" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="详细地址:">
|
||||||
|
<el-input v-model="printForm.detail" type="input" placeholder="街道-小区-门牌号" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="排序:">
|
||||||
|
<el-input v-model="printForm.sort" type="number" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="printVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="commitPrintAddr()" :loading="btnLoading">确定</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { shopAddress, updateShopAddress } from "@/api/shop"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
id: {
|
||||||
|
type: Number,
|
||||||
|
default: () => {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
show: {
|
||||||
|
type: Boolean,
|
||||||
|
default: () => {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
btnLoading: false,
|
||||||
|
showVisible: false,
|
||||||
|
addrList: [],
|
||||||
|
curAddrId: '',
|
||||||
|
loading: false,
|
||||||
|
|
||||||
|
printForm: {},
|
||||||
|
printVisible: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getAddrList() {
|
||||||
|
this.loading = true
|
||||||
|
let params = {
|
||||||
|
shop_id: this.id,
|
||||||
|
page: 1,
|
||||||
|
pageSize: 1000
|
||||||
|
}
|
||||||
|
shopAddress(params).then((res) => {
|
||||||
|
console.log(res)
|
||||||
|
this.addrList = res.data.data
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
addPrintAddr() {
|
||||||
|
this.curAddrId = ''
|
||||||
|
this.printForm = {}
|
||||||
|
this.printVisible = true
|
||||||
|
},
|
||||||
|
commitPrintAddr(){
|
||||||
|
if(!this.printForm.name) {
|
||||||
|
ElMessage({ type: 'warning', message: '请输入姓名' })
|
||||||
|
return
|
||||||
|
} else if(!this.printForm.mobile) {
|
||||||
|
ElMessage({ type: 'warning', message: '请输入联系电话' })
|
||||||
|
return
|
||||||
|
} else if(!this.printForm.province || !this.printForm.city || !this.printForm.district || !this.printForm.detail) {
|
||||||
|
ElMessage({ type: 'warning', message: '请输入地址信息' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.btnLoading = true
|
||||||
|
let params = {
|
||||||
|
...this.printForm
|
||||||
|
}
|
||||||
|
if(this.curAddrId) {
|
||||||
|
params.id = this.curAddrId
|
||||||
|
updateShopAddress(params).then((res) => {
|
||||||
|
this.$message({ type: 'success', message: '编辑成功' })
|
||||||
|
this.printVisible = false
|
||||||
|
this.getAddrList()
|
||||||
|
this.btnLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.btnLoading = false
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
updateShopAddress(params).then((res) => {
|
||||||
|
this.$message({ type: 'success', message: '添加成功' })
|
||||||
|
this.printVisible = false
|
||||||
|
this.getAddrList()
|
||||||
|
this.btnLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.btnLoading = false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
editPrintAddr(row) {
|
||||||
|
this.curAddrId = row.id
|
||||||
|
this.printForm = JSON.parse(JSON.stringify(row))
|
||||||
|
this.printVisible = true
|
||||||
|
},
|
||||||
|
closeDialog() {
|
||||||
|
this.showVisible = false
|
||||||
|
this.$emit('close')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
show: {
|
||||||
|
handler(newVal, oldVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.showVisible = true
|
||||||
|
this.addrList = []
|
||||||
|
this.printList = []
|
||||||
|
this.getAddrList()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
|
||||||
|
</style>
|
||||||
489
resources/frontend/src/views/plat/orderList - 副本.vue
Normal file
489
resources/frontend/src/views/plat/orderList - 副本.vue
Normal file
@ -0,0 +1,489 @@
|
|||||||
|
<template>
|
||||||
|
<div class="conent">
|
||||||
|
<el-card>
|
||||||
|
<el-form ref="form" :inline="true" label-width="90px">
|
||||||
|
<el-form-item label="所属店铺:">
|
||||||
|
<el-select v-model="filter.shop_id" placeholder="店铺" @change="handleChoose()">
|
||||||
|
<el-option v-for="item in shopsList" :key="item.id" :label="item.name" :value="item.id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="发货状态:">
|
||||||
|
<el-select v-model="filter.shipping_status" placeholder="发货状态" @change="handleChoose()">
|
||||||
|
<el-option value="" label="全部"></el-option>
|
||||||
|
<el-option value="0" label="未发货"></el-option>
|
||||||
|
<el-option value="2" label="部分发货"></el-option>
|
||||||
|
<el-option value="1" label="已发货"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="订单类型:">
|
||||||
|
<el-select v-model="filter.is_supplier" placeholder="订单类型" @change="handleChoose()">
|
||||||
|
<el-option value="" label="全部订单"></el-option>
|
||||||
|
<el-option :value="1" label="自卖团订单"></el-option>
|
||||||
|
<el-option :value="0" label="帮卖团订单"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="订单状态:">
|
||||||
|
<el-select v-model="filter.cancel_status" placeholder="订单状态" @change="handleChoose()">
|
||||||
|
<el-option value="" label="全部"></el-option>
|
||||||
|
<el-option :value="0" label="未取消"></el-option>
|
||||||
|
<el-option :value="1" label="已取消"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="售后状态:">
|
||||||
|
<el-select v-model="filter.after_sales_status" placeholder="售后状态" @change="handleChoose()">
|
||||||
|
<el-option value="" label="全部"></el-option>
|
||||||
|
<el-option :value="0" label="未售后"></el-option>
|
||||||
|
<el-option :value="1" label="有售后"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="商品数量:">
|
||||||
|
<el-select v-model="filter.goods_sku_num" placeholder="商品数量" @change="handleChoose()">
|
||||||
|
<el-option value="" label="全部"></el-option>
|
||||||
|
<el-option :value="1" label="1个商品"></el-option>
|
||||||
|
<el-option :value="2" label="2-5个商品"></el-option>
|
||||||
|
<el-option :value="6" label="6个以上商品"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="订单商品:">
|
||||||
|
<el-select v-model="filter.external_sku_ids" multiple filterable remote reserve-keyword placeholder="订单商品"
|
||||||
|
:remote-method="remoteMethod" :loading="searchLoading">
|
||||||
|
<el-option v-for="item in options" :key="item.external_sku_id" :label="item.title"
|
||||||
|
:value="item.external_sku_id">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="下单时间:">
|
||||||
|
<el-date-picker v-model="confirmAt" type="datetimerange" range-separator="-" start-placeholder="起"
|
||||||
|
end-placeholder="止" format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" @change="handleChoose()">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="跟团号:">
|
||||||
|
<el-input v-model="filter.pno" placeholder="跟团号" @keyup.enter.native="handleChoose"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" @click="handleChoose">筛选</el-button>
|
||||||
|
<el-button plain @click="handleReChoose">重置筛选</el-button>
|
||||||
|
<el-button type="primary" @click="openPrint">打印</el-button>
|
||||||
|
<!-- <el-button v-if="form.goods_sku_num === 2" type="primary">配货单导出</el-button> -->
|
||||||
|
<el-button type="warning" :loading="exportLoading" @click="handleExport" icon="el-icon-download">数据导出</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</el-card>
|
||||||
|
|
||||||
|
<el-card style="margin-top: 10px">
|
||||||
|
<el-table v-loading="loading" ref="multipleTable" :data="orderList" style="width: 100%" border
|
||||||
|
@selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="selection" width="55" align="center" />
|
||||||
|
<el-table-column label="店铺名称" prop="shop.name" />
|
||||||
|
<el-table-column label="跟团号" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.is_supplier ? '自卖团: ' : '帮卖团: ' }}
|
||||||
|
{{ scope.row.is_supplier ? scope.row.participate_no : scope.row.supply_participate_no }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="收件人信息" width="240">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<p>{{ scope.row.receiver_name }} {{ scope.row.receiver_mobile }}</p>
|
||||||
|
<p>{{ scope.row.receiver_address_province }}/{{ scope.row.receiver_address_city }}/{{
|
||||||
|
scope.row.receiver_address_district }}</p>
|
||||||
|
<p>{{ scope.row.receiver_address_detail }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="shipping_status" label="发货状态" align="center"></el-table-column>
|
||||||
|
<el-table-column prop="cancel_status" label="订单状态" align="center"></el-table-column>
|
||||||
|
<el-table-column prop="after_sales_status" label="售后状态" align="center"></el-table-column>
|
||||||
|
<el-table-column label="商品信息" width="380">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div v-for="item in scope.row.items" :key="item.id">
|
||||||
|
{{ item.goods_name }}
|
||||||
|
<span style="color: red;">+{{ item.goods_number }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="confirm_at" label="下单时间" width="150" align="center"></el-table-column>
|
||||||
|
</el-table>
|
||||||
|
|
||||||
|
<div class="page-pagination">
|
||||||
|
<el-pagination
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
@current-change="handleCurrentChange"
|
||||||
|
:current-page="page"
|
||||||
|
:page-sizes="[10, 50, 100]"
|
||||||
|
:page-size="per_page"
|
||||||
|
layout="prev, pager, next, sizes, jumper, total"
|
||||||
|
:total="total">
|
||||||
|
</el-pagination>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { platOrderList, printOrders, printSuccess, exportOrder } from "@/api/plat";
|
||||||
|
import { storeList } from "@/api/shop"
|
||||||
|
import { goodsSkusList } from "@/api/goods"
|
||||||
|
import dayjs from 'dayjs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
filter: {
|
||||||
|
shop_id: '',
|
||||||
|
shipping_status: '',
|
||||||
|
is_supplier: '',
|
||||||
|
cancel_status: 0,
|
||||||
|
after_sales_status: 0,
|
||||||
|
goods_sku_num: '',
|
||||||
|
external_sku_ids: '',
|
||||||
|
pno: ''
|
||||||
|
},
|
||||||
|
loading: false,
|
||||||
|
searchLoading: false,
|
||||||
|
options: [],
|
||||||
|
orderList: [],
|
||||||
|
total: 0,
|
||||||
|
page: 1, //当前页
|
||||||
|
per_page: 10, //每页显示数量
|
||||||
|
shopsList: [],
|
||||||
|
confirmAt: [],
|
||||||
|
print_order_ids: '',
|
||||||
|
print_documents: [],
|
||||||
|
socket: null,
|
||||||
|
lockReconnect: false, //是否真正建立连接
|
||||||
|
timeout: 58 * 1000, //58秒一次心跳
|
||||||
|
timeoutObj: null, //心跳心跳倒计时
|
||||||
|
serverTimeoutObj: null, //心跳倒计时
|
||||||
|
timeoutnum: null, //断开 重连倒计时
|
||||||
|
defaultPrinter: null,
|
||||||
|
taskIDArray: [],
|
||||||
|
requestIDGetGlobalConfig: '',
|
||||||
|
exportLoading: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
let start = dayjs().format('YYYY-MM-DD') + ' 00:00:00'
|
||||||
|
let end = dayjs().format('YYYY-MM-DD') + ' 23:59:59'
|
||||||
|
this.confirmAt = [start, end]
|
||||||
|
this.getOrderList()
|
||||||
|
this.getShopsList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getOrderList() {
|
||||||
|
this.loading = true
|
||||||
|
let params = {
|
||||||
|
...this.filter,
|
||||||
|
page: this.page,
|
||||||
|
per_page: this.per_page,
|
||||||
|
confirm_at_start: this.confirmAt ? this.confirmAt[0] : '',
|
||||||
|
confirm_at_end: this.confirmAt ? this.confirmAt[1] : ''
|
||||||
|
}
|
||||||
|
platOrderList(params).then((res) => {
|
||||||
|
this.orderList = res.data.data
|
||||||
|
this.total = res.data.meta.total
|
||||||
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
getShopsList() {
|
||||||
|
let params = {
|
||||||
|
page: 0,
|
||||||
|
per_page: 99
|
||||||
|
}
|
||||||
|
storeList(params).then((res) => {
|
||||||
|
this.shopsList = res.data.data
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.page = 1
|
||||||
|
this.per_page = val
|
||||||
|
this.getOrderList()
|
||||||
|
},
|
||||||
|
handleCurrentChange(val) {
|
||||||
|
this.page = val
|
||||||
|
this.getOrderList()
|
||||||
|
},
|
||||||
|
handleChoose() {
|
||||||
|
this.page = 1
|
||||||
|
this.getOrderList()
|
||||||
|
},
|
||||||
|
handleReChoose() {
|
||||||
|
this.filter = {
|
||||||
|
shop_id: '',
|
||||||
|
shipping_status: '',
|
||||||
|
is_supplier: '',
|
||||||
|
cancel_status: 0,
|
||||||
|
after_sales_status: 0,
|
||||||
|
goods_sku_num: '',
|
||||||
|
external_sku_ids: '',
|
||||||
|
pno: ''
|
||||||
|
}
|
||||||
|
this.page = 1
|
||||||
|
this.getOrderList()
|
||||||
|
},
|
||||||
|
remoteMethod(query) {
|
||||||
|
if (query !== '') {
|
||||||
|
this.searchLoading = true;
|
||||||
|
setTimeout(() => {
|
||||||
|
this.searchLoading = false;
|
||||||
|
goodsSkusList(query).then((res) => {
|
||||||
|
this.options = res.data.filter(item => {
|
||||||
|
return item.title.toLowerCase().indexOf(query.toLowerCase()) > -1;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}, 200);
|
||||||
|
} else {
|
||||||
|
this.options = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
print() {
|
||||||
|
const print_loading = this.$loading({
|
||||||
|
lock: true,
|
||||||
|
text: 'Loading',
|
||||||
|
spinner: 'el-icon-loading',
|
||||||
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
|
});
|
||||||
|
printOrders(this.filter).then((res) => {
|
||||||
|
this.print_documents = res.data.documents;
|
||||||
|
this.print_order_ids = res.data.order_ids;
|
||||||
|
print_loading.close();
|
||||||
|
this.doPrint();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
let ids = []
|
||||||
|
val.forEach((item) => {
|
||||||
|
ids.push(item.id)
|
||||||
|
})
|
||||||
|
this.filter.ids = ids
|
||||||
|
},
|
||||||
|
initWebSocket() {
|
||||||
|
//初始化weosocket
|
||||||
|
const wsuri = "ws://127.0.0.1:5000";
|
||||||
|
this.socket = new WebSocket(wsuri);
|
||||||
|
// 客户端接收服务端数据时触发
|
||||||
|
this.socket.onmessage = this.websocketonmessage;
|
||||||
|
// 连接建立时触发
|
||||||
|
this.socket.onopen = this.websocketonopen;
|
||||||
|
// 通信发生错误时触发
|
||||||
|
this.socket.onerror = this.websocketonerror;
|
||||||
|
// 连接关闭时触发
|
||||||
|
this.socket.onclose = this.websocketclose;
|
||||||
|
},
|
||||||
|
// 连接建立时触发
|
||||||
|
websocketonopen() {
|
||||||
|
//开启心跳
|
||||||
|
this.start();
|
||||||
|
if (this.socket.readyState === 1) {
|
||||||
|
// 获取打印机列表
|
||||||
|
this.getPrinters();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
start() {
|
||||||
|
//开启心跳
|
||||||
|
console.log("开启心跳");
|
||||||
|
var self = this;
|
||||||
|
self.timeoutObj && clearTimeout(self.timeoutObj);
|
||||||
|
self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
|
||||||
|
self.timeoutObj = setTimeout(function () {
|
||||||
|
//这里发送一个心跳,后端收到后,返回一个心跳消息,
|
||||||
|
if (self.socket.readyState == 1) {
|
||||||
|
//如果连接正常
|
||||||
|
} else {
|
||||||
|
//否则重连
|
||||||
|
self.reconnect();
|
||||||
|
}
|
||||||
|
self.serverTimeoutObj = setTimeout(function () {
|
||||||
|
//超时关闭
|
||||||
|
self.socket.close();
|
||||||
|
}, self.timeout);
|
||||||
|
}, self.timeout);
|
||||||
|
},
|
||||||
|
reconnect() {
|
||||||
|
//重新连接
|
||||||
|
var that = this;
|
||||||
|
if (that.lockReconnect) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
that.lockReconnect = true;
|
||||||
|
//没连接上会一直重连,设置延迟避免请求过多
|
||||||
|
that.timeoutnum && clearTimeout(that.timeoutnum);
|
||||||
|
that.timeoutnum = setTimeout(function () {
|
||||||
|
//新连接
|
||||||
|
that.initWebSocket();
|
||||||
|
that.lockReconnect = false;
|
||||||
|
}, 5000);
|
||||||
|
},
|
||||||
|
// 通信发生错误时触发
|
||||||
|
websocketonerror() {
|
||||||
|
console.log("出现错误");
|
||||||
|
this.reconnect();
|
||||||
|
},
|
||||||
|
// 客户端接收服务端数据时触发
|
||||||
|
websocketonmessage(e) {
|
||||||
|
console.log(e);
|
||||||
|
if (JSON.parse(e.data).printers !== undefined) {
|
||||||
|
this.defaultPrinter = JSON.parse(e.data).defaultPrinter;
|
||||||
|
}
|
||||||
|
// JSON.parse 用来解析JSON字符串
|
||||||
|
console.log("默认打印机" + this.defaultPrinter)
|
||||||
|
|
||||||
|
if (JSON.parse(e.data).status === 'success') {
|
||||||
|
console.log("打印就绪..")
|
||||||
|
}
|
||||||
|
if (JSON.parse(e.data).status === 'failed') {
|
||||||
|
console.log("打印未就绪..")
|
||||||
|
}
|
||||||
|
if (JSON.parse(e.data).taskStatus === 'printed') {
|
||||||
|
console.log('出纸成功--打印成功')
|
||||||
|
// 打印成功回调
|
||||||
|
printSuccess({ order_ids: this.print_order_ids }).then((res) => {
|
||||||
|
console.log(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (JSON.parse(e.data).taskStatus === 'failed') {
|
||||||
|
console.log("打印失败!")
|
||||||
|
}
|
||||||
|
if (JSON.parse(e.data).taskStatus === 'canceled') {
|
||||||
|
console.log("打印取消!")
|
||||||
|
}
|
||||||
|
|
||||||
|
//收到服务器信息,心跳重置
|
||||||
|
this.reset();
|
||||||
|
},
|
||||||
|
reset() {
|
||||||
|
//重置心跳
|
||||||
|
var that = this;
|
||||||
|
//清除时间
|
||||||
|
clearTimeout(that.timeoutObj);
|
||||||
|
clearTimeout(that.serverTimeoutObj);
|
||||||
|
//重启心跳
|
||||||
|
that.start();
|
||||||
|
},
|
||||||
|
websocketsend(Data) {
|
||||||
|
//数据发送
|
||||||
|
this.socket.send(Data);
|
||||||
|
},
|
||||||
|
// 连接关闭时触发
|
||||||
|
websocketclose(e) {
|
||||||
|
//关闭
|
||||||
|
console.log("断开连接", e);
|
||||||
|
//重连
|
||||||
|
this.reconnect();
|
||||||
|
},
|
||||||
|
getPrinters() {
|
||||||
|
var request = this.getRequestObject("getPrinters");
|
||||||
|
this.websocketsend(JSON.stringify(request));
|
||||||
|
},
|
||||||
|
doPrint() {
|
||||||
|
var request = this.getRequestObject("print");
|
||||||
|
request.task = new Object();
|
||||||
|
request.task.taskID = this.getUUID(8, 10);
|
||||||
|
// 把每次打印的任务 taskID 保存到 taskIDArray 数组
|
||||||
|
this.taskIDArray.push(request.task.taskID)
|
||||||
|
// 记录当前打印请求的ID
|
||||||
|
this.requestIDGetGlobalConfig = request.task.taskID
|
||||||
|
request.task.preview = false;
|
||||||
|
request.task.printer = this.defaultPrinter;
|
||||||
|
request.task.documents = this.print_documents;
|
||||||
|
console.log(request.task.documents)
|
||||||
|
|
||||||
|
this.websocketsend(JSON.stringify(request));
|
||||||
|
},
|
||||||
|
getRequestObject(cmd) {
|
||||||
|
var request = new Object();
|
||||||
|
// 必须:请求的ID,用于唯一标识每个请求,每个客户端保证生成唯一的ID
|
||||||
|
request.requestID = this.getUUID(8, 16);
|
||||||
|
//必须: 协议当前版本
|
||||||
|
request.version = "1.0";
|
||||||
|
//必须: 请求命令名称
|
||||||
|
request.cmd = cmd;
|
||||||
|
|
||||||
|
return request;
|
||||||
|
},
|
||||||
|
getUUID(len, radix) {
|
||||||
|
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
||||||
|
var uuid = [], i;
|
||||||
|
radix = radix || chars.length;
|
||||||
|
if (len) {
|
||||||
|
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
|
||||||
|
} else {
|
||||||
|
var r;
|
||||||
|
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
||||||
|
uuid[14] = '4';
|
||||||
|
for (i = 0; i < 36; i++) {
|
||||||
|
if (!uuid[i]) {
|
||||||
|
r = 0 | Math.random() * 16;
|
||||||
|
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return uuid.join('');
|
||||||
|
},
|
||||||
|
handleExport() {
|
||||||
|
this.exportLoading = true
|
||||||
|
let params = {
|
||||||
|
...this.form,
|
||||||
|
page: 1,
|
||||||
|
per_page: this.per_page,
|
||||||
|
confirm_at_start: this.confirmAt[0] ? this.confirmAt[0] : '',
|
||||||
|
confirm_at_end: this.confirmAt[1] ? this.confirmAt[1] : '',
|
||||||
|
is_export: 1
|
||||||
|
}
|
||||||
|
// window.open("/api/plat_orders?" + this.objectToQueryString(params))
|
||||||
|
|
||||||
|
exportOrder(params).then((res) => {
|
||||||
|
this.downLoadXls(res.data)
|
||||||
|
this.$message({ type: 'success', message: '导出成功!' })
|
||||||
|
this.exportLoading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.exportLoading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
downLoadXls(response) {
|
||||||
|
const content = response
|
||||||
|
const blob = new Blob([content])
|
||||||
|
const today = new Date().toLocaleDateString()
|
||||||
|
const fileName = `订单列表${today}.xlsx`
|
||||||
|
if ('download' in document.createElement('a')) {
|
||||||
|
// 非IE下载
|
||||||
|
const elink = document.createElement('a')
|
||||||
|
elink.download = fileName
|
||||||
|
elink.style.display = 'none'
|
||||||
|
elink.href = URL.createObjectURL(blob)
|
||||||
|
document.body.appendChild(elink)
|
||||||
|
elink.click()
|
||||||
|
URL.revokeObjectURL(elink.href) // 释放URL 对象
|
||||||
|
document.body.removeChild(elink)
|
||||||
|
} else {
|
||||||
|
// IE10+下载
|
||||||
|
navigator.msSaveBlob(blob, fileName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
objectToQueryString(obj) {
|
||||||
|
return Object.keys(obj)
|
||||||
|
.map(key => encodeURIComponent(key) + '=' + (obj[key] ? encodeURIComponent(obj[key]) : ''))
|
||||||
|
.join('&');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
|
</style>
|
||||||
@ -18,6 +18,10 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="订单ID:">
|
||||||
|
<el-input v-model="filter.id" placeholder="订单编号" @keyup.enter.native="handleChoose"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="订单类型:">
|
<el-form-item label="订单类型:">
|
||||||
<el-select v-model="filter.is_supplier" placeholder="订单类型" @change="handleChoose()">
|
<el-select v-model="filter.is_supplier" placeholder="订单类型" @change="handleChoose()">
|
||||||
<el-option value="" label="全部订单"></el-option>
|
<el-option value="" label="全部订单"></el-option>
|
||||||
@ -60,20 +64,31 @@
|
|||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="下单时间:">
|
<el-form-item label="商品编码:">
|
||||||
<el-date-picker v-model="confirmAt" type="datetimerange" range-separator="-" start-placeholder="起"
|
<el-input v-model="filter.external_sku_id" placeholder="商品编码" @keyup.enter.native="handleChoose"></el-input>
|
||||||
end-placeholder="止" format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" @change="handleChoose()">
|
|
||||||
</el-date-picker>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="跟团号:">
|
<el-form-item label="跟团号:">
|
||||||
<el-input v-model="filter.pno" placeholder="跟团号" @keyup.enter.native="handleChoose"></el-input>
|
<el-input v-model="filter.pno" placeholder="跟团号" @keyup.enter.native="handleChoose"></el-input>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="打印状态:">
|
||||||
|
<el-select v-model="filter.print_status" placeholder="请选择" @change="handleChoose()" clearable>
|
||||||
|
<el-option :value="1" label="已打印"></el-option>
|
||||||
|
<el-option :value="0" label="未打印"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="下单时间:">
|
||||||
|
<el-date-picker v-model="confirmAt" type="datetimerange" range-separator="-" start-placeholder="起"
|
||||||
|
end-placeholder="止" format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" @change="handleChoose()">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleChoose">筛选</el-button>
|
<el-button type="primary" @click="handleChoose">筛选</el-button>
|
||||||
<el-button plain @click="handleReChoose">重置筛选</el-button>
|
<el-button plain @click="handleReChoose">重置筛选</el-button>
|
||||||
<el-button type="primary" @click="print">打印</el-button>
|
<el-button type="primary" @click="openPrint">打印</el-button>
|
||||||
<!-- <el-button v-if="form.goods_sku_num === 2" type="primary">配货单导出</el-button> -->
|
<!-- <el-button v-if="form.goods_sku_num === 2" type="primary">配货单导出</el-button> -->
|
||||||
<el-button type="warning" :loading="exportLoading" @click="handleExport" icon="el-icon-download">数据导出</el-button>
|
<el-button type="warning" :loading="exportLoading" @click="handleExport" icon="el-icon-download">数据导出</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@ -83,7 +98,8 @@
|
|||||||
<el-card style="margin-top: 10px">
|
<el-card style="margin-top: 10px">
|
||||||
<el-table v-loading="loading" ref="multipleTable" :data="orderList" style="width: 100%" border
|
<el-table v-loading="loading" ref="multipleTable" :data="orderList" style="width: 100%" border
|
||||||
@selection-change="handleSelectionChange">
|
@selection-change="handleSelectionChange">
|
||||||
<el-table-column type="selection" width="55" align="center" />
|
<el-table-column type="selection" width="55" align="center" :selectable="selectable" />
|
||||||
|
<el-table-column label="订单ID" prop="id" width="80" align="center" />
|
||||||
<el-table-column label="店铺名称" prop="shop.name" />
|
<el-table-column label="店铺名称" prop="shop.name" />
|
||||||
<el-table-column label="跟团号" align="center">
|
<el-table-column label="跟团号" align="center">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
@ -103,7 +119,7 @@
|
|||||||
<el-table-column prop="shipping_status" label="发货状态" align="center"></el-table-column>
|
<el-table-column prop="shipping_status" label="发货状态" align="center"></el-table-column>
|
||||||
<el-table-column prop="cancel_status" label="订单状态" align="center"></el-table-column>
|
<el-table-column prop="cancel_status" label="订单状态" align="center"></el-table-column>
|
||||||
<el-table-column prop="after_sales_status" label="售后状态" align="center"></el-table-column>
|
<el-table-column prop="after_sales_status" label="售后状态" align="center"></el-table-column>
|
||||||
<el-table-column label="商品信息" width="380">
|
<el-table-column label="商品信息" min-width="150">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div v-for="item in scope.row.items" :key="item.id">
|
<div v-for="item in scope.row.items" :key="item.id">
|
||||||
{{ item.goods_name }}
|
{{ item.goods_name }}
|
||||||
@ -111,6 +127,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
<el-table-column label="面单信息" min-width="100" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div v-if="scope.row.waybill">
|
||||||
|
<el-tag type="info" v-if="scope.row.waybill.status == 0">待申请运单</el-tag>
|
||||||
|
<el-tag type="primary" v-else-if="scope.row.waybill.status == 1">已申请运单</el-tag>
|
||||||
|
<el-tag type="warning" v-else-if="scope.row.waybill.status == 2">待打印</el-tag>
|
||||||
|
<el-tag type="success" v-else-if="scope.row.waybill.status == 3">打印成功</el-tag>
|
||||||
|
<div style="line-height: 16px;margin-top: 10px;">运单号:{{ scope.row.waybill.waybill_code }}</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="打印状态" align="center" width="110">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-if="scope.row.print_status == 1" style="color: rgb(4, 190, 2);">已打印</span>
|
||||||
|
<span v-else>未打印</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column prop="confirm_at" label="下单时间" width="150" align="center"></el-table-column>
|
<el-table-column prop="confirm_at" label="下单时间" width="150" align="center"></el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
@ -119,18 +152,66 @@
|
|||||||
@size-change="handleSizeChange"
|
@size-change="handleSizeChange"
|
||||||
@current-change="handleCurrentChange"
|
@current-change="handleCurrentChange"
|
||||||
:current-page="page"
|
:current-page="page"
|
||||||
:page-sizes="[10, 50, 100]"
|
:page-sizes="[10, 50, 100, 500]"
|
||||||
:page-size="per_page"
|
:page-size="per_page"
|
||||||
layout="prev, pager, next, sizes, jumper, total"
|
layout="prev, pager, next, sizes, jumper, total"
|
||||||
:total="total">
|
:total="total">
|
||||||
</el-pagination>
|
</el-pagination>
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
|
<el-dialog title="发货信息" width="960px" :visible.sync="showPrint" :close-on-click-modal="false" @close="closePrint">
|
||||||
|
<div v-if="connectStatus == 1" style="margin: -20px 0 20px;">
|
||||||
|
<el-alert title="已建立连接" type="success" show-icon></el-alert>
|
||||||
|
</div>
|
||||||
|
<el-table :data="tempList" style="width: 100%" border>
|
||||||
|
<el-table-column label="订单ID" prop="id" width="80" align="center" />
|
||||||
|
<el-table-column label="收件人信息" width="240">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<p>{{ scope.row.receiver_name }} {{ scope.row.receiver_mobile }}</p>
|
||||||
|
<p>{{ scope.row.receiver_address_province }}/{{ scope.row.receiver_address_city }}/{{
|
||||||
|
scope.row.receiver_address_district }}</p>
|
||||||
|
<p>{{ scope.row.receiver_address_detail }}</p>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="shipping_status" label="发货状态" align="center"></el-table-column>
|
||||||
|
<el-table-column prop="cancel_status" label="订单状态" align="center"></el-table-column>
|
||||||
|
<el-table-column label="商品信息" width="220">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<div v-for="item in scope.row.items" :key="item.id">
|
||||||
|
{{ item.goods_name }}
|
||||||
|
<span style="color: red;">+{{ item.goods_number }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="打印状态" align="center">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<span v-if="scope.row.print_status == 0 || !scope.row.print_status">等待打印</span>
|
||||||
|
<span v-else-if="scope.row.print_status == 1" style="color: rgb(4, 190, 2);">打印成功</span>
|
||||||
|
<div v-else-if="scope.row.print_status == 2">
|
||||||
|
<div style="color: #f00;">打印失败</div>
|
||||||
|
<span style="font-size: 12px;color: #777;">{{ scope.row.fail_msg }}</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<el-form label-width="80px" style="margin-top: 20px;">
|
||||||
|
<el-form-item label="打印机:">
|
||||||
|
<el-select v-model="printName" placeholder="请选择打印机">
|
||||||
|
<el-option v-for="(item, i) in printsList" :key="i" :label="item" :value="item"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button plain @click="showPrint = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="toPrint()" :loading="loading1">保存</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { platOrderList, printOrders, printSuccess, exportOrder } from "@/api/plat";
|
import { platOrderList, printOrders, getPrintInfo, exportOrder, printSuccess } from "@/api/plat";
|
||||||
import { storeList } from "@/api/shop"
|
import { storeList } from "@/api/shop"
|
||||||
import { goodsSkusList } from "@/api/goods"
|
import { goodsSkusList } from "@/api/goods"
|
||||||
import dayjs from 'dayjs'
|
import dayjs from 'dayjs'
|
||||||
@ -146,7 +227,8 @@ export default {
|
|||||||
after_sales_status: 0,
|
after_sales_status: 0,
|
||||||
goods_sku_num: '',
|
goods_sku_num: '',
|
||||||
external_sku_ids: '',
|
external_sku_ids: '',
|
||||||
pno: ''
|
pno: '',
|
||||||
|
external_sku_id: ''
|
||||||
},
|
},
|
||||||
loading: false,
|
loading: false,
|
||||||
searchLoading: false,
|
searchLoading: false,
|
||||||
@ -168,7 +250,15 @@ export default {
|
|||||||
defaultPrinter: null,
|
defaultPrinter: null,
|
||||||
taskIDArray: [],
|
taskIDArray: [],
|
||||||
requestIDGetGlobalConfig: '',
|
requestIDGetGlobalConfig: '',
|
||||||
exportLoading: false
|
exportLoading: false,
|
||||||
|
webSocket: null,
|
||||||
|
chooseList: [],
|
||||||
|
showPrint: false,
|
||||||
|
printName: '',
|
||||||
|
printsList: [],
|
||||||
|
loading1: false,
|
||||||
|
connectStatus: -1,
|
||||||
|
tempList: []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -261,176 +351,15 @@ export default {
|
|||||||
this.doPrint();
|
this.doPrint();
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
selectable(row, index) {
|
||||||
|
if (row.shipping_status == '未发货' && row.cancel_status == '未取消' && row.print_status !== 1) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
handleSelectionChange(val) {
|
handleSelectionChange(val) {
|
||||||
let ids = []
|
this.chooseList = val
|
||||||
val.forEach((item) => {
|
|
||||||
ids.push(item.id)
|
|
||||||
})
|
|
||||||
this.filter.ids = ids
|
|
||||||
},
|
|
||||||
initWebSocket() {
|
|
||||||
//初始化weosocket
|
|
||||||
const wsuri = "ws://127.0.0.1:5000";
|
|
||||||
this.socket = new WebSocket(wsuri);
|
|
||||||
// 客户端接收服务端数据时触发
|
|
||||||
this.socket.onmessage = this.websocketonmessage;
|
|
||||||
// 连接建立时触发
|
|
||||||
this.socket.onopen = this.websocketonopen;
|
|
||||||
// 通信发生错误时触发
|
|
||||||
this.socket.onerror = this.websocketonerror;
|
|
||||||
// 连接关闭时触发
|
|
||||||
this.socket.onclose = this.websocketclose;
|
|
||||||
},
|
|
||||||
// 连接建立时触发
|
|
||||||
websocketonopen() {
|
|
||||||
//开启心跳
|
|
||||||
this.start();
|
|
||||||
if (this.socket.readyState === 1) {
|
|
||||||
// 获取打印机列表
|
|
||||||
this.getPrinters();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
start() {
|
|
||||||
//开启心跳
|
|
||||||
console.log("开启心跳");
|
|
||||||
var self = this;
|
|
||||||
self.timeoutObj && clearTimeout(self.timeoutObj);
|
|
||||||
self.serverTimeoutObj && clearTimeout(self.serverTimeoutObj);
|
|
||||||
self.timeoutObj = setTimeout(function () {
|
|
||||||
//这里发送一个心跳,后端收到后,返回一个心跳消息,
|
|
||||||
if (self.socket.readyState == 1) {
|
|
||||||
//如果连接正常
|
|
||||||
} else {
|
|
||||||
//否则重连
|
|
||||||
self.reconnect();
|
|
||||||
}
|
|
||||||
self.serverTimeoutObj = setTimeout(function () {
|
|
||||||
//超时关闭
|
|
||||||
self.socket.close();
|
|
||||||
}, self.timeout);
|
|
||||||
}, self.timeout);
|
|
||||||
},
|
|
||||||
reconnect() {
|
|
||||||
//重新连接
|
|
||||||
var that = this;
|
|
||||||
if (that.lockReconnect) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
that.lockReconnect = true;
|
|
||||||
//没连接上会一直重连,设置延迟避免请求过多
|
|
||||||
that.timeoutnum && clearTimeout(that.timeoutnum);
|
|
||||||
that.timeoutnum = setTimeout(function () {
|
|
||||||
//新连接
|
|
||||||
that.initWebSocket();
|
|
||||||
that.lockReconnect = false;
|
|
||||||
}, 5000);
|
|
||||||
},
|
|
||||||
// 通信发生错误时触发
|
|
||||||
websocketonerror() {
|
|
||||||
console.log("出现错误");
|
|
||||||
this.reconnect();
|
|
||||||
},
|
|
||||||
// 客户端接收服务端数据时触发
|
|
||||||
websocketonmessage(e) {
|
|
||||||
console.log(e);
|
|
||||||
if (JSON.parse(e.data).printers !== undefined) {
|
|
||||||
this.defaultPrinter = JSON.parse(e.data).defaultPrinter;
|
|
||||||
}
|
|
||||||
// JSON.parse 用来解析JSON字符串
|
|
||||||
console.log("默认打印机" + this.defaultPrinter)
|
|
||||||
|
|
||||||
if (JSON.parse(e.data).status === 'success') {
|
|
||||||
console.log("打印就绪..")
|
|
||||||
}
|
|
||||||
if (JSON.parse(e.data).status === 'failed') {
|
|
||||||
console.log("打印未就绪..")
|
|
||||||
}
|
|
||||||
if (JSON.parse(e.data).taskStatus === 'printed') {
|
|
||||||
console.log('出纸成功--打印成功')
|
|
||||||
// 打印成功回调
|
|
||||||
printSuccess({ order_ids: this.print_order_ids }).then((res) => {
|
|
||||||
console.log(res)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (JSON.parse(e.data).taskStatus === 'failed') {
|
|
||||||
console.log("打印失败!")
|
|
||||||
}
|
|
||||||
if (JSON.parse(e.data).taskStatus === 'canceled') {
|
|
||||||
console.log("打印取消!")
|
|
||||||
}
|
|
||||||
|
|
||||||
//收到服务器信息,心跳重置
|
|
||||||
this.reset();
|
|
||||||
},
|
|
||||||
reset() {
|
|
||||||
//重置心跳
|
|
||||||
var that = this;
|
|
||||||
//清除时间
|
|
||||||
clearTimeout(that.timeoutObj);
|
|
||||||
clearTimeout(that.serverTimeoutObj);
|
|
||||||
//重启心跳
|
|
||||||
that.start();
|
|
||||||
},
|
|
||||||
websocketsend(Data) {
|
|
||||||
//数据发送
|
|
||||||
this.socket.send(Data);
|
|
||||||
},
|
|
||||||
// 连接关闭时触发
|
|
||||||
websocketclose(e) {
|
|
||||||
//关闭
|
|
||||||
console.log("断开连接", e);
|
|
||||||
//重连
|
|
||||||
this.reconnect();
|
|
||||||
},
|
|
||||||
getPrinters() {
|
|
||||||
var request = this.getRequestObject("getPrinters");
|
|
||||||
this.websocketsend(JSON.stringify(request));
|
|
||||||
},
|
|
||||||
doPrint() {
|
|
||||||
var request = this.getRequestObject("print");
|
|
||||||
request.task = new Object();
|
|
||||||
request.task.taskID = this.getUUID(8, 10);
|
|
||||||
// 把每次打印的任务 taskID 保存到 taskIDArray 数组
|
|
||||||
this.taskIDArray.push(request.task.taskID)
|
|
||||||
// 记录当前打印请求的ID
|
|
||||||
this.requestIDGetGlobalConfig = request.task.taskID
|
|
||||||
request.task.preview = false;
|
|
||||||
request.task.printer = this.defaultPrinter;
|
|
||||||
request.task.documents = this.print_documents;
|
|
||||||
console.log(request.task.documents)
|
|
||||||
|
|
||||||
this.websocketsend(JSON.stringify(request));
|
|
||||||
},
|
|
||||||
getRequestObject(cmd) {
|
|
||||||
var request = new Object();
|
|
||||||
// 必须:请求的ID,用于唯一标识每个请求,每个客户端保证生成唯一的ID
|
|
||||||
request.requestID = this.getUUID(8, 16);
|
|
||||||
//必须: 协议当前版本
|
|
||||||
request.version = "1.0";
|
|
||||||
//必须: 请求命令名称
|
|
||||||
request.cmd = cmd;
|
|
||||||
|
|
||||||
return request;
|
|
||||||
},
|
|
||||||
getUUID(len, radix) {
|
|
||||||
var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
|
|
||||||
var uuid = [], i;
|
|
||||||
radix = radix || chars.length;
|
|
||||||
if (len) {
|
|
||||||
for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
|
|
||||||
} else {
|
|
||||||
var r;
|
|
||||||
uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
|
|
||||||
uuid[14] = '4';
|
|
||||||
for (i = 0; i < 36; i++) {
|
|
||||||
if (!uuid[i]) {
|
|
||||||
r = 0 | Math.random() * 16;
|
|
||||||
uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return uuid.join('');
|
|
||||||
},
|
},
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.exportLoading = true
|
this.exportLoading = true
|
||||||
@ -476,6 +405,143 @@ export default {
|
|||||||
return Object.keys(obj)
|
return Object.keys(obj)
|
||||||
.map(key => encodeURIComponent(key) + '=' + (obj[key] ? encodeURIComponent(obj[key]) : ''))
|
.map(key => encodeURIComponent(key) + '=' + (obj[key] ? encodeURIComponent(obj[key]) : ''))
|
||||||
.join('&');
|
.join('&');
|
||||||
|
},
|
||||||
|
|
||||||
|
// https://open.jdl.com/#/open-business-document/access-guide/157/54222 京东云打印文档
|
||||||
|
initWebSocket() {
|
||||||
|
try {
|
||||||
|
let State = new Array('正在连接', '已建立连接', '正在关闭连接', '已关闭连接')
|
||||||
|
let host = 'ws://localhost:9113'
|
||||||
|
const that = this
|
||||||
|
that.webSocket = new WebSocket(host)
|
||||||
|
that.webSocket.onopen = function() {
|
||||||
|
console.log(that.webSocket)
|
||||||
|
that.connectStatus = that.webSocket.readyState
|
||||||
|
that.getPrintList()
|
||||||
|
}
|
||||||
|
that.webSocket.onmessage = function(msg) {
|
||||||
|
let returnData = msg.data
|
||||||
|
let json = eval('(' + returnData + ')')
|
||||||
|
let content = json.content;
|
||||||
|
if(json.code == '6'){ // 打印机返回消息
|
||||||
|
that.printsList = content.split(',')
|
||||||
|
} else if(json.success == 'true' && json.code == '2'){ // 打印成功
|
||||||
|
console.log('0.0', json)
|
||||||
|
that.getOrderList()
|
||||||
|
if(json.message == 'print success all'){ // 全部打印成功
|
||||||
|
let ids = []
|
||||||
|
that.tempList.forEach((item, index) => {
|
||||||
|
ids.push(item.id)
|
||||||
|
that.$set(that.tempList[index], 'print_status', 1)
|
||||||
|
})
|
||||||
|
let params = {
|
||||||
|
order_ids: ids.join(',')
|
||||||
|
}
|
||||||
|
printSuccess(params)
|
||||||
|
} else if(json.message == 'print success, partly wrong.') { // 部分打印成功
|
||||||
|
for (let i = 0; i < json.detailinfo.errors.length; i++) {
|
||||||
|
const it = json.detailinfo.errors[i]
|
||||||
|
that.$set(that.tempList[it.seq * 1 - 1], 'print_status', 2) // 打印失败
|
||||||
|
that.$set(that.tempList[it.seq * 1 - 1], 'fail_msg', it.msg) // 失败信息
|
||||||
|
}
|
||||||
|
let ids = []
|
||||||
|
that.tempList.forEach((item, index) => {
|
||||||
|
if(!item.fail_msg) {
|
||||||
|
that.$set(that.tempList[index], 'print_status', 1)
|
||||||
|
ids.push(item.id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
let params = {
|
||||||
|
order_ids: ids.join(',')
|
||||||
|
}
|
||||||
|
printSuccess(params) // 将打印成功的执行特定接口
|
||||||
|
}
|
||||||
|
} else if(json.success == 'true' && json.code == '2') { // 打印失败
|
||||||
|
for (let i = 0; i < json.detailinfo.detail.length; i++) {
|
||||||
|
const it = json.detailinfo.detail[i]
|
||||||
|
that.$set(that.tempList[it.seq * 1 - 1], 'print_status', 2)
|
||||||
|
that.$set(that.tempList[it.seq * 1 - 1], 'fail_msg', it.msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
that.webSocket.onclose = function() {
|
||||||
|
that.$message({ type: 'info', message: State[that.webSocket.readyState] })
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
that.$message({ type: 'info', message: '连接失败' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getPrintList() {
|
||||||
|
if(this.printsList.length){
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//打印机列表
|
||||||
|
var text = "{\"orderType\":\"GET_Printers\",\"pin\":\"用户名\",\"parameters\":{ \"tempUrl\":\"\", \"printName\":\"\", \"printData\":\"\" }}";
|
||||||
|
this.webSocket.send(text)
|
||||||
|
},
|
||||||
|
openPrint() {
|
||||||
|
if(this.chooseList.length) {
|
||||||
|
this.initWebSocket()
|
||||||
|
this.tempList = JSON.parse(JSON.stringify(this.chooseList))
|
||||||
|
this.tempList.forEach((item) => {
|
||||||
|
item.fail_msg = ''
|
||||||
|
})
|
||||||
|
this.showPrint = true
|
||||||
|
} else {
|
||||||
|
this.$message({ type: 'info', message: '请选择需要打印的订单' })
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toPrint() {
|
||||||
|
if(!this.printName) {
|
||||||
|
this.$message({ type: 'info', message: '请选择打印机' })
|
||||||
|
return
|
||||||
|
}
|
||||||
|
this.loading1 = true
|
||||||
|
let ids = []
|
||||||
|
this.chooseList.forEach((item) => {
|
||||||
|
ids.push(item.id)
|
||||||
|
})
|
||||||
|
let params = {
|
||||||
|
ids: ids.join(',')
|
||||||
|
}
|
||||||
|
getPrintInfo(params).then((res) => {
|
||||||
|
let printObject = res.data.data
|
||||||
|
console.log(printObject)
|
||||||
|
let parameters = {
|
||||||
|
"orderType": "print",
|
||||||
|
"version": "2",
|
||||||
|
"parameters": {
|
||||||
|
"printName": this.printName,
|
||||||
|
"contents": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(let key in printObject) {
|
||||||
|
console.log(key)
|
||||||
|
parameters.parameters.contents.push({
|
||||||
|
"tempUrl": printObject[key].templateUrl,
|
||||||
|
"printData": printObject[key].encryptedData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
this.webSocket.send(JSON.stringify(parameters))
|
||||||
|
this.loading1 = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading1 = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
toPrint1() {
|
||||||
|
let printCmd = 'print'
|
||||||
|
let temp = 'https://template-content.jd.com/template-oss?tempCode=jdkd76x130'
|
||||||
|
let tempUser = ''
|
||||||
|
let printDataUser = ''
|
||||||
|
let printData = 'qfJVGzg6XlGK1E/wOVvkE9YuUGEtuO+WNmfEdPZsvBcUWOuVwbe49t9c0ugW89dOZkYANPvI6J9UA1kq8lbMoIu5VeaRX0G6xR5j8WQUc/Rgg0O1LZWULfxmLSCtBXx5pPYn1dM9vuyW333eCu9ULkz9i201C4ukq7Wy7EKjwu3AN7IK/iz/6R4VK2YZKCPeaSRpr7WjbtwTAPEvw+X8i93FOrOQx4p5rAf0wfjmP++XN4E9jaTqqG3Q/hEVAKqk8TKcQ7raOwuQc2jqdM9hQf35i1wWCDqjMw9RVFarLQ6GdL3sA1jo3KPuP0EwEaZb2PfmPz/uO/4z0DsG0t445sfE2yzVY4vKA0R8Ow5744gzZ8ZFALpgUgr91eSLb3bzT2l2+dSUYe8LIzvOq8tudRtDoEFVE/tKpRRPeUFxtG8i1bckIa5dB2XlMbitxF7/bZyuNcwXEKqVkNL3PRECKdHrV7GAEitO8odOaynuMgtCRcAeQHGihEH0MYWQFTzh5p/DDsAMXtKvb+AWcYl8i/FdLRoeS3RKbqi9ETW/2C4EMqVn5qMfNH/lJ8Lot7PFttgjExY9uHsOEx1XN3naKsAHNGTe7y7j4ehlqO8Q3CV5QPMgW7m/uPeFfsAMWwCsZjwwv2Suni4kI80a9bu8qK92qe9BxtEM6D/zCl+pQ0mfqM3QHVCoVOv0+bHwmlA7YqFOjKBnD550FlKmVrXpWzJKxBCzNsFRvQXefbUFn6+iEwp+k3Mt5nuIDaCr0YLG2iCJj6F4MhPIlnujRDQylGrdQTbsBM0b5Qj/GeqMRUBxF4vSOkAT42fcBl/IpYieet7WT468egg5lbnHRgeEglCfxId/G9of/qCBn6F+8IdCNP2LBOgYehViazxS8JoCqWFPlNYT+5dBzv4vTdbyyp9mbHuOl5A/Ob9HEifeU/L4m/Ohw0Hhqb0FzhbOwjCF8x3JqKqBLhjqEwKX2Rijin7u+orzUad9WHA6cG0kiV/rykvNeELZHLJcysIEK1+fdFmAW1spEwGf5wW06aOk9Ya3OIHYnMO5nsqa0h/b/swmqQ5hgBFnjtqgI/U9LOyZjKm6sRJ/ZEdS1eek6Yx4budi45TLCnh1YeLDSEGvsy8mx9tXg+45tSsoLgCsyIrm57nE1MJ6DOtSwZCvALk4xEY2EJ8jV4LLcfaGOF/1w5T0XpA7SiTEI+Pw9OtKDH7J9F6QO0okxCPj8PTrSgx+yQ5pS1Fbk3FeR0vMZ0jEjNcWpapN0C7XACSwZjaDvqq0DmlLUVuTcV5HS8xnSMSM1w5pS1Fbk3FeR0vMZ0jEjNcOaUtRW5NxXkdLzGdIxIzX+uVqSOXVfVJNP02qnFkkXDtoV9dYl/qguh1KtZVt4YwXI2qYZUStSvhpwEfKZDLp40fsxsKXiI4ykH01NVIsdOGxmwoM6QwCm+LoZLyGYCMoYwbfL5UUOHWOz31uDpbkwTjYYlSIkKNEQqTfADO1uDh44o9KTEIyHnV1IinteuW6Jqnd7aCZBm+NB1Y6OKWLWx0JuD+OJCE9YKjIYt6AQboLFW6NVdGXFwTlVrKeGhKY9b4/e67aUZHTJWyCQqYGaYUkTp9YU/Jbkpec/Jt96fXR9ER46uBGZzD/KSiEzh2PHHMwBm+mVJFEKT9EdvsBdrvqNvT8KyjSIFiycLS0zDNAVhK1h3C65xm28gusIwk9NYvKc0a3k1dsUI0APFWoQUJchiYkNxVvXuHNVyRM9GIuXbIRiUScFwg8Fw6hVHK2D1765+8mU+XVHOOD8auigIuh6jobk731GKXFt/XH1G39XhtZqnMwtaGtJJOTLIyQjJ/dw18139iJco9Fz4zZ+4lc8Hpz/nuDjHFyEB1Q+tQUXNV7NpjQX3qSIPS5ZajZuweoVRTljsyE9gB0FpKBZfEcpIKldXAPxgjpSuemy0d8xfwP2N8ip4OoBE+zeIH24sc8RN/e45y9YLrKWL0CwdBJrvAdygsV5oHVQQ5qP4daUBmSDD6u5hFgdgHj2Q+FjukWYEyrDVITcC61n82GI+RMRPSgxWXAjvXgFT8u2ah8EUVyOIQqYzC1tv8n/zku1XTT0c6KDqYBTY2mmJBdkrdWbNNJEER/L3M2lwSBnIyiR12l2KlqwRGDsvLjH6FGVFSWoB23c+wzG3Ck8r+BKhuxUljFD8+tr8LVNuCm538h1+7ouehGlS+oGKSWOexThRHNMik9d7FlCpgfRTx72zg1GnILqRVWpG9pAz5/ZsQ8MS/IA94GdRRhv1YMsRcU9/iwgg80jBPyfccI0a2WZUlud9qOyHZn+wJL8m4skILooF6kgR95qJbVWYgO5RS5UvUuFjaxkuTVEBOV9sNwSjLchboxStXEOrmE2mg5MTyKppREZtfI2CmxgWsT1/xfzoTKDzUKbVcHKp0TMmS7Oc/Qa9Q+AoYYg/gWL7ii57dHwqENTWVjNOf7N1LkLITEapz/VNX14K8H85ctS7EFJDCu9OpvpJeHaNkRFoV5l5boQRDJJPMNtrs6LV1K1VSS/onio29z7B5+x6sOPyhnnn1GM1LEUgFYZ0yKfCz3iRqNQ+xC8ypxiIXqRQOrQAsyt1bUcASbLgNAHiO7QSkjiLNDgZnE1RWuPM44WbZXiqFXb1G85oJ7BtLMvn5qCMC/X+qHY/rbUh9uMmKV0la9RxmMmP9OuXAkgOC1PoH3J1WX/SzoP4SaKs8XN0YkbZKhUuwtIFQ8HvatF5kT0Gj3eWikrVlxB9r+xFhfaZ/S21A/OS4BRL3DC+hifrVvGNt7tVNaqhkyW3zU2bJK5+jqxENfC+8WgUmmi8F8aIwbc+Dx+qFgElm9itY+VzjpoRlz7UwItXOxlshwaWZ84P/1gDu8GqpcDqlvg2QjPgOzISyr3MuHGt8hrKmXvA5ha9Ko1b03i13FFtp9vlHHNRIcGAHVrU0CFN7U0hg8PpAxAgnJt2wZ5muygnB2gROO2ywB7Kuz7ZzMECASXqrmxmN+JFsnMTMYzw5fyGoBsN8EQG2lgjxODQbdhDMh+JGGdj4w8Cx1SDRL0AJnxaqEiaUblQt2mdGo9PFcCA/Y7kcyVX3f/q6I66hkk3aTSl6IbI9MKvv6MW0QeYJrASDjueVyRDFJ7uvr/Rtm/yuAWw2J4sQOa0+J8cDG9tCfuKGE81VuT3K6jgVIanv1m1Gt+CPIIeRraRE8MMFlVPMsjYTDEKWLCDklXO1JD0UP+CYUkpf8EA2H2CZYaZvCFljxVQ4mVx2WtBX3FrO40dQJz6r2hyfKZpj7NWurYpQBJ/98ABzvY6gwaCL3C/f89Ru5yDlO6xIUK8ZknFD4dKdNqcc47xsxuYF77hSej1Ja64dxVgNqyO9kXCqf1R3yt9RBwK7O6LMrqqZZJEIOeeg9xoISyaafhI8SBzfW299VCTT/unZk6YWmRuiOAeQb6P4zSMElWqMtmO6Y2XoZugrI9fhH7uVwCdAWeRQ3mYIFkrvdFWiisQfg33jPu+20GPMSP8XFfSFAlnQRN75V1w11zopIQUkPxtTuZVvz2VSckRVyKLfU1pt7SCWJbjFBy4XSn0Mb0nyzhK5GAamohOmArFf3sapq0/65fpZueUniZecyNBwpSbN5SmcBLeTWuac1jYoKeBvmaEU95rfVeud3X8bHXW7lT5J0qEOYL2zY1XNsXwtousIEuUsyCKrY4NNP+SazbYUFdABYUVD/mudpdmRWD2/J3miK+hg9/PHjEj9p+w2aAct79rNTzpCiz33ncRfxkO9qy53v+DZA+Xrmgf1g3queNecVvVmD9MsQZTDDtaCSEL8nHN7ykOadZdHZxGsmX0eFXJqFyjLRQwbU6+QgShS/bNn6J/SATMllsGojBJWx3bw0Y5cd65x7A/SpSWjOwuYGAtLiAJ+lpoRIar2jFhrjynnSBLABPAm91woTNM75KxRANnNYgJgg70gscUOoTBkmoKpPhsXXUSq2A7jJLsIZPg7pDG57aChqQZUUBMsTkcK6mjLnVYGJixSGSUg3YU074R3D6ij7yzoP43bftG7f/AosiHzjJlNbJA59+7CO58atop4bzmkd5ARHnQAFWOylyotFuqvLqK1iYmLisWV9mXDczuUlLp0YeNMS6HGUquw4N/WRJMYD4fbVhFxyqy2pKauqth9HVzM04LxGb3TZDyad59nchffZ0Zkd1U1AnPsd9i1H4UzbKl5i+9IOb0sEM/9ts3zmErzZbfv2aQJulLupO+7ifesuAqUzEOpo6EJ9nJpLSYQncAukN6vYOWZ2ACn5r/L5a4OcpdjOxUTDKewSyH/mniCrKcBNt5am4XNlFB1ZJtYW6/waGZCp4hAXZ/kyqSo0KiDUyq243lhKmhNNPKRZ/SmzAfX9kZkUMnyJ2pKliD3hcZHMxegnUM7HW+LJq5J8KxQFmjwOvwgoxLnLgqn2c9NLo3I3N/Lx104HUN0UNbI6lpF1gbuLsO9sLyM78dFVpaZ6dshJPtsDL6ltVTLDxVdTIWMT2OA='
|
||||||
|
let text = "{\"orderType\": \""+ printCmd +"\", \"parameters\": {\"printName\": \""+ this.printName +"\", \"tempUrl\": \""+ temp +"\", \"customTempUrl\": \""+ tempUser +"\", \"customData\": [" + printDataUser +"], \"printData\": [\""+ printData +"\"] } }";
|
||||||
|
this.webSocket.send(text)
|
||||||
|
},
|
||||||
|
closePrint() {
|
||||||
|
this.$refs.multipleTable.clearSelection()
|
||||||
|
this.chooseList = []
|
||||||
|
this.printName = ''
|
||||||
|
this.webSocket.close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,28 +18,29 @@
|
|||||||
</el-input>
|
</el-input>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<el-table-column label="操作" width="280">
|
<el-table-column label="操作" width="360">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="danger" v-if="scope.row.status === '未授权'" size="mini"><a :href="scope.row.authUrl"
|
<el-button type="danger" v-if="scope.row.status === '未授权'" size="mini"><a :href="scope.row.authUrl"
|
||||||
target="_blank" rel="noopener noreferrer">授权</a>
|
target="_blank" rel="noopener noreferrer">授权</a>
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
||||||
<div v-if="scope.row.status === '已授权'">
|
<template v-if="scope.row.status === '已授权'">
|
||||||
<el-button type="success" :disabled="true" size="mini">{{ scope.row.status }}</el-button>
|
<el-button type="success" :disabled="true" size="mini">{{ scope.row.status }}</el-button>
|
||||||
<el-button @click="download(scope.row)" size="mini">下载商品</el-button>
|
<el-button @click="download(scope.row)" size="mini">下载商品</el-button>
|
||||||
<el-button type="primary" v-if="scope.row.status === '已授权'" size="mini"
|
<el-button type="primary" v-if="scope.row.status === '已授权'" size="mini"
|
||||||
@click="syncShopStock(scope.row.id)">同步库存</el-button>
|
@click="syncShopStock(scope.row.id)">同步库存</el-button>
|
||||||
</div>
|
</template>
|
||||||
<div v-if="scope.row.status === '重新授权'">
|
<template v-if="scope.row.status === '重新授权'">
|
||||||
<el-button type="danger" target="_blank" size="mini">
|
<el-button type="danger" target="_blank" size="mini">
|
||||||
<a :href="scope.row.authUrl" rel="noopener noreferrer">重新授权</a>
|
<a :href="scope.row.authUrl" rel="noopener noreferrer">重新授权</a>
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button @click="download(scope.row)" size="mini">下载商品</el-button>
|
<el-button @click="download(scope.row)" size="mini">下载商品</el-button>
|
||||||
</div>
|
</template>
|
||||||
|
|
||||||
<div v-if="scope.row.status === '无需授权'">
|
<template v-if="scope.row.status === '无需授权'">
|
||||||
<el-button type="success" :disabled="true" size="mini">{{ scope.row.status }}</el-button>
|
<el-button type="info" :disabled="true" size="mini">{{ scope.row.status }}</el-button>
|
||||||
</div>
|
</template>
|
||||||
|
<el-button type="warning" size="mini" @click="openAddr(scope.row.id)">发货地址</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
@ -72,14 +73,22 @@
|
|||||||
<el-button type="primary" @click="addSubmit">确 定</el-button>
|
<el-button type="primary" @click="addSubmit">确 定</el-button>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
|
<shop-address :show="showAddr" :id="shop_id" @close="showAddr = false"></shop-address>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { shopListId, shopAdd, storeList, downloadGoods, updateStore, syncStoreStock } from "../../api/shop";
|
import { shopListId, shopAdd, storeList, downloadGoods, updateStore, syncStoreStock } from "../../api/shop";
|
||||||
|
import shopAddress from "@/components/shop/address.vue"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
components: { shopAddress },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
showAddr: false,
|
||||||
|
shop_id: 0,
|
||||||
dialogFormVisible: false,
|
dialogFormVisible: false,
|
||||||
form: {
|
form: {
|
||||||
name: "",
|
name: "",
|
||||||
@ -98,7 +107,7 @@ export default {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
storeId: [], // 店铺id
|
storeId: [], // 店铺id
|
||||||
loading: true,
|
loading: false,
|
||||||
tableData: [],
|
tableData: [],
|
||||||
Paginationdata: {}, //分页相关数据
|
Paginationdata: {}, //分页相关数据
|
||||||
current_page: 1, //当前页
|
current_page: 1, //当前页
|
||||||
@ -135,6 +144,7 @@ export default {
|
|||||||
|
|
||||||
// 店铺列表
|
// 店铺列表
|
||||||
getStoreList() {
|
getStoreList() {
|
||||||
|
this.loading = true
|
||||||
let page = {
|
let page = {
|
||||||
page: this.current_page,
|
page: this.current_page,
|
||||||
per_page: this.per_page,
|
per_page: this.per_page,
|
||||||
@ -142,8 +152,11 @@ export default {
|
|||||||
storeList(page).then((res) => {
|
storeList(page).then((res) => {
|
||||||
this.tableData = res.data.data;
|
this.tableData = res.data.data;
|
||||||
this.Paginationdata = res.data.meta;
|
this.Paginationdata = res.data.meta;
|
||||||
});
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
|
}).catch(() => {
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
//分页功能
|
//分页功能
|
||||||
@ -167,19 +180,21 @@ export default {
|
|||||||
|
|
||||||
// 下载商品
|
// 下载商品
|
||||||
download(row) {
|
download(row) {
|
||||||
const loading = this.$loading({
|
const Loading = this.$loading({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: row.name + ' 店铺商品下载中...',
|
text: row.name + ' 店铺商品下载中...',
|
||||||
spinner: 'el-icon-loading',
|
spinner: 'el-icon-loading',
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
});
|
});
|
||||||
downloadGoods(row.id).then((res) => {
|
downloadGoods(row.id).then((res) => {
|
||||||
loading.close();
|
Loading.close();
|
||||||
this.$message({
|
this.$message({
|
||||||
type: "success",
|
type: "success",
|
||||||
message: res.data.message,
|
message: res.data.message,
|
||||||
});
|
});
|
||||||
});
|
}).catch(() => {
|
||||||
|
Loading.close()
|
||||||
|
})
|
||||||
},
|
},
|
||||||
handleCellChange(row) {
|
handleCellChange(row) {
|
||||||
this.$confirm('确认修改成本变动吗?', '提示', {
|
this.$confirm('确认修改成本变动吗?', '提示', {
|
||||||
@ -197,19 +212,25 @@ export default {
|
|||||||
},
|
},
|
||||||
// 同步
|
// 同步
|
||||||
syncShopStock(id) {
|
syncShopStock(id) {
|
||||||
let loading = this.$loading({
|
const Loading = this.$loading({
|
||||||
lock: true,
|
lock: true,
|
||||||
text: '店铺商品库存同步中...',
|
text: '店铺商品库存同步中...',
|
||||||
spinner: 'el-icon-loading',
|
spinner: 'el-icon-loading',
|
||||||
background: 'rgba(0, 0, 0, 0.7)'
|
background: 'rgba(0, 0, 0, 0.7)'
|
||||||
});
|
});
|
||||||
syncStoreStock({ shop_id: id }).then((res) => {
|
syncStoreStock({ shop_id: id }).then((res) => {
|
||||||
loading.close();
|
Loading.close()
|
||||||
this.$message({
|
this.$message({
|
||||||
type: 'info',
|
type: 'info',
|
||||||
message: res.data.message
|
message: res.data.message
|
||||||
})
|
})
|
||||||
});
|
}).catch(() => {
|
||||||
|
Loading.close()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openAddr(id) {
|
||||||
|
this.shop_id = id
|
||||||
|
this.showAddr = true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@ -72,9 +72,13 @@ Route::middleware(['auth:api', 'check.permissions'])->group(function () {
|
|||||||
Route::get('shop/ship', [ShipController::class, 'index'])->name('shop_ship.index');
|
Route::get('shop/ship', [ShipController::class, 'index'])->name('shop_ship.index');
|
||||||
Route::get('print/orders', [BusinessOrderController::class, 'print'])->name('order.print');
|
Route::get('print/orders', [BusinessOrderController::class, 'print'])->name('order.print');
|
||||||
Route::put('print/success', [BusinessOrderController::class, 'printSuccess'])->name('order.printSuccess');
|
Route::put('print/success', [BusinessOrderController::class, 'printSuccess'])->name('order.printSuccess');
|
||||||
|
Route::get('waybill/queryTrace', [\App\Http\Controllers\Business\WaybillController::class, 'queryTrace']);
|
||||||
|
Route::post('waybill/cancel', [\App\Http\Controllers\Business\WaybillController::class, 'cancel']);
|
||||||
// 发货信息
|
// 发货信息
|
||||||
Route::get('shop/ship/senders', [ShipController::class, 'getSenders'])->name('shop_ship.senders.get');
|
Route::get('shop/ship/senders', [ShipController::class, 'getSenders'])->name('shop_ship.senders.get');
|
||||||
Route::post('shop/ship/senders', [ShipController::class, 'saveSenders'])->name('shop_ship.senders.save');
|
Route::post('shop/ship/senders', [ShipController::class, 'saveSenders'])->name('shop_ship.senders.save');
|
||||||
|
Route::resource('shop_sends', 'Shop\ShopSendsController', ['only' => ['index', 'store']]);
|
||||||
|
|
||||||
// 数据中心
|
// 数据中心
|
||||||
Route::get('data_center/sales_report', [DataCenterController::class, 'salesReport'])->name('sales_report.index');
|
Route::get('data_center/sales_report', [DataCenterController::class, 'salesReport'])->name('sales_report.index');
|
||||||
//供应商
|
//供应商
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
|
use App\Services\Business\BusinessFactory;
|
||||||
use Illuminate\Foundation\Inspiring;
|
use Illuminate\Foundation\Inspiring;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user