|
|
@@ -0,0 +1,283 @@
|
|
|
+package shop.alien.store.controller;
|
|
|
+
|
|
|
+import com.baomidou.mybatisplus.core.metadata.IPage;
|
|
|
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
|
|
+import io.swagger.annotations.*;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.springframework.http.MediaType;
|
|
|
+import org.springframework.web.bind.annotation.*;
|
|
|
+import org.springframework.web.multipart.MultipartFile;
|
|
|
+import shop.alien.entity.result.R;
|
|
|
+import shop.alien.entity.store.StoreTable;
|
|
|
+import shop.alien.entity.store.dto.CartDTO;
|
|
|
+import shop.alien.entity.store.vo.*;
|
|
|
+import shop.alien.store.feign.DiningServiceFeign;
|
|
|
+
|
|
|
+import javax.servlet.http.HttpServletRequest;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 点餐服务 Controller
|
|
|
+ * 供前端调用 alien-dining 模块的接口
|
|
|
+ *
|
|
|
+ * @author ssk
|
|
|
+ * @version 1.0
|
|
|
+ * @date 2025/01/XX
|
|
|
+ */
|
|
|
+@Slf4j
|
|
|
+@Api(tags = {"点餐服务接口"})
|
|
|
+@ApiSort(20)
|
|
|
+@CrossOrigin
|
|
|
+@RestController
|
|
|
+@RequestMapping("/dining")
|
|
|
+@RequiredArgsConstructor
|
|
|
+public class DiningServiceController {
|
|
|
+
|
|
|
+ private final DiningServiceFeign diningServiceFeign;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 从请求头获取 Authorization token
|
|
|
+ */
|
|
|
+ private String getAuthorization(HttpServletRequest request) {
|
|
|
+ String authorization = request.getHeader("Authorization");
|
|
|
+ if (authorization == null || authorization.isEmpty()) {
|
|
|
+ authorization = request.getHeader("authorization");
|
|
|
+ }
|
|
|
+ return authorization;
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 点餐相关接口 ====================
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取点餐页面信息", notes = "获取店铺名称、桌号、就餐人数等信息")
|
|
|
+ @ApiOperationSupport(order = 1)
|
|
|
+ @GetMapping("/page-info")
|
|
|
+ public R<DiningPageInfoVO> getDiningPageInfo(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
|
|
|
+ @ApiParam(value = "就餐人数", required = true) @RequestParam Integer dinerCount) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取点餐页面信息: tableId={}, dinerCount={}", tableId, dinerCount);
|
|
|
+ return diningServiceFeign.getDiningPageInfo(authorization, tableId, dinerCount);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取点餐页面信息失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取点餐页面信息失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "搜索菜品", notes = "根据关键词搜索菜品")
|
|
|
+ @ApiOperationSupport(order = 2)
|
|
|
+ @GetMapping("/search")
|
|
|
+ public R<List<CuisineListVO>> searchCuisines(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
|
|
|
+ @ApiParam(value = "搜索关键词", required = true) @RequestParam String keyword,
|
|
|
+ @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("搜索菜品: storeId={}, keyword={}, tableId={}", storeId, keyword, tableId);
|
|
|
+ return diningServiceFeign.searchCuisines(authorization, storeId, keyword, tableId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("搜索菜品失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("搜索菜品失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "根据分类获取菜品列表", notes = "根据分类ID获取菜品列表,支持分页")
|
|
|
+ @ApiOperationSupport(order = 3)
|
|
|
+ @GetMapping("/cuisines")
|
|
|
+ public R<List<CuisineListVO>> getCuisinesByCategory(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId,
|
|
|
+ @ApiParam(value = "分类ID(可为空,查询所有)") @RequestParam(required = false) Integer categoryId,
|
|
|
+ @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId,
|
|
|
+ @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer page,
|
|
|
+ @ApiParam(value = "每页数量", defaultValue = "12") @RequestParam(defaultValue = "12") Integer size) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("根据分类获取菜品列表: storeId={}, categoryId={}, tableId={}, page={}, size={}",
|
|
|
+ storeId, categoryId, tableId, page, size);
|
|
|
+ return diningServiceFeign.getCuisinesByCategory(authorization, storeId, categoryId, tableId, page, size);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("根据分类获取菜品列表失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("根据分类获取菜品列表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取菜品详情", notes = "获取菜品详细信息,包含图片列表、月售数量等")
|
|
|
+ @ApiOperationSupport(order = 4)
|
|
|
+ @GetMapping("/cuisine/{cuisineId}")
|
|
|
+ public R<CuisineDetailVO> getCuisineDetail(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "菜品ID", required = true) @PathVariable Integer cuisineId,
|
|
|
+ @ApiParam(value = "桌号ID", required = true) @RequestParam Integer tableId) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取菜品详情: cuisineId={}, tableId={}", cuisineId, tableId);
|
|
|
+ return diningServiceFeign.getCuisineDetail(authorization, cuisineId, tableId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取菜品详情失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取菜品详情失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取可领取的优惠券列表", notes = "获取用户可领取的优惠券")
|
|
|
+ @ApiOperationSupport(order = 5)
|
|
|
+ @GetMapping("/coupons/available")
|
|
|
+ public R<List<AvailableCouponVO>> getAvailableCoupons(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取可领取的优惠券列表: storeId={}", storeId);
|
|
|
+ return diningServiceFeign.getAvailableCoupons(authorization, storeId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取可领取的优惠券列表失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取可领取的优惠券列表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 订单相关接口 ====================
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取购物车", notes = "根据桌号ID获取购物车信息")
|
|
|
+ @ApiOperationSupport(order = 6)
|
|
|
+ @GetMapping("/order/cart/{tableId}")
|
|
|
+ public R<CartDTO> getCart(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "桌号ID", required = true) @PathVariable Integer tableId) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取购物车: tableId={}", tableId);
|
|
|
+ return diningServiceFeign.getCart(authorization, tableId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取购物车失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取购物车失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取订单详情", notes = "根据订单ID获取订单详细信息")
|
|
|
+ @ApiOperationSupport(order = 7)
|
|
|
+ @GetMapping("/order/{orderId}")
|
|
|
+ public R<OrderDetailWithChangeLogVO> getOrderDetail(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取订单详情: orderId={}", orderId);
|
|
|
+ return diningServiceFeign.getOrderDetail(authorization, orderId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取订单详情失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取订单详情失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取订单列表", notes = "分页获取订单列表,支持按状态筛选")
|
|
|
+ @ApiOperationSupport(order = 8)
|
|
|
+ @GetMapping("/order/list")
|
|
|
+ public R<IPage<StoreOrderPageVO>> getOrderList(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Integer page,
|
|
|
+ @ApiParam(value = "每页数量", defaultValue = "10") @RequestParam(defaultValue = "10") Integer size,
|
|
|
+ @ApiParam(value = "订单状态(可选)") @RequestParam(required = false) Integer status) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取订单列表: page={}, size={}, status={}", page, size, status);
|
|
|
+ return diningServiceFeign.getOrderList(authorization, page, size, status);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取订单列表失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取订单列表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "分页查询订单列表", notes = "分页查询订单列表,包含订单中的菜品数量、菜品名称、菜品图片。支持按订单编号或菜品名称搜索(限15字)")
|
|
|
+ @ApiOperationSupport(order = 8)
|
|
|
+ @GetMapping("/order/page")
|
|
|
+ public R<IPage<StoreOrderPageVO>> getOrderPage(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "页码", defaultValue = "1") @RequestParam(defaultValue = "1") Long current,
|
|
|
+ @ApiParam(value = "每页数量", defaultValue = "10") @RequestParam(defaultValue = "10") Long size,
|
|
|
+ @ApiParam(value = "门店ID") @RequestParam(required = false) Integer storeId,
|
|
|
+ @ApiParam(value = "桌号ID") @RequestParam(required = false) Integer tableId,
|
|
|
+ @ApiParam(value = "订单状态(0:待支付, 1:已支付, 2:已取消, 3:已完成)") @RequestParam(required = false) Integer orderStatus,
|
|
|
+ @ApiParam(value = "搜索关键词(订单编号或菜品名称,限15字)") @RequestParam(required = false) String keyword) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("分页查询订单列表: current={}, size={}, storeId={}, tableId={}, orderStatus={}, keyword={}",
|
|
|
+ current, size, storeId, tableId, orderStatus, keyword);
|
|
|
+ R<Page<StoreOrderPageVO>> result = diningServiceFeign.getOrderPage(authorization, current, size, storeId, tableId, orderStatus, keyword);
|
|
|
+ // 将 Page 转换为 IPage 返回(Page 实现了 IPage 接口,可以直接返回)
|
|
|
+ return R.data(result.getData());
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("分页查询订单列表失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("分页查询订单列表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @ApiOperation(value = "查询订单变更记录", notes = "根据订单ID查询订单的所有变更记录(按批次分组),用于展示每次下单/加餐都加了什么商品")
|
|
|
+ @ApiOperationSupport(order = 9)
|
|
|
+ @GetMapping("/order/change-log/{orderId}")
|
|
|
+ public R<List<OrderChangeLogBatchVO>> getOrderChangeLogs(
|
|
|
+ HttpServletRequest request,
|
|
|
+ @ApiParam(value = "订单ID", required = true) @PathVariable Integer orderId) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("查询订单变更记录: orderId={}", orderId);
|
|
|
+ return diningServiceFeign.getOrderChangeLogs(authorization, orderId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("查询订单变更记录失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("查询订单变更记录失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 用户相关接口 ====================
|
|
|
+
|
|
|
+ @ApiOperation(value = "获取用户信息", notes = "获取当前登录用户的详细信息(从token中获取用户ID)")
|
|
|
+ @ApiOperationSupport(order = 9)
|
|
|
+ @GetMapping("/user/info")
|
|
|
+ public R<Object> getUserInfo(HttpServletRequest request) {
|
|
|
+ try {
|
|
|
+ String authorization = getAuthorization(request);
|
|
|
+ log.info("获取用户信息");
|
|
|
+ return diningServiceFeign.getUserInfo(authorization);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("获取用户信息失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("获取用户信息失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 门店信息接口 ====================
|
|
|
+
|
|
|
+ @ApiOperation(value = "根据门店ID查询桌号列表", notes = "查询指定门店下的所有桌号")
|
|
|
+ @ApiOperationSupport(order = 10)
|
|
|
+ @GetMapping("/store/tables")
|
|
|
+ public R<List<StoreTable>> getTablesByStoreId(
|
|
|
+ @ApiParam(value = "门店ID", required = true) @RequestParam Integer storeId) {
|
|
|
+ try {
|
|
|
+ log.info("根据门店ID查询桌号列表: storeId={}", storeId);
|
|
|
+ return diningServiceFeign.getTablesByStoreId(storeId);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("根据门店ID查询桌号列表失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("根据门店ID查询桌号列表失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // ==================== 文件上传接口 ====================
|
|
|
+
|
|
|
+ @ApiOperation(value = "上传图片到OSS", notes = "支持图片、视频或PDF文件上传,返回OSS文件路径")
|
|
|
+ @ApiOperationSupport(order = 11)
|
|
|
+ @PostMapping(value = "/file/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
|
|
|
+ public R<String> uploadFile(
|
|
|
+ @ApiParam(value = "文件对象", required = true) @RequestParam("file") MultipartFile file) {
|
|
|
+ try {
|
|
|
+ if (file == null || file.isEmpty()) {
|
|
|
+ return R.fail("文件不能为空");
|
|
|
+ }
|
|
|
+ log.info("上传文件: fileName={}, size={}", file.getOriginalFilename(), file.getSize());
|
|
|
+ return diningServiceFeign.uploadFile(file);
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("上传文件失败: {}", e.getMessage(), e);
|
|
|
+ return R.fail("上传文件失败: " + e.getMessage());
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|