100 lines
3.4 KiB
PHP
100 lines
3.4 KiB
PHP
<?php
|
||
|
||
namespace App\Http\Controllers\Mini;
|
||
|
||
use App\Exceptions\RepositoryException;
|
||
use App\Models\ProductCategoryModel;
|
||
use App\Models\ProductModel;
|
||
use App\Models\ProductPriceModel;
|
||
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: true)]
|
||
public function categories(): JsonResponse
|
||
{
|
||
$activeCategoryIds = ProductModel::query()
|
||
->where('status', ProductModel::STATUS_ON)
|
||
->distinct()
|
||
->pluck('category_id')
|
||
->map(static fn ($id) => (int) $id)
|
||
->filter(static fn (int $id) => $id > 0);
|
||
|
||
$categories = ProductCategoryModel::query()
|
||
->where('status', ProductCategoryModel::STATUS_NORMAL)
|
||
->get()
|
||
->keyBy('id');
|
||
|
||
// 保留有上架商品的分类 + 其全部祖先
|
||
$keep = [];
|
||
foreach ($activeCategoryIds as $categoryId) {
|
||
$cursor = $categoryId;
|
||
$guard = 0;
|
||
while ($cursor > 0 && $guard++ < 20 && $categories->has($cursor)) {
|
||
$keep[$cursor] = true;
|
||
$cursor = (int) $categories[$cursor]->parent_id;
|
||
}
|
||
}
|
||
|
||
$filtered = array_values(array_filter(
|
||
$categories->toArray(),
|
||
static fn (array $item) => isset($keep[$item['id']])
|
||
));
|
||
|
||
return $this->success(ProductCategoryModel::buildTree($filtered));
|
||
}
|
||
|
||
/**
|
||
* 商品列表:价格取当前门店客户等级价(未绑等级的门店报错);
|
||
* ?category_id=&keyword=&page=&pageSize=
|
||
*/
|
||
#[GetRoute('/product/list', authorize: true)]
|
||
public function products(Request $request): JsonResponse
|
||
{
|
||
$user = $this->currentUser($request);
|
||
$store = $this->ensureStoreBound($user);
|
||
if ($store->level_id <= 0) {
|
||
throw new RepositoryException('门店未设置客户等级,无法展示价格,请联系客服');
|
||
}
|
||
|
||
$query = ProductModel::query()
|
||
->where('status', ProductModel::STATUS_ON)
|
||
->with('category:id,name')
|
||
->with(['prices' => static fn ($q) => $q->where('level_id', $store->level_id)]);
|
||
|
||
$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 . '%')
|
||
->orWhere('spec', 'like', '%' . $keyword . '%');
|
||
});
|
||
}
|
||
|
||
$pageSize = (int) $request->input('pageSize', 10);
|
||
$data = $query->orderBy('sort')
|
||
->orderBy('id')
|
||
->paginate($pageSize)
|
||
->toArray();
|
||
|
||
// 扁平化价格:prices[0].price → price(未设等级价为 null)
|
||
foreach ($data['data'] as &$row) {
|
||
$row['price'] = $row['prices'][0]['price'] ?? null;
|
||
unset($row['prices']);
|
||
}
|
||
|
||
return $this->success($data);
|
||
}
|
||
}
|