campus-errand/server/Endpoints/ShopEndpoints.cs
2026-04-01 12:50:17 +08:00

389 lines
15 KiB
C#

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<PackingFeeType>(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<PackingFeeType>(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");
}
}