success(ProductCategoryModel::getTreeData(['*'], true)); } /** * 商品列表 */ #[GetRoute('/product/list', authorize: false)] public function products(Request $request): JsonResponse { $query = ProductModel::query() ->where('status', ProductModel::STATUS_ON) ->with('category:id,name'); $categoryId = (int) $request->input('category_id', 0); if ($categoryId > 0) { $query->where('category_id', $categoryId); } $keyword = trim((string) $request->input('keyword', '')); if ($keyword !== '') { $query->where(static function ($q) use ($keyword) { $q->where('name', 'like', '%' . $keyword . '%'); }); } $pageSize = (int) $request->input('pageSize', 10); $paginator = $query->orderBy('sort') ->orderBy('id') ->paginate($pageSize); // 当前门店的等级价格(一次性取出,避免逐行查询) $user = $this->optionalUser($request); $store = $user !== null ? $this->boundStore($user) : null; $priceRows = collect(); if ($store !== null && $store->level_id > 0) { $priceRows = ProductPriceModel::query() ->where('level_id', $store->level_id) ->whereIn('product_id', $paginator->getCollection()->pluck('id')) ->get(['product_id', 'price', 'price_type', 'percent']) ->keyBy('product_id'); } $paginator->getCollection()->transform( static function (ProductModel $product) use ($priceRows): array { $row = $product->toArray(); // 实际价(百分比计价行按成本价上浮换算;成本价不随序列化输出) $priceRow = $priceRows->get($product->id); $row['price'] = $priceRow !== null ? ProductPriceModel::calcActualPrice( (int) $priceRow->price_type, (string) $priceRow->price, (string) $priceRow->percent, (string) $product->cost_price, ) : null; return $row; } ); return $this->success($paginator->toArray()); } /** * 商品详情(免登录浏览;登录门店按等级显示换算价,未登录/未绑店/未设等级 price=null) */ #[GetRoute('/product/{id}', authorize: false, where: ['id' => '[0-9]+'])] public function detail(int $id, Request $request): JsonResponse { $product = ProductModel::query() ->where('status', ProductModel::STATUS_ON) ->with('category:id,name') ->find($id); if ($product === null) { throw new RepositoryException('商品不存在或已下架'); } $price = null; $user = $this->optionalUser($request); $store = $user !== null ? $this->boundStore($user) : null; if ($store !== null && $store->level_id > 0) { $priceRow = ProductPriceModel::query() ->forProductLevel($product->id, $store->level_id) ->first(['price', 'price_type', 'percent']); if ($priceRow !== null) { $price = ProductPriceModel::calcActualPrice( (int) $priceRow->price_type, (string) $priceRow->price, (string) $priceRow->percent, (string) $product->cost_price, ); } } $data = $product->toArray(); $data['price'] = $price; return $this->success($data); } }