p3icsxn5t 8 months ago
commit 27c81b89a9

@ -1,121 +1,182 @@
<?php <?php
namespace App\Http\Controllers\User; namespace App\Http\Controllers\User; // 定义命名空间
use App\Http\Requests\AddressRequest; use App\Http\Requests\AddressRequest; // 引入地址请求验证类
use App\Models\Address; use App\Models\Address; // 引入地址模型
use App\Models\User; use App\Models\User; // 引入用户模型
use Auth; use Auth; // 引入认证类
use DB; use DB; // 引入数据库门面
use Illuminate\Http\Request; use Illuminate\Http\Request; // 引入请求类
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller; // 引入基础控制器类
/**
* 地址控制器
*
* 该控制器处理用户地址的增删改查操作。
*/
class AddressController extends Controller class AddressController extends Controller
{ {
/**
* 显示用户的地址列表
*
* @return \Illuminate\View\View
*/
public function index() public function index()
{ {
// 获取当前用户的地址
$addresses = auth()->user()->addresses; $addresses = auth()->user()->addresses;
// Provincial and municipal regions // 获取省份和城市数据
$provinces = DB::table('provinces')->get(); $provinces = DB::table('provinces')->get(); // 获取所有省份
$cities = DB::table('cities')->where('province_id', $provinces->first()->id)->get(); $cities = DB::table('cities')->where('province_id', $provinces->first()->id)->get(); // 获取第一个省的城市
// 返回地址列表视图
return view('user.addresses.index', compact('addresses', 'provinces', 'cities')); return view('user.addresses.index', compact('addresses', 'provinces', 'cities'));
} }
/**
* 存储新地址
*
* @param AddressRequest $request
* @return \Illuminate\Http\RedirectResponse
*/
public function store(AddressRequest $request) public function store(AddressRequest $request)
{ {
// 获取格式化的请求数据
$addressesData = $this->getFormatRequest($request); $addressesData = $this->getFormatRequest($request);
//
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
$user->addresses()->create($addressesData); $user->addresses()->create($addressesData); // 创建新地址
// 返回带有成功消息的重定向
return back()->with('status', '创建成功'); return back()->with('status', '创建成功');
} }
/**
* 显示指定地址的详细信息
*
* @param Address $address
* @return Address
*/
public function show(Address $address) public function show(Address $address)
{ {
return $address; return $address; // 返回地址实例
} }
/**
* 显示编辑地址的表单
*
* @param Address $address
* @return \Illuminate\View\View
*/
public function edit(Address $address) public function edit(Address $address)
{ {
// 检查当前用户是否有权限编辑该地址
if (auth()->id() != $address->user_id) { if (auth()->id() != $address->user_id) {
abort(403, '非法操作'); // 如果没有权限返回403错误
abort(403, '非法操作');
} }
// 获取当前用户的地址
$addresses = auth()->user()->addresses; $addresses = auth()->user()->addresses;
// Provincial and municipal regions // 获取省份和城市数据
$provinces = DB::table('provinces')->get(); $provinces = DB::table('provinces')->get(); // 获取所有省份
$cities = DB::table('cities')->where('province_id', $address->province_id)->get(); $cities = DB::table('cities')->where('province_id', $address->province_id)->get(); // 获取指定省的城市
// 返回编辑地址的视图
return view('user.addresses.edit', compact('addresses', 'address', 'provinces', 'cities')); 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) public function update(AddressRequest $request, Address $address)
{ {
// 检查当前用户是否有权限更新该地址
if (auth()->id() != $address->user_id) { if (auth()->id() != $address->user_id) {
abort(403, '非法操作'); // 如果没有权限返回403错误
abort(403, '非法操作');
} }
// 获取格式化的请求数据
$addressesData = $this->getFormatRequest($request); $addressesData = $this->getFormatRequest($request);
$address->update($addressesData); $address->update($addressesData); // 更新地址
// 返回带有成功消息的重定向
return back()->with('status', '修改成功'); return back()->with('status', '修改成功');
} }
/**
* 删除指定地址
*
* @param Address $address
* @return \Illuminate\Http\JsonResponse
*/
public function destroy(Address $address) public function destroy(Address $address)
{ {
// 检查当前用户是否有权限删除该地址
if (auth()->id() != $address->user_id) { if (auth()->id() != $address->user_id) {
return responseJson(400, '非法操作'); // 如果没有权限返回400错误
return responseJson(400, '非法操作');
} }
$address->delete(); $address->delete(); // 删除地址
// 返回成功的 JSON 响应
return responseJson(200, '删除成功'); return responseJson(200, '删除成功');
} }
/**
* 设置默认地址
*
* @param Address $address
* @return \Illuminate\Http\JsonResponse
*/
public function setDefaultAddress(Address $address) public function setDefaultAddress(Address $address)
{ {
// 检查当前用户是否有权限设置该地址为默认
if (auth()->id() != $address->user_id) { if (auth()->id() != $address->user_id) {
return responseJson(400, '非法操作'); // 如果没有权限返回400错误
return responseJson(400, '非法操作');
} }
// 将当前用户的所有地址设置为非默认
Address::query()->where('user_id', $address->user_id)->update(['is_default' => 0]); Address::query()->where('user_id', $address->user_id)->update(['is_default' => 0]);
$address->is_default = 1; $address->is_default = 1; // 将指定地址设置为默认
if ($address->save()) { if ($address->save()) {
return responseJson(0, '设置成功'); // 返回成功的 JSON 响应
return responseJson(0, '设置成功');
} }
return responseJson(400, '请稍后再试!'); return responseJson(400, '请稍后再试!'); // 返回失败的 JSON 响应
} }
/**
* 格式化请求数据
*
* @param Request $request
* @return array
*/
protected function getFormatRequest(Request $request) 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) public function getCities(Request $request)
{ {
// 根据省份 ID 查询城市
return DB::table('cities')->where('province_id', $request->input('province_id'))->get(); return DB::table('cities')->where('province_id', $request->input('province_id'))->get();
} }
} }

@ -1,62 +1,86 @@
<?php <?php
namespace App\Http\Controllers\User; namespace App\Http\Controllers\User; // 定义命名空间
use App\Models\Product; use App\Models\Product; // 引入产品模型
use App\Models\User; use App\Models\User; // 引入用户模型
use Auth; use Auth; // 引入认证类
use Illuminate\Http\Request; use Illuminate\Http\Request; // 引入请求类
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller; // 引入基础控制器类
/**
* 用户收藏控制器
*
* 该控制器处理用户对产品的收藏(点赞)功能。
*/
class LikesController extends Controller class LikesController extends Controller
{ {
/**
* 默认响应信息
*
* @var array
*/
protected $response = [ protected $response = [
'code' => 1, 'code' => 1,
'msg' => '服务器异常,请稍后再试', 'msg' => '服务器异常,请稍后再试',
]; ];
/**
* 显示用户收藏的产品列表
*
* @return \Illuminate\View\View
*/
public function index() public function index()
{ {
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
// 获取用户收藏的产品,按最新排序并分页
$likesProducts = $user->products() $likesProducts = $user->products()
->where('user_id', auth()->id()) ->where('user_id', auth()->id())
->withCount('users') ->withCount('users') // 统计每个产品的收藏用户数
->latest() ->latest() // 按照创建时间降序排列
->paginate(10); ->paginate(10); // 每页显示10个产品
// 返回用户收藏产品的视图
return view('user.products.likes', compact('likesProducts')); return view('user.products.likes', compact('likesProducts'));
} }
/**
* 切换产品的收藏状态
*
* @param string $uuid 产品的唯一标识符
* @return \Illuminate\Http\JsonResponse
*/
public function toggle($uuid) public function toggle($uuid)
{ {
/** /**
* @var $product Product * @var $product Product
*/ */
$product = Product::query() $product = Product::query()
->where('uuid', $uuid) ->where('uuid', $uuid) // 根据 UUID 查找产品
->firstOrFail(); ->firstOrFail(); // 如果未找到,抛出 404 异常
$user = auth()->id(); $user = auth()->id(); // 获取当前用户的 ID
// 检查当前用户是否已经收藏该产品
if ($product->users()->where('user_id', $user)->exists()) { if ($product->users()->where('user_id', $user)->exists()) {
// 如果已收藏,则取消收藏
$product->users()->detach($user); $product->users()->detach($user);
// 返回 JSON 响应,表示已取消收藏
return response()->json([ return response()->json([
'code' => 200, 'code' => 200,
'msg' => '欢迎下次收藏' 'msg' => '欢迎下次收藏'
]); ]);
} }
// 如果未收藏,则添加收藏
$product->users()->attach($user); $product->users()->attach($user);
// 返回 JSON 响应,表示已成功收藏
return response()->json([ return response()->json([
'code' => 201, 'code' => 201,
'msg' => '收藏成功' 'msg' => '收藏成功'

@ -1,149 +1,184 @@
<?php <?php
namespace App\Http\Controllers\User; namespace App\Http\Controllers\User; // 定义命名空间
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller; // 引入基础控制器类
use App\Models\User; use App\Models\User; // 引入用户模型
use App\Notifications\CouponCodeNotification; use App\Notifications\CouponCodeNotification; // 引入优惠券通知类(未使用)
use App\Services\NotificationServe; use App\Services\NotificationServe; // 引入通知服务类
use Carbon\Carbon; use Carbon\Carbon; // 引入 Carbon 日期处理库
use Illuminate\Http\Request; use Illuminate\Http\Request; // 引入请求类
use Illuminate\Notifications\DatabaseNotification; use Illuminate\Notifications\DatabaseNotification; // 引入数据库通知模型
/**
* 用户通知控制器
*
* 该控制器处理用户通知的展示、阅读和管理功能。
*/
class NotificationController extends Controller class NotificationController extends Controller
{ {
/**
* 显示用户的通知列表
*
* @param Request $request
* @return \Illuminate\View\View
*/
public function index(Request $request) public function index(Request $request)
{ {
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
// 根据请求的 tab 参数确定查询的通知类型
switch ($request->input('tab', 1)) { switch ($request->input('tab', 1)) {
case 2: case 2:
$query = $user->notifications(); $query = $user->notifications(); // 所有通知
break; break;
case 3: case 3:
$query = $user->readNotifications(); $query = $user->readNotifications(); // 已读通知
break; break;
case 1: case 1:
default: default:
$query = $user->unreadNotifications(); $query = $user->unreadNotifications(); // 未读通知
break; break;
} }
// 分页获取通知
$notifications = $query->paginate(); $notifications = $query->paginate();
// 为每个通知设置标题
foreach ($notifications as $notification) { foreach ($notifications as $notification) {
$notification->title = NotificationServe::getTitle($notification); $notification->title = NotificationServe::getTitle($notification);
} }
// 获取未读和已读通知的数量
$unreadCount = $user->unreadNotifications()->count(); $unreadCount = $user->unreadNotifications()->count();
$readCount = $user->readNotifications()->count(); $readCount = $user->readNotifications()->count();
// 返回通知列表视图
return view('user.notifications.index', compact('notifications', 'unreadCount', 'readCount')); return view('user.notifications.index', compact('notifications', 'unreadCount', 'readCount'));
} }
/**
* 标记指定通知为已读
*
* @param int $id 通知的 ID
* @return \Illuminate\Http\JsonResponse
*/
public function read($id) public function read($id)
{ {
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
/** /**
* @var $notification DatabaseNotification * @var $notification DatabaseNotification
*/ */
$notification = $user->notifications()->find($id); $notification = $user->notifications()->find($id); // 查找指定通知
if (is_null($notification)) { if (is_null($notification)) {
return responseJsonAsBadRequest('无效的通知'); // 返回无效通知的错误
return responseJsonAsBadRequest('无效的通知');
} }
$notification->markAsRead(); $notification->markAsRead(); // 标记通知为已读
return responseJson(); return responseJson(); // 返回成功的 JSON 响应
} }
/**
* 标记所有未读通知为已读
*
* @return \Illuminate\Http\JsonResponse
*/
public function readAll() public function readAll()
{ {
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
// 更新所有未读通知为已读
$count = $user->unreadNotifications()->update(['read_at' => Carbon::now()]); $count = $user->unreadNotifications()->update(['read_at' => Carbon::now()]);
// 返回已读通知数量的 JSON 响应
return responseJson(200, "本次已读{$count}条消息"); return responseJson(200, "本次已读{$count}条消息");
} }
/**
* 显示指定通知的详细信息
*
* @param int $id 通知的 ID
* @return \Illuminate\View\View|\Illuminate\Http\Response
*/
public function show($id) public function show($id)
{ {
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
/** /**
* @var $notification DatabaseNotification * @var $notification DatabaseNotification
*/ */
$notification = $user->notifications()->find($id); $notification = $user->notifications()->find($id); // 查找指定通知
if (is_null($notification)) { if (is_null($notification)) {
return abort(403, '无效的通知'); // 返回403错误
return abort(403, '无效的通知');
} }
// 查看是否有上一条下一条 // 查找上一条和下一条通知
$last = $user->notifications()->where('created_at', '<', $notification->created_at)->first(); $last = $user->notifications()->where('created_at', '<', $notification->created_at)->first();
$next = $user->notifications()->where('created_at', '>', $notification->created_at)->first(); $next = $user->notifications()->where('created_at', '>', $notification->created_at)->first();
// 标记为已读
// 标记通知为已读
$notification->markAsRead(); $notification->markAsRead();
// 获取通知的视图
$view = NotificationServe::getView($notification); $view = NotificationServe::getView($notification);
if (! view()->exists($view)) { if (! view()->exists($view)) {
abort(404, '未知的的消息'); // 如果视图不存在返回404错误
abort(404, '未知的的消息');
} }
// 设置通知的标题
$notification->title = NotificationServe::getTitle($notification); $notification->title = NotificationServe::getTitle($notification);
$data = $notification->data; $data = $notification->data; // 获取通知的数据
// 返回通知详细信息的视图
return view('user.notifications.show', compact('last', 'next', 'notification', 'view', 'data')); return view('user.notifications.show', compact('last', 'next', 'notification', 'view', 'data'));
} }
/**
* 获取未读通知的数量
*
* @return \Illuminate\Http\JsonResponse
*/
public function getUnreadCount() public function getUnreadCount()
{ {
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
/** /**
* @var $notification DatabaseNotification * @var $notification DatabaseNotification
*/ */
$count = $user->unreadNotifications()->count(); $count = $user->unreadNotifications()->count(); // 获取未读通知的数量
// 初始化通知的标题、内容和 ID
$title = ''; $title = '';
$content = ''; $content = '';
$id = null; $id = null;
if ($count > 0) { if ($count > 0) {
$notification = $user->unreadNotifications()->first(); // 获取第一条未读通知
$notification = $user->unreadNotifications()->first();
// 前端弹窗内容和标题相反显示,所以变量名会有点怪 // 前端弹窗内容和标题相反显示,所以变量名会有点怪
$id = $notification->id; $id = $notification->id; // 获取通知 ID
$title = NotificationServe::getContent($notification); $title = NotificationServe::getContent($notification); // 获取通知内容
$content = NotificationServe::getTitle($notification); $content = NotificationServe::getTitle($notification); // 获取通知标题
} }
// 返回未读通知数量的 JSON 响应
return responseJson(200, 'success', compact('count', 'title', 'content', 'id')); return responseJson(200, 'success', compact('count', 'title', 'content', 'id'));
} }
} }

@ -1,28 +1,37 @@
<?php <?php
namespace App\Http\Controllers\User; namespace App\Http\Controllers\User; // 定义命名空间
use App\Admin\Transforms\OrderShipStatusTransform; use App\Admin\Transforms\OrderShipStatusTransform; // 引入订单发货状态转换类
use App\Admin\Transforms\OrderStatusTransform; use App\Admin\Transforms\OrderStatusTransform; // 引入订单状态转换类
use App\Enums\OrderShipStatusEnum; use App\Enums\OrderShipStatusEnum; // 引入订单发货状态枚举
use App\Enums\OrderStatusEnum; use App\Enums\OrderStatusEnum; // 引入订单状态枚举
use App\Enums\ScoreRuleIndexEnum; use App\Enums\ScoreRuleIndexEnum; // 引入积分规则索引枚举
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller; // 引入基础控制器类
use App\Models\Address; use App\Models\Address; // 引入地址模型
use App\Models\Comment; use App\Models\Comment; // 引入评论模型
use App\Models\Order; use App\Models\Order; // 引入订单模型
use App\Models\OrderDetail; use App\Models\OrderDetail; // 引入订单详情模型
use App\Models\ScoreRule; use App\Models\ScoreRule; // 引入积分规则模型
use App\Models\User; use App\Models\User; // 引入用户模型
use App\Services\OrderStatusButtonServe; use App\Services\OrderStatusButtonServe; // 引入订单状态按钮服务类
use App\Services\ScoreLogServe; use App\Services\ScoreLogServe; // 引入积分日志服务类
use Illuminate\Http\Request; use Illuminate\Http\Request; // 引入请求类
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB; // 引入数据库门面
use Yansongda\Pay\Pay; use Yansongda\Pay\Pay; // 引入支付类
/**
* 用户订单控制器
*
* 该控制器处理用户的订单相关操作,包括订单列表展示、订单详情、完成订单、确认收货等功能。
*/
class OrderController extends Controller class OrderController extends Controller
{ {
/**
* 显示用户的订单列表
*
* @return \Illuminate\View\View
*/
public function index() public function index()
{ {
// 获取积分比例 // 获取积分比例
@ -31,153 +40,162 @@ class OrderController extends Controller
/** /**
* @var $user User * @var $user User
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
$query = $user->orders(); $query = $user->orders(); // 获取用户的订单查询构建器
// 根据请求的 tab 参数筛选订单状态
switch (request('tab', 0)) { switch (request('tab', 0)) {
case 0: case 0:
break; break; // 默认显示所有订单
case 1: case 1:
// 待付款 // 待付款
$query->where('status', OrderStatusEnum::UN_PAY); $query->where('status', OrderStatusEnum::UN_PAY);
break; break;
case 2: case 2:
// 未发货 // 未发货
$query->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::PENDING); $query->where('status', OrderStatusEnum::PAID)
->where('ship_status', OrderShipStatusEnum::PENDING);
break; break;
case 3: case 3:
// 待收货 // 待收货
$query->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::DELIVERED); $query->where('status', OrderStatusEnum::PAID)
->where('ship_status', OrderShipStatusEnum::DELIVERED);
break; break;
case 4: case 4:
// 待评价 // 待评价
$query->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::RECEIVED); $query->where('status', OrderStatusEnum::PAID)
->where('ship_status', OrderShipStatusEnum::RECEIVED);
break; break;
} }
$orders = $query->latest() // 获取订单列表并进行处理
->with('details', 'details.product') $orders = $query->latest() // 按照创建时间降序排列
->with('details', 'details.product') // 预加载订单详情和产品
->get() ->get()
->map( ->map(
function (Order $order) use ($scoreRatio) { function (Order $order) use ($scoreRatio) {
// 计算可以获得的积分
// 可以或得到的积分
$order->score = ceil($order->amount * $scoreRatio); $order->score = ceil($order->amount * $scoreRatio);
// 完成按钮必须是已经支付和确认收货 // 设置订单状态文本
$order->status_text = OrderStatusTransform::trans($order->status); $order->status_text = OrderStatusTransform::trans($order->status);
// 如果订单是付款了则显示发货状态 // 如果订单已付款,则显示发货状态
if ($order->status == OrderStatusEnum::PAID) { if ($order->status == OrderStatusEnum::PAID) {
// 如果已发货,则显示发货信息
// 如果发货了,则显示发货信息
$order->status_text = OrderShipStatusTransform::trans($order->ship_status); $order->status_text = OrderShipStatusTransform::trans($order->ship_status);
} }
// 创建订单状态按钮服务实例
$buttonServe = new OrderStatusButtonServe($order); $buttonServe = new OrderStatusButtonServe($order);
switch ($order->status) { switch ($order->status) {
// 未支付的 // 未支付的订单
case OrderStatusEnum::UN_PAY: case OrderStatusEnum::UN_PAY:
$buttonServe->payButton()->cancelOrderButton(); // 添加支付和取消订单按钮
$buttonServe->payButton()->cancelOrderButton();
break; break;
case OrderStatusEnum::PAID: case OrderStatusEnum::PAID:
// 已经确认收获了 // 已确认收货
if ($order->ship_status == OrderShipStatusEnum::RECEIVED) { if ($order->ship_status == OrderShipStatusEnum::RECEIVED) {
$buttonServe->completeButton(); // 添加完成按钮
$buttonServe->completeButton();
} elseif ($order->ship_status == OrderShipStatusEnum::DELIVERED) { } elseif ($order->ship_status == OrderShipStatusEnum::DELIVERED) {
$buttonServe->shipButton(); // 添加发货按钮
$buttonServe->shipButton();
} else { } else {
$buttonServe->refundButton(); // 添加退款按钮
$buttonServe->refundButton();
} }
break; break;
// 手动取消的订单 // 手动取消的订单、已完成的订单、超时取消的订单
// 已经完成的订单
// 超时取消的订单
case OrderStatusEnum::UN_PAY_CANCEL: case OrderStatusEnum::UN_PAY_CANCEL:
case OrderStatusEnum::COMPLETED: case OrderStatusEnum::COMPLETED:
case OrderStatusEnum::TIMEOUT_CANCEL: case OrderStatusEnum::TIMEOUT_CANCEL:
$buttonServe->replyBuyButton()->deleteButton(); $buttonServe->replyBuyButton()->deleteButton(); // 添加重新购买和删除按钮
break; break;
} }
// 获取按钮集合
$order->buttons = $buttonServe->getButtons(); $order->buttons = $buttonServe->getButtons();
return $order; return $order; // 返回处理后的订单
} }
); );
// 查询不同状态的订单数量
// 查询订单总量
$unPayCount = $user->orders()->where('status', OrderStatusEnum::UN_PAY)->count(); $unPayCount = $user->orders()->where('status', OrderStatusEnum::UN_PAY)->count();
$shipPendingCount = $user->orders()->where('status', OrderStatusEnum::PAID)->where('ship_status', OrderShipStatusEnum::PENDING)->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(); $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(); $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')); 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) public function show(Order $order)
{ {
// 检查当前用户是否有权限查看该订单
if ($order->isNotUser(auth()->id())) { if ($order->isNotUser(auth()->id())) {
abort(403, '你没有权限'); abort(403, '你没有权限'); // 返回403错误
} }
// 设置发货和确认收货状态
$order->ship_send = $order->ship_status == OrderShipStatusEnum::DELIVERED; $order->ship_send = $order->ship_status == OrderShipStatusEnum::DELIVERED;
$order->confirm_ship = $order->ship_status == OrderShipStatusEnum::RECEIVED; $order->confirm_ship = $order->ship_status == OrderShipStatusEnum::RECEIVED;
// 如果已确认收货,标记为已发货
if ($order->confirm_ship) { if ($order->confirm_ship) {
$order->ship_send = true; $order->ship_send = true;
} }
$order->completed = $order->status == OrderShipStatusEnum::RECEIVED; // 设置订单是否已完成
$order->completed = $order->status == OrderStatusEnum::RECEIVED;
// 返回订单详情视图
return view('user.orders.show', compact('order')); return view('user.orders.show', compact('order'));
} }
/**
* 完成订单并添加评论
*
* @param Order $order
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function completeOrder(Order $order, Request $request) public function completeOrder(Order $order, Request $request)
{ {
// 获取评分和评论内容
$star = intval($request->input('star')); $star = intval($request->input('star'));
$content = $request->input('content'); $content = $request->input('content');
if ($star < 0 || $star > 5) {
return responseJsonAsBadRequest('无效的评分'); // 验证评分范围
if ($star < 0 || $star > 5) {
return responseJsonAsBadRequest('无效的评分'); // 返回错误响应
} }
// 验证评论内容
if (empty($content)) { if (empty($content)) {
return responseJsonAsBadRequest('请至少写一些内容吧'); // 返回错误响应
return responseJsonAsBadRequest('请至少些一些内容吧');
} }
// 判断是当前用户的订单才可以删除 // 检查当前用户是否有权限完成该订单
$user = auth()->user(); $user = auth()->user();
if ($order->isNotUser($user->id)) { if ($order->isNotUser($user->id)) {
return responseJsonAsBadRequest('你没有权限'); // 返回错误响应
return responseJsonAsBadRequest('你没有权限');
} }
// 只有付完款的订单,而且必须是未完成的, 确认收货 // 只有已付款且确认收货的订单才能完成
if ( if (!($order->status == OrderStatusEnum::PAID && $order->ship_status == OrderShipStatusEnum::RECEIVED)) {
// 必须是已经付款,且已经确认收货的 return responseJsonAsBadRequest('订单当前状态不能完成'); // 返回错误响应
! ($order->status == OrderStatusEnum::PAID && $order->ship_status == OrderShipStatusEnum::RECEIVED)
) {
return responseJsonAsBadRequest('订单当前状态不能完成');
} }
// 获取订单详情
$orderDetails = $order->details()->get(); $orderDetails = $order->details()->get();
// 构建评论数据
$comments = $orderDetails->map(function (OrderDetail $orderDetail) use ($user, $content, $star) { $comments = $orderDetails->map(function (OrderDetail $orderDetail) use ($user, $content, $star) {
return [ return [
'order_id' => $orderDetail->order_id, 'order_id' => $orderDetail->order_id,
'order_detail_id' => $orderDetail->id, 'order_detail_id' => $orderDetail->id,
@ -188,89 +206,95 @@ class OrderController extends Controller
]; ];
}); });
DB::beginTransaction(); DB::beginTransaction(); // 开始数据库事务
try { try {
// 更新订单状态为完成
// 订单完成
$order->status = OrderStatusEnum::COMPLETED; $order->status = OrderStatusEnum::COMPLETED;
$order->save(); $order->save();
// 评论内容 // 保存评论内容
Comment::query()->insert($comments->all()); Comment::query()->insert($comments->all());
// 更新订单详情为已评论
OrderDetail::query()->where('order_id', $order->id)->update(['is_commented' => true]); OrderDetail::query()->where('order_id', $order->id)->update(['is_commented' => true]);
// 完成订单增加积分 // 完成订单增加积分
(new ScoreLogServe)->completeOrderAddScore($order); (new ScoreLogServe)->completeOrderAddScore($order);
DB::commit(); DB::commit(); // 提交事务
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollBack(); // 回滚事务
return responseJsonAsServerError('服务器异常,请稍后再试'); return responseJsonAsServerError('服务器异常,请稍后再试'); // 返回错误响应
} }
return responseJson(200, '完成订单已增加积分'); // 返回成功响应
return responseJson(200, '完成订单已增加积分');
} }
/**
* 确认收货
*
* @param Order $order
* @return \Illuminate\Http\RedirectResponse
*/
public function confirmShip(Order $order) public function confirmShip(Order $order)
{ {
// 判断是当前用户的订单才可以删除 // 检查当前用户是否有权限确认收货
if ($order->isNotUser(auth()->id())) { if ($order->isNotUser(auth()->id())) {
abort(403, '你没有权限'); abort(403, '你没有权限'); // 返回403错误
} }
// 验证订单状态
if ($order->status != OrderStatusEnum::PAID) { if ($order->status != OrderStatusEnum::PAID) {
return back()->withErrors('订单未付款'); // 返回错误
return back()->withErrors('订单未付款');
} }
if ($order->ship_status != OrderShipStatusEnum::DELIVERED) { if ($order->ship_status != OrderShipStatusEnum::DELIVERED) {
return back()->withErrors('订单未发货'); // 返回错误
return back()->withErrors('订单未发货');
} }
// 更新订单发货状态为已收货
$order->ship_status = OrderShipStatusEnum::RECEIVED; $order->ship_status = OrderShipStatusEnum::RECEIVED;
$order->save(); $order->save();
return back()->with('status', '收货成功'); return back()->with('status', '收货成功'); // 返回成功消息
} }
/**
* 取消订单
*
* @param Order $order
* @return \Illuminate\Http\RedirectResponse
*/
public function cancelOrder(Order $order) public function cancelOrder(Order $order)
{ {
// 判断是当前用户的订单才可以删除 // 检查当前用户是否有权限取消订单
if ($order->isNotUser(auth()->id())) { if ($order->isNotUser(auth()->id())) {
abort(403, '你没有权限'); abort(403, '你没有权限'); // 返回403错误
} }
// 验证订单状态
if ($order->status != OrderStatusEnum::UN_PAY) { 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 { try {
// 取消订单
$orderData = [ $orderData = [
'out_trade_no' => $order->no, 'out_trade_no' => $order->no,
]; ];
$result = $pay->cancel($orderData); $result = $pay->cancel($orderData); // 调用支付取消接口
// 更新订单状态为未支付取消
$order->status = OrderStatusEnum::UN_PAY_CANCEL; $order->status = OrderStatusEnum::UN_PAY_CANCEL;
$order->save(); $order->save();
} catch (\Exception $e) { } 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() protected function getScoreRatio()
{ {
// 查询积分规则
$scoreRule = ScoreRule::query()->where('index_code', ScoreRuleIndexEnum::COMPLETE_ORDER)->firstOrFail(); $scoreRule = ScoreRule::query()->where('index_code', ScoreRuleIndexEnum::COMPLETE_ORDER)->firstOrFail();
return $scoreRule->score ?? 1; // 返回积分比例默认为1
return $scoreRule->score ?? 1;
} }
/** /**
* 地址是否存在 * 检查地址是否存在
* *
* @param $address * @param $address
* @return bool * @return bool
*/ */
protected function hasAddress($address) protected function hasAddress($address)
{ {
// 查询用户是否拥有该地址
return Address::query() return Address::query()
->where('user_id', auth()->id()) ->where('user_id', auth()->id())
->where('id', $address) ->where('id', $address)
->exists(); ->exists();
} }
/**
* 删除订单
*
* @param int $id 订单 ID
* @return \Illuminate\Http\RedirectResponse
*/
public function destroy($id) public function destroy($id)
{ {
/** /**
* @var $order Order * @var $order Order
*/ */
$order = Order::query()->findOrFail($id); $order = Order::query()->findOrFail($id); // 查找订单
// 判断是当前用户的订单才可以删除 // 检查当前用户是否有权限删除该订单
if ($order->isNotUser(auth()->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])) { if (!in_array($order->status, [OrderStatusEnum::UN_PAY_CANCEL, OrderStatusEnum::TIMEOUT_CANCEL, OrderStatusEnum::COMPLETED])) {
abort(403, '订单不能删除'); // 返回403错误
abort(403, '订单不能删除');
} }
$order->delete(); $order->delete(); // 删除订单
return back()->with('status', '删除成功'); return back()->with('status', '删除成功'); // 返回成功消息
} }
} }

@ -2,183 +2,179 @@
namespace App\Http\Controllers\User; namespace App\Http\Controllers\User;
use App\Enums\OrderTypeEnum; use App\Enums\OrderTypeEnum; // 引入订单类型枚举
use App\Enums\SettingKeyEnum; use App\Enums\SettingKeyEnum; // 引入设置键枚举
use App\Jobs\CancelUnPayOrder; use App\Jobs\CancelUnPayOrder; // 引入取消未支付订单的任务
use App\Models\Address; use App\Models\Address; // 引入地址模型
use App\Models\Order; use App\Models\Order; // 引入订单模型
use App\Models\OrderDetail; use App\Models\OrderDetail; // 引入订单详情模型
use App\Models\Product; use App\Models\Product; // 引入产品模型
use App\Models\Seckill; use App\Models\Seckill; // 引入秒杀模型
use App\Models\User; use App\Models\User; // 引入用户模型
use App\Utils\OrderUtil; use App\Utils\OrderUtil; // 引入订单工具类
use Carbon\Carbon; use Carbon\Carbon; // 引入 Carbon 日期处理库
use Illuminate\Auth\SessionGuard; use Illuminate\Auth\SessionGuard; // 引入会话守卫
use Illuminate\Http\Request; use Illuminate\Http\Request; // 引入请求类
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB; // 引入数据库门面
use Illuminate\Support\Facades\Redis; use Illuminate\Support\Facades\Redis; // 引入 Redis 门面
use Jenssegers\Agent\Agent; use Jenssegers\Agent\Agent; // 引入用户代理类
/**
* 秒杀控制器
*
* 该控制器处理与秒杀活动相关的操作,包括展示秒杀商品、参与秒杀、获取参与秒杀的用户等。
*/
class SeckillController extends PaymentController class SeckillController extends PaymentController
{ {
protected $redisSeckill; protected $redisSeckill; // 存储秒杀活动的 Redis 数据
/**
* 显示秒杀活动的详细信息
*
* @param int $id 秒杀活动的 ID
* @return \Illuminate\View\View
*/
public function show($id) public function show($id)
{ {
$seckill = new Seckill(compact('id')); $seckill = new Seckill(compact('id')); // 创建秒杀活动实例
$redisSeckill = $this->getSeckill($seckill); $redisSeckill = $this->getSeckill($seckill); // 从 Redis 获取秒杀活动数据
$product = $redisSeckill->product; $product = $redisSeckill->product; // 获取秒杀商品信息
/** /**
* @var $user User * @var $user User
* 如果登录返回所有地址列表,如果没有,则返回一个空集合 * 如果用户已登录,则返回该用户的所有地址列表;否则返回一个空集合
*/ */
$addresses = collect(); $addresses = collect(); // 初始化地址集合
if ($user = auth()->user()) { 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 Request $request 请求对象
* @param $id * @param int $id 秒杀活动的 ID
* @return \Illuminate\Http\JsonResponse * @return \Illuminate\Http\JsonResponse
* @throws \Exception * @throws \Exception
*/ */
public function storeSeckill(Request $request, $id) public function storeSeckill(Request $request, $id)
{ {
/** /**
* 直接从 session 中读取 id,不经过数据库 * 直接从 session 中读取用户 ID,不经过数据库
* *
* @var $user User * @var $user User
* @var $auth SessionGuard * @var $auth SessionGuard
*/ */
$seckill = new Seckill(compact('id')); $seckill = new Seckill(compact('id')); // 创建秒杀活动实例
$auth = auth('web'); $auth = auth('web'); // 获取当前会话
$userId = session()->get($auth->getName()); $userId = session()->get($auth->getName()); // 获取用户 ID
try { try {
// 检查请求中是否包含地址 ID
if (!$request->has('address_id')) { if (!$request->has('address_id')) {
throw new \Exception('必须选择一个地址'); // 抛出异常
throw new \Exception('必须选择一个地址');
} }
// 验证是否有这个秒杀 // 验证秒杀活动是否存在及是否已开始
// 验证秒杀活动是否已经结束
$redisSeckill = $this->redisSeckill = $this->getSeckill($seckill); $redisSeckill = $this->redisSeckill = $this->getSeckill($seckill);
if (!$redisSeckill->is_start) { if (!$redisSeckill->is_start) {
throw new \Exception('秒杀未开始'); throw new \Exception('秒杀未开始'); // 抛出异常
} }
} catch (\Exception $e) { } 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()))) { if (is_null(Redis::lpop($seckill->getRedisQueueKey()))) {
return responseJson(403, '已经抢购完了'); // 返回错误响应
return responseJson(403, '已经抢购完了');
} }
DB::beginTransaction(); // 开始数据库事务
DB::beginTransaction();
try { try {
$product = $redisSeckill->product; // 获取秒杀商品
$product = $redisSeckill->product;
if (is_null($product)) { if (is_null($product)) {
return responseJson(400, '商品已下架'); return responseJson(400, '商品已下架'); // 返回错误响应
} }
// 已经通过抢购请求,可以查询数据库 // 验证用户的收货地址是否有效
// 在这里验证一下地址是不是本人的
$user = auth()->user(); $user = auth()->user();
$address = Address::query()->where('user_id', $user->id)->find($request->input('address_id')); $address = Address::query()->where('user_id', $user->id)->find($request->input('address_id'));
if (is_null($address)) { if (is_null($address)) {
return responseJson(400, '无效的收货地址'); return responseJson(400, '无效的收货地址'); // 返回错误响应
} }
// 创建一个秒杀主表订单和明细表订单,默认数量一个 // 创建秒杀主表订单和明细表订单,默认数量为 1
$masterOrder = ($orderUtil = new OrderUtil([['product' => $product]]))->make($user->id, $address); $masterOrder = ($orderUtil = new OrderUtil([['product' => $product]]))->make($user->id, $address);
$masterOrder->type = OrderTypeEnum::SEC_KILL; $masterOrder->type = OrderTypeEnum::SEC_KILL; // 设置订单类型为秒杀
$masterOrder->amount = $redisSeckill->price; $masterOrder->amount = $redisSeckill->price; // 设置订单金额
$masterOrder->save(); $masterOrder->save(); // 保存订单
// 创建订单明细 // 创建订单明细
$details = $orderUtil->getDetails(); $details = $orderUtil->getDetails();
data_set($details, '*.order_id', $masterOrder->id); data_set($details, '*.order_id', $masterOrder->id); // 设置订单 ID
OrderDetail::query()->insert($details); OrderDetail::query()->insert($details); // 保存订单明细
// 设置未支付订单的自动取消时间
// 当订单超过三十分钟未付款,自动取消订单
$setting = new SettingKeyEnum(SettingKeyEnum::UN_PAY_CANCEL_TIME); $setting = new SettingKeyEnum(SettingKeyEnum::UN_PAY_CANCEL_TIME);
$delay = Carbon::now()->addMinute(setting($setting, 30)); $delay = Carbon::now()->addMinute(setting($setting, 30)); // 设置延迟时间
CancelUnPayOrder::dispatch($masterOrder)->delay($delay); CancelUnPayOrder::dispatch($masterOrder)->delay($delay); // 调度取消任务
// 生成支付信息 // 生成支付信息
$form = $this->buildPayForm($masterOrder, (new Agent)->isMobile())->getContent(); $form = $this->buildPayForm($masterOrder, (new Agent)->isMobile())->getContent();
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollBack(); // 回滚事务
DB::rollBack(); // 回滚秒杀数量
// 回滚一个秒杀数量
Redis::lpush($seckill->getRedisQueueKey(), 9); Redis::lpush($seckill->getRedisQueueKey(), 9);
// 把当前用户踢出,给他继续抢购 // 从 Redis 中删除当前用户的抢购记录,允许用户重新抢购
Redis::del($seckill->getUsersKey($userId)); 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(); $user = auth()->user();
Redis::hset($seckill->getUsersKey($userId), 'name', $user->hidden_name); 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) public function getSeckillUsers($id)
{ {
$seckill = new Seckill(compact('id')); $seckill = new Seckill(compact('id')); // 创建秒杀活动实例
$keys = Redis::keys($seckill->getUsersKey('*')); $keys = Redis::keys($seckill->getUsersKey('*')); // 获取所有参与用户的键
$users = collect(); $users = collect(); // 初始化用户集合
foreach ($keys as $key) { 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 * @return mixed
*/ */
protected function getSeckill(Seckill $seckill) protected function getSeckill(Seckill $seckill)
@ -186,50 +182,48 @@ class SeckillController extends PaymentController
/** /**
* @var $product Product * @var $product Product
*/ */
$json = Redis::get($seckill->getRedisModelKey()); $json = Redis::get($seckill->getRedisModelKey()); // 从 Redis 获取秒杀活动数据
$redisSeckill = json_decode($json); $redisSeckill = json_decode($json); // 解析 JSON 数据
if (is_null($redisSeckill)) { if (is_null($redisSeckill)) {
abort(403, "没有这个秒杀活动"); // 返回 403 错误
abort(403, "没有这个秒杀活动");
} }
// 得到这些时间 // 获取当前时间和秒杀结束时间
$now = Carbon::now(); $now = Carbon::now();
$endAt = Carbon::make($redisSeckill->end_at); $endAt = Carbon::make($redisSeckill->end_at);
if ($now->gt($endAt)) { if ($now->gt($endAt)) {
abort(403, "秒杀已经结束"); // 返回 403 错误
abort(403, "秒杀已经结束");
} }
// 秒杀是否已经开始 // 检查秒杀是否已经开始
$startAt = Carbon::make($redisSeckill->start_at); $startAt = Carbon::make($redisSeckill->start_at);
$redisSeckill->is_start = $now->gt($startAt); $redisSeckill->is_start = $now->gt($startAt); // 设置活动是否开始
// 开始倒计时 // 计算倒计时
$redisSeckill->diff_time = $startAt->getTimestamp() - time(); $redisSeckill->diff_time = $startAt->getTimestamp() - time();
return $redisSeckill; return $redisSeckill; // 返回秒杀活动数据
} }
/** /**
* 重写父类的构建订单明细 * 重写父类的构建订单明细
* *
* @param Product $product * @param Product $product 产品实例
* @param $number * @param int $number 数量
* @return array * @return array 订单明细数组
*/ */
protected function buildOrderDetail(Product $product, $number) protected function buildOrderDetail(Product $product, $number)
{ {
$attribute = [ $attribute = [
'product_id' => $product->id, 'product_id' => $product->id, // 设置产品 ID
'number' => $number 'number' => $number // 设置数量
]; ];
// 价格为秒杀的价格, 直接从 redis 中读取 // 价格为秒杀的价格,直接从 Redis 中读取
$attribute['price'] = ceilTwoPrice($this->redisSeckill->price); $attribute['price'] = ceilTwoPrice($this->redisSeckill->price); // 设置价格
$attribute['total'] = ceilTwoPrice($attribute['price'] * $attribute['number']); $attribute['total'] = ceilTwoPrice($attribute['price'] * $attribute['number']); // 计算总价
return $attribute; return $attribute; // 返回订单明细数组
} }
} }

@ -2,217 +2,219 @@
namespace App\Http\Controllers\User; namespace App\Http\Controllers\User;
use App\Enums\OrderStatusEnum; use App\Enums\OrderStatusEnum; // 引入订单状态枚举
use App\Enums\OrderTypeEnum; use App\Enums\OrderTypeEnum; // 引入订单类型枚举
use App\Enums\SettingKeyEnum; use App\Enums\SettingKeyEnum; // 引入设置键枚举
use App\Exceptions\OrderException; use App\Exceptions\OrderException; // 引入订单异常
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller; // 引入基础控制器
use App\Jobs\CancelUnPayOrder; use App\Jobs\CancelUnPayOrder; // 引入取消未支付订单的任务
use App\Models\Address; use App\Models\Address; // 引入地址模型
use App\Models\Car; use App\Models\Car; // 引入购物车模型
use App\Models\Order; use App\Models\Order; // 引入订单模型
use App\Models\OrderDetail; use App\Models\OrderDetail; // 引入订单详情模型
use App\Models\Product; use App\Models\Product; // 引入产品模型
use App\Models\User; use App\Models\User; // 引入用户模型
use App\Utils\OrderUtil; use App\Utils\OrderUtil; // 引入订单工具类
use Carbon\Carbon; use Carbon\Carbon; // 引入 Carbon 日期处理库
use Illuminate\Http\Request; use Illuminate\Http\Request; // 引入请求类
use Illuminate\Support\Collection; use Illuminate\Support\Collection; // 引入集合类
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB; // 引入数据库门面
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response; // 引入响应类
class StoreOrderController extends Controller class StoreOrderController extends Controller
{ {
/**
* 创建订单页面
*
* @param Request $request 请求对象
* @return \Illuminate\View\View
*/
public function create(Request $request) public function create(Request $request)
{ {
/** /**
* @var $user User * @var $user User
* 获取当前登录用户
*/ */
$user = auth()->user(); $user = auth()->user();
// 从请求中获取购物车信息和商品 ID
$cars = $request->input('cars', []); $cars = $request->input('cars', []);
$ids = $request->input('ids'); $ids = $request->input('ids');
$numbers = $request->input('numbers'); $numbers = $request->input('numbers');
// 验证商品 ID 和数量的有效性
if (count($ids) === 0 || count($ids) !== count($numbers)) { if (count($ids) === 0 || count($ids) !== count($numbers)) {
return back()->with('error', '无效的商品'); // 返回错误信息
return back()->with('error', '无效的商品');
} }
// 查询数据库中存在的商品
$products = Product::query()->whereIn('uuid', $ids)->get(); $products = Product::query()->whereIn('uuid', $ids)->get();
if ($products->count() === 0 || $products->count() !== count($numbers)) { if ($products->count() === 0 || $products->count() !== count($numbers)) {
return back()->with('error', '无效的商品'); // 返回错误信息
return back()->with('error', '无效的商品');
} }
$totalAmount = 0; $totalAmount = 0; // 初始化总金额
$products->transform(function (Product $product, $i) use ($numbers, &$totalAmount) {
$product->number = $numbers[$i]; // 计算每个商品的总金额并更新商品数量
$product->total_amount = round($product->price * $product->number); $products->transform(function (Product $product, $i) use ($numbers, &$totalAmount) {
$totalAmount += $product->total_amount; $product->number = $numbers[$i]; // 设置商品数量
$product->total_amount = round($product->price * $product->number); // 计算商品总金额
return $product; $totalAmount += $product->total_amount; // 累加总金额
return $product; // 返回更新后的商品
}); });
// 增加邮费 // 增加邮费
$postAmount = \setting(new SettingKeyEnum(SettingKeyEnum::POST_AMOUNT)); $postAmount = \setting(new SettingKeyEnum(SettingKeyEnum::POST_AMOUNT));
$totalAmount += $postAmount; $totalAmount += $postAmount; // 将邮费加到总金额
/** // 获取用户的收货地址
* @var $user User
*/
$user = auth()->user();
$addresses = $user->addresses()->latest()->get(); $addresses = $user->addresses()->latest()->get();
// 可用的优惠券 // 获取可用的优惠券
$today = Carbon::today()->toDateString(); $today = Carbon::today()->toDateString();
$coupons = $user->coupons() $coupons = $user->coupons()
->where('start_date', '<=', $today) ->where('start_date', '<=', $today) // 优惠券开始日期
->where('end_date', '>=', $today) ->where('end_date', '>=', $today) // 优惠券结束日期
->whereNull('used_at') ->whereNull('used_at') // 未使用的优惠券
->where('full_amount', '<=', $totalAmount) ->where('full_amount', '<=', $totalAmount) // 满足使用条件的优惠券
->latest() ->latest()
->get(); ->get();
// 返回创建订单页面的视图
return view('orders.create', compact('products', 'cars', 'addresses', 'totalAmount', 'coupons', 'postAmount')); return view('orders.create', compact('products', 'cars', 'addresses', 'totalAmount', 'coupons', 'postAmount'));
} }
/**
* 存储订单
*
* @param Request $request 请求对象
* @return \Illuminate\Http\JsonResponse
*/
public function store(Request $request) public function store(Request $request)
{ {
// 验证请求数据的有效性
if (($response = $this->validateRequest($request)) instanceof Response) { 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) { $detailsData = Collection::make($ids)->map(function ($id, $index) use ($numbers, $productMap) {
return [ return [
'number' => $numbers[$index], 'number' => $numbers[$index], // 商品数量
'product' => $productMap[$id] 'product' => $productMap[$id] // 商品信息
]; ];
}); });
DB::beginTransaction(); // 开始数据库事务
DB::beginTransaction();
try { try {
// 创建主订单
$masterOrder = ($orderUtil = new OrderUtil($detailsData))->make(auth()->id(), $address); $masterOrder = ($orderUtil = new OrderUtil($detailsData))->make(auth()->id(), $address);
// 验证优惠券的使用条件
if (!is_null($couponModel) && $masterOrder->amount < $couponModel->full_amount) { if (!is_null($couponModel) && $masterOrder->amount < $couponModel->full_amount) {
throw new \Exception('优惠券门槛金额为 ' . $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 = $masterOrder->amount > $couponModel->amount ?
($masterOrder->amount - $couponModel->amount) : 0.01; ($masterOrder->amount - $couponModel->amount) : 0.01; // 计算实际支付金额
$couponModel->used_at = Carbon::now()->toDateTimeString(); $couponModel->used_at = Carbon::now()->toDateTimeString(); // 标记优惠券为已使用
$couponModel->save(); $couponModel->save(); // 保存优惠券状态
$masterOrder->coupon_id = $couponModel->id; $masterOrder->coupon_id = $couponModel->id; // 关联优惠券 ID
$masterOrder->coupon_amount = $couponModel->amount; $masterOrder->coupon_amount = $couponModel->amount; // 记录优惠券金额
} }
$masterOrder->save(); $masterOrder->save(); // 保存主订单
// 创建订单明细 // 创建订单明细
$details = $orderUtil->getDetails(); $details = $orderUtil->getDetails(); // 获取订单明细数据
data_set($details, '*.order_id', $masterOrder->id); data_set($details, '*.order_id', $masterOrder->id); // 设置订单 ID
OrderDetail::query()->insert($details); OrderDetail::query()->insert($details); // 保存订单明细
// 如果存在购物车,把购物车删除 // 如果存在购物车,删除购物车中的商品
$cars = $request->input('cars'); $cars = $request->input('cars');
if (is_array($cars) && !empty($cars)) { if (is_array($cars) && !empty($cars)) {
Car::query()->where('user_id', auth()->id())->where('id', $cars)->delete(); // 删除购物车商品
Car::query()->where('user_id', auth()->id())->where('id', $cars)->delete();
} }
// 当订单超过三十分钟未付款,自动取消订单 // 设置未支付订单的自动取消时间
$settingKey = new SettingKeyEnum(SettingKeyEnum::UN_PAY_CANCEL_TIME); $settingKey = new SettingKeyEnum(SettingKeyEnum::UN_PAY_CANCEL_TIME);
$delay = Carbon::now()->addMinute(setting($settingKey, 30)); $delay = Carbon::now()->addMinute(setting($settingKey, 30)); // 设置延迟时间
CancelUnPayOrder::dispatch($masterOrder)->delay($delay); CancelUnPayOrder::dispatch($masterOrder)->delay($delay); // 调度取消任务
DB::commit(); DB::commit(); // 提交事务
} catch (\Exception $e) { } catch (\Exception $e) {
DB::rollBack(); // 回滚事务
DB::rollBack(); return responseJsonAsBadRequest($e->getMessage()); // 返回错误响应
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) private function validateRequest(Request $request)
{ {
/** /**
* @var $user User * @var $user User
* @var $address Address * @var $address Address
*/ */
$user = auth()->user(); $user = auth()->user(); // 获取当前用户
$ids = $request->input('ids'); $ids = $request->input('ids'); // 获取商品 ID
$numbers = $request->input('numbers'); $numbers = $request->input('numbers'); // 获取商品数量
// 验证商品 ID 和数量的有效性
if (count($ids) === 0 || count($ids) !== count($numbers)) { if (count($ids) === 0 || count($ids) !== count($numbers)) {
return responseJsonAsBadRequest('无效的商品'); // 返回错误响应
return responseJsonAsBadRequest('无效的商品');
} }
// 查询数据库中存在的商品
$productMap = Product::query()->whereIn('uuid', $ids)->get()->mapWithKeys(function (Product $product) { $productMap = Product::query()->whereIn('uuid', $ids)->get()->mapWithKeys(function (Product $product) {
return [$product->uuid => $product]; // 将商品映射为 ID 和商品对象
return [$product->uuid => $product];
}); });
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')); $address = $user->addresses()->find($request->input('address_id'));
if (is_null($address)) { if (is_null($address)) {
return responseJsonAsBadRequest('请选择收货地址'); // 返回错误响应
return responseJsonAsBadRequest('请选择收货地址');
} }
// 验证优惠券的有效性
// 查看是否有优惠券的价格
$couponModel = null; $couponModel = null;
if ($couponId = $request->input('coupon_id')) { if ($couponId = $request->input('coupon_id')) {
$couponModel = $user->coupons()->find($couponId); // 查询优惠券
$couponModel = $user->coupons()->find($couponId);
if (is_null($couponModel)) { if (is_null($couponModel)) {
return responseJsonAsBadRequest('无效的优惠券'); // 返回错误响应
return responseJsonAsBadRequest('无效的优惠券');
} }
$today = Carbon::today(); $today = Carbon::today();
$startDate = Carbon::make($couponModel->start_date) ?? Carbon::tomorrow(); $startDate = Carbon::make($couponModel->start_date) ?? Carbon::tomorrow(); // 优惠券开始日期
$endDate = Carbon::make($couponModel->end_date) ?? Carbon::yesterday(); $endDate = Carbon::make($couponModel->end_date) ?? Carbon::yesterday(); // 优惠券结束日期
if ($today->lt($startDate) || $today->gt($endDate)) { if ($today->lt($startDate) || $today->gt($endDate)) {
return responseJsonAsBadRequest('优惠券已过使用期'); // 返回错误响应
return responseJsonAsBadRequest('优惠券已过使用期');
} }
if (!is_null($couponModel->used_at)) { if (!is_null($couponModel->used_at)) {
return responseJsonAsBadRequest('优惠券已使用过'); // 返回错误响应
return responseJsonAsBadRequest('优惠券已使用过');
} }
} }
return [$ids, $numbers, $productMap, $address, $couponModel]; return [$ids, $numbers, $productMap, $address, $couponModel]; // 返回验证结果
} }
} }

Loading…
Cancel
Save