Files
xin-procurement/app/Http/Controllers/Mini/ProductController.php
T
2026-09-04 22:10:28 +08:00

124 lines
4.7 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Http\Controllers\Mini;
use App\Exceptions\RepositoryException;
use App\Models\CustomerLevelModel;
use App\Models\ProductCategoryModel;
use App\Models\ProductModel;
use App\Services\CartService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\AnnoRoute\Attribute\GetRoute;
use Modules\AnnoRoute\Attribute\RequestAttribute;
/**
* 小程序商品
*/
#[RequestAttribute('/mini', 'mini', authGuard: 'users')]
class ProductController extends BaseMiniController
{
/** 分类树(全部启用分类,含暂无商品的分类) */
#[GetRoute('/product/categories', authorize: false)]
public function categories(): JsonResponse
{
return $this->success(ProductCategoryModel::getTreeData(['*'], true));
}
/**
* 商品列表(登录门店附 cart_id/cart_quantity 供列表直接加减购物车;
* data.cart 为购物车悬浮球汇总,未登录返回零值结构)
*/
#[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 . '%');
});
}
// 先按分类树展示顺序(与小程序分类栏一致;不在启用分类树中的商品排最后),再按商品排序
$categoryIds = ProductCategoryModel::getTreeOrderedIds(true);
if ($categoryIds !== []) {
$cases = [];
foreach ($categoryIds as $position => $categoryId) {
$cases[] = "WHEN {$categoryId} THEN {$position}";
}
$query->orderByRaw(
'CASE category_id ' . implode(' ', $cases) . ' ELSE ' . count($categoryIds) . ' END'
);
}
$pageSize = (int) $request->input('pageSize', 10);
$paginator = $query->orderBy('sort', 'desc')
->orderBy('id')
->paginate($pageSize);
// 当前门店的等级(售价 = 成本价 × (100 + 等级上浮比例) / 100)与购物车行
$store = $this->optionalStore($request);
$level = ($store !== null && $store->level_id > 0) ? $store->level : null;
$cartService = app(CartService::class);
$cartRows = $store !== null ? $cartService->cartRowMap($store->id) : [];
$paginator->getCollection()->transform(
static function (ProductModel $product) use ($level, $cartRows): array {
$row = $product->toArray();
// 实际价(按等级上浮比例换算;成本价不随序列化输出)
$row['price'] = $level !== null
? CustomerLevelModel::calcLevelPrice($product->cost_price, $level->percent)
: null;
// 购物车数量(列表直接加减用;不在购物车为 0/'0.00'
$row['cart_id'] = $cartRows[$product->id]['id'] ?? 0;
$row['cart_quantity'] = $cartRows[$product->id]['quantity'] ?? '0.00';
return $row;
}
);
$data = $paginator->toArray();
$data['cart'] = $cartService->summary($store);
return $this->success($data);
}
/**
* 商品详情(免登录浏览;登录门店按等级上浮比例显示换算价,未登录/未设等级 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;
$store = $this->optionalStore($request);
$level = ($store !== null && $store->level_id > 0) ? $store->level : null;
if ($level !== null) {
$price = CustomerLevelModel::calcLevelPrice($product->cost_price, $level->percent);
}
$cartRows = $store !== null ? app(CartService::class)->cartRowMap($store->id) : [];
$data = $product->toArray();
$data['price'] = $price;
$data['cart_id'] = $cartRows[$product->id]['id'] ?? 0;
$data['cart_quantity'] = $cartRows[$product->id]['quantity'] ?? '0.00';
return $this->success($data);
}
}