刘云鑫 1 zi în urmă
părinte
comite
1713a01f49

+ 1 - 1
alien-entity/src/main/resources/mapper/LifeAppealManageMapper.xml

@@ -68,7 +68,7 @@
             AND `comment`.content LIKE CONCAT('%', #{storeContact}, '%')
         </if>
         <if test="storePhone != null and storePhone != ''">
-            AND lu.user_phone LIKE CONCAT('%', #{storePhone}, '%')
+            AND store.store_tel LIKE CONCAT('%', #{storePhone}, '%')
         </if>
         <if test="appealType != null and appealType != ''">
             AND appeal.appeal_status = #{appealType}

+ 651 - 651
alien-store/src/main/java/shop/alien/store/controller/StoreCuisineController.java

@@ -1,651 +1,651 @@
-package shop.alien.store.controller;
-
-import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
-import com.baomidou.mybatisplus.core.metadata.IPage;
-import com.baomidou.mybatisplus.core.toolkit.StringUtils;
-import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
-import io.swagger.annotations.*;
-import lombok.RequiredArgsConstructor;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.web.bind.annotation.*;
-import shop.alien.entity.result.R;
-import shop.alien.entity.store.StoreCuisine;
-import shop.alien.entity.store.StoreCuisineCombo;
-import shop.alien.entity.store.StoreInfo;
-import shop.alien.entity.store.StorePrice;
-import shop.alien.entity.store.dto.CuisineComboDto;
-import shop.alien.entity.store.dto.CuisineTypeResponseDto;
-import shop.alien.entity.store.dto.TablewareFeeDto;
-import shop.alien.entity.store.vo.PriceListVo;
-import shop.alien.mapper.StoreCuisineMapper;
-import shop.alien.store.annotation.TrackEvent;
-import shop.alien.store.service.StoreCuisineComboService;
-import shop.alien.store.service.StoreCuisineService;
-import shop.alien.store.service.StoreInfoService;
-import shop.alien.store.service.StorePriceService;
-import shop.alien.store.util.ai.AiContentModerationUtil;
-import shop.alien.store.util.ai.AiGetPriceUtil;
-
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-/**
- * 美食价目表
- *
- * @author auto-generated
- * @since 2025-12-30
- */
-@Slf4j
-@Api(tags = {"美食价目表"})
-@ApiSort(1)
-@CrossOrigin
-@RestController
-@RequestMapping("/store/cuisine")
-@RequiredArgsConstructor
-public class StoreCuisineController {
-
-    private final StoreCuisineService storeCuisineService;
-
-    private final AiGetPriceUtil aiGetPriceUtil;
-
-    private final StorePriceService storePriceService;
-
-    private final StoreInfoService storeInfoService;
-
-    private final AiContentModerationUtil aiContentModerationUtil;
-
-    private final StoreCuisineMapper storeCuisineMapper;
-
-    private final StoreCuisineComboService storeCuisineComboService;
-
-    @ApiOperation("新增美食套餐或单品")
-    @ApiOperationSupport(order = 1)
-    @PostMapping("/addCuisineCombo")
-    public R<StoreCuisine> addCuisineCombo(@RequestBody CuisineComboDto cuisineComboDto) {
-        log.info("StoreCuisineController.addCuisineCombo?cuisineComboDto={}", cuisineComboDto);
-        
-        // 参数验证
-        if (cuisineComboDto == null) {
-            log.error("新增美食套餐或单品失败:参数不能为空");
-            return R.fail("参数不能为空");
-        }
-        
-        try {
-            // 保存数据
-            boolean saveResult = storeCuisineService.addCuisineCombo(cuisineComboDto);
-            if (!saveResult) {
-                log.error("新增美食套餐或单品失败:保存操作返回false");
-                return R.fail("新增失败");
-            }
-            
-            // 由于 addCuisineCombo 方法返回的是 boolean,我们需要通过查询获取保存后的记录
-            // 通过 storeId + name + cuisineType + 最新的创建时间 来查询,确保获取到刚保存的记录
-            StoreCuisine savedCuisine = null;
-            if (cuisineComboDto.getStoreId() != null && StringUtils.isNotEmpty(cuisineComboDto.getName()) 
-                    && cuisineComboDto.getCuisineType() != null) {
-                LambdaQueryWrapper<StoreCuisine> queryWrapper = new LambdaQueryWrapper<>();
-                queryWrapper.eq(StoreCuisine::getStoreId, cuisineComboDto.getStoreId())
-                        .eq(StoreCuisine::getName, cuisineComboDto.getName())
-                        .eq(StoreCuisine::getCuisineType, cuisineComboDto.getCuisineType())
-                        .orderByDesc(StoreCuisine::getCreatedTime)
-                        .last("LIMIT 1");
-                savedCuisine = storeCuisineService.getOne(queryWrapper);
-            }
-            
-            if (savedCuisine == null) {
-                log.error("新增美食套餐或单品失败:保存后查询不到数据");
-                return R.fail("新增失败:数据保存异常");
-            }
-            
-            // 将状态置为"审核中"(0)
-            LambdaUpdateWrapper<StoreCuisine> auditingWrapper = new LambdaUpdateWrapper<>();
-            auditingWrapper.eq(StoreCuisine::getId, savedCuisine.getId());
-            auditingWrapper.set(StoreCuisine::getStatus, 0);
-            auditingWrapper.set(StoreCuisine::getRejectionReason, null);
-            auditingWrapper.set(StoreCuisine::getAuditTime, new Date());
-            storeCuisineMapper.update(null, auditingWrapper);
-            
-            // 组装 AI 审核文本和图片
-            StringBuilder textContent = new StringBuilder();
-            if (StringUtils.isNotEmpty(cuisineComboDto.getName())) {
-                textContent.append(cuisineComboDto.getName()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getDetailContent())) {
-                textContent.append(cuisineComboDto.getDetailContent()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getDescription())) {
-                textContent.append(cuisineComboDto.getDescription()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getDishReview())) {
-                textContent.append(cuisineComboDto.getDishReview()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getExtraNote())) {
-                textContent.append(cuisineComboDto.getExtraNote()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getReserveRule())) {
-                textContent.append(cuisineComboDto.getReserveRule()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getUsageRule())) {
-                textContent.append(cuisineComboDto.getUsageRule()).append(" ");
-            }
-
-            List<String> imageUrls = new ArrayList<>();
-
-            if (StringUtils.isNotEmpty(cuisineComboDto.getImages())) {
-                String[] urls = cuisineComboDto.getImages().split(",");
-                for (String url : urls) {
-                    if (StringUtils.isNotEmpty(url.trim())) {
-                        String trimmedUrl = url.trim();
-                        imageUrls.add(trimmedUrl);
-                    }
-                }
-            }
-
-            if (StringUtils.isNotEmpty(cuisineComboDto.getImageContent())) {
-                String[] urls = cuisineComboDto.getImageContent().split(",");
-                for (String url : urls) {
-                    if (StringUtils.isNotEmpty(url.trim())) {
-                        String trimmedUrl = url.trim();
-                        imageUrls.add(trimmedUrl);
-                    }
-                }
-            }
-
-            // AI:菜品图前端审;auditContent 仅 textContent,第二参固定 null(imageUrls 仍用于是否进入审核分支)
-            if (StringUtils.isNotEmpty(textContent.toString()) || imageUrls.size() > 0) {
-                AiContentModerationUtil.AuditResult auditResult = aiContentModerationUtil.auditContent(textContent.toString(), null);
-                
-                LambdaUpdateWrapper<StoreCuisine> auditUpdateWrapper = new LambdaUpdateWrapper<>();
-                auditUpdateWrapper.eq(StoreCuisine::getId, savedCuisine.getId());
-                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, auditResult.getFailureReason());
-                auditUpdateWrapper.set(StoreCuisine::getAuditTime, new Date());
-                
-                if (auditResult.isPassed()) {
-                    // 审核通过 审核状态为1 上架状态为1 已上架
-                    auditUpdateWrapper.set(StoreCuisine::getStatus, 1);
-                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 1);
-                    log.info("AI审核通过,ID: {}", savedCuisine.getId());
-                } else {
-                    // 审核拒绝 审核状态为2 上架状态为0 没有上下架状态
-                    auditUpdateWrapper.set(StoreCuisine::getStatus, 2);
-                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 0);
-                    log.info("AI审核拒绝,ID: {}", savedCuisine.getId());
-                }
-                storeCuisineMapper.update(null, auditUpdateWrapper);
-            }
-            
-            // 重新查询一次,返回最新的数据
-            StoreCuisine finalCuisine = storeCuisineService.getById(savedCuisine.getId());
-            if (finalCuisine != null) {
-                log.info("新增成功,返回ID: {}", finalCuisine.getId());
-                return R.data(finalCuisine, "新增成功");
-            }
-            
-            // 如果查询失败,返回保存后的对象(至少包含ID)
-            log.warn("新增成功但最终查询失败,返回保存后的对象,ID: {}", savedCuisine.getId());
-            return R.data(savedCuisine, "新增成功");
-            
-        } catch (Exception e) {
-            log.error("新增美食套餐或单品异常", e);
-            return R.fail("新增失败:" + e.getMessage());
-        }
-    }
-
-    @ApiOperation("修改美食套餐或单品")
-    @ApiOperationSupport(order = 2)
-    @PostMapping("/updateCuisineCombo")
-    public R<String> updateCuisineCombo(@RequestBody CuisineComboDto cuisineComboDto) {
-        log.info("StoreCuisineController.updateCuisineCombo?dto={}", cuisineComboDto);
-        
-        // 参数验证
-        if (cuisineComboDto == null) {
-            log.error("修改美食套餐或单品失败:参数不能为空");
-            return R.fail("参数不能为空");
-        }
-        
-        // 校验ID不能为空
-        if (cuisineComboDto.getId() == null) {
-            log.error("修改美食套餐或单品失败:ID不能为空");
-            return R.fail("ID不能为空");
-        }
-        
-        try {
-            // 更新数据
-            boolean updateResult = storeCuisineService.updateCuisineCombo(cuisineComboDto);
-            if (!updateResult) {
-                log.error("修改美食套餐或单品失败:更新操作返回false");
-                return R.fail("修改失败");
-            }
-            
-            // 查询更新后的记录
-            StoreCuisine updatedCuisine = storeCuisineService.getById(cuisineComboDto.getId());
-            if (updatedCuisine == null) {
-                log.error("修改美食套餐或单品失败:更新后查询不到数据,ID={}", cuisineComboDto.getId());
-                return R.fail("修改失败:数据更新异常");
-            }
-            
-            // 将状态置为"审核中"(0)
-            LambdaUpdateWrapper<StoreCuisine> auditingWrapper = new LambdaUpdateWrapper<>();
-            auditingWrapper.eq(StoreCuisine::getId, updatedCuisine.getId());
-            auditingWrapper.set(StoreCuisine::getStatus, 0);
-            auditingWrapper.set(StoreCuisine::getRejectionReason, null);
-            auditingWrapper.set(StoreCuisine::getAuditTime, new Date());
-            storeCuisineMapper.update(null, auditingWrapper);
-            
-            // 组装 AI 审核文本和图片
-            StringBuilder textContent = new StringBuilder();
-            if (StringUtils.isNotEmpty(cuisineComboDto.getName())) {
-                textContent.append(cuisineComboDto.getName()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getDetailContent())) {
-                textContent.append(cuisineComboDto.getDetailContent()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getDescription())) {
-                textContent.append(cuisineComboDto.getDescription()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getDishReview())) {
-                textContent.append(cuisineComboDto.getDishReview()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getExtraNote())) {
-                textContent.append(cuisineComboDto.getExtraNote()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getReserveRule())) {
-                textContent.append(cuisineComboDto.getReserveRule()).append(" ");
-            }
-            if (StringUtils.isNotEmpty(cuisineComboDto.getUsageRule())) {
-                textContent.append(cuisineComboDto.getUsageRule()).append(" ");
-            }
-
-            List<String> imageUrls = new ArrayList<>();
-
-            if (StringUtils.isNotEmpty(cuisineComboDto.getImages())) {
-                String[] urls = cuisineComboDto.getImages().split(",");
-                for (String url : urls) {
-                    if (StringUtils.isNotEmpty(url.trim())) {
-                        String trimmedUrl = url.trim();
-                        imageUrls.add(trimmedUrl);
-                    }
-                }
-            }
-
-            if (StringUtils.isNotEmpty(cuisineComboDto.getImageContent())) {
-                String[] urls = cuisineComboDto.getImageContent().split(",");
-                for (String url : urls) {
-                    if (StringUtils.isNotEmpty(url.trim())) {
-                        String trimmedUrl = url.trim();
-                        imageUrls.add(trimmedUrl);
-                    }
-                }
-            }
-
-            // AI:菜品图前端审;auditContent 仅 textContent,第二参固定 null(imageUrls 仍用于是否进入审核分支)
-            if (StringUtils.isNotEmpty(textContent.toString()) || imageUrls.size() > 0) {
-                AiContentModerationUtil.AuditResult auditResult = aiContentModerationUtil.auditContent(textContent.toString(), null);
-//                boolean allPassed = (auditResult != null);
-                
-                LambdaUpdateWrapper<StoreCuisine> auditUpdateWrapper = new LambdaUpdateWrapper<>();
-                auditUpdateWrapper.eq(StoreCuisine::getId, updatedCuisine.getId());
-                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, auditResult.getFailureReason());
-                auditUpdateWrapper.set(StoreCuisine::getAuditTime, new Date());
-                
-                if (auditResult.isPassed()) {
-                    // 审核通过 审核状态为1 上架状态为1 已上架
-                    auditUpdateWrapper.set(StoreCuisine::getStatus, 1);
-                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 1);
-                    log.info("AI审核通过,ID: {}", updatedCuisine.getId());
-                } else {
-                    // 审核拒绝 审核状态为2 上架状态为0 没有上下架状态
-                    auditUpdateWrapper.set(StoreCuisine::getStatus, 2);
-                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 0);
-                    log.info("AI审核拒绝,ID: {}", updatedCuisine.getId());
-                }
-                storeCuisineMapper.update(null, auditUpdateWrapper);
-            }
-            
-            return R.success("修改成功");
-            
-        } catch (Exception e) {
-            log.error("修改美食套餐或单品异常", e);
-            return R.fail("修改失败:" + e.getMessage());
-        }
-    }
-
-    @ApiOperation("获取所有美食单品名称,用于添加套餐")
-    @ApiOperationSupport(order = 1)
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
-    })
-    @GetMapping("/getSingleName")
-    public R<List<StoreCuisine>> getSingleName(@RequestParam Integer storeId) {
-        log.info("StoreCuisineController.getSingleName?storeId={}", storeId);
-        if (storeId == null) {
-            return R.fail("门店ID不能为空");
-        }
-        return R.data(storeCuisineService.getSingleName(storeId));
-    }
-
-    @TrackEvent(
-            eventType = "PRICE_VIEW",
-            eventCategory = "PRICE",
-            storeId = "#{result.data.data.storeId}",
-            targetId = "#{#id}",
-            targetType = "PRICE"
-    )
-    @ApiOperation("根据id与类型获取美食单品或套餐详情")
-    @ApiOperationSupport(order = 4)
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "id", value = "美食/套餐 id", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "cuisineType", value = "美食类型:1-单品,2-套餐", dataType = "Integer", paramType = "query", required = true)
-    })
-    @GetMapping("/getByCuisineType")
-    public R<CuisineTypeResponseDto> getByCuisineType(Integer id, Integer cuisineType) {
-        return R.data(storeCuisineService.getByCuisineTypeNew(id, cuisineType));
-    }
-
-
-    @ApiOperation("删除美食价目")
-    @ApiOperationSupport(order = 5)
-    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "美食价目id", dataType = "Integer", paramType = "query", required = true)})
-    @PostMapping("/delete")
-    public R<String> delete(Integer id) {
-        log.info("StoreCuisineController.delete?id={}", id);
-        if (storeCuisineService.removeById(id)) {
-            return R.success("删除成功");
-        }
-        return R.fail("删除失败");
-    }
-
-    @ApiOperation("批量删除美食价目")
-    @ApiOperationSupport(order = 6)
-    @PostMapping("/deleteBatch")
-    public R<String> deleteBatch(@RequestBody List<Integer> ids) {
-        log.info("StoreCuisineController.deleteBatch?ids={}", ids);
-        if (storeCuisineService.removeByIds(ids)) {
-            return R.success("批量删除成功");
-        }
-        return R.fail("批量删除失败");
-    }
-
-    @ApiOperation("美食上下架:1-上架,2-下架")
-    @ApiOperationSupport(order = 6)
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "id", value = "美食价目id", dataType = "Integer", paramType = "query", required = true),
-            @ApiImplicitParam(name = "shelfStatus", value = "上下架状态:1-上架,2-下架", dataType = "Integer", paramType = "query", required = true)
-    })
-    @PostMapping("/changeShelfStatus")
-    public R<String> changeShelfStatus(@RequestParam("id") Integer id, @RequestParam("shelfStatus") Integer shelfStatus) {
-        log.info("StoreCuisineController.changeShelfStatus?id={},shelfStatus={}", id, shelfStatus);
-        
-        // 参数验证
-        if (id == null) {
-            return R.fail("美食价目ID不能为空");
-        }
-        if (shelfStatus == null || (shelfStatus != 1 && shelfStatus != 2)) {
-            return R.fail("上下架状态不合法(只能为1或2)");
-        }
-        
-        try {
-            // 查询当前美食信息
-            StoreCuisine cuisine = storeCuisineService.getById(id);
-            if (cuisine == null) {
-                return R.fail("美食价目不存在");
-            }
-            
-            // 如果是下架操作(shelfStatus == 2),且是单品(cuisineType == 1),需要检查是否被套餐引用
-            if (shelfStatus == 2 && cuisine.getCuisineType() != null && cuisine.getCuisineType() == 1) {
-                // 查询是否有套餐引用了该单品
-                LambdaQueryWrapper<StoreCuisineCombo> comboQueryWrapper = new LambdaQueryWrapper<>();
-                comboQueryWrapper.eq(StoreCuisineCombo::getSid, id);
-                List<StoreCuisineCombo> comboList = storeCuisineComboService.list(comboQueryWrapper);
-                
-                if (comboList != null && !comboList.isEmpty()) {
-                    // 收集所有引用该单品的套餐ID
-                    List<Integer> comboIds = comboList.stream()
-                            .map(StoreCuisineCombo::getCid)
-                            .distinct()
-                            .collect(java.util.stream.Collectors.toList());
-                    
-                    // 查询这些套餐的上架状态
-                    List<StoreCuisine> combos = new ArrayList<>(storeCuisineService.listByIds(comboIds));
-                    List<String> onShelfComboNames = new ArrayList<>();
-                    
-                    for (StoreCuisine combo : combos) {
-                        // 检查套餐是否还在上架状态(shelfStatus == 1)
-                        if (combo.getShelfStatus() != null && combo.getShelfStatus() == 1) {
-                            onShelfComboNames.add(combo.getName());
-                        }
-                    }
-                    
-                    // 如果有套餐还在上架,不能下架单品
-                    if (!onShelfComboNames.isEmpty()) {
-                        String comboNames = String.join("、", onShelfComboNames);
-                        log.warn("下架单品失败:单品ID={}被以下套餐引用且套餐还在上架:{}", id, comboNames);
-                        return R.fail("该单品被套餐引用,无法下架。请先下架以下套餐:" + comboNames);
-                    }
-                }
-            }
-            
-            // 执行上下架操作
-            if (storeCuisineService.changeShelfStatus(id, shelfStatus)) {
-                return R.success("操作成功");
-            }
-            return R.fail("操作失败");
-            
-        } catch (Exception e) {
-            log.error("上下架操作异常,ID: {}, shelfStatus: {}", id, shelfStatus, e);
-            return R.fail("操作失败:" + e.getMessage());
-        }
-    }
-
-    @ApiOperation("分页查询美食价目/通用价目")
-    @ApiOperationSupport(order = 7)
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
-            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true),
-            @ApiImplicitParam(name = "storeId", value = "商户id", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "name", value = "菜名", dataType = "String", paramType = "query"),
-            @ApiImplicitParam(name = "status", value = "状态:0-待审核 1-审核通过 2-审核拒绝", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "type", value = "类型:1-美食 2-通用", dataType = "Integer", paramType = "query"),
-            @ApiImplicitParam(name = "startCreatedTime", value = "创建时间开始(yyyy-MM-dd HH:mm:ss)", dataType = "String", paramType = "query", required = false),
-            @ApiImplicitParam(name = "endCreatedTime", value = "创建时间结束(yyyy-MM-dd HH:mm:ss)", dataType = "String", paramType = "query", required = false)
-    })
-    @GetMapping("/getPage")
-    public R<List<PriceListVo>> getPage(
-            @RequestParam int pageNum,
-            @RequestParam int pageSize,
-            @RequestParam(required = false) Integer storeId,
-            @RequestParam(required = false) String name,
-            @RequestParam(required = false) Integer status,
-            @RequestParam(required = true) Integer type,
-            @RequestParam(required = false) Integer origin,
-            @RequestParam(required = false) String startCreatedTime,
-            @RequestParam(required = false) String endCreatedTime)
-    {
-        log.info("StoreCuisineController.getPage?pageNum={},pageSize={},storeId={},name={},status={},type={},startCreatedTime={},endCreatedTime={}", pageNum, pageSize, storeId, name, status, type, startCreatedTime, endCreatedTime);
-        List<PriceListVo> priceListVo = new ArrayList<>();
-
-        // 解析时间参数
-        Date startTime = null;
-        Date endTime = null;
-        if (startCreatedTime != null && !startCreatedTime.isEmpty()) {
-            try {
-                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                startTime = sdf.parse(startCreatedTime);
-            } catch (Exception e) {
-                log.warn("解析开始时间失败: {}", startCreatedTime, e);
-            }
-        }
-        if (endCreatedTime != null && !endCreatedTime.isEmpty()) {
-            try {
-                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
-                endTime = sdf.parse(endCreatedTime);
-            } catch (Exception e) {
-                log.warn("解析结束时间失败: {}", endCreatedTime, e);
-            }
-        }
-
-        if(type == 1){
-            Page<StoreCuisine> page = new Page<>(pageNum, pageSize);
-            LambdaQueryWrapper<StoreCuisine> queryWrapper = new LambdaQueryWrapper<>();
-            // 默认只查询已上架的菜品/套餐(shelf_status = 1)
-            if(null==origin){
-                queryWrapper.eq(StoreCuisine::getShelfStatus, 1);
-            }else if(origin == 0){
-                queryWrapper.in(StoreCuisine::getShelfStatus, 0,1,2);
-            }
-            else{
-                queryWrapper.eq(StoreCuisine::getShelfStatus, origin);
-            }
-            if (storeId != null) {
-                queryWrapper.eq(StoreCuisine::getStoreId, storeId);
-            }
-            if (name != null && !name.isEmpty()) {
-                queryWrapper.like(StoreCuisine::getName, name);
-            }
-            if (status != null) {
-                queryWrapper.eq(StoreCuisine::getStatus, status);
-            }
-            // 创建时间范围查询
-            if (startTime != null) {
-                queryWrapper.ge(StoreCuisine::getCreatedTime, startTime);
-            }
-            if (endTime != null) {
-                queryWrapper.le(StoreCuisine::getCreatedTime, endTime);
-            }
-            queryWrapper.orderByDesc(StoreCuisine::getCreatedTime);
-            IPage<StoreCuisine> result = storeCuisineService.page(page, queryWrapper);
-            List<StoreCuisine> cuisineList = result.getRecords();
-
-            if (cuisineList != null && !cuisineList.isEmpty()) {
-                for (StoreCuisine cuisine : cuisineList) {
-                    PriceListVo vo = new PriceListVo();
-
-                    BeanUtils.copyProperties(cuisine, vo);
-                    // 设置分类名称
-                    vo.setCategoryNames(storeCuisineService.getCategoryNames(cuisine.getCategoryIds()));
-                    priceListVo.add(vo);
-                }
-            }
-            return R.data(priceListVo);
-        }else{
-            Page<StorePrice> page = new Page<>(pageNum, pageSize);
-            LambdaQueryWrapper<StorePrice> queryWrapper = new LambdaQueryWrapper<>();
-            if (storeId != null) {
-                queryWrapper.eq(StorePrice::getStoreId, storeId);
-            }
-            if (name != null && !name.isEmpty()) {
-                queryWrapper.like(StorePrice::getName, name);
-            }
-            if (status != null) {
-                queryWrapper.eq(StorePrice::getStatus, status);
-            }
-            // 默认只查询已上架的菜品/套餐(shelf_status = 1)
-            if(null==origin){
-                queryWrapper.eq(StorePrice::getShelfStatus, 1);
-            }else if(origin == 0){
-                queryWrapper.in(StorePrice::getShelfStatus, 0,1,2);
-            }
-            else{
-                queryWrapper.eq(StorePrice::getShelfStatus, origin);
-            }
-//            queryWrapper.eq(StorePrice::getShelfStatus, 1);
-            // 创建时间范围查询
-            if (startTime != null) {
-                queryWrapper.ge(StorePrice::getCreatedTime, startTime);
-            }
-            if (endTime != null) {
-                queryWrapper.le(StorePrice::getCreatedTime, endTime);
-            }
-            queryWrapper.orderByDesc(StorePrice::getCreatedTime);
-            IPage<StorePrice> result = storePriceService.page(page, queryWrapper);
-            List<StorePrice> storePrices = result.getRecords();
-            if (storePrices != null && !storePrices.isEmpty()) {
-                for (StorePrice storePrice : storePrices) {
-                    PriceListVo vo = new PriceListVo();
-
-                    BeanUtils.copyProperties(storePrice, vo);
-                    priceListVo.add(vo);
-                }
-            }
-            return R.data(priceListVo);
-        }
-    }
-
-    @ApiOperation("根据菜品和位置查询推荐菜价")
-    @ApiOperationSupport(order = 6)
-    @PostMapping("/getPrice")
-    public R<String> getPrice(String dish_name,String location) {
-        JSONObject dishPrice = aiGetPriceUtil.getDishPrice(dish_name, location);
-        
-        // 检查响应状态码
-        Integer code = dishPrice.getInteger("code");
-        if (code == null || code != 200) {
-            String message = dishPrice.getString("message");
-            log.warn("查询菜品价格失败,code: {}, message: {}", code, message);
-            return R.fail(message != null ? message : "查询菜品价格失败");
-        }
-        
-        // 获取 data 对象
-        JSONObject data = dishPrice.getJSONObject("data");
-        if (data == null) {
-            log.warn("查询菜品价格响应中 data 为空");
-            return R.fail("查询菜品价格失败:响应数据为空");
-        }
-        
-        // 从 data 中获取 price
-        Object priceObj = data.get("price");
-        if (priceObj == null) {
-            log.warn("查询菜品价格响应中 price 为空");
-            return R.fail("查询菜品价格失败:价格信息为空");
-        }
-        
-        // 将价格转换为字符串返回
-        String price = priceObj.toString();
-        return R.data(price);
-    }
-
-    @ApiOperation("保存或更新餐具费")
-    @ApiOperationSupport(order = 8)
-    @PostMapping("/saveTablewareFee")
-    public R<String> saveTablewareFee(@RequestBody TablewareFeeDto tablewareFeeDto) {
-        log.info("StoreCuisineController.saveTablewareFee?storeId={},tablewareFee={}", 
-                tablewareFeeDto.getStoreId(), tablewareFeeDto.getTablewareFee());
-        
-        if (tablewareFeeDto.getStoreId() == null) {
-            return R.fail("门店ID不能为空");
-        }
-        
-        if (storeInfoService.saveOrUpdateTablewareFee(tablewareFeeDto.getStoreId(), tablewareFeeDto.getTablewareFee())) {
-            return R.success("保存成功");
-        }
-        return R.fail("保存失败");
-    }
-
-    @ApiOperation("查询餐具费")
-    @ApiOperationSupport(order = 9)
-    @ApiImplicitParams({
-            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
-    })
-    @GetMapping("/getTablewareFee")
-    public R<Integer> getTablewareFee(@RequestParam("storeId") Integer storeId) {
-        log.info("StoreCuisineController.getTablewareFee?storeId={}", storeId);
-        
-        if (storeId == null) {
-            return R.fail("门店ID不能为空");
-        }
-        
-        StoreInfo storeInfo = storeInfoService.getById(storeId);
-        if (storeInfo == null) {
-            return R.fail("门店不存在");
-        }
-        
-        return R.data(storeInfo.getTablewareFee());
-    }
-}
-
-
+package shop.alien.store.controller;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.BeanUtils;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StoreCuisine;
+import shop.alien.entity.store.StoreCuisineCombo;
+import shop.alien.entity.store.StoreInfo;
+import shop.alien.entity.store.StorePrice;
+import shop.alien.entity.store.dto.CuisineComboDto;
+import shop.alien.entity.store.dto.CuisineTypeResponseDto;
+import shop.alien.entity.store.dto.TablewareFeeDto;
+import shop.alien.entity.store.vo.PriceListVo;
+import shop.alien.mapper.StoreCuisineMapper;
+import shop.alien.store.annotation.TrackEvent;
+import shop.alien.store.service.StoreCuisineComboService;
+import shop.alien.store.service.StoreCuisineService;
+import shop.alien.store.service.StoreInfoService;
+import shop.alien.store.service.StorePriceService;
+import shop.alien.store.util.ai.AiContentModerationUtil;
+import shop.alien.store.util.ai.AiGetPriceUtil;
+
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 美食价目表
+ *
+ * @author auto-generated
+ * @since 2025-12-30
+ */
+@Slf4j
+@Api(tags = {"美食价目表"})
+@ApiSort(1)
+@CrossOrigin
+@RestController
+@RequestMapping("/store/cuisine")
+@RequiredArgsConstructor
+public class StoreCuisineController {
+
+    private final StoreCuisineService storeCuisineService;
+
+    private final AiGetPriceUtil aiGetPriceUtil;
+
+    private final StorePriceService storePriceService;
+
+    private final StoreInfoService storeInfoService;
+
+    private final AiContentModerationUtil aiContentModerationUtil;
+
+    private final StoreCuisineMapper storeCuisineMapper;
+
+    private final StoreCuisineComboService storeCuisineComboService;
+
+    @ApiOperation("新增美食套餐或单品")
+    @ApiOperationSupport(order = 1)
+    @PostMapping("/addCuisineCombo")
+    public R<StoreCuisine> addCuisineCombo(@RequestBody CuisineComboDto cuisineComboDto) {
+        log.info("StoreCuisineController.addCuisineCombo?cuisineComboDto={}", cuisineComboDto);
+        
+        // 参数验证
+        if (cuisineComboDto == null) {
+            log.error("新增美食套餐或单品失败:参数不能为空");
+            return R.fail("参数不能为空");
+        }
+        
+        try {
+            // 保存数据
+            boolean saveResult = storeCuisineService.addCuisineCombo(cuisineComboDto);
+            if (!saveResult) {
+                log.error("新增美食套餐或单品失败:保存操作返回false");
+                return R.fail("新增失败");
+            }
+            
+            // 由于 addCuisineCombo 方法返回的是 boolean,我们需要通过查询获取保存后的记录
+            // 通过 storeId + name + cuisineType + 最新的创建时间 来查询,确保获取到刚保存的记录
+            StoreCuisine savedCuisine = null;
+            if (cuisineComboDto.getStoreId() != null && StringUtils.isNotEmpty(cuisineComboDto.getName()) 
+                    && cuisineComboDto.getCuisineType() != null) {
+                LambdaQueryWrapper<StoreCuisine> queryWrapper = new LambdaQueryWrapper<>();
+                queryWrapper.eq(StoreCuisine::getStoreId, cuisineComboDto.getStoreId())
+                        .eq(StoreCuisine::getName, cuisineComboDto.getName())
+                        .eq(StoreCuisine::getCuisineType, cuisineComboDto.getCuisineType())
+                        .orderByDesc(StoreCuisine::getCreatedTime)
+                        .last("LIMIT 1");
+                savedCuisine = storeCuisineService.getOne(queryWrapper);
+            }
+            
+            if (savedCuisine == null) {
+                log.error("新增美食套餐或单品失败:保存后查询不到数据");
+                return R.fail("新增失败:数据保存异常");
+            }
+            
+            // 将状态置为"审核中"(0)
+            LambdaUpdateWrapper<StoreCuisine> auditingWrapper = new LambdaUpdateWrapper<>();
+            auditingWrapper.eq(StoreCuisine::getId, savedCuisine.getId());
+            auditingWrapper.set(StoreCuisine::getStatus, 0);
+            auditingWrapper.set(StoreCuisine::getRejectionReason, null);
+            auditingWrapper.set(StoreCuisine::getAuditTime, new Date());
+            storeCuisineMapper.update(null, auditingWrapper);
+            
+            // 组装 AI 审核文本和图片
+            StringBuilder textContent = new StringBuilder();
+            if (StringUtils.isNotEmpty(cuisineComboDto.getName())) {
+                textContent.append(cuisineComboDto.getName()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getDetailContent())) {
+                textContent.append(cuisineComboDto.getDetailContent()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getDescription())) {
+                textContent.append(cuisineComboDto.getDescription()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getDishReview())) {
+                textContent.append(cuisineComboDto.getDishReview()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getExtraNote())) {
+                textContent.append(cuisineComboDto.getExtraNote()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getReserveRule())) {
+                textContent.append(cuisineComboDto.getReserveRule()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getUsageRule())) {
+                textContent.append(cuisineComboDto.getUsageRule()).append(" ");
+            }
+
+            List<String> imageUrls = new ArrayList<>();
+
+            if (StringUtils.isNotEmpty(cuisineComboDto.getImages())) {
+                String[] urls = cuisineComboDto.getImages().split(",");
+                for (String url : urls) {
+                    if (StringUtils.isNotEmpty(url.trim())) {
+                        String trimmedUrl = url.trim();
+                        imageUrls.add(trimmedUrl);
+                    }
+                }
+            }
+
+            if (StringUtils.isNotEmpty(cuisineComboDto.getImageContent())) {
+                String[] urls = cuisineComboDto.getImageContent().split(",");
+                for (String url : urls) {
+                    if (StringUtils.isNotEmpty(url.trim())) {
+                        String trimmedUrl = url.trim();
+                        imageUrls.add(trimmedUrl);
+                    }
+                }
+            }
+
+            // AI:菜品图前端审;auditContent 仅 textContent,第二参固定 null(imageUrls 仍用于是否进入审核分支)
+            if (StringUtils.isNotEmpty(textContent.toString()) || imageUrls.size() > 0) {
+                AiContentModerationUtil.AuditResult auditResult = aiContentModerationUtil.auditContent(textContent.toString(), null);
+                
+                LambdaUpdateWrapper<StoreCuisine> auditUpdateWrapper = new LambdaUpdateWrapper<>();
+                auditUpdateWrapper.eq(StoreCuisine::getId, savedCuisine.getId());
+                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, auditResult.getFailureReason());
+                auditUpdateWrapper.set(StoreCuisine::getAuditTime, new Date());
+                
+                if (auditResult.isPassed()) {
+                    // 审核通过 审核状态为1 上架状态为1 已上架
+                    auditUpdateWrapper.set(StoreCuisine::getStatus, 1);
+                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 1);
+                    log.info("AI审核通过,ID: {}", savedCuisine.getId());
+                } else {
+                    // 审核拒绝 审核状态为2 上架状态为0 没有上下架状态
+                    auditUpdateWrapper.set(StoreCuisine::getStatus, 2);
+                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 0);
+                    log.info("AI审核拒绝,ID: {}", savedCuisine.getId());
+                }
+                storeCuisineMapper.update(null, auditUpdateWrapper);
+            }
+            
+            // 重新查询一次,返回最新的数据
+            StoreCuisine finalCuisine = storeCuisineService.getById(savedCuisine.getId());
+            if (finalCuisine != null) {
+                log.info("新增成功,返回ID: {}", finalCuisine.getId());
+                return R.data(finalCuisine, "新增成功");
+            }
+            
+            // 如果查询失败,返回保存后的对象(至少包含ID)
+            log.warn("新增成功但最终查询失败,返回保存后的对象,ID: {}", savedCuisine.getId());
+            return R.data(savedCuisine, "新增成功");
+            
+        } catch (Exception e) {
+            log.error("新增美食套餐或单品异常", e);
+            return R.fail("新增失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("修改美食套餐或单品")
+    @ApiOperationSupport(order = 2)
+    @PostMapping("/updateCuisineCombo")
+    public R<String> updateCuisineCombo(@RequestBody CuisineComboDto cuisineComboDto) {
+        log.info("StoreCuisineController.updateCuisineCombo?dto={}", cuisineComboDto);
+        
+        // 参数验证
+        if (cuisineComboDto == null) {
+            log.error("修改美食套餐或单品失败:参数不能为空");
+            return R.fail("参数不能为空");
+        }
+        
+        // 校验ID不能为空
+        if (cuisineComboDto.getId() == null) {
+            log.error("修改美食套餐或单品失败:ID不能为空");
+            return R.fail("ID不能为空");
+        }
+        
+        try {
+            // 更新数据
+            boolean updateResult = storeCuisineService.updateCuisineCombo(cuisineComboDto);
+            if (!updateResult) {
+                log.error("修改美食套餐或单品失败:更新操作返回false");
+                return R.fail("修改失败");
+            }
+            
+            // 查询更新后的记录
+            StoreCuisine updatedCuisine = storeCuisineService.getById(cuisineComboDto.getId());
+            if (updatedCuisine == null) {
+                log.error("修改美食套餐或单品失败:更新后查询不到数据,ID={}", cuisineComboDto.getId());
+                return R.fail("修改失败:数据更新异常");
+            }
+            
+            // 将状态置为"审核中"(0)
+            LambdaUpdateWrapper<StoreCuisine> auditingWrapper = new LambdaUpdateWrapper<>();
+            auditingWrapper.eq(StoreCuisine::getId, updatedCuisine.getId());
+            auditingWrapper.set(StoreCuisine::getStatus, 0);
+            auditingWrapper.set(StoreCuisine::getRejectionReason, null);
+            auditingWrapper.set(StoreCuisine::getAuditTime, new Date());
+            storeCuisineMapper.update(null, auditingWrapper);
+            
+            // 组装 AI 审核文本和图片
+            StringBuilder textContent = new StringBuilder();
+            if (StringUtils.isNotEmpty(cuisineComboDto.getName())) {
+                textContent.append(cuisineComboDto.getName()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getDetailContent())) {
+                textContent.append(cuisineComboDto.getDetailContent()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getDescription())) {
+                textContent.append(cuisineComboDto.getDescription()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getDishReview())) {
+                textContent.append(cuisineComboDto.getDishReview()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getExtraNote())) {
+                textContent.append(cuisineComboDto.getExtraNote()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getReserveRule())) {
+                textContent.append(cuisineComboDto.getReserveRule()).append(" ");
+            }
+            if (StringUtils.isNotEmpty(cuisineComboDto.getUsageRule())) {
+                textContent.append(cuisineComboDto.getUsageRule()).append(" ");
+            }
+
+            List<String> imageUrls = new ArrayList<>();
+
+            if (StringUtils.isNotEmpty(cuisineComboDto.getImages())) {
+                String[] urls = cuisineComboDto.getImages().split(",");
+                for (String url : urls) {
+                    if (StringUtils.isNotEmpty(url.trim())) {
+                        String trimmedUrl = url.trim();
+                        imageUrls.add(trimmedUrl);
+                    }
+                }
+            }
+
+            if (StringUtils.isNotEmpty(cuisineComboDto.getImageContent())) {
+                String[] urls = cuisineComboDto.getImageContent().split(",");
+                for (String url : urls) {
+                    if (StringUtils.isNotEmpty(url.trim())) {
+                        String trimmedUrl = url.trim();
+                        imageUrls.add(trimmedUrl);
+                    }
+                }
+            }
+
+            // AI:菜品图前端审;auditContent 仅 textContent,第二参固定 null(imageUrls 仍用于是否进入审核分支)
+            if (StringUtils.isNotEmpty(textContent.toString()) || imageUrls.size() > 0) {
+                AiContentModerationUtil.AuditResult auditResult = aiContentModerationUtil.auditContent(textContent.toString(), null);
+//                boolean allPassed = (auditResult != null);
+                
+                LambdaUpdateWrapper<StoreCuisine> auditUpdateWrapper = new LambdaUpdateWrapper<>();
+                auditUpdateWrapper.eq(StoreCuisine::getId, updatedCuisine.getId());
+                auditUpdateWrapper.set(StoreCuisine::getRejectionReason, auditResult.getFailureReason());
+                auditUpdateWrapper.set(StoreCuisine::getAuditTime, new Date());
+                
+                if (auditResult.isPassed()) {
+                    // 审核通过 审核状态为1 上架状态为1 已上架
+                    auditUpdateWrapper.set(StoreCuisine::getStatus, 1);
+                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 1);
+                    log.info("AI审核通过,ID: {}", updatedCuisine.getId());
+                } else {
+                    // 审核拒绝 审核状态为2 上架状态为0 没有上下架状态
+                    auditUpdateWrapper.set(StoreCuisine::getStatus, 2);
+                    auditUpdateWrapper.set(StoreCuisine::getShelfStatus, 0);
+                    log.info("AI审核拒绝,ID: {}", updatedCuisine.getId());
+                }
+                storeCuisineMapper.update(null, auditUpdateWrapper);
+            }
+            
+            return R.success("修改成功");
+            
+        } catch (Exception e) {
+            log.error("修改美食套餐或单品异常", e);
+            return R.fail("修改失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("获取所有美食单品名称,用于添加套餐")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getSingleName")
+    public R<List<StoreCuisine>> getSingleName(@RequestParam Integer storeId) {
+        log.info("StoreCuisineController.getSingleName?storeId={}", storeId);
+        if (storeId == null) {
+            return R.fail("门店ID不能为空");
+        }
+        return R.data(storeCuisineService.getSingleName(storeId));
+    }
+
+    @TrackEvent(
+            eventType = "PRICE_VIEW",
+            eventCategory = "PRICE",
+            storeId = "#{result.data.data.storeId}",
+            targetId = "#{#id}",
+            targetType = "PRICE"
+    )
+    @ApiOperation("根据id与类型获取美食单品或套餐详情")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "美食/套餐 id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "cuisineType", value = "美食类型:1-单品,2-套餐", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getByCuisineType")
+    public R<CuisineTypeResponseDto> getByCuisineType(Integer id, Integer cuisineType) {
+        return R.data(storeCuisineService.getByCuisineTypeNew(id, cuisineType));
+    }
+
+
+    @ApiOperation("删除美食价目")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({@ApiImplicitParam(name = "id", value = "美食价目id", dataType = "Integer", paramType = "query", required = true)})
+    @PostMapping("/delete")
+    public R<String> delete(Integer id) {
+        log.info("StoreCuisineController.delete?id={}", id);
+        if (storeCuisineService.removeById(id)) {
+            return R.success("删除成功");
+        }
+        return R.fail("删除失败");
+    }
+
+    @ApiOperation("批量删除美食价目")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/deleteBatch")
+    public R<String> deleteBatch(@RequestBody List<Integer> ids) {
+        log.info("StoreCuisineController.deleteBatch?ids={}", ids);
+        if (storeCuisineService.removeByIds(ids)) {
+            return R.success("批量删除成功");
+        }
+        return R.fail("批量删除失败");
+    }
+
+    @ApiOperation("美食上下架:1-上架,2-下架")
+    @ApiOperationSupport(order = 6)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "美食价目id", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "shelfStatus", value = "上下架状态:1-上架,2-下架", dataType = "Integer", paramType = "query", required = true)
+    })
+    @PostMapping("/changeShelfStatus")
+    public R<String> changeShelfStatus(@RequestParam("id") Integer id, @RequestParam("shelfStatus") Integer shelfStatus) {
+        log.info("StoreCuisineController.changeShelfStatus?id={},shelfStatus={}", id, shelfStatus);
+        
+        // 参数验证
+        if (id == null) {
+            return R.fail("美食价目ID不能为空");
+        }
+        if (shelfStatus == null || (shelfStatus != 1 && shelfStatus != 2)) {
+            return R.fail("上下架状态不合法(只能为1或2)");
+        }
+        
+        try {
+            // 查询当前美食信息
+            StoreCuisine cuisine = storeCuisineService.getById(id);
+            if (cuisine == null) {
+                return R.fail("美食价目不存在");
+            }
+            
+            // 如果是下架操作(shelfStatus == 2),且是单品(cuisineType == 1),需要检查是否被套餐引用
+            if (shelfStatus == 2 && cuisine.getCuisineType() != null && cuisine.getCuisineType() == 1) {
+                // 查询是否有套餐引用了该单品
+                LambdaQueryWrapper<StoreCuisineCombo> comboQueryWrapper = new LambdaQueryWrapper<>();
+                comboQueryWrapper.eq(StoreCuisineCombo::getSid, id);
+                List<StoreCuisineCombo> comboList = storeCuisineComboService.list(comboQueryWrapper);
+                
+                if (comboList != null && !comboList.isEmpty()) {
+                    // 收集所有引用该单品的套餐ID
+                    List<Integer> comboIds = comboList.stream()
+                            .map(StoreCuisineCombo::getCid)
+                            .distinct()
+                            .collect(java.util.stream.Collectors.toList());
+                    
+                    // 查询这些套餐的上架状态
+                    List<StoreCuisine> combos = new ArrayList<>(storeCuisineService.listByIds(comboIds));
+                    List<String> onShelfComboNames = new ArrayList<>();
+                    
+                    for (StoreCuisine combo : combos) {
+                        // 检查套餐是否还在上架状态(shelfStatus == 1)
+                        if (combo.getShelfStatus() != null && combo.getShelfStatus() == 1) {
+                            onShelfComboNames.add(combo.getName());
+                        }
+                    }
+                    
+                    // 如果有套餐还在上架,不能下架单品
+                    if (!onShelfComboNames.isEmpty()) {
+                        String comboNames = String.join("、", onShelfComboNames);
+                        log.warn("下架单品失败:单品ID={}被以下套餐引用且套餐还在上架:{}", id, comboNames);
+                        return R.fail("该单品被套餐引用,无法下架。请先下架以下套餐:" + comboNames);
+                    }
+                }
+            }
+            
+            // 执行上下架操作
+            if (storeCuisineService.changeShelfStatus(id, shelfStatus)) {
+                return R.success("操作成功");
+            }
+            return R.fail("操作失败");
+            
+        } catch (Exception e) {
+            log.error("上下架操作异常,ID: {}, shelfStatus: {}", id, shelfStatus, e);
+            return R.fail("操作失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("分页查询美食价目/通用价目")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "pageNum", value = "页码", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "pageSize", value = "页容", dataType = "int", paramType = "query", required = true),
+            @ApiImplicitParam(name = "storeId", value = "商户id", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "name", value = "菜名", dataType = "String", paramType = "query"),
+            @ApiImplicitParam(name = "status", value = "状态:0-待审核 1-审核通过 2-审核拒绝", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "type", value = "类型:1-美食 2-通用", dataType = "Integer", paramType = "query"),
+            @ApiImplicitParam(name = "startCreatedTime", value = "创建时间开始(yyyy-MM-dd HH:mm:ss)", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "endCreatedTime", value = "创建时间结束(yyyy-MM-dd HH:mm:ss)", dataType = "String", paramType = "query", required = false)
+    })
+    @GetMapping("/getPage")
+    public R<List<PriceListVo>> getPage(
+            @RequestParam int pageNum,
+            @RequestParam int pageSize,
+            @RequestParam(required = false) Integer storeId,
+            @RequestParam(required = false) String name,
+            @RequestParam(required = false) Integer status,
+            @RequestParam(required = true) Integer type,
+            @RequestParam(required = false) Integer origin,
+            @RequestParam(required = false) String startCreatedTime,
+            @RequestParam(required = false) String endCreatedTime)
+    {
+        log.info("StoreCuisineController.getPage?pageNum={},pageSize={},storeId={},name={},status={},type={},startCreatedTime={},endCreatedTime={}", pageNum, pageSize, storeId, name, status, type, startCreatedTime, endCreatedTime);
+        List<PriceListVo> priceListVo = new ArrayList<>();
+
+        // 解析时间参数
+        Date startTime = null;
+        Date endTime = null;
+        if (startCreatedTime != null && !startCreatedTime.isEmpty()) {
+            try {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                startTime = sdf.parse(startCreatedTime);
+            } catch (Exception e) {
+                log.warn("解析开始时间失败: {}", startCreatedTime, e);
+            }
+        }
+        if (endCreatedTime != null && !endCreatedTime.isEmpty()) {
+            try {
+                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                endTime = sdf.parse(endCreatedTime);
+            } catch (Exception e) {
+                log.warn("解析结束时间失败: {}", endCreatedTime, e);
+            }
+        }
+
+        if(type == 1){
+            Page<StoreCuisine> page = new Page<>(pageNum, pageSize);
+            LambdaQueryWrapper<StoreCuisine> queryWrapper = new LambdaQueryWrapper<>();
+            // 默认只查询已上架的菜品/套餐(shelf_status = 1)
+            if(null==origin){
+                queryWrapper.eq(StoreCuisine::getShelfStatus, 1);
+            }else if(origin == 0){
+                queryWrapper.in(StoreCuisine::getShelfStatus, 0,1,2);
+            }
+            else{
+                queryWrapper.eq(StoreCuisine::getShelfStatus, origin);
+            }
+            if (storeId != null) {
+                queryWrapper.eq(StoreCuisine::getStoreId, storeId);
+            }
+            if (name != null && !name.isEmpty()) {
+                queryWrapper.like(StoreCuisine::getName, name);
+            }
+            if (status != null) {
+                queryWrapper.eq(StoreCuisine::getStatus, status);
+            }
+            // 创建时间范围查询
+            if (startTime != null) {
+                queryWrapper.ge(StoreCuisine::getCreatedTime, startTime);
+            }
+            if (endTime != null) {
+                queryWrapper.le(StoreCuisine::getCreatedTime, endTime);
+            }
+            queryWrapper.orderByDesc(StoreCuisine::getCreatedTime);
+            IPage<StoreCuisine> result = storeCuisineService.page(page, queryWrapper);
+            List<StoreCuisine> cuisineList = result.getRecords();
+
+            if (cuisineList != null && !cuisineList.isEmpty()) {
+                for (StoreCuisine cuisine : cuisineList) {
+                    PriceListVo vo = new PriceListVo();
+
+                    BeanUtils.copyProperties(cuisine, vo);
+                    // 设置分类名称
+                    vo.setCategoryNames(storeCuisineService.getCategoryNames(cuisine.getCategoryIds()));
+                    priceListVo.add(vo);
+                }
+            }
+            return R.data(priceListVo);
+        }else{
+            Page<StorePrice> page = new Page<>(pageNum, pageSize);
+            LambdaQueryWrapper<StorePrice> queryWrapper = new LambdaQueryWrapper<>();
+            if (storeId != null) {
+                queryWrapper.eq(StorePrice::getStoreId, storeId);
+            }
+            if (name != null && !name.isEmpty()) {
+                queryWrapper.like(StorePrice::getName, name);
+            }
+            if (status != null) {
+                queryWrapper.eq(StorePrice::getStatus, status);
+            }
+            // 默认只查询已上架的菜品/套餐(shelf_status = 1)
+            if(null==origin){
+                queryWrapper.eq(StorePrice::getShelfStatus, 1);
+            }else if(origin == 0){
+                queryWrapper.in(StorePrice::getShelfStatus, 0,1,2);
+            }
+            else{
+                queryWrapper.eq(StorePrice::getShelfStatus, origin);
+            }
+//            queryWrapper.eq(StorePrice::getShelfStatus, 1);
+            // 创建时间范围查询
+            if (startTime != null) {
+                queryWrapper.ge(StorePrice::getCreatedTime, startTime);
+            }
+            if (endTime != null) {
+                queryWrapper.le(StorePrice::getCreatedTime, endTime);
+            }
+            queryWrapper.orderByDesc(StorePrice::getCreatedTime);
+            IPage<StorePrice> result = storePriceService.page(page, queryWrapper);
+            List<StorePrice> storePrices = result.getRecords();
+            if (storePrices != null && !storePrices.isEmpty()) {
+                for (StorePrice storePrice : storePrices) {
+                    PriceListVo vo = new PriceListVo();
+
+                    BeanUtils.copyProperties(storePrice, vo);
+                    priceListVo.add(vo);
+                }
+            }
+            return R.data(priceListVo);
+        }
+    }
+
+    @ApiOperation("根据菜品和位置查询推荐菜价")
+    @ApiOperationSupport(order = 6)
+    @PostMapping("/getPrice")
+    public R<String> getPrice(String dish_name,String location) {
+        JSONObject dishPrice = aiGetPriceUtil.getDishPrice(dish_name, location);
+        
+        // 检查响应状态码
+        Integer code = dishPrice.getInteger("code");
+        if (code == null || code != 200) {
+            String message = dishPrice.getString("message");
+            log.warn("查询菜品价格失败,code: {}, message: {}", code, message);
+            return R.fail(message != null ? message : "查询菜品价格失败");
+        }
+        
+        // 获取 data 对象
+        JSONObject data = dishPrice.getJSONObject("data");
+        if (data == null) {
+            log.warn("查询菜品价格响应中 data 为空");
+            return R.fail("查询菜品价格失败:响应数据为空");
+        }
+        
+        // 从 data 中获取 price
+        Object priceObj = data.get("price");
+        if (priceObj == null) {
+            log.warn("查询菜品价格响应中 price 为空");
+            return R.fail("查询菜品价格失败:价格信息为空");
+        }
+        
+        // 将价格转换为字符串返回
+        String price = priceObj.toString();
+        return R.data(price);
+    }
+
+    @ApiOperation("保存或更新餐具费")
+    @ApiOperationSupport(order = 8)
+    @PostMapping("/saveTablewareFee")
+    public R<String> saveTablewareFee(@RequestBody TablewareFeeDto tablewareFeeDto) {
+        log.info("StoreCuisineController.saveTablewareFee?storeId={},tablewareFee={}", 
+                tablewareFeeDto.getStoreId(), tablewareFeeDto.getTablewareFee());
+        
+        if (tablewareFeeDto.getStoreId() == null) {
+            return R.fail("门店ID不能为空");
+        }
+        
+        if (storeInfoService.saveOrUpdateTablewareFee(tablewareFeeDto.getStoreId(), tablewareFeeDto.getTablewareFee())) {
+            return R.success("保存成功");
+        }
+        return R.fail("保存失败");
+    }
+
+    @ApiOperation("查询餐具费")
+    @ApiOperationSupport(order = 9)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/getTablewareFee")
+    public R<Integer> getTablewareFee(@RequestParam("storeId") Integer storeId) {
+        log.info("StoreCuisineController.getTablewareFee?storeId={}", storeId);
+        
+        if (storeId == null) {
+            return R.fail("门店ID不能为空");
+        }
+        
+        StoreInfo storeInfo = storeInfoService.getById(storeId);
+        if (storeInfo == null) {
+            return R.fail("门店不存在");
+        }
+        
+        return R.data(storeInfo.getTablewareFee());
+    }
+}
+
+