购物车悬浮

This commit is contained in:
liu
2026-08-27 18:13:43 +08:00
parent 52dc6efadf
commit f3e190f460
9 changed files with 330 additions and 6 deletions
@@ -7,6 +7,7 @@ use App\Http\Requests\Mini\MiniCartRequest;
use App\Models\CartModel;
use App\Models\CustomerLevelModel;
use App\Models\ProductModel;
use App\Services\CartService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
@@ -207,6 +208,15 @@ class CartController extends BaseMiniController
return $this->success([], '已删除');
}
/**
* 购物车悬浮球汇总(轻量接口):种数/总数量/总金额,供任意页面刷新右下角悬浮球
*/
#[GetRoute('/cart/summary', authorize: true)]
public function summary(Request $request): JsonResponse
{
return $this->success(app(CartService::class)->summary($this->currentStore($request)));
}
/**
* 清空购物车(仅当前用户)
*/
+5 -1
View File
@@ -5,19 +5,22 @@ namespace App\Http\Controllers\Mini;
use App\Models\HomeBannerModel;
use App\Models\HomeNavModel;
use App\Models\HomePromoModel;
use App\Services\CartService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Modules\AnnoRoute\Attribute\GetRoute;
use Modules\AnnoRoute\Attribute\RequestAttribute;
/**
* 小程序首页配置(轮播图 + 宫格导航 + 促销推荐卡片,仅返回启用项)
* 登录门店附加 cart 购物车悬浮球汇总(未登录返回零值结构)
*/
#[RequestAttribute('/mini', 'mini', authGuard: 'users')]
class HomeController extends BaseMiniController
{
/** 首页配置聚合:banners / navs / promos,按 sort 升序 */
#[GetRoute('/home', authorize: false)]
public function index(): JsonResponse
public function index(Request $request): JsonResponse
{
$banners = HomeBannerModel::query()
->where('status', HomeBannerModel::STATUS_NORMAL)
@@ -41,6 +44,7 @@ class HomeController extends BaseMiniController
'banners' => $banners,
'navs' => $navs,
'promos' => $promos,
'cart' => app(CartService::class)->summary($this->optionalStore($request)),
]);
}
}
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Mini;
use App\Exceptions\RepositoryException;
use App\Http\Requests\Mini\MiniOrderRequest;
use App\Models\BillModel;
use App\Models\CartModel;
use App\Models\CustomerLevelModel;
use App\Models\ProductModel;
@@ -37,6 +38,26 @@ class OrderController extends BaseMiniController
throw new RepositoryException('门店未设置客户等级,无法下单,请联系客服');
}
// 回款周期校验:存在逾期未回款账单(未支付即拦截,含审核中)时禁止下单
// 周期 0 天=立即结清:任何未回款账单(含当天)都拦截;周期 N≥1:账单日 + N 天 < 今天(超过回款周期)才拦截
$cycleDays = (int) $store->payment_cycle_days;
$overdueQuery = BillModel::query()
->where('store_id', $store->id)
->where('status', BillModel::STATUS_UNPAID);
if ($cycleDays > 0) {
$overdueQuery->whereDate('bill_date', '<', now()->subDays($cycleDays)->toDateString());
}
$overdue = $overdueQuery
->selectRaw('COUNT(*) as aggregate_count, COALESCE(SUM(total_amount), 0) as aggregate_amount')
->first();
if ((int) $overdue->aggregate_count > 0) {
$amountText = bcadd((string) $overdue->aggregate_amount, '0', 2);
throw new RepositoryException($cycleDays > 0
? '您有 ' . (int) $overdue->aggregate_count . ' 笔账单已超过回款周期未回款(合计 ¥' . $amountText . '),请先结清后再下单'
: '您有 ' . (int) $overdue->aggregate_count . ' 笔账单未回款(合计 ¥' . $amountText . '),回款周期为当日结清,请先结清后再下单'
);
}
$items = $request->validated('items');
$remark = (string) ($request->validated('remark') ?? '');
@@ -6,6 +6,7 @@ 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;
@@ -25,7 +26,8 @@ class ProductController extends BaseMiniController
}
/**
* 商品列表
* 商品列表(登录门店附 cart_id/cart_quantity 供列表直接加减购物车;
* data.cart 为购物车悬浮球汇总,未登录返回零值结构)
*/
#[GetRoute('/product/list', authorize: false)]
public function products(Request $request): JsonResponse
@@ -50,22 +52,30 @@ class ProductController extends BaseMiniController
->orderBy('id')
->paginate($pageSize);
// 当前门店的等级(售价 = 成本价 × (100 + 等级上浮比例) / 100
// 当前门店的等级(售价 = 成本价 × (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): array {
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;
}
);
return $this->success($paginator->toArray());
$data = $paginator->toArray();
$data['cart'] = $cartService->summary($store);
return $this->success($data);
}
/**
@@ -89,8 +99,12 @@ class ProductController extends BaseMiniController
$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);
}