diff --git a/app/Console/Commands/AddShopToEsSearchCommand.php b/app/Console/Commands/AddShopToEsSearchCommand.php index 739bdc5..f156835 100644 --- a/app/Console/Commands/AddShopToEsSearchCommand.php +++ b/app/Console/Commands/AddShopToEsSearchCommand.php @@ -29,6 +29,8 @@ class AddShopToEsSearchCommand extends Command * * @return void */ + + public function __construct() { parent::__construct(); @@ -41,51 +43,75 @@ class AddShopToEsSearchCommand extends Command */ public function handle() { + + try { + ElasticSearchTrait::client()->ping([ 'client' => [ 'timeout' => 5, + 'connect_timeout' => 5 ] ]); } catch (\Exception $exception) { - + + + $this->info($exception->getMessage()); - $this->info('无法连接到 elasticsearch 服务器,请配置 config/elasticsearch.php 文件'); + + + + $this->info('无法连接到 elasticse + + + + arch 服务器,请配置 config/elasticsearch.php 文件'); + $this->info('默认使用 MySQL 的模糊搜索'); $this->info('配置完毕后可运行: php artisan add:shop-to-search 添加索引'); + + + return; } - - + + // 新建商品索引 if (Product::indexExists()) { - + + + Product::deleteIndex(); $this->info('删除索引'); } + Product::createIndex(); $this->info('新建索引成功'); - - + + + // 开始导入数据 $query = Product::query(); - + $count = $query->count(); $handle = 0; - + $query->with('category')->chunk(1000, function (Collection $models) use ($count, &$handle) { - + $models->map(function (Product $product) use ($count, &$handle) { - + $product->addToIndex($product->getSearchData()); - + ++ $handle; echo "\r {$handle}/$count"; }); }); - + + + echo PHP_EOL; + $this->info('索引生成完毕'); } } diff --git a/app/Console/Commands/DelExpireScoreData.php b/app/Console/Commands/DelExpireScoreData.php index 65e1c4c..44990dc 100644 --- a/app/Console/Commands/DelExpireScoreData.php +++ b/app/Console/Commands/DelExpireScoreData.php @@ -19,6 +19,7 @@ class DelExpireScoreData extends Command /** * The console command description. * + * @var string */ protected $description = 'Command description'; diff --git a/app/Console/Commands/SyncProducViewCommand.php b/app/Console/Commands/SyncProducViewCommand.php index 5510965..ec0fe30 100644 --- a/app/Console/Commands/SyncProducViewCommand.php +++ b/app/Console/Commands/SyncProducViewCommand.php @@ -37,22 +37,42 @@ class SyncProducViewCommand extends Command * Execute the console command. * * @return mixed + + + + + */ public function handle() { - $yesterday = Carbon::yesterday()->toDateString(); + $yesterday = Carbon::yesterday()->toDateStr + + + + + ing(); $products = Product::query()->where('today_has_view', 1)->get(); + + $products->map(function (Product $product) use ($yesterday) { + + + $viewCount = Cache::pull($product->getViewCountKey($yesterday), 0); - $product->view_count += $viewCount; + $product->view_count += $vi + ewCount; $product->today_has_view = 0; $product->save(); }); + + createSystemLog("系统同步{$yesterday}商品浏览量", ['date' => $yesterday]); } + + } diff --git a/app/Console/Commands/UninstallShop.php b/app/Console/Commands/UninstallShop.php index 01c6854..bfaff6f 100644 --- a/app/Console/Commands/UninstallShop.php +++ b/app/Console/Commands/UninstallShop.php @@ -24,6 +24,9 @@ class UninstallShop extends BaseCommand * * @return void */ + + + public function __construct() { parent::__construct(); diff --git a/app/Console/Commands/UpdateCacheHomeData.php b/app/Console/Commands/UpdateCacheHomeData.php index b0dcdea..774eb81 100644 --- a/app/Console/Commands/UpdateCacheHomeData.php +++ b/app/Console/Commands/UpdateCacheHomeData.php @@ -7,6 +7,8 @@ use App\Models\Category; use App\Models\Product; use App\Models\User; use App\Utils\HomeCacheDataUtil; + + use Carbon\Carbon; use Illuminate\Console\Command; use Illuminate\Support\Facades\Cache; @@ -47,9 +49,24 @@ class UpdateCacheHomeData extends Command // 每分钟有定时任务更新 $ttl = 60 * 2; + + HomeCacheDataUtil::categories($ttl, true); + + + + + HomeCacheDataUtil::hotProducts($ttl, true); + + HomeCacheDataUtil::latestProducts($ttl, true); + + HomeCacheDataUtil::users($ttl, true); + } } + + + diff --git a/app/Exceptions/BadRequestException.php b/app/Exceptions/BadRequestException.php index 52b3988..4d0167d 100644 --- a/app/Exceptions/BadRequestException.php +++ b/app/Exceptions/BadRequestException.php @@ -8,3 +8,5 @@ class BadRequestException extends Exception { // } + + diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 66fe8b2..e16fb65 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -1,7 +1,6 @@ reportable(function (Throwable $e) { - // + // 可以在这里记录异常或执行其他操作 }); - + // 处理可渲染的异常 $this->renderable(function (\Exception $exception, Request $request) { + // 检查请求是否为 API 请求 if ($request->is('api*')) { - + // 处理 JWT 相关的异常 if ($exception instanceof JWTException) { - + // 映射 JWT 异常到用户友好的消息 $mapExceptions = [ TokenInvalidException::class => '无效的token', TokenBlacklistedException::class => 'token 已被加入黑名单,请重新登录' ]; - + // 获取对应的错误消息 $msg = $mapExceptions[get_class($exception)] ?? $exception->getMessage(); - return responseJsonAsUnAuthorized($msg); + return responseJsonAsUnAuthorized($msg); // 返回未授权的 JSON 响应 } // 拦截表单验证错误抛出的异常 elseif ($exception instanceof ValidationException) { - - return responseJsonAsBadRequest($exception->validator->errors()->first()); + return responseJsonAsBadRequest($exception->validator->errors()->first()); // 返回验证错误的 JSON 响应 } - - + // 处理其他服务器错误 return responseJsonAsServerError($exception->getMessage()); } - - + // 对于非 API 请求,返回服务器错误信息 return responseJsonAsServerError($exception->getMessage(), null); }); } diff --git a/app/Exceptions/OrderException.php b/app/Exceptions/OrderException.php index 6900b5b..ec107c4 100644 --- a/app/Exceptions/OrderException.php +++ b/app/Exceptions/OrderException.php @@ -5,10 +5,7 @@ * Date: 2018/10/19 * Time: 22:04 */ - namespace App\Exceptions; - - class OrderException extends \Exception { diff --git a/app/Exceptions/UploadException.php b/app/Exceptions/UploadException.php index b6a9ff6..afe813c 100644 --- a/app/Exceptions/UploadException.php +++ b/app/Exceptions/UploadException.php @@ -12,4 +12,7 @@ namespace App\Exceptions; class UploadException extends \Exception { + + + } diff --git a/app/Http/Controllers/Api/V1/AuthController.php b/app/Http/Controllers/Api/V1/AuthController.php index 5a282f6..89799e5 100644 --- a/app/Http/Controllers/Api/V1/AuthController.php +++ b/app/Http/Controllers/Api/V1/AuthController.php @@ -18,38 +18,43 @@ class AuthController extends Controller /** * 登录的接口 * - * @param LoginRequest $request - * @return \Illuminate\Http\JsonResponse + * @param LoginRequest $request 登录请求数据 + * @return \Illuminate\Http\JsonResponse 返回登录结果的 JSON 响应 */ public function login(LoginRequest $request) { + // 获取用户名和密码 $username = $request->input('username'); $password = $request->input('password'); + // 查询用户 $user = User::query() ->whereNotNull('name') ->where('name', $username) ->first(); + // 检查用户是否存在 if (is_null($user)) { return responseJsonAsBadRequest('用户名或者密码错误'); } + // 验证密码是否正确 if (! Hash::check($password, $user->getAuthPassword())) { return responseJsonAsBadRequest('用户名或者密码错误'); } - + // 返回成功响应和 token return responseJson(200, '登录成功', $this->getToken($user)); } /** * 注销的接口 * - * @return \Illuminate\Http\JsonResponse + * @return \Illuminate\Http\JsonResponse 返回注销结果的 JSON 响应 */ public function logout() { + // 注销用户 auth('api')->logout(); return responseJsonAsDeleted('注销成功'); @@ -58,47 +63,46 @@ class AuthController extends Controller /** * 注册的接口 * - * @param RegisterUserRequest $request - * @return \Illuminate\Http\JsonResponse + * @param RegisterUserRequest $request 注册请求数据 + * @return \Illuminate\Http\JsonResponse 返回注册结果的 JSON 响应 */ public function register(RegisterUserRequest $request) { + // 获取用户名和密码 $username = $request->input('username'); $password = $request->input('password'); + // 检查用户名是否已存在 if (User::query()->where('name', $username)->exists()) { - return responseJsonAsBadRequest('用户名已经存在, 请换一个用户名'); } + // 创建新用户 $user = new User(); $user->name = $username; - $user->password = $password; - $user->sex = UserSexEnum::MAN; - $user->is_init_email = 1; - // api 注册的用户默认激活 - $user->is_active = UserStatusEnum::ACTIVE; - $user->save(); - + $user->password = Hash::make($password); // 确保密码被哈希处理 + $user->sex = UserSexEnum::MAN; // 默认性别 + $user->is_init_email = 1; // 初始化邮箱状态 + $user->is_active = UserStatusEnum::ACTIVE; // 默认激活状态 + $user->save(); // 保存用户信息 + // 返回成功响应和 token return responseJson(201, '注册成功', $this->getToken($user)); } - - /** * 拼接 token * - * @param User $user - * @return array + * @param User $user 用户模型 + * @return array 返回包含 token 的数组 */ protected function getToken(User $user) { - // 换取 token + // 生成 token $prefix = 'Bearer'; - $token = auth('api')->login($user); - $me = new OwnResource($user); + $token = auth('api')->login($user); // 登录并获取 token + $me = new OwnResource($user); // 创建用户资源 - return compact('prefix', 'token', 'me'); + return compact('prefix', 'token', 'me'); // 返回 token 和用户信息 } } diff --git a/app/Http/Controllers/Api/V1/CategoryController.php b/app/Http/Controllers/Api/V1/CategoryController.php index 35a7ed9..417ab75 100644 --- a/app/Http/Controllers/Api/V1/CategoryController.php +++ b/app/Http/Controllers/Api/V1/CategoryController.php @@ -11,44 +11,60 @@ use App\Http\Controllers\Controller; class CategoryController extends Controller { + /** + * 获取分类列表 + * + * @param PageServe $serve 分页服务 + * @return \Illuminate\Http\JsonResponse 返回分类列表的 JSON 响应 + */ public function index(PageServe $serve) { + // 获取分页参数 list($limit, $offset) = $serve->getPageParameters(); + // 构建分类查询 $query = Category::query(); + // 根据名称过滤分类 if ($title = $serve->input('name')) { - $query->where('title', 'like', "%{$title}%"); } - + // 获取总数和分类数据 $count = $query->count(); $categories = $query->orderBy('order')->limit($limit)->offset($offset)->get(); - $categories = CategoreResource::collection($categories); + $categories = CategoreResource::collection($categories); // 转换为资源集合 - return responseJson(200, 'success', $categories, compact('count')); + return responseJson(200, 'success', $categories, compact('count')); // 返回成功响应 } - + /** + * 获取指定分类下的产品 + * + * @param PageServe $serve 分页服务 + * @param int $category 分类 ID + * @return \Illuminate\Http\JsonResponse 返回产品列表的 JSON 响应 + */ public function getProducts(PageServe $serve, $category) { + // 获取分页参数 list($limit, $offset) = $serve->getPageParameters(); // 排序的字段和排序的值 $orderField = $serve->input('order_field'); $orderValue = $serve->input('order_value'); + // 查找指定分类 /** * @var $category Category */ $category = Category::query()->findOrFail($category); + // 获取该分类下的产品查询 $query = $category->products(); - + // 根据名称过滤产品 if ($name = $serve->input('name')) { - $query->where('name', 'like', "%{$name}%"); } @@ -56,18 +72,17 @@ class CategoryController extends Controller $allFields = ['created_at', 'sale_count', 'view_count']; $orderField = in_array($orderField, $allFields) ? $orderField : - array_first($allFields); - $orderValue = $orderValue === 'asc' ? 'asc' : 'desc'; - + array_first($allFields); // 默认排序字段 + $orderValue = $orderValue === 'asc' ? 'asc' : 'desc'; // 默认排序方式 // 获取数据 - $count = $query->count(); + $count = $query->count(); // 获取产品总数 $products = $query->orderBy($orderField, $orderValue) ->limit($limit) ->offset($offset) ->get(); - $products = ProductResource::collection($products); + $products = ProductResource::collection($products); // 转换为资源集合 - return responseJson(200, 'success', $products, compact('count')); + return responseJson(200, 'success', $products, compact('count')); // 返回成功响应 } } diff --git a/app/Http/Controllers/Api/V1/OwnController.php b/app/Http/Controllers/Api/V1/OwnController.php index bb5425c..4de0022 100644 --- a/app/Http/Controllers/Api/V1/OwnController.php +++ b/app/Http/Controllers/Api/V1/OwnController.php @@ -11,31 +11,51 @@ use App\Http\Controllers\Controller; class OwnController extends Controller { + /** + * 获取当前用户的信息 + * + * @return \Illuminate\Http\JsonResponse 返回当前用户信息的 JSON 响应 + */ public function me() { + // 获取当前认证用户 $me = auth()->user(); + // 返回成功响应和用户信息 return responseJson(200, 'success', new OwnResource($me)); } + /** + * 获取当前用户的积分日志 + * + * @param PageServe $serve 分页服务 + * @return \Illuminate\Http\JsonResponse 返回积分日志的 JSON 响应 + */ public function scoreLogs(PageServe $serve) { + // 获取分页参数 list($limit, $offset) = $serve->getPageParameters(); + /** * @var $me User */ + // 获取当前认证用户 $me = auth()->user(); + // 获取用户的积分日志查询 $query = $me->scoreLogs(); + // 获取积分日志总数 $count = $query->count(); + + // 获取分页后的积分日志数据 $scoreLogs = $me->scoreLogs() - ->latest() - ->offset($offset) - ->limit($limit) + ->latest() // 按时间降序排列 + ->offset($offset) // 设置偏移量 + ->limit($limit) // 设置限制 ->get(); - + // 返回成功响应和积分日志 return responseJson(200, 'success', ScoreLogResource::collection($scoreLogs), compact('count')); } } diff --git a/app/Http/Controllers/CarController.php b/app/Http/Controllers/CarController.php index d1a0bd5..a43b587 100644 --- a/app/Http/Controllers/CarController.php +++ b/app/Http/Controllers/CarController.php @@ -9,35 +9,40 @@ use Illuminate\Http\Request; class CarController extends Controller { + // 构造函数,设置中间件 public function __construct() { + // 仅对 store 和 destroy 方法应用用户身份验证中间件 $this->middleware('user.auth')->only('store', 'destroy'); } /** - * 购物车列表 + * 显示购物车列表 * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回购物车视图 */ public function index() { - $cars = collect(); + $cars = collect(); // 初始化购物车集合 /** * @var $user User */ + // 获取当前登录用户的购物车 if ($user = \auth()->user()) { - // 直接获取当前登录用户的购物车 + // 直接获取当前用户的购物车及其关联的产品 $cars = $user->cars()->with('product')->get(); } + // 返回购物车视图,并传递购物车数据 return view('cars.index', compact('cars')); } /** - * 添加购物车 - * @param Request $request - * @return array + * 添加商品到购物车 + * + * @param Request $request 请求对象 + * @return array 返回操作结果 */ public function store(Request $request) { @@ -46,43 +51,47 @@ class CarController extends Controller * @var $product Product * @var $user User */ + // 根据产品 UUID 查找产品 $product = Product::query()->where('uuid', $request->input('product_id'))->firstOrFail(); + // 获取当前用户 $user = auth()->user(); + // 查找或新建购物车记录 $car = $user->cars()->firstOrNew([ 'user_id' => \auth()->id(), 'product_id' => $product->id ]); - - // 如果是同步,则只是赋值,如果是添加购物车则是添加 - $change = 0; - $number = $request->input('number', 1); + // 处理购物车数量变化 + $change = 0; // 数量变化 + $number = $request->input('number', 1); // 获取请求中的数量,默认为 1 if ($request->input('action') == 'sync') { - + // 如果是同步操作,直接设置数量 $change = $number - $car->number; $car->number = $number; } else { - + // 否则,增加数量 $car->number += $number; } + // 检查库存是否足够 if ($car->number > $product->count) { - - return responseJson(403, '库存不足'); + return responseJson(403, '库存不足'); // 返回库存不足的响应 } - + // 保存购物车记录 $car->save(); + // 返回成功响应 return responseJson(200, '加入购物车成功', compact('change')); } - /** - * @param $id - * @return array + * 从购物车中删除商品 + * + * @param $id 购物车项的 ID + * @return array 返回操作结果 */ public function destroy($id) { @@ -90,16 +99,19 @@ class CarController extends Controller /** * @var $user User */ + // 获取当前用户 $user = auth()->user(); + // 查找购物车项并删除 $car = $user->cars()->whereKey($id)->firstOrFail(); $car->delete(); } catch (\Exception $e) { - - dd($e); + // 捕获异常并返回错误响应 + dd($e); // 可选:调试输出异常信息 return responseJson(500, '服务器异常,请稍后再试'); } + // 返回成功响应 return responseJson(200, '删除成功'); } } diff --git a/app/Http/Controllers/CategoryController.php b/app/Http/Controllers/CategoryController.php index a20c69c..d18d6f9 100644 --- a/app/Http/Controllers/CategoryController.php +++ b/app/Http/Controllers/CategoryController.php @@ -6,35 +6,41 @@ use App\Http\Controllers\Controller; use App\Models\Category; use Illuminate\Http\Request; - class CategoryController extends Controller { /** - * 前台分类列表 + * 显示前台分类列表 * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回分类列表视图 */ public function index() { + // 获取最新的分类,分页显示,每页 30 条 $categories = Category::query()->latest()->paginate(30); - + // 返回分类列表视图,并传递分类数据 return view('categories.index', compact('categories')); } /** - * 分类详情 + * 显示分类详情 * - * @param Request $request - * @param Category $category - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @param Request $request 请求对象 + * @param Category $category 分类模型实例 + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回分类详情视图 */ public function show(Request $request, Category $category) { + // 获取排序字段,默认为 'created_at' $orderBy = $request->input('orderBy', 'created_at'); - $categoryProducts = $category->products()->withCount('users')->orderBy($orderBy, 'desc')->paginate(10); + // 获取该分类下的产品,并按指定字段排序,分页显示,每页 10 条 + $categoryProducts = $category->products() + ->withCount('users') // 计算每个产品的用户数量 + ->orderBy($orderBy, 'desc') + ->paginate(10); + // 返回分类详情视图,并传递分类及其产品数据 return view('categories.show', compact('category', 'categoryProducts')); } } diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php index 03e02a2..c76d58f 100644 --- a/app/Http/Controllers/Controller.php +++ b/app/Http/Controllers/Controller.php @@ -9,5 +9,8 @@ use Illuminate\Foundation\Auth\Access\AuthorizesRequests; class Controller extends BaseController { + // 使用 Laravel 的授权请求、任务调度和请求验证功能 use AuthorizesRequests, DispatchesJobs, ValidatesRequests; + + // 此类作为所有控制器的基类,提供通用功能 } diff --git a/app/Http/Controllers/CouponController.php b/app/Http/Controllers/CouponController.php index ec87126..53a1f3f 100644 --- a/app/Http/Controllers/CouponController.php +++ b/app/Http/Controllers/CouponController.php @@ -12,66 +12,73 @@ use Illuminate\Support\Facades\DB; class CouponController extends Controller { + /** + * 处理用户领取优惠券的请求 + * + * @param Request $request 请求对象 + * @return \Illuminate\Http\JsonResponse 返回 JSON 响应 + */ public function store(Request $request) { + // 获取请求中的优惠券模板 ID $templateId = $request->input('template_id'); /** * @var $user User */ + // 获取当前登录用户 $user = auth()->user(); + // 如果用户未登录,返回未授权响应 if (is_null($user)) { - return responseJsonAsUnAuthorized('请先登录再领取优惠券'); } + // 查找优惠券模板 $template = CouponTemplate::query()->find($templateId); + // 如果模板不存在,返回无效优惠券响应 if (is_null($template)) { - return responseJsonAsBadRequest('无效的优惠券'); } // 判断优惠券是否过期 $today = Carbon::today(); $endDate = Carbon::make($template->end_date); + // 如果当前日期大于优惠券结束日期,返回过期响应 if ($today->gt($endDate)) { - return responseJsonAsBadRequest('优惠券已过期'); } + // 检查用户积分是否足够 if ($user->score_now < $template->score) { - return responseJsonAsBadRequest("积分不足{$template->score},请先去获取积分"); } - // 这里我会只让每个用户只能领取一张优惠券 + // 确保每个用户只能领取一张优惠券 if ($user->coupons()->where('template_id', $templateId)->exists()) { - return responseJsonAsBadRequest('你已经领取过优惠券了'); } + // 开始数据库事务 DB::beginTransaction(); try { - // 用户减少积分 if ($template->score > 0) { - $user->score_now -= $template->score; $user->save(); + // 生成积分日志 $log = new ScoreLog(); $log->user_id = $user->getKey(); $log->description = "领取优惠券"; - $log->score = -1 * $template->score; + $log->score = -1 * $template->score; // 记录减少的积分 $log->save(); } - // 开始领取优惠券 + // 创建用户优惠券记录 $coupon = new UserHasCoupon(); $coupon->template_id = $template->getKey(); $coupon->user_id = $user->getKey(); - $coupon->title = $template->title; $coupon->amount = $template->amount; $coupon->full_amount = $template->full_amount; @@ -80,13 +87,15 @@ class CouponController extends Controller $coupon->save(); } catch (\Exception $e) { - + // 如果发生异常,回滚事务 DB::rollBack(); return responseJsonAsServerError('服务器异常,请稍后再试'); } + // 提交事务 DB::commit(); + // 返回成功响应 return responseJson(200, '领取成功'); } } diff --git a/app/Http/Controllers/CouponTemplateController.php b/app/Http/Controllers/CouponTemplateController.php index 089b599..ffb8012 100644 --- a/app/Http/Controllers/CouponTemplateController.php +++ b/app/Http/Controllers/CouponTemplateController.php @@ -8,21 +8,26 @@ use Illuminate\Http\Request; class CouponTemplateController extends Controller { + /** + * 显示可用的优惠券模板 + * + * @return \Illuminate\View\View 返回包含优惠券模板的视图 + */ public function index() { + // 获取今天的日期,格式为 YYYY-MM-DD $today = Carbon::today()->toDateString(); - // 只查询未过期的 - // 标记已经领取过的 + // 查询未过期的优惠券模板,并标记用户已领取的优惠券 $templates = CouponTemplate::query() - ->withCount(['coupons' => function ($b) { - - $b->where('user_id', auth()->id()); + ->withCount(['coupons' => function ($query) { + // 统计当前用户已领取的优惠券数量 + $query->where('user_id', auth()->id()); }]) - ->where('end_date', '>=', $today) - ->get(); - + ->where('end_date', '>=', $today) // 只选择未过期的优惠券模板 + ->get(); // 执行查询并获取结果 + // 返回包含优惠券模板的视图 return view('coupons.templates', compact('templates')); } } diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php index bf49e03..30fd2ae 100644 --- a/app/Http/Controllers/HomeController.php +++ b/app/Http/Controllers/HomeController.php @@ -10,22 +10,24 @@ use App\Utils\HomeCacheDataUtil; class HomeController extends Controller { /** - * 首页显示的数据 + * 显示首页的数据 * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回首页视图 */ public function index() { - // 取出后台排序好的九个分类,并且关联出商品的总数 - // 如没有 key,存入缓存中,防止用户未配置好任务调度确访问首页 - // 数据将不会从首页更新,每分钟任务调度更新,请务必配置好 + // 设置缓存过期时间,随机增加 10 到 30 秒 $ttl = 120 + mt_rand(10, 30); + + // 获取后台排序好的九个分类,并关联商品总数 + // 如果没有缓存的 key,存入缓存中,防止用户未配置好任务调度时访问首页 + // 数据将不会从首页更新,每分钟任务调度更新,请务必配置好 $categories = HomeCacheDataUtil::categories($ttl); $hotProducts = HomeCacheDataUtil::hotProducts($ttl); $latestProducts = HomeCacheDataUtil::latestProducts($ttl); $users = HomeCacheDataUtil::users($ttl); - // 秒杀数据 + // 获取秒杀数据 $secKills = HomeCacheDataUtil::getSeckillData(); /** @@ -33,35 +35,45 @@ class HomeController extends Controller * * @var $loginUser User */ + // 如果用户已登录,加载其订阅信息 if ($loginUser = auth()->user()) { - $loginUser->load('subscribe'); } - // 查询优惠券 + // 查询优惠券模板 $couponTemplates = HomeCacheDataUtil::couponTemplates(); + // 检查秒杀功能是否开启 $setting = new SettingKeyEnum(SettingKeyEnum::IS_OPEN_SECKILL); - $isOpenSeckill = setting($setting) == 1; + $isOpenSeckill = setting($setting) == 1; // 1 表示开启 + // 返回首页视图,并传递所需的数据 return view( 'homes.index', compact('categories', 'hotProducts', 'latestProducts', 'users', 'secKills', 'loginUser', 'isOpenSeckill', 'couponTemplates') ); } - + /** + * 取消订阅功能 + * + * @param string $email 加密的邮箱地址 + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回取消订阅的结果视图 + */ public function unSubscribe($email) { - try { + // 解密邮箱地址 $email = decrypt($email); } catch (\Exception $e) { - + // 如果解密失败,返回错误提示视图 return view('hint.error', ['status' => '未知的账号']); } + // 更新订阅状态为未订阅 Subscribe::query()->where('email', $email)->update(['is_subscribe' => 0]); + + // 返回成功提示视图 return view('hint.success', ['status' => '已取消订阅']); } } diff --git a/app/Http/Controllers/PaymentNotificationController.php b/app/Http/Controllers/PaymentNotificationController.php index 137e498..d8aefcd 100644 --- a/app/Http/Controllers/PaymentNotificationController.php +++ b/app/Http/Controllers/PaymentNotificationController.php @@ -16,80 +16,80 @@ class PaymentNotificationController extends Controller { protected $config; - public function __construct() { + // 从配置文件中加载支付宝支付配置 $this->config = config('pay.ali'); } - /** - * 后台通知的接口 + * 处理支付宝后台通知的接口 * * @param Request $request - * @return \Symfony\Component\HttpFoundation\Response + * @return \Symfony\Component\HttpFoundation\Response 返回支付宝的成功响应 */ public function payNotify(Request $request) { $alipay = Pay::alipay($this->config); - // TODO , 加一个轮询接口配合后台通知修改订单状态 - // 后台异步通知接口有可能会因为网络问题接收不到 - // 使用轮询插接订单状态,如果支付了停止轮询 - try{ - $data = $alipay->verify(); // 是的,验签就这么简单! + // TODO: 加入轮询接口以配合后台通知修改订单状态 + // 后台异步通知接口可能因网络问题而未能接收 + // 使用轮询检查订单状态,如果支付成功则停止轮询 + try { + $data = $alipay->verify(); // 验签操作 // 验证 app_id - // 可:判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额); + // 可判断 total_amount 是否为该订单的实际金额 if ($data->get('app_id') == $this->config['app_id']) { // 支付成功 if ($data->get('trade_status') == 'TRADE_SUCCESS') { - // 更新订单 + // 更新订单信息 $order = Order::query()->where('no', $data->get('out_trade_no'))->firstOrFail(); - $order->paid_at = $data->get('notify_time'); - $order->pay_no = $data->get('trade_no'); - $order->pay_amount = $data->get('receipt_amount'); - $order->status = OrderStatusEnum::PAID; - $order->pay_type = OrderPayTypeEnum::ALI; - $order->save(); + $order->paid_at = $data->get('notify_time'); // 支付时间 + $order->pay_no = $data->get('trade_no'); // 支付交易号 + $order->pay_amount = $data->get('receipt_amount'); // 实际支付金额 + $order->status = OrderStatusEnum::PAID; // 更新订单状态为已支付 + $order->pay_type = OrderPayTypeEnum::ALI; // 支付类型 + $order->save(); // 保存订单信息 } } + // 记录支付宝通知日志 Log::debug('Alipay notify', $data->all()); } catch (\Exception $e) { - + // 记录异常日志 Log::debug('Alipay notify', $e->getMessage()); } + // 返回支付宝的成功响应 return $alipay->success(); } - /** - * 前台跳转的接口 + * 处理前台跳转的接口 * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回支付结果视图 */ public function payReturn() { + // 获取最新的 9 个产品 $latestProducts = Product::query()->latest()->take(9)->get(); $order = null; try { - + // 验证支付数据 $data = Pay::alipay($this->config)->verify(); + // 根据订单号查询订单 $order = Order::query()->where('no', $data->get('out_trade_no'))->firstOrFail(); - } catch (\Exception $e) { - + // 处理异常(可以记录日志或返回错误视图) } + // 返回支付结果视图,并传递订单和最新产品数据 return view('user.payments.result', compact('order', 'latestProducts')); } - - } diff --git a/app/Http/Controllers/ProductController.php b/app/Http/Controllers/ProductController.php index 1a5f867..97e85de 100644 --- a/app/Http/Controllers/ProductController.php +++ b/app/Http/Controllers/ProductController.php @@ -16,98 +16,99 @@ use Illuminate\Support\Facades\Cache; class ProductController extends Controller { - /** - * 商品列表 + * 显示商品列表 * - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回商品列表视图 */ public function index() { - // 随机查出一些商品展示 + // 随机查出一些商品展示,取前 9 个商品 $products = Product::query()->inRandomOrder()->take(9)->get(['uuid', 'name'])->split(3); + // 获取所有商品的拼音 $pinyins = ProductPinYin::query()->orderBy('pinyin')->pluck('pinyin'); + // 返回商品列表视图,并传递商品和拼音数据 return view('products.index', compact('products', 'pinyins')); } - /** - * ajax 通过商品首字母查询商品 - * @param $pinyin - * @return mixed + * 通过商品首字母查询商品(AJAX请求) + * + * @param string $pinyin 商品首字母 + * @return mixed 返回符合条件的商品集合 */ public function getProductsByPinyin($pinyin) { + // 查询首字母为指定字母的商品,并返回 $products = Product::query()->where('first_pinyin', $pinyin)->get(['id', 'name'])->split(3); return $products; } - /** - * 商品搜索 + * 商品搜索功能 * - * @param Request $request - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @param Request $request 请求对象 + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回搜索结果视图 */ public function search(Request $request) { - $keyword = $request->input('keyword', ''); - $page = abs((int)$request->get('page', 1)); - $limit = (int)$request->get('limit', 20); - $offset = (int) ($page - 1) * $limit; - - // 全文索引 + $keyword = $request->input('keyword', ''); // 获取搜索关键词 + $page = abs((int)$request->get('page', 1)); // 获取当前页码 + $limit = (int)$request->get('limit', 20); // 获取每页显示的商品数量 + $offset = (int) ($page - 1) * $limit; // 计算偏移量 + + // 尝试使用全文索引搜索商品 try { - $parameters = [ 'multi_match' => [ 'query' => $keyword, 'fields' => ['title', 'body'], ] ]; - + + // 获取搜索结果数量 $count = Product::searchCount($parameters); - $searchCount = $count['count'] ?? 0; - $searchResult = Product::search($parameters, $limit, $offset); - $filterIds = Collection::make($searchResult['hits']['hits'] ?? [])->pluck('_source.id'); - $models = Product::query()->findMany($filterIds); - + $searchCount = $count['count'] ?? 0; // 搜索结果总数 + $searchResult = Product::search($parameters, $limit, $offset); // 获取搜索结果 + $filterIds = Collection::make($searchResult['hits']['hits'] ?? [])->pluck('_source.id'); // 提取商品ID + $models = Product::query()->findMany($filterIds); // 根据ID查询商品 + + // 创建分页对象 $products = new LengthAwarePaginator($models, $searchCount, $limit, $page); - + } catch (\Exception $e) { - + // 如果全文索引搜索失败,使用模糊搜索 $products = Product::query()->withCount('users')->where('name', 'like', "%{$keyword}%")->paginate($limit); } + // 返回搜索结果视图 return view('products.search', compact('products')); } /** - * 单个商品显示 + * 显示单个商品的详细信息 * - * @param $uuid - * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View + * @param string $uuid 商品的UUID + * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View 返回商品详情视图 */ public function show($uuid) { - /** - * @var $user User|null - */ + // 查询商品 $product = Product::query()->where('uuid', $uuid)->firstOrFail(); - - if (! $product->today_has_view) { + // 记录今日是否已查看 + if (!$product->today_has_view) { $product->today_has_view = true; $product->save(); } - // 直接使用缓存 + + // 增加商品浏览次数 $today = Carbon::today()->toDateString(); Cache::increment($product->getViewCountKey($today)); - - // 商品浏览次数 + 1 + // 当前登录用户 $user = auth()->user(); // 同类商品推荐 @@ -116,28 +117,30 @@ class ProductController extends Controller ->take(5) ->get(); - // 加载出详情,收藏的人数, 评论 + // 加载商品的详细信息、收藏用户和评论 $product->load([ 'detail', 'users', 'comments' => function ($query) { - $query->latest(); + $query->latest(); // 按最新评论排序 }, 'comments.user' ]); + // 检查当前用户是否已收藏该商品 $product->userIsLike = $product->users()->where('id', auth()->id())->exists(); - // 如果登录返回所有地址列表,如果没有,则返回一个空集合 + // 如果用户已登录,增加积分 if ($user) { - - // 浏览商品增加积分 (new ScoreLogServe)->visitedProductAddScore($user, $product); } + // 返回商品详情视图 return view('products.show', compact('product', 'recommendProducts')); } /** + * 获取当前认证用户的守卫 + * * @return \Illuminate\Contracts\Auth\StatefulGuard */ protected function guard() diff --git a/composer.json b/composer.json index cd99a20..16ea2b1 100644 --- a/composer.json +++ b/composer.json @@ -76,7 +76,12 @@ "repositories": { "packagist": { "type": "composer", - "url": "https://mirrors.aliyun.com/composer/" + "url": "https://mirrors.aliyun.com/composer/", + + + + + } } }