Переглянути джерело

feet:设施区域新增删除

panzhilin 2 днів тому
батько
коміт
63620d290f

+ 67 - 0
alien-entity/src/main/java/shop/alien/entity/store/SportsFacilityArea.java

@@ -0,0 +1,67 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 运动设施区域表实体类
+ * 对应表: sports_facility_area
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@TableName("sports_facility_area")
+@ApiModel(value = "SportsFacilityArea对象", description = "运动设施区域表")
+public class SportsFacilityArea implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    @ApiModelProperty(value = "门店ID", required = true)
+    @TableField("store_id")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "区域名称(必填,限10字)", required = true)
+    @TableField("area_name")
+    private String areaName;
+
+    @ApiModelProperty(value = "排序号(数字越小越靠前)")
+    @TableField("sort_order")
+    private Integer sortOrder;
+
+    @ApiModelProperty(value = "删除标记(0-未删除,1-已删除)")
+    @TableField("delete_flag")
+    @TableLogic
+    private Integer deleteFlag;
+
+    @ApiModelProperty(value = "创建时间")
+    @TableField(value = "created_time", fill = FieldFill.INSERT)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createdTime;
+
+    @ApiModelProperty(value = "创建人ID")
+    @TableField(value = "created_user_id", fill = FieldFill.INSERT)
+    private Integer createdUserId;
+
+    @ApiModelProperty(value = "修改时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    @ApiModelProperty(value = "修改人ID")
+    @TableField(value = "updated_user_id", fill = FieldFill.INSERT_UPDATE)
+    private Integer updatedUserId;
+}
+

+ 29 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/CreateAreaRequestVo.java

@@ -0,0 +1,29 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 新建区域请求VO
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "CreateAreaRequestVo对象", description = "新建区域请求视图对象")
+public class CreateAreaRequestVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "门店ID", required = true, example = "1")
+    private Integer storeId;
+
+    @ApiModelProperty(value = "区域名称(必填,限10字)", required = true, example = "有氧区")
+    private String facilityCategoryName;
+}
+

+ 26 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/DeleteAreaRequestVo.java

@@ -0,0 +1,26 @@
+package shop.alien.entity.store.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * 删除区域请求VO
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "DeleteAreaRequestVo对象", description = "删除区域请求视图对象")
+public class DeleteAreaRequestVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "区域ID", required = true, example = "1")
+    private Integer areaId;
+}
+

+ 17 - 0
alien-entity/src/main/java/shop/alien/mapper/SportsFacilityAreaMapper.java

@@ -0,0 +1,17 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import shop.alien.entity.store.SportsFacilityArea;
+
+/**
+ * 运动设施区域 Mapper 接口
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+@Mapper
+public interface SportsFacilityAreaMapper extends BaseMapper<SportsFacilityArea> {
+
+}
+

+ 218 - 0
alien-store/src/main/java/shop/alien/store/controller/SportsFacilityAreaController.java

@@ -0,0 +1,218 @@
+package shop.alien.store.controller;
+
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.SportsFacilityArea;
+import shop.alien.entity.store.vo.CreateAreaRequestVo;
+import shop.alien.entity.store.vo.DeleteAreaRequestVo;
+import shop.alien.store.service.SportsFacilityAreaService;
+
+import java.util.List;
+
+/**
+ * 运动设施区域Controller
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+@Slf4j
+@Api(tags = {"商户端-运动设施区域管理"})
+@ApiSort(2)
+@CrossOrigin
+@RestController
+@RequestMapping("/sports/facility/area")
+@RequiredArgsConstructor
+public class SportsFacilityAreaController {
+
+    private final SportsFacilityAreaService areaService;
+
+    /**
+     * 最小有效值
+     */
+    private static final int MIN_VALID_VALUE = 1;
+
+    /**
+     * 门店ID无效消息
+     */
+    private static final String INVALID_STORE_ID_MSG = "门店ID不能为空且必须大于0";
+
+    @ApiOperation("新建区域(创建新的设施区域)")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "request", value = "新建区域请求参数", dataType = "CreateAreaRequestVo", paramType = "body", required = true)
+    })
+    @PostMapping("/create")
+    public R<Integer> createArea(@RequestBody CreateAreaRequestVo request) {
+        log.info("新建区域,request={}", request);
+        try {
+            // 参数验证
+            if (request == null) {
+                log.warn("新建区域失败,请求参数为空");
+                return R.fail("请求参数不能为空");
+            }
+
+            if (request.getStoreId() == null || request.getStoreId() < MIN_VALID_VALUE) {
+                log.warn("新建区域失败,门店ID无效:{}", request.getStoreId());
+                return R.fail(INVALID_STORE_ID_MSG);
+            }
+
+            if (StringUtils.isBlank(request.getFacilityCategoryName())) {
+                log.warn("新建区域失败,区域名称为空");
+                return R.fail("区域名称不能为空");
+            }
+
+            // 调用Service创建区域
+            Integer areaId = areaService.createArea(request.getStoreId(), request.getFacilityCategoryName());
+            log.info("新建区域成功,storeId={},areaName={},区域ID={}", 
+                    request.getStoreId(), request.getFacilityCategoryName(), areaId);
+            return R.data(areaId, "新建区域成功");
+        } catch (IllegalArgumentException e) {
+            log.warn("新建区域失败,参数验证失败:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("新建区域异常,request={},异常信息:{}", request, e.getMessage(), e);
+            return R.fail("新建区域失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("查询指定门店下的所有区域列表")
+    @ApiOperationSupport(order = 2)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/list")
+    public R<List<SportsFacilityArea>> listAreas(@RequestParam("storeId") Integer storeId) {
+        log.info("查询区域列表,storeId={}", storeId);
+        try {
+            // 参数验证
+            if (storeId == null || storeId < MIN_VALID_VALUE) {
+                log.warn("查询区域列表失败,门店ID无效:{}", storeId);
+                return R.fail(INVALID_STORE_ID_MSG);
+            }
+
+            List<SportsFacilityArea> areaList = areaService.listAreas(storeId);
+            log.info("查询区域列表成功,storeId={},区域数量:{}", storeId, areaList.size());
+            return R.data(areaList);
+        } catch (IllegalArgumentException e) {
+            log.warn("查询区域列表失败,参数验证失败:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("查询区域列表异常,storeId={},异常信息:{}", storeId, e.getMessage(), e);
+            return R.fail("查询区域列表失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("更新区域信息")
+    @ApiOperationSupport(order = 3)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "areaId", value = "区域ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "areaName", value = "区域名称(可选)", dataType = "String", paramType = "query", required = false),
+            @ApiImplicitParam(name = "sortOrder", value = "排序号(可选)", dataType = "Integer", paramType = "query", required = false)
+    })
+    @PostMapping("/update")
+    public R<Boolean> updateArea(
+            @RequestParam("areaId") Integer areaId,
+            @RequestParam(required = false) String areaName,
+            @RequestParam(required = false) Integer sortOrder) {
+        log.info("更新区域,areaId={},areaName={},sortOrder={}", areaId, areaName, sortOrder);
+        try {
+            // 参数验证
+            if (areaId == null || areaId < MIN_VALID_VALUE) {
+                log.warn("更新区域失败,区域ID无效:{}", areaId);
+                return R.fail("区域ID不能为空且必须大于0");
+            }
+
+            boolean result = areaService.updateArea(areaId, areaName, sortOrder);
+            if (result) {
+                log.info("更新区域成功,areaId={}", areaId);
+                return R.success("更新区域成功");
+            }
+            return R.fail("更新区域失败");
+        } catch (IllegalArgumentException e) {
+            log.warn("更新区域失败,参数验证失败:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("更新区域异常,areaId={},异常信息:{}", areaId, e.getMessage(), e);
+            return R.fail("更新区域失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("删除区域(逻辑删除,同时删除该区域下的所有设施)")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "request", value = "删除区域请求参数", dataType = "DeleteAreaRequestVo", paramType = "body", required = true)
+    })
+    @PostMapping("/delete")
+    public R<Boolean> deleteArea(@RequestBody DeleteAreaRequestVo request) {
+        log.info("删除区域,request={}", request);
+        try {
+            // 参数验证
+            if (request == null) {
+                log.warn("删除区域失败,请求参数为空");
+                return R.fail("请求参数不能为空");
+            }
+
+            if (request.getAreaId() == null || request.getAreaId() < MIN_VALID_VALUE) {
+                log.warn("删除区域失败,区域ID无效:{}", request.getAreaId());
+                return R.fail("区域ID不能为空且必须大于0");
+            }
+
+            boolean result = areaService.deleteArea(request.getAreaId());
+            if (result) {
+                log.info("删除区域成功,areaId={}", request.getAreaId());
+                return R.success("删除区域成功");
+            }
+            return R.fail("删除区域失败");
+        } catch (IllegalArgumentException e) {
+            log.warn("删除区域失败,参数验证失败:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("删除区域异常,request={},异常信息:{}", request, e.getMessage(), e);
+            return R.fail("删除区域失败:" + e.getMessage());
+        }
+    }
+
+    @ApiOperation("批量删除区域(逻辑删除,同时删除这些区域下的所有设施)")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "门店ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "areaIds", value = "区域ID列表", dataType = "List<Integer>", paramType = "body", required = true)
+    })
+    @PostMapping("/batchDelete")
+    public R<Boolean> batchDeleteAreas(
+            @RequestParam("storeId") Integer storeId,
+            @RequestBody List<Integer> areaIds) {
+        log.info("批量删除区域,storeId={},areaIds={}", storeId, areaIds);
+        try {
+            // 参数验证
+            if (storeId == null || storeId < MIN_VALID_VALUE) {
+                log.warn("批量删除区域失败,门店ID无效:{}", storeId);
+                return R.fail(INVALID_STORE_ID_MSG);
+            }
+
+            if (areaIds == null || areaIds.isEmpty()) {
+                log.warn("批量删除区域失败,区域ID列表为空");
+                return R.fail("区域ID列表不能为空");
+            }
+
+            boolean result = areaService.batchDeleteAreas(storeId, areaIds);
+            if (result) {
+                log.info("批量删除区域成功,storeId={},区域数量:{}", storeId, areaIds.size());
+                return R.success("批量删除区域成功");
+            }
+            return R.fail("批量删除区域失败");
+        } catch (IllegalArgumentException e) {
+            log.warn("批量删除区域失败,参数验证失败:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("批量删除区域异常,storeId={},areaIds={},异常信息:{}", 
+                    storeId, areaIds, e.getMessage(), e);
+            return R.fail("批量删除区域失败:" + e.getMessage());
+        }
+    }
+}
+

+ 63 - 0
alien-store/src/main/java/shop/alien/store/service/SportsFacilityAreaService.java

@@ -0,0 +1,63 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.SportsFacilityArea;
+
+import java.util.List;
+
+/**
+ * 运动设施区域服务接口
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+public interface SportsFacilityAreaService extends IService<SportsFacilityArea> {
+
+    /**
+     * 新建区域
+     * 创建新的设施区域
+     *
+     * @param storeId  门店ID,不能为空且必须大于0
+     * @param areaName 区域名称,必填,限10字
+     * @return 创建的区域ID
+     */
+    Integer createArea(Integer storeId, String areaName);
+
+    /**
+     * 查询指定门店下的所有区域列表
+     *
+     * @param storeId 门店ID,不能为空且必须大于0
+     * @return 区域列表,按排序号升序,相同排序号按创建时间降序
+     */
+    List<SportsFacilityArea> listAreas(Integer storeId);
+
+    /**
+     * 更新区域信息
+     *
+     * @param areaId   区域ID
+     * @param areaName 区域名称(可选)
+     * @param sortOrder 排序号(可选)
+     * @return 更新是否成功
+     */
+    boolean updateArea(Integer areaId, String areaName, Integer sortOrder);
+
+    /**
+     * 删除区域(逻辑删除)
+     * 删除区域时,会同时逻辑删除该区域下的所有设施
+     *
+     * @param areaId 区域ID
+     * @return 删除是否成功
+     */
+    boolean deleteArea(Integer areaId);
+
+    /**
+     * 批量删除区域(逻辑删除)
+     * 删除区域时,会同时逻辑删除该区域下的所有设施
+     *
+     * @param storeId 门店ID
+     * @param areaIds 区域ID列表
+     * @return 删除是否成功
+     */
+    boolean batchDeleteAreas(Integer storeId, List<Integer> areaIds);
+}
+

+ 279 - 0
alien-store/src/main/java/shop/alien/store/service/impl/SportsFacilityAreaServiceImpl.java

@@ -0,0 +1,279 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import shop.alien.entity.store.SportsEquipmentFacility;
+import shop.alien.entity.store.SportsFacilityArea;
+import shop.alien.entity.store.StoreImg;
+import shop.alien.mapper.SportsEquipmentFacilityMapper;
+import shop.alien.mapper.SportsFacilityAreaMapper;
+import shop.alien.mapper.StoreImgMapper;
+import shop.alien.store.service.SportsFacilityAreaService;
+
+import java.util.List;
+
+/**
+ * 运动设施区域服务实现类
+ *
+ * @author assistant
+ * @since 2025-12-19
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+@Transactional(rollbackFor = Exception.class)
+public class SportsFacilityAreaServiceImpl extends ServiceImpl<SportsFacilityAreaMapper, SportsFacilityArea>
+        implements SportsFacilityAreaService {
+
+    private final SportsFacilityAreaMapper areaMapper;
+    private final SportsEquipmentFacilityMapper facilityMapper;
+    private final StoreImgMapper storeImgMapper;
+
+    /**
+     * 运动器材设施图片类型
+     */
+    private static final Integer IMG_TYPE_SPORTS_EQUIPMENT = 28;
+
+    /**
+     * 删除标志:未删除
+     */
+    private static final int DELETE_FLAG_NOT_DELETED = 0;
+
+    /**
+     * 删除标志:已删除
+     */
+    private static final int DELETE_FLAG_DELETED = 1;
+
+    /**
+     * 默认排序号
+     */
+    private static final int DEFAULT_SORT_ORDER = 0;
+
+    @Override
+    public Integer createArea(Integer storeId, String areaName) {
+        log.info("新建区域,storeId={},areaName={}", storeId, areaName);
+
+        // 1. 参数验证
+        if (storeId == null || storeId <= 0) {
+            log.warn("新建区域失败,门店ID无效:{}", storeId);
+            throw new IllegalArgumentException("门店ID不能为空且必须大于0");
+        }
+
+        if (StringUtils.isBlank(areaName)) {
+            log.warn("新建区域失败,区域名称为空");
+            throw new IllegalArgumentException("区域名称不能为空");
+        }
+
+        // 2. 区域名称长度验证(限10字)
+        String trimmedAreaName = areaName.trim();
+        if (trimmedAreaName.length() > 10) {
+            log.warn("新建区域失败,区域名称长度超过10字:{},长度:{}", trimmedAreaName, trimmedAreaName.length());
+            throw new IllegalArgumentException("区域名称长度不能超过10个字符");
+        }
+
+        // 3. 检查该门店下是否已存在相同名称的区域(未删除的)
+        LambdaQueryWrapper<SportsFacilityArea> checkWrapper = new LambdaQueryWrapper<>();
+        checkWrapper.eq(SportsFacilityArea::getStoreId, storeId)
+                .eq(SportsFacilityArea::getAreaName, trimmedAreaName)
+                .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED);
+        long existCount = this.count(checkWrapper);
+        if (existCount > 0) {
+            log.warn("新建区域失败,该门店下已存在相同名称的区域:storeId={},areaName={}", storeId, trimmedAreaName);
+            throw new IllegalArgumentException("该门店下已存在相同名称的区域");
+        }
+
+        // 4. 创建区域记录
+        SportsFacilityArea area = new SportsFacilityArea();
+        area.setStoreId(storeId);
+        area.setAreaName(trimmedAreaName);
+        area.setSortOrder(DEFAULT_SORT_ORDER);
+        area.setDeleteFlag(DELETE_FLAG_NOT_DELETED);
+
+        // 5. 保存到数据库
+        boolean saveResult = this.save(area);
+        if (!saveResult) {
+            log.error("新建区域失败,保存数据库失败:storeId={},areaName={}", storeId, trimmedAreaName);
+            throw new RuntimeException("新建区域失败,保存数据库失败");
+        }
+
+        log.info("新建区域成功,storeId={},areaName={},区域ID={}", storeId, trimmedAreaName, area.getId());
+        return area.getId();
+    }
+
+    @Override
+    public List<SportsFacilityArea> listAreas(Integer storeId) {
+        log.info("查询区域列表,storeId={}", storeId);
+
+        // 参数验证
+        if (storeId == null || storeId <= 0) {
+            log.warn("查询区域列表失败,门店ID无效:{}", storeId);
+            throw new IllegalArgumentException("门店ID不能为空且必须大于0");
+        }
+
+        // 查询该门店下的所有未删除区域,按排序号升序,相同排序号按创建时间降序
+        LambdaQueryWrapper<SportsFacilityArea> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.eq(SportsFacilityArea::getStoreId, storeId)
+                .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED)
+                .orderByAsc(SportsFacilityArea::getSortOrder)
+                .orderByDesc(SportsFacilityArea::getCreatedTime);
+
+        List<SportsFacilityArea> areaList = this.list(queryWrapper);
+        log.info("查询区域列表成功,storeId={},区域数量:{}", storeId, areaList.size());
+        return areaList;
+    }
+
+    @Override
+    public boolean updateArea(Integer areaId, String areaName, Integer sortOrder) {
+        log.info("更新区域,areaId={},areaName={},sortOrder={}", areaId, areaName, sortOrder);
+
+        // 参数验证
+        if (areaId == null || areaId <= 0) {
+            log.warn("更新区域失败,区域ID无效:{}", areaId);
+            throw new IllegalArgumentException("区域ID不能为空且必须大于0");
+        }
+
+        // 查询区域是否存在
+        SportsFacilityArea existingArea = this.getById(areaId);
+        if (existingArea == null || existingArea.getDeleteFlag() == DELETE_FLAG_DELETED) {
+            log.warn("更新区域失败,区域不存在或已删除:areaId={}", areaId);
+            throw new IllegalArgumentException("区域不存在或已删除");
+        }
+
+        // 构建更新条件
+        LambdaUpdateWrapper<SportsFacilityArea> updateWrapper = new LambdaUpdateWrapper<>();
+        updateWrapper.eq(SportsFacilityArea::getId, areaId);
+
+        // 更新区域名称
+        if (StringUtils.isNotBlank(areaName)) {
+            String trimmedAreaName = areaName.trim();
+            // 验证长度
+            if (trimmedAreaName.length() > 10) {
+                log.warn("更新区域失败,区域名称长度超过10字:{},长度:{}", trimmedAreaName, trimmedAreaName.length());
+                throw new IllegalArgumentException("区域名称长度不能超过10个字符");
+            }
+            // 检查是否与其他区域重复(排除自己)
+            LambdaQueryWrapper<SportsFacilityArea> checkWrapper = new LambdaQueryWrapper<>();
+            checkWrapper.eq(SportsFacilityArea::getStoreId, existingArea.getStoreId())
+                    .eq(SportsFacilityArea::getAreaName, trimmedAreaName)
+                    .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED)
+                    .ne(SportsFacilityArea::getId, areaId);
+            long existCount = this.count(checkWrapper);
+            if (existCount > 0) {
+                log.warn("更新区域失败,该门店下已存在相同名称的区域:storeId={},areaName={}", existingArea.getStoreId(), trimmedAreaName);
+                throw new IllegalArgumentException("该门店下已存在相同名称的区域");
+            }
+            updateWrapper.set(SportsFacilityArea::getAreaName, trimmedAreaName);
+        }
+
+        // 更新排序号
+        if (sortOrder != null) {
+            updateWrapper.set(SportsFacilityArea::getSortOrder, sortOrder);
+        }
+
+        // 执行更新
+        boolean updateResult = this.update(updateWrapper);
+        log.info("更新区域{},areaId={}", updateResult ? "成功" : "失败", areaId);
+        return updateResult;
+    }
+
+    @Override
+    public boolean deleteArea(Integer areaId) {
+        log.info("删除区域,areaId={}", areaId);
+
+        // 参数验证
+        if (areaId == null || areaId <= 0) {
+            log.warn("删除区域失败,区域ID无效:{}", areaId);
+            throw new IllegalArgumentException("区域ID不能为空且必须大于0");
+        }
+
+        // 查询区域是否存在
+        SportsFacilityArea area = this.getById(areaId);
+        if (area == null || area.getDeleteFlag() == DELETE_FLAG_DELETED) {
+            log.warn("删除区域失败,区域不存在或已删除:areaId={}", areaId);
+            throw new IllegalArgumentException("区域不存在或已删除");
+        }
+
+        // 1. 逻辑删除区域
+        LambdaUpdateWrapper<SportsFacilityArea> areaUpdateWrapper = new LambdaUpdateWrapper<>();
+        areaUpdateWrapper.eq(SportsFacilityArea::getId, areaId)
+                .set(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_DELETED);
+        boolean deleteAreaResult = this.update(areaUpdateWrapper);
+
+        // 2. 逻辑删除该区域下的所有设施
+        LambdaUpdateWrapper<SportsEquipmentFacility> facilityUpdateWrapper = new LambdaUpdateWrapper<>();
+        facilityUpdateWrapper.eq(SportsEquipmentFacility::getAreaId, areaId)
+                .set(SportsEquipmentFacility::getDeleteFlag, DELETE_FLAG_DELETED);
+        int deletedFacilityCount = facilityMapper.update(null, facilityUpdateWrapper);
+
+        // 3. 物理删除该区域下的所有实景图片
+        LambdaQueryWrapper<StoreImg> deleteImageWrapper = new LambdaQueryWrapper<>();
+        deleteImageWrapper.eq(StoreImg::getStoreId, area.getStoreId())
+                .eq(StoreImg::getBusinessId, areaId)
+                .eq(StoreImg::getImgType, IMG_TYPE_SPORTS_EQUIPMENT);
+        int deletedImageCount = storeImgMapper.delete(deleteImageWrapper);
+
+        log.info("删除区域{},areaId={},同时删除了{}个设施和{}张图片", 
+                deleteAreaResult ? "成功" : "失败", areaId, deletedFacilityCount, deletedImageCount);
+        return deleteAreaResult;
+    }
+
+    @Override
+    public boolean batchDeleteAreas(Integer storeId, List<Integer> areaIds) {
+        log.info("批量删除区域,storeId={},areaIds={}", storeId, areaIds);
+
+        // 参数验证
+        if (storeId == null || storeId <= 0) {
+            log.warn("批量删除区域失败,门店ID无效:{}", storeId);
+            throw new IllegalArgumentException("门店ID不能为空且必须大于0");
+        }
+
+        if (CollectionUtils.isEmpty(areaIds)) {
+            log.warn("批量删除区域失败,区域ID列表为空");
+            throw new IllegalArgumentException("区域ID列表不能为空");
+        }
+
+        // 验证所有区域都属于该门店
+        LambdaQueryWrapper<SportsFacilityArea> checkWrapper = new LambdaQueryWrapper<>();
+        checkWrapper.eq(SportsFacilityArea::getStoreId, storeId)
+                .in(SportsFacilityArea::getId, areaIds)
+                .eq(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_NOT_DELETED);
+        long validCount = this.count(checkWrapper);
+        if (validCount != areaIds.size()) {
+            log.warn("批量删除区域失败,部分区域不存在或不属于该门店:storeId={},areaIds={},有效数量={}", storeId, areaIds, validCount);
+            throw new IllegalArgumentException("部分区域不存在或不属于该门店");
+        }
+
+        // 1. 批量逻辑删除区域
+        LambdaUpdateWrapper<SportsFacilityArea> areaUpdateWrapper = new LambdaUpdateWrapper<>();
+        areaUpdateWrapper.eq(SportsFacilityArea::getStoreId, storeId)
+                .in(SportsFacilityArea::getId, areaIds)
+                .set(SportsFacilityArea::getDeleteFlag, DELETE_FLAG_DELETED);
+        boolean deleteAreaResult = this.update(areaUpdateWrapper);
+
+        // 2. 批量逻辑删除这些区域下的所有设施
+        LambdaUpdateWrapper<SportsEquipmentFacility> facilityUpdateWrapper = new LambdaUpdateWrapper<>();
+        facilityUpdateWrapper.eq(SportsEquipmentFacility::getStoreId, storeId)
+                .in(SportsEquipmentFacility::getAreaId, areaIds)
+                .set(SportsEquipmentFacility::getDeleteFlag, DELETE_FLAG_DELETED);
+        int deletedFacilityCount = facilityMapper.update(null, facilityUpdateWrapper);
+
+        // 3. 批量物理删除这些区域下的所有实景图片
+        LambdaQueryWrapper<StoreImg> deleteImageWrapper = new LambdaQueryWrapper<>();
+        deleteImageWrapper.eq(StoreImg::getStoreId, storeId)
+                .in(StoreImg::getBusinessId, areaIds)
+                .eq(StoreImg::getImgType, IMG_TYPE_SPORTS_EQUIPMENT);
+        int deletedImageCount = storeImgMapper.delete(deleteImageWrapper);
+
+        log.info("批量删除区域{},storeId={},区域数量={},同时删除了{}个设施和{}张图片", 
+                deleteAreaResult ? "成功" : "失败", storeId, areaIds.size(), deletedFacilityCount, deletedImageCount);
+        return deleteAreaResult;
+    }
+}
+