diff --git a/app/Http/Controllers/User/AddressController.php b/app/Http/Controllers/User/AddressController.php index ba85772..ae990ee 100644 --- a/app/Http/Controllers/User/AddressController.php +++ b/app/Http/Controllers/User/AddressController.php @@ -1,121 +1,182 @@ user()->addresses; - // Provincial and municipal regions - $provinces = DB::table('provinces')->get(); - $cities = DB::table('cities')->where('province_id', $provinces->first()->id)->get(); + // 获取省份和城市数据 + $provinces = DB::table('provinces')->get(); // 获取所有省份 + $cities = DB::table('cities')->where('province_id', $provinces->first()->id)->get(); // 获取第一个省的城市 + // 返回地址列表视图 return view('user.addresses.index', compact('addresses', 'provinces', 'cities')); } - + /** + * 存储新地址 + * + * @param AddressRequest $request + * @return \Illuminate\Http\RedirectResponse + */ public function store(AddressRequest $request) { + // 获取格式化的请求数据 $addressesData = $this->getFormatRequest($request); - // /** * @var $user User */ - $user = auth()->user(); - $user->addresses()->create($addressesData); + $user = auth()->user(); // 获取当前用户 + $user->addresses()->create($addressesData); // 创建新地址 + // 返回带有成功消息的重定向 return back()->with('status', '创建成功'); } - + /** + * 显示指定地址的详细信息 + * + * @param Address $address + * @return Address + */ public function show(Address $address) { - return $address; + return $address; // 返回地址实例 } - + /** + * 显示编辑地址的表单 + * + * @param Address $address + * @return \Illuminate\View\View + */ public function edit(Address $address) { + // 检查当前用户是否有权限编辑该地址 if (auth()->id() != $address->user_id) { - - abort(403, '非法操作'); + abort(403, '非法操作'); // 如果没有权限,返回403错误 } + // 获取当前用户的地址 $addresses = auth()->user()->addresses; - // Provincial and municipal regions - $provinces = DB::table('provinces')->get(); - $cities = DB::table('cities')->where('province_id', $address->province_id)->get(); + // 获取省份和城市数据 + $provinces = DB::table('provinces')->get(); // 获取所有省份 + $cities = DB::table('cities')->where('province_id', $address->province_id)->get(); // 获取指定省的城市 + // 返回编辑地址的视图 return view('user.addresses.edit', compact('addresses', 'address', 'provinces', 'cities')); } - + /** + * 更新指定地址 + * + * @param AddressRequest $request + * @param Address $address + * @return \Illuminate\Http\RedirectResponse + */ public function update(AddressRequest $request, Address $address) { + // 检查当前用户是否有权限更新该地址 if (auth()->id() != $address->user_id) { - - abort(403, '非法操作'); + abort(403, '非法操作'); // 如果没有权限,返回403错误 } + // 获取格式化的请求数据 $addressesData = $this->getFormatRequest($request); - $address->update($addressesData); + $address->update($addressesData); // 更新地址 + // 返回带有成功消息的重定向 return back()->with('status', '修改成功'); } + /** + * 删除指定地址 + * + * @param Address $address + * @return \Illuminate\Http\JsonResponse + */ public function destroy(Address $address) { + // 检查当前用户是否有权限删除该地址 if (auth()->id() != $address->user_id) { - - return responseJson(400, '非法操作'); + return responseJson(400, '非法操作'); // 如果没有权限,返回400错误 } - $address->delete(); + $address->delete(); // 删除地址 + // 返回成功的 JSON 响应 return responseJson(200, '删除成功'); } - + /** + * 设置默认地址 + * + * @param Address $address + * @return \Illuminate\Http\JsonResponse + */ public function setDefaultAddress(Address $address) { + // 检查当前用户是否有权限设置该地址为默认 if (auth()->id() != $address->user_id) { - - return responseJson(400, '非法操作'); + return responseJson(400, '非法操作'); // 如果没有权限,返回400错误 } + // 将当前用户的所有地址设置为非默认 Address::query()->where('user_id', $address->user_id)->update(['is_default' => 0]); - $address->is_default = 1; + $address->is_default = 1; // 将指定地址设置为默认 if ($address->save()) { - - return responseJson(0, '设置成功'); + return responseJson(0, '设置成功'); // 返回成功的 JSON 响应 } - return responseJson(400, '请稍后再试!'); + return responseJson(400, '请稍后再试!'); // 返回失败的 JSON 响应 } - + /** + * 格式化请求数据 + * + * @param Request $request + * @return array + */ protected function getFormatRequest(Request $request) { - return $request->only(['name', 'phone', 'province_id', 'city_id','detail_address']); + // 只获取指定的请求参数 + return $request->only(['name', 'phone', 'province_id', 'city_id', 'detail_address']); } - + /** + * 根据省份 ID 获取城市 + * + * @param Request $request + * @return \Illuminate\Support\Collection + */ public function getCities(Request $request) { + // 根据省份 ID 查询城市 return DB::table('cities')->where('province_id', $request->input('province_id'))->get(); } } diff --git a/app/Http/Controllers/User/LikesController.php b/app/Http/Controllers/User/LikesController.php index c386fae..0ff5072 100644 --- a/app/Http/Controllers/User/LikesController.php +++ b/app/Http/Controllers/User/LikesController.php @@ -1,65 +1,89 @@ 1, 'msg' => '服务器异常,请稍后再试', ]; - + /** + * 显示用户收藏的产品列表 + * + * @return \Illuminate\View\View + */ public function index() { /** * @var $user User */ - $user = auth()->user(); + $user = auth()->user(); // 获取当前用户 + // 获取用户收藏的产品,按最新排序并分页 $likesProducts = $user->products() ->where('user_id', auth()->id()) - ->withCount('users') - ->latest() - ->paginate(10); + ->withCount('users') // 统计每个产品的收藏用户数 + ->latest() // 按照创建时间降序排列 + ->paginate(10); // 每页显示10个产品 + // 返回用户收藏产品的视图 return view('user.products.likes', compact('likesProducts')); } - + /** + * 切换产品的收藏状态 + * + * @param string $uuid 产品的唯一标识符 + * @return \Illuminate\Http\JsonResponse + */ public function toggle($uuid) { /** * @var $product Product */ $product = Product::query() - ->where('uuid', $uuid) - ->firstOrFail(); + ->where('uuid', $uuid) // 根据 UUID 查找产品 + ->firstOrFail(); // 如果未找到,抛出 404 异常 + $user = auth()->id(); // 获取当前用户的 ID - $user = auth()->id(); - + // 检查当前用户是否已经收藏该产品 if ($product->users()->where('user_id', $user)->exists()) { - + // 如果已收藏,则取消收藏 $product->users()->detach($user); + // 返回 JSON 响应,表示已取消收藏 return response()->json([ 'code' => 200, 'msg' => '欢迎下次收藏' ]); } + // 如果未收藏,则添加收藏 $product->users()->attach($user); + // 返回 JSON 响应,表示已成功收藏 return response()->json([ 'code' => 201, 'msg' => '收藏成功' ]); -} + } } diff --git a/app/Http/Controllers/User/NotificationController.php b/app/Http/Controllers/User/NotificationController.php index 6fbba21..0b0a17a 100644 --- a/app/Http/Controllers/User/NotificationController.php +++ b/app/Http/Controllers/User/NotificationController.php @@ -1,149 +1,184 @@ user(); - + $user = auth()->user(); // 获取当前用户 + // 根据请求的 tab 参数确定查询的通知类型 switch ($request->input('tab', 1)) { - case 2: - $query = $user->notifications(); + $query = $user->notifications(); // 所有通知 break; case 3: - $query = $user->readNotifications(); + $query = $user->readNotifications(); // 已读通知 break; case 1: default: - $query = $user->unreadNotifications(); + $query = $user->unreadNotifications(); // 未读通知 break; } + // 分页获取通知 $notifications = $query->paginate(); + // 为每个通知设置标题 foreach ($notifications as $notification) { - $notification->title = NotificationServe::getTitle($notification); } + // 获取未读和已读通知的数量 $unreadCount = $user->unreadNotifications()->count(); $readCount = $user->readNotifications()->count(); + // 返回通知列表视图 return view('user.notifications.index', compact('notifications', 'unreadCount', 'readCount')); } + /** + * 标记指定通知为已读 + * + * @param int $id 通知的 ID + * @return \Illuminate\Http\JsonResponse + */ public function read($id) { /** * @var $user User */ - $user = auth()->user(); + $user = auth()->user(); // 获取当前用户 /** * @var $notification DatabaseNotification */ - $notification = $user->notifications()->find($id); + $notification = $user->notifications()->find($id); // 查找指定通知 if (is_null($notification)) { - - return responseJsonAsBadRequest('无效的通知'); + return responseJsonAsBadRequest('无效的通知'); // 返回无效通知的错误 } - $notification->markAsRead(); + $notification->markAsRead(); // 标记通知为已读 - return responseJson(); + return responseJson(); // 返回成功的 JSON 响应 } + /** + * 标记所有未读通知为已读 + * + * @return \Illuminate\Http\JsonResponse + */ public function readAll() { /** * @var $user User */ - $user = auth()->user(); - + $user = auth()->user(); // 获取当前用户 + // 更新所有未读通知为已读 $count = $user->unreadNotifications()->update(['read_at' => Carbon::now()]); - + // 返回已读通知数量的 JSON 响应 return responseJson(200, "本次已读{$count}条消息"); } + /** + * 显示指定通知的详细信息 + * + * @param int $id 通知的 ID + * @return \Illuminate\View\View|\Illuminate\Http\Response + */ public function show($id) { - /** * @var $user User */ - $user = auth()->user(); + $user = auth()->user(); // 获取当前用户 /** * @var $notification DatabaseNotification */ - $notification = $user->notifications()->find($id); + $notification = $user->notifications()->find($id); // 查找指定通知 if (is_null($notification)) { - - return abort(403, '无效的通知'); + return abort(403, '无效的通知'); // 返回403错误 } - // 查看是否有上一条下一条 + // 查找上一条和下一条通知 $last = $user->notifications()->where('created_at', '<', $notification->created_at)->first(); $next = $user->notifications()->where('created_at', '>', $notification->created_at)->first(); - // 标记为已读 + + // 标记通知为已读 $notification->markAsRead(); + // 获取通知的视图 $view = NotificationServe::getView($notification); if (! view()->exists($view)) { - - abort(404, '未知的的消息'); + abort(404, '未知的的消息'); // 如果视图不存在,返回404错误 } + // 设置通知的标题 $notification->title = NotificationServe::getTitle($notification); - $data = $notification->data; + $data = $notification->data; // 获取通知的数据 + // 返回通知详细信息的视图 return view('user.notifications.show', compact('last', 'next', 'notification', 'view', 'data')); } - + /** + * 获取未读通知的数量 + * + * @return \Illuminate\Http\JsonResponse + */ public function getUnreadCount() { /** * @var $user User */ - $user = auth()->user(); + $user = auth()->user(); // 获取当前用户 /** * @var $notification DatabaseNotification */ - $count = $user->unreadNotifications()->count(); - + $count = $user->unreadNotifications()->count(); // 获取未读通知的数量 + // 初始化通知的标题、内容和 ID $title = ''; $content = ''; $id = null; if ($count > 0) { - - $notification = $user->unreadNotifications()->first(); + $notification = $user->unreadNotifications()->first(); // 获取第一条未读通知 // 前端弹窗内容和标题相反显示,所以变量名会有点怪 - $id = $notification->id; - $title = NotificationServe::getContent($notification); - $content = NotificationServe::getTitle($notification); + $id = $notification->id; // 获取通知 ID + $title = NotificationServe::getContent($notification); // 获取通知内容 + $content = NotificationServe::getTitle($notification); // 获取通知标题 } + // 返回未读通知数量的 JSON 响应 return responseJson(200, 'success', compact('count', 'title', 'content', 'id')); } } + diff --git a/app/Http/Controllers/User/OrderController.php b/app/Http/Controllers/User/OrderController.php index 0bbee4d..6cba66d 100644 --- a/app/Http/Controllers/User/OrderController.php +++ b/app/Http/Controllers/User/OrderController.php @@ -1,28 +1,37 @@ user(); - $query = $user->orders(); + $user = auth()->user(); // 获取当前用户 + $query = $user->orders(); // 获取用户的订单查询构建器 + // 根据请求的 tab 参数筛选订单状态 switch (request('tab', 0)) { - case 0: - break; + break; // 默认显示所有订单 case 1: // 待付款 $query->where('status', OrderStatusEnum::UN_PAY); break; case 2: // 未发货 - $query->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::PENDING); + $query->where('status', OrderStatusEnum::PAID) + ->where('ship_status', OrderShipStatusEnum::PENDING); break; case 3: // 待收货 - $query->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::DELIVERED); + $query->where('status', OrderStatusEnum::PAID) + ->where('ship_status', OrderShipStatusEnum::DELIVERED); break; case 4: // 待评价 - $query->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::RECEIVED); + $query->where('status', OrderStatusEnum::PAID) + ->where('ship_status', OrderShipStatusEnum::RECEIVED); break; } - $orders = $query->latest() - ->with('details', 'details.product') + // 获取订单列表并进行处理 + $orders = $query->latest() // 按照创建时间降序排列 + ->with('details', 'details.product') // 预加载订单详情和产品 ->get() ->map( function (Order $order) use ($scoreRatio) { + // 计算可以获得的积分 + $order->score = ceil($order->amount * $scoreRatio); - // 可以或得到的积分 - $order->score = ceil($order->amount*$scoreRatio); - - // 完成按钮必须是已经支付和确认收货 + // 设置订单状态文本 $order->status_text = OrderStatusTransform::trans($order->status); - // 如果订单是付款了则显示发货状态 + // 如果订单已付款,则显示发货状态 if ($order->status == OrderStatusEnum::PAID) { - - // 如果发货了,则显示发货信息 + // 如果已发货,则显示发货信息 $order->status_text = OrderShipStatusTransform::trans($order->ship_status); } + // 创建订单状态按钮服务实例 $buttonServe = new OrderStatusButtonServe($order); switch ($order->status) { - // 未支付的 + // 未支付的订单 case OrderStatusEnum::UN_PAY: - - $buttonServe->payButton()->cancelOrderButton(); + $buttonServe->payButton()->cancelOrderButton(); // 添加支付和取消订单按钮 break; case OrderStatusEnum::PAID: - // 已经确认收获了 + // 已确认收货 if ($order->ship_status == OrderShipStatusEnum::RECEIVED) { - - $buttonServe->completeButton(); + $buttonServe->completeButton(); // 添加完成按钮 } elseif ($order->ship_status == OrderShipStatusEnum::DELIVERED) { - - $buttonServe->shipButton(); + $buttonServe->shipButton(); // 添加发货按钮 } else { - - $buttonServe->refundButton(); + $buttonServe->refundButton(); // 添加退款按钮 } break; - // 手动取消的订单 - // 已经完成的订单 - // 超时取消的订单 + // 手动取消的订单、已完成的订单、超时取消的订单 case OrderStatusEnum::UN_PAY_CANCEL: case OrderStatusEnum::COMPLETED: case OrderStatusEnum::TIMEOUT_CANCEL: - $buttonServe->replyBuyButton()->deleteButton(); + $buttonServe->replyBuyButton()->deleteButton(); // 添加重新购买和删除按钮 break; } + // 获取按钮集合 $order->buttons = $buttonServe->getButtons(); - return $order; + return $order; // 返回处理后的订单 } ); - - // 查询订单总量 + // 查询不同状态的订单数量 $unPayCount = $user->orders()->where('status', OrderStatusEnum::UN_PAY)->count(); $shipPendingCount = $user->orders()->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::PENDING)->count(); $shipDeliveredCount = $user->orders()->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::DELIVERED)->count(); $shipReceivedCount = $user->orders()->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::RECEIVED)->count(); - $ordersCount = $user->orders()->count(); + $ordersCount = $user->orders()->count(); // 获取订单总数 + // 返回订单列表视图 return view('user.orders.index', compact('orders', 'unPayCount', 'shipPendingCount', 'shipDeliveredCount', 'shipReceivedCount', 'ordersCount')); } - - - + /** + * 显示指定订单的详细信息 + * + * @param Order $order + * @return \Illuminate\View\View|\Illuminate\Http\Response + */ public function show(Order $order) { + // 检查当前用户是否有权限查看该订单 if ($order->isNotUser(auth()->id())) { - abort(403, '你没有权限'); + abort(403, '你没有权限'); // 返回403错误 } + // 设置发货和确认收货状态 $order->ship_send = $order->ship_status == OrderShipStatusEnum::DELIVERED; $order->confirm_ship = $order->ship_status == OrderShipStatusEnum::RECEIVED; + // 如果已确认收货,标记为已发货 if ($order->confirm_ship) { - $order->ship_send = true; } - $order->completed = $order->status == OrderShipStatusEnum::RECEIVED; + // 设置订单是否已完成 + $order->completed = $order->status == OrderStatusEnum::RECEIVED; + // 返回订单详情视图 return view('user.orders.show', compact('order')); } - + /** + * 完成订单并添加评论 + * + * @param Order $order + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ public function completeOrder(Order $order, Request $request) { + // 获取评分和评论内容 $star = intval($request->input('star')); $content = $request->input('content'); - if ($star < 0 || $star > 5) { - return responseJsonAsBadRequest('无效的评分'); + // 验证评分范围 + if ($star < 0 || $star > 5) { + return responseJsonAsBadRequest('无效的评分'); // 返回错误响应 } + // 验证评论内容 if (empty($content)) { - - return responseJsonAsBadRequest('请至少些一些内容吧'); + return responseJsonAsBadRequest('请至少写一些内容吧'); // 返回错误响应 } - // 判断是当前用户的订单才可以删除 + // 检查当前用户是否有权限完成该订单 $user = auth()->user(); if ($order->isNotUser($user->id)) { - - return responseJsonAsBadRequest('你没有权限'); + return responseJsonAsBadRequest('你没有权限'); // 返回错误响应 } - // 只有付完款的订单,而且必须是未完成的, 确认收货 - if ( - // 必须是已经付款,且已经确认收货的 - ! ($order->status == OrderStatusEnum::PAID && $order->ship_status == OrderShipStatusEnum::RECEIVED) - ) { - return responseJsonAsBadRequest('订单当前状态不能完成'); + // 只有已付款且确认收货的订单才能完成 + if (!($order->status == OrderStatusEnum::PAID && $order->ship_status == OrderShipStatusEnum::RECEIVED)) { + return responseJsonAsBadRequest('订单当前状态不能完成'); // 返回错误响应 } - + // 获取订单详情 $orderDetails = $order->details()->get(); + // 构建评论数据 $comments = $orderDetails->map(function (OrderDetail $orderDetail) use ($user, $content, $star) { - return [ 'order_id' => $orderDetail->order_id, 'order_detail_id' => $orderDetail->id, @@ -188,89 +206,95 @@ class OrderController extends Controller ]; }); - DB::beginTransaction(); + DB::beginTransaction(); // 开始数据库事务 try { - - // 订单完成 + // 更新订单状态为完成 $order->status = OrderStatusEnum::COMPLETED; $order->save(); - // 评论内容 + // 保存评论内容 Comment::query()->insert($comments->all()); + // 更新订单详情为已评论 OrderDetail::query()->where('order_id', $order->id)->update(['is_commented' => true]); // 完成订单增加积分 (new ScoreLogServe)->completeOrderAddScore($order); - DB::commit(); + DB::commit(); // 提交事务 } catch (\Exception $e) { - - return responseJsonAsServerError('服务器异常,请稍后再试'); + DB::rollBack(); // 回滚事务 + return responseJsonAsServerError('服务器异常,请稍后再试'); // 返回错误响应 } - - return responseJson(200, '完成订单已增加积分'); + return responseJson(200, '完成订单已增加积分'); // 返回成功响应 } - + /** + * 确认收货 + * + * @param Order $order + * @return \Illuminate\Http\RedirectResponse + */ public function confirmShip(Order $order) { - // 判断是当前用户的订单才可以删除 + // 检查当前用户是否有权限确认收货 if ($order->isNotUser(auth()->id())) { - abort(403, '你没有权限'); + abort(403, '你没有权限'); // 返回403错误 } + // 验证订单状态 if ($order->status != OrderStatusEnum::PAID) { - - return back()->withErrors('订单未付款'); + return back()->withErrors('订单未付款'); // 返回错误 } if ($order->ship_status != OrderShipStatusEnum::DELIVERED) { - - return back()->withErrors('订单未发货'); + return back()->withErrors('订单未发货'); // 返回错误 } + // 更新订单发货状态为已收货 $order->ship_status = OrderShipStatusEnum::RECEIVED; $order->save(); - return back()->with('status', '收货成功'); + return back()->with('status', '收货成功'); // 返回成功消息 } - + /** + * 取消订单 + * + * @param Order $order + * @return \Illuminate\Http\RedirectResponse + */ public function cancelOrder(Order $order) { - // 判断是当前用户的订单才可以删除 + // 检查当前用户是否有权限取消订单 if ($order->isNotUser(auth()->id())) { - abort(403, '你没有权限'); + abort(403, '你没有权限'); // 返回403错误 } + // 验证订单状态 if ($order->status != OrderStatusEnum::UN_PAY) { - - return back()->withErrors('未付款的订单才能取消'); + return back()->withErrors('未付款的订单才能取消'); // 返回错误 } - - - $pay = Pay::alipay(config('pay.ali')); + $pay = Pay::alipay(config('pay.ali')); // 获取支付宝支付实例 try { + // 取消订单 $orderData = [ 'out_trade_no' => $order->no, ]; - $result = $pay->cancel($orderData); + $result = $pay->cancel($orderData); // 调用支付取消接口 + // 更新订单状态为未支付取消 $order->status = OrderStatusEnum::UN_PAY_CANCEL; $order->save(); - } catch (\Exception $e) { - - return back()->withErrors('服务器异常,请稍后再试'); + return back()->withErrors('服务器异常,请稍后再试'); // 返回错误 } - - return back()->with('status', '取消成功'); + return back()->with('status', '取消成功'); // 返回成功消息 } /** @@ -280,47 +304,50 @@ class OrderController extends Controller */ protected function getScoreRatio() { + // 查询积分规则 $scoreRule = ScoreRule::query()->where('index_code', ScoreRuleIndexEnum::COMPLETE_ORDER)->firstOrFail(); - - return $scoreRule->score ?? 1; + return $scoreRule->score ?? 1; // 返回积分比例,默认为1 } - /** - * 地址是否存在 + * 检查地址是否存在 * * @param $address * @return bool */ protected function hasAddress($address) { + // 查询用户是否拥有该地址 return Address::query() ->where('user_id', auth()->id()) ->where('id', $address) ->exists(); } - + /** + * 删除订单 + * + * @param int $id 订单 ID + * @return \Illuminate\Http\RedirectResponse + */ public function destroy($id) { /** * @var $order Order */ - $order = Order::query()->findOrFail($id); - // 判断是当前用户的订单才可以删除 + $order = Order::query()->findOrFail($id); // 查找订单 + // 检查当前用户是否有权限删除该订单 if ($order->isNotUser(auth()->id())) { - abort(403, '你没有权限'); + abort(403, '你没有权限'); // 返回403错误 } - // 支付的订单不能删除 - if (! in_array($order->status, [OrderStatusEnum::UN_PAY_CANCEL, OrderStatusEnum::TIMEOUT_CANCEL, OrderStatusEnum::COMPLETED])) { - - abort(403, '订单不能删除'); + // 检查订单状态,支付的订单不能删除 + if (!in_array($order->status, [OrderStatusEnum::UN_PAY_CANCEL, OrderStatusEnum::TIMEOUT_CANCEL, OrderStatusEnum::COMPLETED])) { + abort(403, '订单不能删除'); // 返回403错误 } - $order->delete(); + $order->delete(); // 删除订单 - return back()->with('status', '删除成功'); + return back()->with('status', '删除成功'); // 返回成功消息 } - } diff --git a/app/Http/Controllers/User/SeckillController.php b/app/Http/Controllers/User/SeckillController.php index c169083..ae59f75 100644 --- a/app/Http/Controllers/User/SeckillController.php +++ b/app/Http/Controllers/User/SeckillController.php @@ -2,183 +2,179 @@ namespace App\Http\Controllers\User; -use App\Enums\OrderTypeEnum; -use App\Enums\SettingKeyEnum; -use App\Jobs\CancelUnPayOrder; -use App\Models\Address; -use App\Models\Order; -use App\Models\OrderDetail; -use App\Models\Product; -use App\Models\Seckill; -use App\Models\User; -use App\Utils\OrderUtil; -use Carbon\Carbon; -use Illuminate\Auth\SessionGuard; -use Illuminate\Http\Request; -use Illuminate\Support\Facades\DB; -use Illuminate\Support\Facades\Redis; -use Jenssegers\Agent\Agent; - +use App\Enums\OrderTypeEnum; // 引入订单类型枚举 +use App\Enums\SettingKeyEnum; // 引入设置键枚举 +use App\Jobs\CancelUnPayOrder; // 引入取消未支付订单的任务 +use App\Models\Address; // 引入地址模型 +use App\Models\Order; // 引入订单模型 +use App\Models\OrderDetail; // 引入订单详情模型 +use App\Models\Product; // 引入产品模型 +use App\Models\Seckill; // 引入秒杀模型 +use App\Models\User; // 引入用户模型 +use App\Utils\OrderUtil; // 引入订单工具类 +use Carbon\Carbon; // 引入 Carbon 日期处理库 +use Illuminate\Auth\SessionGuard; // 引入会话守卫 +use Illuminate\Http\Request; // 引入请求类 +use Illuminate\Support\Facades\DB; // 引入数据库门面 +use Illuminate\Support\Facades\Redis; // 引入 Redis 门面 +use Jenssegers\Agent\Agent; // 引入用户代理类 + +/** + * 秒杀控制器 + * + * 该控制器处理与秒杀活动相关的操作,包括展示秒杀商品、参与秒杀、获取参与秒杀的用户等。 + */ class SeckillController extends PaymentController { - protected $redisSeckill; + protected $redisSeckill; // 存储秒杀活动的 Redis 数据 + /** + * 显示秒杀活动的详细信息 + * + * @param int $id 秒杀活动的 ID + * @return \Illuminate\View\View + */ public function show($id) { - $seckill = new Seckill(compact('id')); - $redisSeckill = $this->getSeckill($seckill); + $seckill = new Seckill(compact('id')); // 创建秒杀活动实例 + $redisSeckill = $this->getSeckill($seckill); // 从 Redis 获取秒杀活动数据 - $product = $redisSeckill->product; + $product = $redisSeckill->product; // 获取秒杀商品信息 /** * @var $user User - * 如果登录返回所有地址列表,如果没有,则返回一个空集合 + * 如果用户已登录,则返回该用户的所有地址列表;否则返回一个空集合 */ - $addresses = collect(); + $addresses = collect(); // 初始化地址集合 if ($user = auth()->user()) { - - $addresses = $user->addresses()->get(); + $addresses = $user->addresses()->get(); // 获取用户地址 } - return view('seckills.show', compact('redisSeckill', 'product', 'addresses')); + return view('seckills.show', compact('redisSeckill', 'product', 'addresses')); // 返回视图 } /** - * 抢购秒杀 + * 抢购秒杀商品 * - * @param Request $request - * @param $id + * @param Request $request 请求对象 + * @param int $id 秒杀活动的 ID * @return \Illuminate\Http\JsonResponse * @throws \Exception */ public function storeSeckill(Request $request, $id) { /** - * 直接从 session 中读取 id,不经过数据库 + * 直接从 session 中读取用户 ID,不经过数据库 * * @var $user User * @var $auth SessionGuard */ - $seckill = new Seckill(compact('id')); - $auth = auth('web'); - $userId = session()->get($auth->getName()); + $seckill = new Seckill(compact('id')); // 创建秒杀活动实例 + $auth = auth('web'); // 获取当前会话 + $userId = session()->get($auth->getName()); // 获取用户 ID try { - - if (! $request->has('address_id')) { - - throw new \Exception('必须选择一个地址'); + // 检查请求中是否包含地址 ID + if (!$request->has('address_id')) { + throw new \Exception('必须选择一个地址'); // 抛出异常 } - // 验证是否有这个秒杀 - // 验证秒杀活动是否已经结束 + // 验证秒杀活动是否存在及是否已开始 $redisSeckill = $this->redisSeckill = $this->getSeckill($seckill); - - if (! $redisSeckill->is_start) { - throw new \Exception('秒杀未开始'); + if (!$redisSeckill->is_start) { + throw new \Exception('秒杀未开始'); // 抛出异常 } - } catch (\Exception $e) { - - return responseJson(402, $e->getMessage()); + return responseJson(402, $e->getMessage()); // 返回错误响应 } -// // 返回 0,代表之前已经设置过了,代表已经抢过 -// if (0 == Redis::hset($seckill->getUsersKey($userId), 'id', $userId)) { -// -// return responseJson(403, '你已经抢购过了'); -// } - - // 开始抢购逻辑,如果从队列中读取不到了,代表已经抢购完成 + // 开始抢购逻辑,检查队列中是否还有可抢购的商品 if (is_null(Redis::lpop($seckill->getRedisQueueKey()))) { - - return responseJson(403, '已经抢购完了'); + return responseJson(403, '已经抢购完了'); // 返回错误响应 } - - DB::beginTransaction(); + DB::beginTransaction(); // 开始数据库事务 try { - - $product = $redisSeckill->product; + $product = $redisSeckill->product; // 获取秒杀商品 if (is_null($product)) { - return responseJson(400, '商品已下架'); + return responseJson(400, '商品已下架'); // 返回错误响应 } - // 已经通过抢购请求,可以查询数据库 - // 在这里验证一下地址是不是本人的 + // 验证用户的收货地址是否有效 $user = auth()->user(); $address = Address::query()->where('user_id', $user->id)->find($request->input('address_id')); - if (is_null($address)) { - return responseJson(400, '无效的收货地址'); + return responseJson(400, '无效的收货地址'); // 返回错误响应 } - // 创建一个秒杀主表订单和明细表订单,默认数量一个 + // 创建秒杀主表订单和明细表订单,默认数量为 1 $masterOrder = ($orderUtil = new OrderUtil([['product' => $product]]))->make($user->id, $address); - $masterOrder->type = OrderTypeEnum::SEC_KILL; - $masterOrder->amount = $redisSeckill->price; - $masterOrder->save(); + $masterOrder->type = OrderTypeEnum::SEC_KILL; // 设置订单类型为秒杀 + $masterOrder->amount = $redisSeckill->price; // 设置订单金额 + $masterOrder->save(); // 保存订单 // 创建订单明细 $details = $orderUtil->getDetails(); - data_set($details, '*.order_id', $masterOrder->id); - OrderDetail::query()->insert($details); - + data_set($details, '*.order_id', $masterOrder->id); // 设置订单 ID + OrderDetail::query()->insert($details); // 保存订单明细 - // 当订单超过三十分钟未付款,自动取消订单 + // 设置未支付订单的自动取消时间 $setting = new SettingKeyEnum(SettingKeyEnum::UN_PAY_CANCEL_TIME); - $delay = Carbon::now()->addMinute(setting($setting, 30)); - CancelUnPayOrder::dispatch($masterOrder)->delay($delay); + $delay = Carbon::now()->addMinute(setting($setting, 30)); // 设置延迟时间 + CancelUnPayOrder::dispatch($masterOrder)->delay($delay); // 调度取消任务 // 生成支付信息 $form = $this->buildPayForm($masterOrder, (new Agent)->isMobile())->getContent(); } catch (\Exception $e) { + DB::rollBack(); // 回滚事务 - DB::rollBack(); - - // 回滚一个秒杀数量 + // 回滚秒杀数量 Redis::lpush($seckill->getRedisQueueKey(), 9); - // 把当前用户踢出,给他继续抢购 + // 从 Redis 中删除当前用户的抢购记录,允许用户重新抢购 Redis::del($seckill->getUsersKey($userId)); - return responseJson(403, $e->getMessage()); + return responseJson(403, $e->getMessage()); // 返回错误响应 } - DB::commit(); + DB::commit(); // 提交事务 + + // 更新秒杀活动的剩余数量 + $redisSeckill->sale_count += 1; // 增加销售数量 + $redisSeckill->number -= 1; // 减少库存数量 + Redis::set($seckill->getRedisModelKey(), json_encode($redisSeckill)); // 更新 Redis 中的秒杀活动数据 - // 数量减 - - $redisSeckill->sale_count += 1; - $redisSeckill->number -= 1; - Redis::set($seckill->getRedisModelKey(), json_encode($redisSeckill)); // 存储抢购成功的用户名 $user = auth()->user(); Redis::hset($seckill->getUsersKey($userId), 'name', $user->hidden_name); - - - return responseJson(200, '抢购成功', compact('form')); + return responseJson(200, '抢购成功', compact('form')); // 返回成功响应 } + /** + * 获取参与秒杀活动的用户 + * + * @param int $id 秒杀活动的 ID + * @return \Illuminate\Http\JsonResponse + */ public function getSeckillUsers($id) { - $seckill = new Seckill(compact('id')); - $keys = Redis::keys($seckill->getUsersKey('*')); + $seckill = new Seckill(compact('id')); // 创建秒杀活动实例 + $keys = Redis::keys($seckill->getUsersKey('*')); // 获取所有参与用户的键 - $users = collect(); + $users = collect(); // 初始化用户集合 foreach ($keys as $key) { - - $users->push(Redis::hget($key, 'name')); + $users->push(Redis::hget($key, 'name')); // 获取用户名称并添加到集合 } - return responseJson(200, 'success', $users); + return responseJson(200, 'success', $users); // 返回成功响应 } /** - * 从 redis 中获取秒杀的数据 + * 从 Redis 中获取秒杀活动的数据 * - * @param Seckill $seckill + * @param Seckill $seckill 秒杀活动实例 * @return mixed */ protected function getSeckill(Seckill $seckill) @@ -186,50 +182,48 @@ class SeckillController extends PaymentController /** * @var $product Product */ - $json = Redis::get($seckill->getRedisModelKey()); - $redisSeckill = json_decode($json); + $json = Redis::get($seckill->getRedisModelKey()); // 从 Redis 获取秒杀活动数据 + $redisSeckill = json_decode($json); // 解析 JSON 数据 if (is_null($redisSeckill)) { - - abort(403, "没有这个秒杀活动"); + abort(403, "没有这个秒杀活动"); // 返回 403 错误 } - // 得到这些时间 + // 获取当前时间和秒杀结束时间 $now = Carbon::now(); $endAt = Carbon::make($redisSeckill->end_at); if ($now->gt($endAt)) { - - abort(403, "秒杀已经结束"); + abort(403, "秒杀已经结束"); // 返回 403 错误 } - // 秒杀是否已经开始 + // 检查秒杀是否已经开始 $startAt = Carbon::make($redisSeckill->start_at); - $redisSeckill->is_start = $now->gt($startAt); - // 开始倒计时 + $redisSeckill->is_start = $now->gt($startAt); // 设置活动是否开始 + // 计算倒计时 $redisSeckill->diff_time = $startAt->getTimestamp() - time(); - return $redisSeckill; + return $redisSeckill; // 返回秒杀活动数据 } /** * 重写父类的构建订单明细 * - * @param Product $product - * @param $number - * @return array + * @param Product $product 产品实例 + * @param int $number 数量 + * @return array 订单明细数组 */ protected function buildOrderDetail(Product $product, $number) { - $attribute = [ - 'product_id' => $product->id, - 'number' => $number + $attribute = [ + 'product_id' => $product->id, // 设置产品 ID + 'number' => $number // 设置数量 ]; - // 价格为秒杀的价格, 直接从 redis 中读取 - $attribute['price'] = ceilTwoPrice($this->redisSeckill->price); - $attribute['total'] = ceilTwoPrice($attribute['price'] * $attribute['number']); + // 价格为秒杀的价格,直接从 Redis 中读取 + $attribute['price'] = ceilTwoPrice($this->redisSeckill->price); // 设置价格 + $attribute['total'] = ceilTwoPrice($attribute['price'] * $attribute['number']); // 计算总价 - return $attribute; + return $attribute; // 返回订单明细数组 } } diff --git a/app/Http/Controllers/User/StoreOrderController.php b/app/Http/Controllers/User/StoreOrderController.php index 66c2da4..6d7a66a 100644 --- a/app/Http/Controllers/User/StoreOrderController.php +++ b/app/Http/Controllers/User/StoreOrderController.php @@ -2,217 +2,219 @@ namespace App\Http\Controllers\User; -use App\Enums\OrderStatusEnum; -use App\Enums\OrderTypeEnum; -use App\Enums\SettingKeyEnum; -use App\Exceptions\OrderException; -use App\Http\Controllers\Controller; -use App\Jobs\CancelUnPayOrder; -use App\Models\Address; -use App\Models\Car; -use App\Models\Order; -use App\Models\OrderDetail; -use App\Models\Product; -use App\Models\User; -use App\Utils\OrderUtil; -use Carbon\Carbon; -use Illuminate\Http\Request; -use Illuminate\Support\Collection; -use Illuminate\Support\Facades\DB; -use Symfony\Component\HttpFoundation\Response; +use App\Enums\OrderStatusEnum; // 引入订单状态枚举 +use App\Enums\OrderTypeEnum; // 引入订单类型枚举 +use App\Enums\SettingKeyEnum; // 引入设置键枚举 +use App\Exceptions\OrderException; // 引入订单异常 +use App\Http\Controllers\Controller; // 引入基础控制器 +use App\Jobs\CancelUnPayOrder; // 引入取消未支付订单的任务 +use App\Models\Address; // 引入地址模型 +use App\Models\Car; // 引入购物车模型 +use App\Models\Order; // 引入订单模型 +use App\Models\OrderDetail; // 引入订单详情模型 +use App\Models\Product; // 引入产品模型 +use App\Models\User; // 引入用户模型 +use App\Utils\OrderUtil; // 引入订单工具类 +use Carbon\Carbon; // 引入 Carbon 日期处理库 +use Illuminate\Http\Request; // 引入请求类 +use Illuminate\Support\Collection; // 引入集合类 +use Illuminate\Support\Facades\DB; // 引入数据库门面 +use Symfony\Component\HttpFoundation\Response; // 引入响应类 class StoreOrderController extends Controller { + /** + * 创建订单页面 + * + * @param Request $request 请求对象 + * @return \Illuminate\View\View + */ public function create(Request $request) { /** * @var $user User + * 获取当前登录用户 */ $user = auth()->user(); - + // 从请求中获取购物车信息和商品 ID $cars = $request->input('cars', []); $ids = $request->input('ids'); $numbers = $request->input('numbers'); + // 验证商品 ID 和数量的有效性 if (count($ids) === 0 || count($ids) !== count($numbers)) { - - return back()->with('error', '无效的商品'); + return back()->with('error', '无效的商品'); // 返回错误信息 } + // 查询数据库中存在的商品 $products = Product::query()->whereIn('uuid', $ids)->get(); if ($products->count() === 0 || $products->count() !== count($numbers)) { - - return back()->with('error', '无效的商品'); + return back()->with('error', '无效的商品'); // 返回错误信息 } - $totalAmount = 0; - $products->transform(function (Product $product, $i) use ($numbers, &$totalAmount) { - - $product->number = $numbers[$i]; - $product->total_amount = round($product->price * $product->number); - $totalAmount += $product->total_amount; + $totalAmount = 0; // 初始化总金额 - return $product; + // 计算每个商品的总金额并更新商品数量 + $products->transform(function (Product $product, $i) use ($numbers, &$totalAmount) { + $product->number = $numbers[$i]; // 设置商品数量 + $product->total_amount = round($product->price * $product->number); // 计算商品总金额 + $totalAmount += $product->total_amount; // 累加总金额 + return $product; // 返回更新后的商品 }); // 增加邮费 $postAmount = \setting(new SettingKeyEnum(SettingKeyEnum::POST_AMOUNT)); - $totalAmount += $postAmount; + $totalAmount += $postAmount; // 将邮费加到总金额 - /** - * @var $user User - */ - $user = auth()->user(); + // 获取用户的收货地址 $addresses = $user->addresses()->latest()->get(); - // 可用的优惠券 + // 获取可用的优惠券 $today = Carbon::today()->toDateString(); $coupons = $user->coupons() - ->where('start_date', '<=', $today) - ->where('end_date', '>=', $today) - ->whereNull('used_at') - ->where('full_amount', '<=', $totalAmount) + ->where('start_date', '<=', $today) // 优惠券开始日期 + ->where('end_date', '>=', $today) // 优惠券结束日期 + ->whereNull('used_at') // 未使用的优惠券 + ->where('full_amount', '<=', $totalAmount) // 满足使用条件的优惠券 ->latest() ->get(); + // 返回创建订单页面的视图 return view('orders.create', compact('products', 'cars', 'addresses', 'totalAmount', 'coupons', 'postAmount')); } + /** + * 存储订单 + * + * @param Request $request 请求对象 + * @return \Illuminate\Http\JsonResponse + */ public function store(Request $request) { + // 验证请求数据的有效性 if (($response = $this->validateRequest($request)) instanceof Response) { - - return $response; + return $response; // 返回响应 } + list($ids, $numbers, $productMap, $address, $couponModel) = $response; // 解构响应数据 - list($ids, $numbers, $productMap, $address, $couponModel) = $response; - - // 构建出订单所需的详情 + // 构建订单详情数据 $detailsData = Collection::make($ids)->map(function ($id, $index) use ($numbers, $productMap) { - return [ - 'number' => $numbers[$index], - 'product' => $productMap[$id] + 'number' => $numbers[$index], // 商品数量 + 'product' => $productMap[$id] // 商品信息 ]; }); - - DB::beginTransaction(); + DB::beginTransaction(); // 开始数据库事务 try { - - + // 创建主订单 $masterOrder = ($orderUtil = new OrderUtil($detailsData))->make(auth()->id(), $address); - if (! is_null($couponModel) && $masterOrder->amount < $couponModel->full_amount) { - - throw new \Exception('优惠券门槛金额为 ' . $couponModel->full_amount); + // 验证优惠券的使用条件 + if (!is_null($couponModel) && $masterOrder->amount < $couponModel->full_amount) { + throw new \Exception('优惠券门槛金额为 ' . $couponModel->full_amount); // 抛出异常 } - // 订单价格等于原价 - 优惠价格 - if (! is_null($couponModel)) { - + // 计算订单金额 + if (!is_null($couponModel)) { $masterOrder->amount = $masterOrder->amount > $couponModel->amount ? - ($masterOrder->amount - $couponModel->amount) : 0.01; + ($masterOrder->amount - $couponModel->amount) : 0.01; // 计算实际支付金额 - $couponModel->used_at = Carbon::now()->toDateTimeString(); - $couponModel->save(); + $couponModel->used_at = Carbon::now()->toDateTimeString(); // 标记优惠券为已使用 + $couponModel->save(); // 保存优惠券状态 - $masterOrder->coupon_id = $couponModel->id; - $masterOrder->coupon_amount = $couponModel->amount; + $masterOrder->coupon_id = $couponModel->id; // 关联优惠券 ID + $masterOrder->coupon_amount = $couponModel->amount; // 记录优惠券金额 } - $masterOrder->save(); + $masterOrder->save(); // 保存主订单 // 创建订单明细 - $details = $orderUtil->getDetails(); - data_set($details, '*.order_id', $masterOrder->id); - OrderDetail::query()->insert($details); + $details = $orderUtil->getDetails(); // 获取订单明细数据 + data_set($details, '*.order_id', $masterOrder->id); // 设置订单 ID + OrderDetail::query()->insert($details); // 保存订单明细 - // 如果存在购物车,把购物车删除 + // 如果存在购物车,删除购物车中的商品 $cars = $request->input('cars'); - if (is_array($cars) && ! empty($cars)) { - - Car::query()->where('user_id', auth()->id())->where('id', $cars)->delete(); + if (is_array($cars) && !empty($cars)) { + Car::query()->where('user_id', auth()->id())->where('id', $cars)->delete(); // 删除购物车商品 } - // 当订单超过三十分钟未付款,自动取消订单 + // 设置未支付订单的自动取消时间 $settingKey = new SettingKeyEnum(SettingKeyEnum::UN_PAY_CANCEL_TIME); - $delay = Carbon::now()->addMinute(setting($settingKey, 30)); - CancelUnPayOrder::dispatch($masterOrder)->delay($delay); + $delay = Carbon::now()->addMinute(setting($settingKey, 30)); // 设置延迟时间 + CancelUnPayOrder::dispatch($masterOrder)->delay($delay); // 调度取消任务 - DB::commit(); + DB::commit(); // 提交事务 } catch (\Exception $e) { - - DB::rollBack(); - return responseJsonAsBadRequest($e->getMessage()); + DB::rollBack(); // 回滚事务 + return responseJsonAsBadRequest($e->getMessage()); // 返回错误响应 } - return responseJson(200, '创建订单成功', ['order_id' => $masterOrder->id]); + return responseJson(200, '创建订单成功', ['order_id' => $masterOrder->id]); // 返回成功响应 } - - + /** + * 验证请求数据的有效性 + * + * @param Request $request 请求对象 + * @return array|Response 验证结果 + */ private function validateRequest(Request $request) { /** * @var $user User * @var $address Address */ - $user = auth()->user(); + $user = auth()->user(); // 获取当前用户 - $ids = $request->input('ids'); - $numbers = $request->input('numbers'); + $ids = $request->input('ids'); // 获取商品 ID + $numbers = $request->input('numbers'); // 获取商品数量 + // 验证商品 ID 和数量的有效性 if (count($ids) === 0 || count($ids) !== count($numbers)) { - - return responseJsonAsBadRequest('无效的商品'); + return responseJsonAsBadRequest('无效的商品'); // 返回错误响应 } + // 查询数据库中存在的商品 $productMap = Product::query()->whereIn('uuid', $ids)->get()->mapWithKeys(function (Product $product) { - - return [$product->uuid => $product]; + return [$product->uuid => $product]; // 将商品映射为 ID 和商品对象 }); - if (count($productMap) === 0 || count($productMap) !== count($numbers)) { - return responseJsonAsBadRequest('无效的商品.'); + if (count($productMap) === 0 || count($productMap) !== count($numbers)) { + return responseJsonAsBadRequest('无效的商品.'); // 返回错误响应 } - + // 验证收货地址的有效性 $address = $user->addresses()->find($request->input('address_id')); if (is_null($address)) { - - return responseJsonAsBadRequest('请选择收货地址'); + return responseJsonAsBadRequest('请选择收货地址'); // 返回错误响应 } - - // 查看是否有优惠券的价格 + // 验证优惠券的有效性 $couponModel = null; if ($couponId = $request->input('coupon_id')) { - - $couponModel = $user->coupons()->find($couponId); + $couponModel = $user->coupons()->find($couponId); // 查询优惠券 if (is_null($couponModel)) { - - return responseJsonAsBadRequest('无效的优惠券'); + return responseJsonAsBadRequest('无效的优惠券'); // 返回错误响应 } $today = Carbon::today(); - $startDate = Carbon::make($couponModel->start_date) ?? Carbon::tomorrow(); - $endDate = Carbon::make($couponModel->end_date) ?? Carbon::yesterday(); + $startDate = Carbon::make($couponModel->start_date) ?? Carbon::tomorrow(); // 优惠券开始日期 + $endDate = Carbon::make($couponModel->end_date) ?? Carbon::yesterday(); // 优惠券结束日期 if ($today->lt($startDate) || $today->gt($endDate)) { - - return responseJsonAsBadRequest('优惠券已过使用期'); + return responseJsonAsBadRequest('优惠券已过使用期'); // 返回错误响应 } - if (! is_null($couponModel->used_at)) { - - return responseJsonAsBadRequest('优惠券已使用过'); + if (!is_null($couponModel->used_at)) { + return responseJsonAsBadRequest('优惠券已使用过'); // 返回错误响应 } } - return [$ids, $numbers, $productMap, $address, $couponModel]; + return [$ids, $numbers, $productMap, $address, $couponModel]; // 返回验证结果 } }