ai 5 months ago
parent
commit
2686be3201

+ 74 - 0
app/Command/EndOrderAdminCommand.php

@@ -0,0 +1,74 @@
+<?php
+
+declare (strict_types = 1);
+
+namespace App\Command;
+
+use App\Model\Ad;
+use App\Model\Order;
+use App\Model\OrderAd;
+use Hyperf\Command\Annotation\Command; // 假设Order模型在App\Model命名空间下
+use Hyperf\Command\Command as HyperfCommand; // 假设OrderAd模型在App\Model命名空间下
+use Hyperf\DbConnection\Db;
+use Psr\Log\LoggerInterface;
+
+// 假设Ad模型在App\Model命名空间下
+
+#[Command]
+class EndOrderAdminCommand extends HyperfCommand
+{
+    protected ?string $name = 'end:order-admin';
+    protected $logger;
+    public function __construct(LoggerInterface $logger)
+    {
+        parent::__construct();
+        $this->logger = $logger;
+    }
+
+    public function configure()
+    {
+        parent::configure();
+        $this->setDescription('结束订单并处理相关记录');
+    }
+
+    public function handle()
+    {
+        // 获取需要处理的订单ID列表
+        // $currentTime = time();
+        $currentTime = date('Y-m-d H:i:s');
+        $orderIds = Order::where('status', 6)
+            ->where('edtime', '<=', $currentTime)
+            ->pluck('id')
+            ->toArray();
+        $this->info('需要处理的订单ID列表:' . implode(', ', $orderIds));
+
+        foreach ($orderIds as $orderId) {
+            $data = ['id' => $orderId];
+            $this->processOrder($data);
+        }
+    }
+    private function processOrder(array $data)
+    {
+        $order = Order::where('id', $data['id'])->first();
+        if (empty($order)) {
+            $this->logger->warning("没有找到订单ID: {$data['id']}");
+            return;
+        }
+        Db::beginTransaction();
+        try {
+            $order->status = 7;
+            $order->ad_status = 7;
+            $order->save();
+            // 获取 order_ad 表中的记录
+            OrderAd::where('order_id', $data['id'])
+                ->update(['status' => 7]);
+            // 在ad表中删除相同pid的数据
+            Ad::where('order_id', $data['id'])->delete();
+
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            $this->logger->error("处理订单ID: {$data['id']} 时发生错误: " . $e->getMessage());
+        }
+    }
+}

+ 288 - 34
app/JsonRpc/OrderService.php

@@ -2,80 +2,334 @@
 namespace App\JsonRpc;
 namespace App\JsonRpc;
 
 
 use App\Model\Ad;
 use App\Model\Ad;
-use App\Model\AdPlace;
 use App\Model\Order;
 use App\Model\Order;
 use App\Model\OrderAd;
 use App\Model\OrderAd;
 use App\Tools\Result;
 use App\Tools\Result;
+use Hyperf\DbConnection\Db;
 use Hyperf\RpcServer\Annotation\RpcService;
 use Hyperf\RpcServer\Annotation\RpcService;
 
 
 #[RpcService(name: "OrderService", protocol: "jsonrpc-http", server: "jsonrpc-http")]
 #[RpcService(name: "OrderService", protocol: "jsonrpc-http", server: "jsonrpc-http")]
 class OrderService implements OrderServiceInterface
 class OrderService implements OrderServiceInterface
 {
 {
 
 
-   /**
+    /**
      * 查询没有广告的广告位
      * 查询没有广告的广告位
      * @param
      * @param
      * @return void
      * @return void
-    */
+     */
     public function getAD(array $data): array
     public function getAD(array $data): array
     {
     {
         $where = [
         $where = [
             'width' => $data['width'],
             'width' => $data['width'],
-            'height' => $data['height']
+            'height' => $data['height'],
         ];
         ];
         $start = $data['starttime'];
         $start = $data['starttime'];
         $end = $data['endtime'];
         $end = $data['endtime'];
-        $rep=Ad::where($where)
-        ->where('fromtime','<',$start)
-        ->where('totime','>',$end)
-        ->orderBy('id')
-        ->limit($data['pageSize'])
-        ->offset(($data['page']-1)*$data['pageSize'])->get();
+        $rep = Ad::where($where)
+            ->where('fromtime', '<', $start)
+            ->where('totime', '>', $end)
+            ->orderBy('id')
+            ->limit($data['pageSize'])
+            ->offset(($data['page'] - 1) * $data['pageSize'])->get();
         $count = Ad::where($where)->count();
         $count = Ad::where($where)->count();
         $data = [
         $data = [
-            'rows'=>$rep->toArray(),
-            'count'=>$count
+            'rows' => $rep->toArray(),
+            'count' => $count,
         ];
         ];
         $ads = Ad::whereIn($data['id'])
         $ads = Ad::whereIn($data['id'])
-                ->leftJoin('ad_place','ad.pid','ad_place.id')
-                ->leftJoin("article_data","article.id","article_data.article_id")
-                ->select("ad_place.*","ad.*")
-                ->orderBy("ad.id","desc") 
-                ->limit($data['pageSize'])
-                ->offset(($data['page']-1)*$data['pageSize'])->get();
+            ->leftJoin('ad_place', 'ad.pid', 'ad_place.id')
+            ->leftJoin("article_data", "article.id", "article_data.article_id")
+            ->select("ad_place.*", "ad.*")
+            ->orderBy("ad.id", "desc")
+            ->limit($data['pageSize'])
+            ->offset(($data['page'] - 1) * $data['pageSize'])->get();
         $count = Ad::whereIn($data['id'])->count();
         $count = Ad::whereIn($data['id'])->count();
         $data = [
         $data = [
-            'rows'=>$ads->toArray(),
-            'count'=>$count
+            'rows' => $ads->toArray(),
+            'count' => $count,
         ];
         ];
-        if(empty($rep)){
+        if (empty($rep)) {
             return Result::error("没有信息数据");
             return Result::error("没有信息数据");
         }
         }
         return Result::success($data);
         return Result::success($data);
     }
     }
     /**
     /**
-    * 添加订单
-    * @param
-    * @return void
-    */
+     * 添加订单
+     * @param
+     * @return void
+     */
     public function addOrder(array $data): array
     public function addOrder(array $data): array
     {
     {
         $ads = Ad::whereIn($data['id'])
         $ads = Ad::whereIn($data['id'])
-                ->leftJoin('ad_place','ad.pid','ad_place.id')
-                ->leftJoin("article_data","article.id","article_data.article_id")
-                ->select("ad_place.*","ad.*")
-                ->orderBy("ad.id","desc") 
-                ->limit($data['pageSize'])
-                ->offset(($data['page']-1)*$data['pageSize'])->get();
+            ->leftJoin('ad_place', 'ad.pid', 'ad_place.id')
+            ->leftJoin("article_data", "article.id", "article_data.article_id")
+            ->select("ad_place.*", "ad.*")
+            ->orderBy("ad.id", "desc")
+            ->limit($data['pageSize'])
+            ->offset(($data['page'] - 1) * $data['pageSize'])->get();
         $count = Ad::whereIn($data['id'])->count();
         $count = Ad::whereIn($data['id'])->count();
         $data = [
         $data = [
-            'rows'=>$ads->toArray(),
-            'count'=>$count
+            'rows' => $ads->toArray(),
+            'count' => $count,
         ];
         ];
-        if(empty($rep)){
+        if (empty($rep)) {
             return Result::error("没有信息数据");
             return Result::error("没有信息数据");
         }
         }
         return Result::success($data);
         return Result::success($data);
     }
     }
 
 
+    /**
+     * 获取订单列表
+     * @param
+     * @return void
+     */
+    public function getOrderListAdmin(array $data): array
+    {
+        // 获取分页参数,默认每页 10 条记录
+        $page = isset($data['page']) ? (int) $data['page'] : 1;
+        $perPage = isset($data['pagesize']) ? (int) $data['pagesize'] : 10;
+
+        // 构建查询条件
+        $where = [
+            'order.status' => $data['status'], // 明确指定 order 表的 status 列
+        ];
+
+        // 添加订单号查询条件
+        if (!empty($data['order_num'])) {
+            $where['order.order_num'] = $data['order_num']; // 明确指定 order 表的 order_num 列
+        }
+
+        // 处理时间范围查询
+        $start = $data['sttime'];
+        $end = $data['edtime'];
+
+        // 查询数据并分页
+        $query = Order::where($where)
+            ->when(!empty($start) && !empty($end), function ($q) use ($start, $end) {
+                $q->whereBetween('order.fromtime', [$start, $end]); // 明确指定 order 表的 fromtime 列
+            })
+            ->when(!empty($start), function ($q) use ($start) {
+                $q->where('order.fromtime', '>=', $start); // 明确指定 order 表的 fromtime 列
+            })
+            ->when(!empty($end), function ($q) use ($end) {
+                $q->where('order.totime', '<=', $end); // 明确指定 order 表的 totime 列
+            })
+            ->leftJoin('user as admin_user', 'order.admin_user_id', '=', 'admin_user.id')
+            ->leftJoin('user as user', 'order.user_id', '=', 'user.id')
+            ->select(
+                'order.*',
+                'admin_user.user_name as admin_user_name',
+                'user.user_name as user_name'
+            )
+            ->orderBy('order.id');
+
+        // 执行分页查询
+        $result = $query->paginate($perPage, ['*'], 'page', $page);
+
+        // 返回分页结果
+        return Result::success([
+            'count' => $result->total(),
+            'current_page' => $result->currentPage(),
+            'last_page' => $result->lastPage(),
+            'pagesize' => $result->perPage(),
+            'rows' => $result->items(),
+        ]);
+    }
+    /**
+     * 获取订单详情
+     * @param
+     * @return void
+     */
+    public function getOrderDetailAdmin(array $data): array
+    {
+        $order = Order::where('order.id', $data['id'])
+            ->leftJoin('user as admin_user', 'order.admin_user_id', '=', 'admin_user.id')
+            ->leftJoin('user as user', 'order.user_id', '=', 'user.id')
+            ->select(
+                'order.*',
+                'admin_user.user_name as admin_user_name',
+                'user.user_name as user_name'
+            )->first();
+        if (empty($order)) {
+            return Result::error("没有信息数据");
+        }
+
+        $pid = $order['id'];
+        $ad = OrderAd::where('order_id', $pid)->get();
+        $order['ad'] = $ad;
+        return Result::success($order);
+    }
+    /**
+     * 修改订单价格
+     * @param
+     * @return void
+     */
+    public function editPriceOrderAdmin(array $data): array
+    {
+        $order = Order::where('id', $data['id'])->first();
+        if (empty($order)) {
+            return Result::error("没有信息数据");
+        }
+        $order->price = $data['price'];
+        $order->save();
+        return Result::success($order);
+    }
+    /**
+     *拒绝订单
+     * @param
+     * @return void
+     */
+    public function rejectOrderAdmin(array $data): array
+    {
+        $order = Order::where('id', $data['id'])->first();
+        if (empty($order)) {
+            return Result::error("没有信息数据");
+        }
+        Db::beginTransaction();
+        try {
+            $order->status = 2; //订单状态:1:通过;2:驳回;3:撤回;4:修改;5:过期;6:待审核;7:结束
+            $order->ad_status = 2; 
+            $order->reason = $data['reason'];
+            $order->bhtime = date('Y-m-d H:i:s');
+            $order->save();
+            
+            OrderAd::where('order_id', $data['id'])
+                ->update(['status' => 2]);
+            
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            return Result::error("操作失败");
+        }
+        return Result::success($order);
+    }
+
+    /**
+     * 结束订单
+     * @param
+     * @return void
+     */
+    public function endOrderAdmin(array $data): array
+    {
+        $order = Order::where('id', $data['id'])->first();
+        if (empty($order)) {
+            return Result::error("没有信息数据");
+        }
+
+        Db::beginTransaction();
+        try {
+            $order->status = 7;
+            $order->jstime = date('Y-m-d H:i:s');
+            $order->save();
+
+            // 获取 order_ad 表中的记录
+            $orderAds = OrderAd::where('order_id', $data['id'])
+                ->update(['status' => 7]);
+               
+                // 在ad表中删除相同pid的数据
+            Ad::where('order_id',$data['id'])->delete();
+                        
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            return Result::error("操作失败" . $e->getMessage());
+        }
+        return Result::success($order);
+    }
+    /**
+     * 删除订单
+     * @param
+     * @return void
+     */
+    public function delOrderAdmin(array $data): array
+    {
+        // 获取订单信息
+        $order = Order::where('id', $data['id'])->first();
+
+        if (empty($order)) {
+            return Result::error("没有信息数据");
+        }
+        Db::beginTransaction();
+        try {
+            // 获取 order_ad 表中的记录
+            OrderAd::where('order_id', $data['id'])->delete();
+            // 删除 ad 表中的记录
+           Ad::where('order_id', $order['id'])->delete();)
+            // 提交事务
+            Db::commit();
+        } catch (\Exception $e) {
+            // 回滚事务
+            Db::rollBack();
+            // 返回错误信息
+            return Result::error($e->getMessage());
+        }
+        // 返回成功信息
+        return Result::success("删除成功");
+    }
+    /**
+     * 审核订单
+     * @param
+     * @return void
+     */
+    public function applyOrderStatusAdmin(array $data): array
+    {
+        $order = Order::where('id', $data['id'])
+            ->where('status', 6)
+            ->first();
+        if (empty($order)) {
+            return Result::error("没有信息数据");
+        }
+        Db::beginTransaction();
+        try {
+            $order->status = 1;
+            $order->ad_status = 1;
+            $order->shtime = date('Y-m-d H:i:s');
+            $order->save();
+            // 批量更新 order_ad 表中的状态 
+            OrderAd::where('order_id', $data['id'])
+            ->where('status', 6)
+            ->update(['status' => 1]);
+ 
+           //判断的当前时间是否在订单的开始时间之后,并且小于等于订单的结束时间
+            if (time() >= strtotime($order->sttime) && time() < strtotime($order->edtime)) {
+                $ad_status = 1; //审核生效
+            } else {
+                $ad_status = 2; //审核
+            }
+
+            $ads = [];
+            foreach ($orderAds as $orderAd) {
+                $ads[] = [
+                    'name' => $orderAd->name,
+                    'pid' => $orderAd->pid,
+                    'areaid' => $orderAd->areaid,
+                    'amount' => $orderAd->amount,
+                    'introduce' => $orderAd->introduce,
+                    'hits' => $orderAd->hits,
+                    'admin_user_id' => $orderAd->admin_user_id,
+                    'fromtime' => $orderAd->fromtime,
+                    'totime' => $orderAd->totime,
+                    'text_name' => $orderAd->text_name,
+                    'text_url' => $orderAd->text_url,
+                    'text_title' => $orderAd->text_title,
+                    'image_src' => $orderAd->image_src,
+                    'image_url' => $orderAd->image_url,
+                    'image_alt' => $orderAd->image_alt,
+                    'video_src' => $orderAd->video_src,
+                    'video_url' => $orderAd->video_url,
+                    'video_auto' => $orderAd->video_auto,
+                    'video_loop' => $orderAd->video_loop,
+                    'status' => $ad_status,
+                    'order_id' => $orderAd->order_id,
+                ];
+            }
+            Ad::insert($ads);
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            return Result::error($e->getMessage());
+        }
+        return Result::success($order);
+    }
+
 }
 }

+ 34 - 0
app/JsonRpc/OrderServiceInterface.php

@@ -9,4 +9,38 @@ interface OrderServiceInterface
      */
      */
     public function getAD(array $data): array;
     public function getAD(array $data): array;
 
 
+    /**
+     * @param array $data
+     *  @return array
+     */
+    public function getOrderListAdmin(array $data): array;
+    /**
+     * @param array $data
+     *  @return array
+     */
+    public function getOrderDetailAdmin(array $data): array;
+
+    /**
+     * @param array $data
+     *  @return array
+     */
+    public function applyOrderStatusAdmin(array $data): array;
+
+    public function editPriceOrderAdmin(array $data): array;
+    /**
+     * @param array $data
+     *  @return array
+     */
+    public function rejectOrderAdmin(array $data): array;
+    /**
+     * @param array $data
+     *  @return array
+     */
+    public function endOrderAdmin(array $data): array;
+    /**
+     * @param array $data
+     *  @return array
+     */
+    public function delOrderAdmin(array $data): array;
+
 }
 }

+ 129 - 0
app/Task/EndOrderAdminTask.php

@@ -0,0 +1,129 @@
+<?php
+
+declare (strict_types = 1);
+
+namespace App\Task;
+
+use App\Model\Ad;
+use App\Model\Order;
+use App\Model\OrderAd;
+use Hyperf\Contract\StdoutLoggerInterface;
+use Hyperf\DbConnection\Db;
+use Hyperf\Di\Annotation\Inject;
+use Psr\Log\LoggerInterface;
+
+class EndOrderAdminTask
+{
+    /**
+     * @Inject
+     * @var StdoutLoggerInterface
+     */
+    private $logger;
+    public function __construct(LoggerInterface $logger)
+    {
+        $this->logger = $logger;
+    }
+    public function __invoke()
+    {
+        // 获取需要处理的订单ID列表  判断是否能够结束
+        $currentTime = date('Y-m-d H:i:s');
+        $orderIds = Order::where('status', 1) //已经审核,等待结束
+            ->where('edtime', '<=', $currentTime)
+            ->pluck('id')
+            ->toArray();
+
+        //单个处理
+        // foreach ($orderIds as $orderId) {
+        //     $data = ['id' => $orderId];
+        //     $this->singleOverOrder($data);
+        // }
+        // 批量处理结束订单
+        if ($orderIds) {
+            $this->logger->info('需要处理的订单ID列表:' . implode(', ', $orderIds));
+            $this->OverOder($orderIds);
+        }
+        //过期时间
+        //$exploredTime = date('Y-m-d H:i:s', (time() + 60 * 60 * 2));
+        // 获取所有状态为6的订单
+        $orders = Order::where('status', 6) // 未审核等待过期
+            ->get();
+        $expiredOrderIds = [];
+        foreach ($orders as $order) {
+            // 计算 created_at + 2小时
+            $exploredTime = date('Y-m-d H:i:s', strtotime($order->created_at . ' +2 hours'));
+            $this->logger->info('exploredTime: ' . $exploredTime . ' 当前时间' . $order->created_at);
+            // 检查当前时间是否大于 exploredTime
+            if (time() > strtotime($exploredTime)) {
+                $expiredOrderIds[] = $order->id;
+            }
+        }
+        if ($expiredOrderIds) {
+            $this->logger->info('需要处理的订单ID列表:' . implode(', ', $expiredOrderIds));
+            //单个处理
+            // 获取需要处理的订单ID列表  判断是否能够过期
+            $this->ExpiredOrder($expiredOrderIds);
+        }
+    }
+    /**
+     * 处理单个订单是否结束
+     */
+    private function singleOverOrder(array $data)
+    {
+        $order = Order::where('id', $data['id'])->first();
+        if (empty($order)) {
+            $this->logger->warning("没有找到订单ID: {$data['id']}");
+            return;
+        }
+        Db::beginTransaction();
+        try {
+            $order->status = 7;
+            $order->ad_status = 7;
+            $order->save();
+            //获取 order_ad 表中的记录
+            $orderAds = OrderAd::where('order_id', $data['id'])->get();
+            if ($orderAds->isEmpty()) {
+                $this->logger->warning("没有找到订单ID: {$data['id']} 的 order_ad 记录");
+                return;
+            }
+            //获取 order_ad 表中的记录
+            OrderAd::where('order_id', $data['id'])
+                ->update(['status' => 7]);
+            //在ad表中删除的数据
+            Ad::where('order_id', $data['id'])->delete();
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            $this->logger->error("处理订单ID: {$data['id']} 时发生错误: " . $e->getMessage());
+        }
+    }
+    private function OverOder(array $data): void
+    {
+        Db::beginTransaction();
+        try {
+            //设置订单状态
+            Order::whereIn('id', $data)->update(['status' => 7, 'ad_status' => 7]);
+            //设置广告状态
+            OrderAd::whereIn('order_id', $data)->update(['status' => 7]);
+            //ad 变更状态为已经审核但是不生效,或者删除订单,或者加入别的状态:比如过期
+            Ad::whereIn('order_id', $data)->update(['status' => 2]);
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            $this->logger->error("处理订单ID: {$data['id']} 时发生错误: " . $e->getMessage());
+        }
+    }
+    private function ExpiredOrder(array $data): void
+    {
+        Db::beginTransaction();
+        try {
+            //设置订单状态
+            Order::whereIn('id', $data)->update(['status' => 5, 'ad_status' => 5]);
+            //设置广告状态
+            OrderAd::whereIn('order_id', $data)->update(['status' => 5]);
+            Db::commit();
+        } catch (\Exception $e) {
+            Db::rollBack();
+            $this->logger->error("处理订单ID: {$data['id']} 时发生错误: " . $e->getMessage());
+        }
+    }
+}

+ 10 - 7
composer.json

@@ -13,29 +13,32 @@
     "license": "Apache-2.0",
     "license": "Apache-2.0",
     "require": {
     "require": {
         "php": ">=8.1",
         "php": ">=8.1",
+        "hyperf/amqp": "~3.1.0",
+        "hyperf/async-queue": "~3.1.0",
         "hyperf/cache": "~3.1.0",
         "hyperf/cache": "~3.1.0",
         "hyperf/command": "~3.1.0",
         "hyperf/command": "~3.1.0",
         "hyperf/config": "~3.1.0",
         "hyperf/config": "~3.1.0",
+        "hyperf/constants": "~3.1.0",
+        "hyperf/crontab": "^3.1",
+        "hyperf/database": "~3.1.0",
         "hyperf/db-connection": "~3.1.0",
         "hyperf/db-connection": "~3.1.0",
+        "hyperf/elasticsearch": "~3.1.0",
         "hyperf/engine": "^2.10",
         "hyperf/engine": "^2.10",
         "hyperf/framework": "~3.1.0",
         "hyperf/framework": "~3.1.0",
         "hyperf/guzzle": "~3.1.0",
         "hyperf/guzzle": "~3.1.0",
         "hyperf/http-server": "~3.1.0",
         "hyperf/http-server": "~3.1.0",
+        "hyperf/json-rpc": "~3.1.0",
         "hyperf/logger": "~3.1.0",
         "hyperf/logger": "~3.1.0",
         "hyperf/memory": "~3.1.0",
         "hyperf/memory": "~3.1.0",
+        "hyperf/model-cache": "~3.1.0",
+        "hyperf/paginator": "^3.1",
         "hyperf/process": "~3.1.0",
         "hyperf/process": "~3.1.0",
-        "hyperf/database": "~3.1.0",
         "hyperf/redis": "~3.1.0",
         "hyperf/redis": "~3.1.0",
-        "hyperf/json-rpc": "~3.1.0",
         "hyperf/rpc": "~3.1.0",
         "hyperf/rpc": "~3.1.0",
         "hyperf/rpc-client": "~3.1.0",
         "hyperf/rpc-client": "~3.1.0",
         "hyperf/rpc-server": "~3.1.0",
         "hyperf/rpc-server": "~3.1.0",
         "hyperf/service-governance": "~3.1.0",
         "hyperf/service-governance": "~3.1.0",
-        "hyperf/constants": "~3.1.0",
-        "hyperf/async-queue": "~3.1.0",
-        "hyperf/amqp": "~3.1.0",
-        "hyperf/model-cache": "~3.1.0",
-        "hyperf/elasticsearch": "~3.1.0",
+        "hyperf/task": "^3.1",
         "hyperf/tracer": "~3.1.0"
         "hyperf/tracer": "~3.1.0"
     },
     },
     "require-dev": {
     "require-dev": {

+ 471 - 1
composer.lock

@@ -4,7 +4,7 @@
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
         "This file is @generated automatically"
         "This file is @generated automatically"
     ],
     ],
-    "content-hash": "fbcdbc7b050522570fd377ee53f971d9",
+    "content-hash": "07e3fe8a845725aabc81b8158ccf8c3f",
     "packages": [
     "packages": [
         {
         {
             "name": "carbonphp/carbon-doctrine-types",
             "name": "carbonphp/carbon-doctrine-types",
@@ -1791,6 +1791,77 @@
             ],
             ],
             "time": "2024-09-25T02:54:12+00:00"
             "time": "2024-09-25T02:54:12+00:00"
         },
         },
+        {
+            "name": "hyperf/crontab",
+            "version": "v3.1.42",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/hyperf/crontab.git",
+                "reference": "be1187515aabbfe96b2f6a5330b4ddd742e971c7"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/hyperf/crontab/zipball/be1187515aabbfe96b2f6a5330b4ddd742e971c7",
+                "reference": "be1187515aabbfe96b2f6a5330b4ddd742e971c7",
+                "shasum": ""
+            },
+            "require": {
+                "hyperf/conditionable": "~3.1.0",
+                "hyperf/framework": "~3.1.0",
+                "hyperf/support": "~3.1.0",
+                "hyperf/tappable": "~3.1.0",
+                "hyperf/utils": "~3.1.0",
+                "nesbot/carbon": "^2.0",
+                "php": ">=8.1"
+            },
+            "suggest": {
+                "hyperf/command": "Required to use command trigger.",
+                "hyperf/process": "Auto register the Crontab process for server."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev"
+                },
+                "hyperf": {
+                    "config": "Hyperf\\Crontab\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Hyperf\\Crontab\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "A crontab component for Hyperf.",
+            "homepage": "https://hyperf.io",
+            "keywords": [
+                "crontab",
+                "hyperf",
+                "php",
+                "swoole"
+            ],
+            "support": {
+                "docs": "https://hyperf.wiki",
+                "issues": "https://github.com/hyperf/hyperf/issues",
+                "pull-request": "https://github.com/hyperf/hyperf/pulls",
+                "source": "https://github.com/hyperf/hyperf"
+            },
+            "funding": [
+                {
+                    "url": "https://hyperf.wiki/#/zh-cn/donate",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://opencollective.com/hyperf",
+                    "type": "open_collective"
+                }
+            ],
+            "time": "2024-09-25T02:54:12+00:00"
+        },
         {
         {
             "name": "hyperf/database",
             "name": "hyperf/database",
             "version": "v3.1.44",
             "version": "v3.1.44",
@@ -3180,6 +3251,74 @@
             ],
             ],
             "time": "2024-09-25T02:54:12+00:00"
             "time": "2024-09-25T02:54:12+00:00"
         },
         },
+        {
+            "name": "hyperf/paginator",
+            "version": "v3.1.42",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/hyperf/paginator.git",
+                "reference": "b637a3deeee69f4a3e5a6d62ab8214244b98412a"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/hyperf/paginator/zipball/b637a3deeee69f4a3e5a6d62ab8214244b98412a",
+                "reference": "b637a3deeee69f4a3e5a6d62ab8214244b98412a",
+                "shasum": ""
+            },
+            "require": {
+                "hyperf/contract": "~3.1.0",
+                "hyperf/support": "~3.1.0",
+                "hyperf/utils": "~3.1.0",
+                "php": ">=8.1"
+            },
+            "suggest": {
+                "hyperf/event": "Reqiured to use PageResolverListener.",
+                "hyperf/framework": "Reqiured to use PageResolverListener.",
+                "hyperf/http-server": "Reqiured to use PageResolverListener."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev"
+                },
+                "hyperf": {
+                    "config": "Hyperf\\Paginator\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Hyperf\\Paginator\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "A paginator component for hyperf.",
+            "homepage": "https://hyperf.io",
+            "keywords": [
+                "hyperf",
+                "paginator",
+                "php"
+            ],
+            "support": {
+                "docs": "https://hyperf.wiki",
+                "issues": "https://github.com/hyperf/hyperf/issues",
+                "pull-request": "https://github.com/hyperf/hyperf/pulls",
+                "source": "https://github.com/hyperf/hyperf"
+            },
+            "funding": [
+                {
+                    "url": "https://hyperf.wiki/#/zh-cn/donate",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://opencollective.com/hyperf",
+                    "type": "open_collective"
+                }
+            ],
+            "time": "2024-09-25T02:54:12+00:00"
+        },
         {
         {
             "name": "hyperf/pipeline",
             "name": "hyperf/pipeline",
             "version": "v3.1.42",
             "version": "v3.1.42",
@@ -4125,6 +4264,79 @@
             ],
             ],
             "time": "2024-09-25T02:54:12+00:00"
             "time": "2024-09-25T02:54:12+00:00"
         },
         },
+        {
+            "name": "hyperf/task",
+            "version": "v3.1.42",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/hyperf/task.git",
+                "reference": "c764c465cb9a03a2ccc9d10fce639c2a9d493901"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/hyperf/task/zipball/c764c465cb9a03a2ccc9d10fce639c2a9d493901",
+                "reference": "c764c465cb9a03a2ccc9d10fce639c2a9d493901",
+                "shasum": ""
+            },
+            "require": {
+                "hyperf/contract": "~3.1.0",
+                "hyperf/framework": "~3.1.0",
+                "hyperf/serializer": "~3.1.0",
+                "hyperf/support": "~3.1.0",
+                "hyperf/utils": "~3.1.0",
+                "php": ">=8.1",
+                "psr/container": "^1.0 || ^2.0",
+                "psr/event-dispatcher": "^1.0",
+                "symfony/property-access": "^5.0 || ^6.0",
+                "symfony/serializer": "^5.0 || ^6.0"
+            },
+            "suggest": {
+                "hyperf/di": "Required to use annotation."
+            },
+            "type": "library",
+            "extra": {
+                "branch-alias": {
+                    "dev-master": "3.1-dev"
+                },
+                "hyperf": {
+                    "config": "Hyperf\\Task\\ConfigProvider"
+                }
+            },
+            "autoload": {
+                "psr-4": {
+                    "Hyperf\\Task\\": "src/"
+                }
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "description": "A task library for Hyperf.",
+            "homepage": "https://hyperf.io",
+            "keywords": [
+                "hyperf",
+                "php",
+                "swoole",
+                "task"
+            ],
+            "support": {
+                "docs": "https://hyperf.wiki",
+                "issues": "https://github.com/hyperf/hyperf/issues",
+                "pull-request": "https://github.com/hyperf/hyperf/pulls",
+                "source": "https://github.com/hyperf/hyperf"
+            },
+            "funding": [
+                {
+                    "url": "https://hyperf.wiki/#/zh-cn/donate",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://opencollective.com/hyperf",
+                    "type": "open_collective"
+                }
+            ],
+            "time": "2024-09-25T02:54:12+00:00"
+        },
         {
         {
             "name": "hyperf/tracer",
             "name": "hyperf/tracer",
             "version": "v3.1.42",
             "version": "v3.1.42",
@@ -6737,6 +6949,264 @@
             ],
             ],
             "time": "2024-09-09T11:45:10+00:00"
             "time": "2024-09-09T11:45:10+00:00"
         },
         },
+        {
+            "name": "symfony/property-access",
+            "version": "v6.4.13",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/property-access.git",
+                "reference": "8cc779d88d12e440adaa26387bcfc25744064afe"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/property-access/zipball/8cc779d88d12e440adaa26387bcfc25744064afe",
+                "reference": "8cc779d88d12e440adaa26387bcfc25744064afe",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/property-info": "^5.4|^6.0|^7.0"
+            },
+            "require-dev": {
+                "symfony/cache": "^5.4|^6.0|^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\PropertyAccess\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Provides functions to read and write from/to an object or array using a simple string notation",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "access",
+                "array",
+                "extraction",
+                "index",
+                "injection",
+                "object",
+                "property",
+                "property-path",
+                "reflection"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/property-access/tree/v6.4.13"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-25T14:18:03+00:00"
+        },
+        {
+            "name": "symfony/property-info",
+            "version": "v6.4.13",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/property-info.git",
+                "reference": "ea388133aadf407dfa54092873d1b7e52f439515"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/property-info/zipball/ea388133aadf407dfa54092873d1b7e52f439515",
+                "reference": "ea388133aadf407dfa54092873d1b7e52f439515",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "symfony/string": "^5.4|^6.0|^7.0"
+            },
+            "conflict": {
+                "phpdocumentor/reflection-docblock": "<5.2",
+                "phpdocumentor/type-resolver": "<1.5.1",
+                "symfony/dependency-injection": "<5.4",
+                "symfony/serializer": "<6.4"
+            },
+            "require-dev": {
+                "phpdocumentor/reflection-docblock": "^5.2",
+                "phpstan/phpdoc-parser": "^1.0",
+                "symfony/cache": "^5.4|^6.0|^7.0",
+                "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+                "symfony/serializer": "^6.4|^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\PropertyInfo\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Kévin Dunglas",
+                    "email": "dunglas@gmail.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Extracts information about PHP class' properties using metadata of popular sources",
+            "homepage": "https://symfony.com",
+            "keywords": [
+                "doctrine",
+                "phpdoc",
+                "property",
+                "symfony",
+                "type",
+                "validator"
+            ],
+            "support": {
+                "source": "https://github.com/symfony/property-info/tree/v6.4.13"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-09-25T14:18:03+00:00"
+        },
+        {
+            "name": "symfony/serializer",
+            "version": "v6.4.13",
+            "source": {
+                "type": "git",
+                "url": "https://github.com/symfony/serializer.git",
+                "reference": "8be421505938b11a0ca4f656e4322232236386f0"
+            },
+            "dist": {
+                "type": "zip",
+                "url": "https://api.github.com/repos/symfony/serializer/zipball/8be421505938b11a0ca4f656e4322232236386f0",
+                "reference": "8be421505938b11a0ca4f656e4322232236386f0",
+                "shasum": ""
+            },
+            "require": {
+                "php": ">=8.1",
+                "symfony/deprecation-contracts": "^2.5|^3",
+                "symfony/polyfill-ctype": "~1.8"
+            },
+            "conflict": {
+                "doctrine/annotations": "<1.12",
+                "phpdocumentor/reflection-docblock": "<3.2.2",
+                "phpdocumentor/type-resolver": "<1.4.0",
+                "symfony/dependency-injection": "<5.4",
+                "symfony/property-access": "<5.4",
+                "symfony/property-info": "<5.4.24|>=6,<6.2.11",
+                "symfony/uid": "<5.4",
+                "symfony/validator": "<6.4",
+                "symfony/yaml": "<5.4"
+            },
+            "require-dev": {
+                "doctrine/annotations": "^1.12|^2",
+                "phpdocumentor/reflection-docblock": "^3.2|^4.0|^5.0",
+                "seld/jsonlint": "^1.10",
+                "symfony/cache": "^5.4|^6.0|^7.0",
+                "symfony/config": "^5.4|^6.0|^7.0",
+                "symfony/console": "^5.4|^6.0|^7.0",
+                "symfony/dependency-injection": "^5.4|^6.0|^7.0",
+                "symfony/error-handler": "^5.4|^6.0|^7.0",
+                "symfony/filesystem": "^5.4|^6.0|^7.0",
+                "symfony/form": "^5.4|^6.0|^7.0",
+                "symfony/http-foundation": "^5.4|^6.0|^7.0",
+                "symfony/http-kernel": "^5.4|^6.0|^7.0",
+                "symfony/messenger": "^5.4|^6.0|^7.0",
+                "symfony/mime": "^5.4|^6.0|^7.0",
+                "symfony/property-access": "^5.4.26|^6.3|^7.0",
+                "symfony/property-info": "^5.4.24|^6.2.11|^7.0",
+                "symfony/translation-contracts": "^2.5|^3",
+                "symfony/uid": "^5.4|^6.0|^7.0",
+                "symfony/validator": "^6.4|^7.0",
+                "symfony/var-dumper": "^5.4|^6.0|^7.0",
+                "symfony/var-exporter": "^5.4|^6.0|^7.0",
+                "symfony/yaml": "^5.4|^6.0|^7.0"
+            },
+            "type": "library",
+            "autoload": {
+                "psr-4": {
+                    "Symfony\\Component\\Serializer\\": ""
+                },
+                "exclude-from-classmap": [
+                    "/Tests/"
+                ]
+            },
+            "notification-url": "https://packagist.org/downloads/",
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Fabien Potencier",
+                    "email": "fabien@symfony.com"
+                },
+                {
+                    "name": "Symfony Community",
+                    "homepage": "https://symfony.com/contributors"
+                }
+            ],
+            "description": "Handles serializing and deserializing data structures, including object graphs, into array structures or other formats like XML and JSON.",
+            "homepage": "https://symfony.com",
+            "support": {
+                "source": "https://github.com/symfony/serializer/tree/v6.4.13"
+            },
+            "funding": [
+                {
+                    "url": "https://symfony.com/sponsor",
+                    "type": "custom"
+                },
+                {
+                    "url": "https://github.com/fabpot",
+                    "type": "github"
+                },
+                {
+                    "url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
+                    "type": "tidelift"
+                }
+            ],
+            "time": "2024-10-03T09:58:04+00:00"
+        },
         {
         {
             "name": "symfony/service-contracts",
             "name": "symfony/service-contracts",
             "version": "v3.5.0",
             "version": "v3.5.0",

+ 2 - 1
config/autoload/commands.php

@@ -1,6 +1,6 @@
 <?php
 <?php
 
 
-declare(strict_types=1);
+declare (strict_types = 1);
 /**
 /**
  * This file is part of Hyperf.
  * This file is part of Hyperf.
  *
  *
@@ -10,4 +10,5 @@ declare(strict_types=1);
  * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
  * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
  */
  */
 return [
 return [
+    \App\Command\EndOrderAdminCommand::class,
 ];
 ];

+ 18 - 0
config/autoload/crontab.php

@@ -0,0 +1,18 @@
+<?php
+
+declare (strict_types = 1);
+
+use Hyperf\Crontab\Crontab;
+
+return [
+    // 是否开启定时任务
+    'enable' => true,
+    'crontab' => [
+        (new Crontab())
+            ->setName('endOrderAdminTask')
+            ->setRule('* * * * *') // 每分钟执行一次
+            ->setCallback([App\Task\EndOrderAdminTask::class, '__invoke'])
+            ->setMemo('处理订单状态变更任务')
+            ->setTimezone('Asia/Shanghai'),
+    ],
+];

+ 3 - 1
config/autoload/processes.php

@@ -1,6 +1,7 @@
 <?php
 <?php
 
 
-declare(strict_types=1);
+declare (strict_types = 1);
+use Hyperf\Crontab\Process\CrontabDispatcherProcess;
 /**
 /**
  * This file is part of Hyperf.
  * This file is part of Hyperf.
  *
  *
@@ -10,4 +11,5 @@ declare(strict_types=1);
  * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
  * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
  */
  */
 return [
 return [
+    CrontabDispatcherProcess::class,
 ];
 ];

+ 5 - 0
config/autoload/server.php

@@ -42,8 +42,13 @@ return [
         Constant::OPTION_MAX_REQUEST => 100000,
         Constant::OPTION_MAX_REQUEST => 100000,
         Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,
         Constant::OPTION_SOCKET_BUFFER_SIZE => 2 * 1024 * 1024,
         Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,
         Constant::OPTION_BUFFER_OUTPUT_SIZE => 2 * 1024 * 1024,
+        'task_worker_num' => swoole_cpu_num(), //
+        'task_enable_coroutine' => false,
     ],
     ],
     'callbacks' => [
     'callbacks' => [
+        // Task callbacks
+        Event::ON_TASK => [Hyperf\Framework\Bootstrap\TaskCallback::class, 'onTask'],
+        Event::ON_FINISH => [Hyperf\Framework\Bootstrap\FinishCallback::class, 'onFinish'],
         Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
         Event::ON_WORKER_START => [Hyperf\Framework\Bootstrap\WorkerStartCallback::class, 'onWorkerStart'],
         Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
         Event::ON_PIPE_MESSAGE => [Hyperf\Framework\Bootstrap\PipeMessageCallback::class, 'onPipeMessage'],
         Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],
         Event::ON_WORKER_EXIT => [Hyperf\Framework\Bootstrap\WorkerExitCallback::class, 'onWorkerExit'],