using CampusErrand.Data; using CampusErrand.Models; using CampusErrand.Models.Dtos; using CampusErrand.Helpers; using Microsoft.EntityFrameworkCore; namespace CampusErrand.Endpoints; public static class ShopEndpoints { public static void MapShopEndpoints(this WebApplication app) { // 前端获取门店列表(仅启用门店,含菜品种类数量) app.MapGet("/api/shops", async (AppDbContext db) => { var shops = await db.Shops .Where(s => s.IsEnabled) .Select(s => new ShopListResponse { Id = s.Id, Name = s.Name, Photo = s.Photo, Location = s.Location, DishCount = s.Dishes.Count(d => d.IsEnabled) }) .ToListAsync(); return Results.Ok(shops); }); // 前端获取门店详情(含 Banner 和菜品) app.MapGet("/api/shops/{id}", async (int id, AppDbContext db) => { var shop = await db.Shops .Include(s => s.ShopBanners) .Include(s => s.Dishes) .FirstOrDefaultAsync(s => s.Id == id); if (shop == null) { return Results.NotFound(new { code = 404, message = "门店不存在" }); } var response = new ShopDetailResponse { Id = shop.Id, Name = shop.Name, Photo = shop.Photo, Location = shop.Location, Notice = shop.Notice, PackingFeeType = shop.PackingFeeType.ToString(), PackingFeeAmount = shop.PackingFeeAmount, IsEnabled = shop.IsEnabled, Banners = shop.ShopBanners .OrderBy(b => b.SortOrder) .Select(b => new ShopBannerResponse { Id = b.Id, ImageUrl = b.ImageUrl, SortOrder = b.SortOrder }).ToList(), Dishes = shop.Dishes .Where(d => d.IsEnabled) .Select(d => new DishResponse { Id = d.Id, ShopId = d.ShopId, Name = d.Name, Photo = d.Photo, Price = d.Price, IsEnabled = d.IsEnabled }).ToList() }; return Results.Ok(response); }); // 管理端获取门店列表(全部) app.MapGet("/api/admin/shops", async (AppDbContext db) => { var shops = await db.Shops .Select(s => new AdminShopResponse { Id = s.Id, Name = s.Name, Photo = s.Photo, Location = s.Location, Notice = s.Notice, PackingFeeType = s.PackingFeeType.ToString(), PackingFeeAmount = s.PackingFeeAmount, IsEnabled = s.IsEnabled, DishCount = s.Dishes.Count }) .ToListAsync(); return Results.Ok(shops); }).RequireAuthorization("AdminOnly"); // 管理端创建门店 app.MapPost("/api/admin/shops", async (ShopRequest request, AppDbContext db) => { var errors = BusinessHelpers.ValidateShopRequest(request); if (errors.Count > 0) { return Results.BadRequest(new { code = 400, message = "校验失败", errors }); } if (!Enum.TryParse(request.PackingFeeType, true, out var feeType) || !Enum.IsDefined(feeType)) { return Results.BadRequest(new { code = 400, message = "校验失败", errors = new[] { new { field = "packingFeeType", message = "打包费类型不合法" } } }); } var shop = new Shop { Name = request.Name, Photo = request.Photo, Location = request.Location, Notice = request.Notice, PackingFeeType = feeType, PackingFeeAmount = request.PackingFeeAmount, IsEnabled = request.IsEnabled }; db.Shops.Add(shop); await db.SaveChangesAsync(); return Results.Created($"/api/admin/shops/{shop.Id}", new AdminShopResponse { Id = shop.Id, Name = shop.Name, Photo = shop.Photo, Location = shop.Location, Notice = shop.Notice, PackingFeeType = shop.PackingFeeType.ToString(), PackingFeeAmount = shop.PackingFeeAmount, IsEnabled = shop.IsEnabled, DishCount = 0 }); }).RequireAuthorization("AdminOnly"); // 管理端更新门店 app.MapPut("/api/admin/shops/{id}", async (int id, ShopRequest request, AppDbContext db) => { var shop = await db.Shops.FindAsync(id); if (shop == null) { return Results.NotFound(new { code = 404, message = "门店不存在" }); } var errors = BusinessHelpers.ValidateShopRequest(request); if (errors.Count > 0) { return Results.BadRequest(new { code = 400, message = "校验失败", errors }); } if (!Enum.TryParse(request.PackingFeeType, true, out var feeType) || !Enum.IsDefined(feeType)) { return Results.BadRequest(new { code = 400, message = "校验失败", errors = new[] { new { field = "packingFeeType", message = "打包费类型不合法" } } }); } shop.Name = request.Name; shop.Photo = request.Photo; shop.Location = request.Location; shop.Notice = request.Notice; shop.PackingFeeType = feeType; shop.PackingFeeAmount = request.PackingFeeAmount; shop.IsEnabled = request.IsEnabled; await db.SaveChangesAsync(); return Results.Ok(new AdminShopResponse { Id = shop.Id, Name = shop.Name, Photo = shop.Photo, Location = shop.Location, Notice = shop.Notice, PackingFeeType = shop.PackingFeeType.ToString(), PackingFeeAmount = shop.PackingFeeAmount, IsEnabled = shop.IsEnabled, DishCount = await db.Dishes.CountAsync(d => d.ShopId == shop.Id) }); }).RequireAuthorization("AdminOnly"); // 管理端删除门店 app.MapDelete("/api/admin/shops/{id}", async (int id, AppDbContext db) => { var shop = await db.Shops .Include(s => s.Dishes) .Include(s => s.ShopBanners) .FirstOrDefaultAsync(s => s.Id == id); if (shop == null) { return Results.NotFound(new { code = 404, message = "门店不存在" }); } try { // 先删除订单中引用该门店的菜品项 var dishIds = shop.Dishes.Select(d => d.Id).ToList(); db.FoodOrderItems.RemoveRange(db.FoodOrderItems.Where(f => f.ShopId == id || dishIds.Contains(f.DishId))); await db.SaveChangesAsync(); // 再删除菜品和门店 Banner db.Dishes.RemoveRange(shop.Dishes); db.ShopBanners.RemoveRange(shop.ShopBanners); await db.SaveChangesAsync(); // 最后删除门店 db.Shops.Remove(shop); await db.SaveChangesAsync(); return Results.NoContent(); } catch (Exception ex) { Console.WriteLine($"[管理端] 删除门店失败: {ex.InnerException?.Message ?? ex.Message}"); return Results.BadRequest(new { code = 400, message = $"删除失败: {ex.InnerException?.Message ?? ex.Message}" }); } }).RequireAuthorization("AdminOnly"); // 获取门店 Banner 列表 app.MapGet("/api/admin/shops/{shopId}/banners", async (int shopId, AppDbContext db) => { var shop = await db.Shops.FindAsync(shopId); if (shop == null) return Results.NotFound(new { code = 404, message = "门店不存在" }); var banners = await db.ShopBanners .Where(b => b.ShopId == shopId) .OrderBy(b => b.SortOrder) .Select(b => new ShopBannerResponse { Id = b.Id, ImageUrl = b.ImageUrl, SortOrder = b.SortOrder }) .ToListAsync(); return Results.Ok(banners); }).RequireAuthorization("AdminOnly"); // 创建门店 Banner app.MapPost("/api/admin/shops/{shopId}/banners", async (int shopId, ShopBannerRequest request, AppDbContext db) => { var shop = await db.Shops.FindAsync(shopId); if (shop == null) return Results.NotFound(new { code = 404, message = "门店不存在" }); if (string.IsNullOrWhiteSpace(request.ImageUrl)) return Results.BadRequest(new { code = 400, message = "校验失败", errors = new[] { new { field = "imageUrl", message = "图片地址不能为空" } } }); var banner = new ShopBanner { ShopId = shopId, ImageUrl = request.ImageUrl, SortOrder = request.SortOrder }; db.ShopBanners.Add(banner); await db.SaveChangesAsync(); return Results.Created($"/api/admin/shops/{shopId}/banners/{banner.Id}", new ShopBannerResponse { Id = banner.Id, ImageUrl = banner.ImageUrl, SortOrder = banner.SortOrder }); }).RequireAuthorization("AdminOnly"); // 删除门店 Banner app.MapDelete("/api/admin/shops/{shopId}/banners/{bannerId}", async (int shopId, int bannerId, AppDbContext db) => { var banner = await db.ShopBanners.FirstOrDefaultAsync(b => b.Id == bannerId && b.ShopId == shopId); if (banner == null) return Results.NotFound(new { code = 404, message = "门店 Banner 不存在" }); db.ShopBanners.Remove(banner); await db.SaveChangesAsync(); return Results.NoContent(); }).RequireAuthorization("AdminOnly"); // 获取门店菜品列表 app.MapGet("/api/admin/shops/{shopId}/dishes", async (int shopId, AppDbContext db) => { var shop = await db.Shops.FindAsync(shopId); if (shop == null) { return Results.NotFound(new { code = 404, message = "门店不存在" }); } var dishes = await db.Dishes .Where(d => d.ShopId == shopId) .Select(d => new DishResponse { Id = d.Id, ShopId = d.ShopId, Name = d.Name, Photo = d.Photo, Price = d.Price, IsEnabled = d.IsEnabled }) .ToListAsync(); return Results.Ok(dishes); }).RequireAuthorization("AdminOnly"); // 创建菜品 app.MapPost("/api/admin/shops/{shopId}/dishes", async (int shopId, DishRequest request, AppDbContext db) => { var shop = await db.Shops.FindAsync(shopId); if (shop == null) { return Results.NotFound(new { code = 404, message = "门店不存在" }); } var errors = BusinessHelpers.ValidateDishRequest(request); if (errors.Count > 0) { return Results.BadRequest(new { code = 400, message = "校验失败", errors }); } var dish = new Dish { ShopId = shopId, Name = request.Name, Photo = request.Photo, Price = request.Price, IsEnabled = request.IsEnabled }; db.Dishes.Add(dish); await db.SaveChangesAsync(); return Results.Created($"/api/admin/shops/{shopId}/dishes/{dish.Id}", new DishResponse { Id = dish.Id, ShopId = dish.ShopId, Name = dish.Name, Photo = dish.Photo, Price = dish.Price, IsEnabled = dish.IsEnabled }); }).RequireAuthorization("AdminOnly"); // 更新菜品 app.MapPut("/api/admin/shops/{shopId}/dishes/{dishId}", async (int shopId, int dishId, DishRequest request, AppDbContext db) => { var dish = await db.Dishes.FirstOrDefaultAsync(d => d.Id == dishId && d.ShopId == shopId); if (dish == null) { return Results.NotFound(new { code = 404, message = "菜品不存在" }); } var errors = BusinessHelpers.ValidateDishRequest(request); if (errors.Count > 0) { return Results.BadRequest(new { code = 400, message = "校验失败", errors }); } dish.Name = request.Name; dish.Photo = request.Photo; dish.Price = request.Price; dish.IsEnabled = request.IsEnabled; await db.SaveChangesAsync(); return Results.Ok(new DishResponse { Id = dish.Id, ShopId = dish.ShopId, Name = dish.Name, Photo = dish.Photo, Price = dish.Price, IsEnabled = dish.IsEnabled }); }).RequireAuthorization("AdminOnly"); // 删除菜品 app.MapDelete("/api/admin/shops/{shopId}/dishes/{dishId}", async (int shopId, int dishId, AppDbContext db) => { var dish = await db.Dishes.FirstOrDefaultAsync(d => d.Id == dishId && d.ShopId == shopId); if (dish == null) { return Results.NotFound(new { code = 404, message = "菜品不存在" }); } try { // 先删除订单中引用该菜品的记录 db.FoodOrderItems.RemoveRange(db.FoodOrderItems.Where(f => f.DishId == dishId)); await db.SaveChangesAsync(); db.Dishes.Remove(dish); await db.SaveChangesAsync(); return Results.NoContent(); } catch (Exception ex) { Console.WriteLine($"[管理端] 删除菜品失败: {ex.InnerException?.Message ?? ex.Message}"); return Results.BadRequest(new { code = 400, message = $"删除失败: {ex.InnerException?.Message ?? ex.Message}" }); } }).RequireAuthorization("AdminOnly"); } }