DispatchService.php 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. <?php
  2. namespace common\components\delivery\services;
  3. use common\components\delivery\services\adapter\{ ShansongAdapter, HuolalaAdapter, FengniaoAdapter}; // MeituanAdapter, DadaAdapter, SFAdapter, UUAdapter,
  4. use common\components\delivery\models\{DeliveryOrder, DeliveryAccount};
  5. use Yii;
  6. /**
  7. * 聚合调度逻辑(平台选择/优先级)
  8. * Class DispatchService
  9. * @package App\Services
  10. */
  11. class DispatchService
  12. {
  13. protected $adapters;
  14. public function __construct()
  15. {
  16. $this->adapters = [
  17. //'meituan' => new MeituanAdapter(),
  18. //'dada' => new DadaAdapter(),
  19. //'sf' => new SFAdapter(),
  20. //'uu' => new UUAdapter(),
  21. 'shansong' => new ShansongAdapter(),
  22. //'huolala' => new HuolalaAdapter(),
  23. //'fengniao' => new FengniaoAdapter(),
  24. ];
  25. }
  26. /**
  27. * 发单调度
  28. */
  29. public function createOrder($mainId, $orderData)
  30. {
  31. $merchantAccount = DeliveryAccount::where('mainId', $mainId)
  32. ->where('is_active', 1)
  33. ->first();
  34. // 优先使用商户自配
  35. if ($merchantAccount) {
  36. $adapter = $this->adapters[$merchantAccount->platform];
  37. return $adapter->createOrder($merchantAccount, $orderData);
  38. }
  39. // 否则使用平台优惠价策略调度
  40. $platform = $this->getBestPlatform($orderData);
  41. $adapter = $this->adapters[$platform];
  42. return $adapter->createOrder($orderData);
  43. }
  44. protected function getBestPlatform($orderData)
  45. {
  46. // 简化策略:根据距离、重量、历史价格动态选择
  47. $candidates = ['shansong']; //'meituan', 'dada', 'sf', 'uu'
  48. return $candidates[array_rand($candidates)];
  49. }
  50. public function getBestPlatformByPrice($orderData)
  51. {
  52. $results = [];
  53. $accessToken = '';
  54. foreach ($this->adapters as $name => $adapter) {
  55. try {
  56. $quote = $adapter->getPrice($orderData, $accessToken);
  57. if ($quote) {
  58. $results[] = $quote;
  59. }
  60. } catch (\Exception $e) {
  61. Yii::warning("报价失败: {$name} - {$e->getMessage()}");
  62. }
  63. }
  64. if (empty($results)) {
  65. return ['error' => '全部平台报价失败'];
  66. }
  67. // 排序,选择最低价
  68. usort($results, function($a, $b) {
  69. return $a['price'] <=> $b['price'];
  70. });
  71. // 返回所有报价供前端展示
  72. return [
  73. 'quotes' => $results,
  74. 'best' => $results[0],
  75. ];
  76. }
  77. }