zhangchen hace 3 meses
padre
commit
17d3eae9a1

+ 103 - 0
alien-entity/src/main/java/shop/alien/entity/store/StoreStaffTitle.java

@@ -0,0 +1,103 @@
+package shop.alien.entity.store;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+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 lombok.EqualsAndHashCode;
+
+import java.util.Date;
+
+/**
+ * 员工标题实体类
+ * 对应表: store_staff_title
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@TableName("store_staff_title")
+@ApiModel(value = "StoreStaffTitle对象", description = "员工标题")
+public class StoreStaffTitle extends Model<StoreStaffTitle> {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键ID
+     */
+    @ApiModelProperty(value = "主键ID")
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 门店ID
+     */
+    @ApiModelProperty(value = "门店ID")
+    @TableField("store_id")
+    private Integer storeId;
+
+    /**
+     * 员工IDs(逗号分隔)
+     */
+    @ApiModelProperty(value = "员工IDs(逗号分隔)")
+    @TableField("staff_ids")
+    private String staffIds;
+
+    /**
+     * 标题名称
+     */
+    @ApiModelProperty(value = "标题名称")
+    @TableField("title_name")
+    private String titleName;
+
+    /**
+     * 员工数量
+     */
+    @ApiModelProperty(value = "员工数量")
+    @TableField("staff_count")
+    private Integer staffCount;
+
+    /**
+     * 删除状态(0-未删除,1-已删除)
+     */
+    @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 = "更新时间")
+    @TableField(value = "updated_time", fill = FieldFill.INSERT_UPDATE)
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date updatedTime;
+
+    /**
+     * 创建人ID
+     */
+    @ApiModelProperty(value = "创建人ID")
+    @TableField("created_user_id")
+    private Integer createdUserId;
+
+    /**
+     * 修改人ID
+     */
+    @ApiModelProperty(value = "修改人ID")
+    @TableField("updated_user_id")
+    private Integer updatedUserId;
+}
+

+ 50 - 0
alien-entity/src/main/java/shop/alien/entity/store/vo/StaffTitleGroupVo.java

@@ -0,0 +1,50 @@
+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 shop.alien.entity.store.StoreStaffConfig;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 员工标题分组VO
+ * 用于按标题分组展示员工列表
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Data
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@ApiModel(value = "StaffTitleGroupVo对象", description = "员工标题分组")
+public class StaffTitleGroupVo implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 标题ID
+     */
+    @ApiModelProperty(value = "标题ID")
+    private Integer titleId;
+
+    /**
+     * 标题名称(人员阵容名称)
+     */
+    @ApiModelProperty(value = "标题名称(人员阵容名称)")
+    private String titleName;
+
+    /**
+     * 员工数量
+     */
+    @ApiModelProperty(value = "员工数量")
+    private Integer staffCount;
+
+    /**
+     * 员工列表
+     */
+    @ApiModelProperty(value = "员工列表")
+    private List<StoreStaffConfig> staffList;
+}
+

+ 14 - 0
alien-entity/src/main/java/shop/alien/mapper/StoreStaffTitleMapper.java

@@ -0,0 +1,14 @@
+package shop.alien.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import shop.alien.entity.store.StoreStaffTitle;
+
+/**
+ * 员工标题Mapper接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StoreStaffTitleMapper extends BaseMapper<StoreStaffTitle> {
+}
+

+ 95 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreStaffConfigController.java

@@ -10,6 +10,7 @@ import shop.alien.entity.result.R;
 import shop.alien.entity.store.StoreDictionary;
 import shop.alien.entity.store.StoreStaffConfig;
 import shop.alien.entity.store.dto.StoreStaffConfigListQueryDto;
+import shop.alien.entity.store.vo.StaffTitleGroupVo;
 import shop.alien.entity.store.vo.StoreStaffDetailVo;
 import shop.alien.entity.store.vo.StoreStaffDetailWithPerformanceVo;
 import shop.alien.entity.store.vo.StoreStaffFitnessDetailVo;
@@ -265,6 +266,100 @@ public class StoreStaffConfigController {
     }
 
     /**
+     * 员工列表查询(按标题分组)(用户端)
+     * <p>
+     * 根据店铺ID查询store_staff_title表中的记录,并通过staff_ids关联出store_staff_config
+     * 返回按标题分组的员工列表,每个标题下包含对应的员工信息
+     * 保留原有逻辑:今日是否有演出、点赞数、好评数等
+     * </p>
+     *
+     * @param storeId 店铺ID,必填,必须大于0
+     * @return 按标题分组的员工列表
+     */
+    @ApiOperation("员工列表查询(按标题分组)(用户端)")
+    @ApiOperationSupport(order = 7)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/queryStaffListByTitle")
+    public R<List<StaffTitleGroupVo>> queryStaffListByTitle(
+            @RequestParam(value = "storeId") Integer storeId) {
+        log.info("查询员工列表(按标题分组),参数:storeId={}", storeId);
+
+        try {
+            // 参数校验
+            if (storeId == null || storeId <= 0) {
+                log.warn("查询员工列表(按标题分组)参数校验失败,店铺ID无效:storeId={}", storeId);
+                return R.fail("店铺ID不能为空且必须大于0");
+            }
+
+            // 调用服务层查询
+            List<StaffTitleGroupVo> result = storeStaffConfigService.queryStaffListByTitle(storeId);
+
+            log.info("查询员工列表(按标题分组)成功,店铺ID={},标题数量:{}", storeId, result != null ? result.size() : 0);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("查询员工列表(按标题分组)参数错误,storeId={},错误信息:{}", storeId, e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("查询员工列表(按标题分组)异常,storeId={},异常信息:{}", storeId, e.getMessage(), e);
+            return R.fail("查询员工列表(按标题分组)失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 根据标题ID查询员工列表(用户端)
+     * <p>
+     * 根据店铺ID和标题ID查询store_staff_title表中的记录,并通过staff_ids关联出store_staff_config
+     * 返回该标题下的员工列表
+     * 保留原有逻辑:今日是否有演出、点赞数、好评数等
+     * </p>
+     *
+     * @param storeId 店铺ID,必填,必须大于0
+     * @param titleId 标题ID,必填,必须大于0
+     * @return 员工列表
+     */
+    @ApiOperation("根据标题ID查询员工列表(用户端)")
+    @ApiOperationSupport(order = 8)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query", required = true),
+            @ApiImplicitParam(name = "titleId", value = "标题ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/queryStaffListByTitleId")
+    public R<List<StoreStaffConfig>> queryStaffListByTitleId(
+            @RequestParam(value = "storeId") Integer storeId,
+            @RequestParam(value = "titleId") Integer titleId) {
+        log.info("根据标题ID查询员工列表,参数:storeId={}, titleId={}", storeId, titleId);
+
+        try {
+            // 参数校验
+            if (storeId == null || storeId <= 0) {
+                log.warn("根据标题ID查询员工列表参数校验失败,店铺ID无效:storeId={}", storeId);
+                return R.fail("店铺ID不能为空且必须大于0");
+            }
+            if (titleId == null || titleId <= 0) {
+                log.warn("根据标题ID查询员工列表参数校验失败,标题ID无效:titleId={}", titleId);
+                return R.fail("标题ID不能为空且必须大于0");
+            }
+
+            // 调用服务层查询
+            List<StoreStaffConfig> result = storeStaffConfigService.queryStaffListByTitleId(storeId, titleId);
+
+            log.info("根据标题ID查询员工列表成功,店铺ID={},标题ID={},员工数量:{}", 
+                    storeId, titleId, result != null ? result.size() : 0);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("根据标题ID查询员工列表参数错误,storeId={}, titleId={},错误信息:{}", 
+                    storeId, titleId, e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("根据标题ID查询员工列表异常,storeId={}, titleId={},异常信息:{}", 
+                    storeId, titleId, e.getMessage(), e);
+            return R.fail("根据标题ID查询员工列表失败,请稍后重试");
+        }
+    }
+
+    /**
      * 查询擅长类型和标签(用于人员配置)
      * 返回格式:{types: [{id, dictId, dictDetail, typeDetail, tags: [...]}]}
      *

+ 252 - 0
alien-store/src/main/java/shop/alien/store/controller/StoreStaffTitleController.java

@@ -0,0 +1,252 @@
+package shop.alien.store.controller;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import io.swagger.annotations.*;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import shop.alien.entity.result.R;
+import shop.alien.entity.store.StoreStaffTitle;
+import shop.alien.store.service.StoreStaffTitleService;
+import shop.alien.store.util.CommonConstant;
+
+/**
+ * 员工标题Controller
+ * 提供员工标题的增删改查接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Api(tags = {"员工标题管理"})
+@CrossOrigin
+@RestController
+@RequestMapping("/storeStaffTitle")
+@RequiredArgsConstructor
+public class StoreStaffTitleController {
+
+    private final StoreStaffTitleService storeStaffTitleService;
+
+    /**
+     * 分页查询员工标题列表
+     * <p>
+     * 根据店铺ID查询员工标题列表,支持分页
+     * 只返回未删除的记录
+     * </p>
+     *
+     * @param page    分页页数,默认1,必须大于0
+     * @param size    分页条数,默认10,必须大于0且不超过100
+     * @param storeId 店铺ID,可选
+     * @return 员工标题列表分页结果
+     */
+    @ApiOperation("分页查询员工标题列表")
+    @ApiOperationSupport(order = 1)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "page", value = "分页页数", dataType = "Integer", paramType = "query", required = false),
+            @ApiImplicitParam(name = "size", value = "分页条数", dataType = "Integer", paramType = "query", required = false),
+            @ApiImplicitParam(name = "storeId", value = "店铺ID", dataType = "Integer", paramType = "query", required = false)
+    })
+    @GetMapping("/query")
+    public R<IPage<StoreStaffTitle>> queryStaffTitleList(
+            @RequestParam(value = "page", defaultValue = "1") Integer page,
+            @RequestParam(value = "size", defaultValue = "10") Integer size,
+            @RequestParam(value = "storeId", required = false) Integer storeId) {
+        log.info("查询员工标题列表,参数:page={}, size={}, storeId={}", page, size, storeId);
+
+        try {
+            // 参数校验
+            if (page != null && page < 1) {
+                log.warn("查询员工标题列表参数校验失败,分页页数无效:page={}", page);
+                return R.fail("分页页数必须大于0");
+            }
+            if (size != null && size < 1) {
+                log.warn("查询员工标题列表参数校验失败,分页条数无效:size={}", size);
+                return R.fail("分页条数必须大于0");
+            }
+            if (size != null && size > CommonConstant.MAX_PAGE_SIZE) {
+                log.warn("查询员工标题列表参数校验失败,分页条数超过最大值:size={}", size);
+                return R.fail("分页条数不能超过" + CommonConstant.MAX_PAGE_SIZE);
+            }
+
+            // 规范化分页参数
+            Integer normalizedPage = (page == null || page < 1) ? CommonConstant.DEFAULT_PAGE_NUM : page;
+            Integer normalizedSize;
+            if (size == null || size < 1) {
+                normalizedSize = CommonConstant.DEFAULT_PAGE_SIZE;
+            } else if (size > CommonConstant.MAX_PAGE_SIZE) {
+                normalizedSize = CommonConstant.MAX_PAGE_SIZE;
+            } else {
+                normalizedSize = size;
+            }
+
+            // 调用服务层查询
+            IPage<StoreStaffTitle> result = storeStaffTitleService.queryStaffTitleList(
+                    normalizedPage, normalizedSize, storeId);
+
+            log.info("查询员工标题列表成功,共{}条记录,当前页{}条",
+                    result.getTotal(), result.getRecords() != null ? result.getRecords().size() : 0);
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("查询员工标题列表参数错误,错误信息:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("查询员工标题列表异常,异常信息:{}", e.getMessage(), e);
+            return R.fail("查询员工标题列表失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 新增员工标题
+     * <p>
+     * 新增员工标题,自动计算员工数量
+     * </p>
+     *
+     * @param storeStaffTitle 员工标题信息
+     * @return 新增结果
+     */
+    @ApiOperation("新增员工标题")
+    @ApiOperationSupport(order = 2)
+    @PostMapping("/add")
+    public R<String> addStaffTitle(@RequestBody StoreStaffTitle storeStaffTitle) {
+        log.info("新增员工标题,参数:{}", storeStaffTitle);
+
+        try {
+            Integer result = storeStaffTitleService.addStaffTitle(storeStaffTitle);
+
+            if (result > 0) {
+                log.info("新增员工标题成功,id={}", storeStaffTitle.getId());
+                return R.data("新增员工标题成功");
+            } else {
+                log.warn("新增员工标题失败,插入记录数为0");
+                return R.fail("新增员工标题失败");
+            }
+        } catch (IllegalArgumentException e) {
+            log.warn("新增员工标题参数错误,错误信息:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("新增员工标题异常,异常信息:{}", e.getMessage(), e);
+            return R.fail("新增员工标题失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 更新员工标题
+     * <p>
+     * 更新员工标题信息,自动重新计算员工数量
+     * </p>
+     *
+     * @param storeStaffTitle 员工标题信息
+     * @return 更新结果
+     */
+    @ApiOperation("更新员工标题")
+    @ApiOperationSupport(order = 3)
+    @PostMapping("/update")
+    public R<String> updateStaffTitle(@RequestBody StoreStaffTitle storeStaffTitle) {
+        log.info("更新员工标题,参数:{}", storeStaffTitle);
+
+        try {
+            Integer result = storeStaffTitleService.updateStaffTitle(storeStaffTitle);
+
+            if (result > 0) {
+                log.info("更新员工标题成功,id={}", storeStaffTitle.getId());
+                return R.data("更新员工标题成功");
+            } else {
+                log.warn("更新员工标题失败,更新记录数为0,id={}", storeStaffTitle.getId());
+                return R.fail("更新员工标题失败,记录不存在或已被删除");
+            }
+        } catch (IllegalArgumentException e) {
+            log.warn("更新员工标题参数错误,错误信息:{}", e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("更新员工标题异常,id={},异常信息:{}", storeStaffTitle.getId(), e.getMessage(), e);
+            return R.fail("更新员工标题失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 删除员工标题(逻辑删除)
+     * <p>
+     * 根据ID逻辑删除员工标题
+     * </p>
+     *
+     * @param id 员工标题ID,必填,必须大于0
+     * @return 删除结果
+     */
+    @ApiOperation("删除员工标题")
+    @ApiOperationSupport(order = 4)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "员工标题ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/delete")
+    public R<String> deleteStaffTitle(@RequestParam(value = "id") Integer id) {
+        log.info("删除员工标题,参数:id={}", id);
+
+        try {
+            // 参数校验
+            if (id == null || id <= 0) {
+                log.warn("删除员工标题参数校验失败,ID无效:id={}", id);
+                return R.fail("员工标题ID不能为空且必须大于0");
+            }
+
+            Integer result = storeStaffTitleService.deleteStaffTitle(id);
+
+            if (result > 0) {
+                log.info("删除员工标题成功,id={}", id);
+                return R.data("删除员工标题成功");
+            } else {
+                log.warn("删除员工标题失败,删除记录数为0,id={}", id);
+                return R.fail("删除员工标题失败,记录不存在或已被删除");
+            }
+        } catch (IllegalArgumentException e) {
+            log.warn("删除员工标题参数错误,id={},错误信息:{}", id, e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("删除员工标题异常,id={},异常信息:{}", id, e.getMessage(), e);
+            return R.fail("删除员工标题失败,请稍后重试");
+        }
+    }
+
+    /**
+     * 查询员工标题详情
+     * <p>
+     * 根据ID查询员工标题详细信息
+     * </p>
+     *
+     * @param id 员工标题ID,必填,必须大于0
+     * @return 员工标题详情
+     */
+    @ApiOperation("查询员工标题详情")
+    @ApiOperationSupport(order = 5)
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "员工标题ID", dataType = "Integer", paramType = "query", required = true)
+    })
+    @GetMapping("/detail")
+    public R<StoreStaffTitle> getStaffTitleDetail(@RequestParam(value = "id") Integer id) {
+        log.info("查询员工标题详情,参数:id={}", id);
+
+        try {
+            // 参数校验
+            if (id == null || id <= 0) {
+                log.warn("查询员工标题详情参数校验失败,ID无效:id={}", id);
+                return R.fail("员工标题ID不能为空且必须大于0");
+            }
+
+            StoreStaffTitle result = storeStaffTitleService.getStaffTitleDetail(id);
+
+            if (result == null) {
+                log.warn("查询员工标题详情失败,记录不存在:id={}", id);
+                return R.fail("员工标题不存在");
+            }
+
+            log.info("查询员工标题详情成功,id={},标题名称={}", id, result.getTitleName());
+            return R.data(result);
+        } catch (IllegalArgumentException e) {
+            log.warn("查询员工标题详情参数错误,id={},错误信息:{}", id, e.getMessage());
+            return R.fail(e.getMessage());
+        } catch (Exception e) {
+            log.error("查询员工标题详情异常,id={},异常信息:{}", id, e.getMessage(), e);
+            return R.fail("查询员工标题详情失败,请稍后重试");
+        }
+    }
+}
+

+ 27 - 0
alien-store/src/main/java/shop/alien/store/service/StoreStaffConfigService.java

@@ -90,6 +90,33 @@ public interface StoreStaffConfigService {
     IPage<StoreStaffConfig> queryStaffList(Integer page, Integer size, Integer storeId, String status, String staffPosition);
 
     /**
+     * 员工列表查询(按标题分组)(用户端)
+     * <p>
+     * 根据店铺ID查询store_staff_title表中的记录,并通过staff_ids关联出store_staff_config
+     * 返回按标题分组的员工列表,每个标题下包含对应的员工信息
+     * 保留原有逻辑:今日是否有演出、点赞数、好评数等
+     * </p>
+     *
+     * @param storeId 店铺ID,必须大于0
+     * @return 按标题分组的员工列表
+     */
+    List<shop.alien.entity.store.vo.StaffTitleGroupVo> queryStaffListByTitle(Integer storeId);
+
+    /**
+     * 根据标题ID查询员工列表(用户端)
+     * <p>
+     * 根据店铺ID和标题ID查询store_staff_title表中的记录,并通过staff_ids关联出store_staff_config
+     * 返回该标题下的员工列表
+     * 保留原有逻辑:今日是否有演出、点赞数、好评数等
+     * </p>
+     *
+     * @param storeId 店铺ID,必须大于0
+     * @param titleId 标题ID,必须大于0
+     * @return 员工列表
+     */
+    List<StoreStaffConfig> queryStaffListByTitleId(Integer storeId, Integer titleId);
+
+    /**
      * 员工详情查询(用户端)
      *
      * @param id 员工主键id

+ 73 - 0
alien-store/src/main/java/shop/alien/store/service/StoreStaffTitleService.java

@@ -0,0 +1,73 @@
+package shop.alien.store.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import shop.alien.entity.store.StoreStaffTitle;
+
+/**
+ * 员工标题服务接口
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+public interface StoreStaffTitleService extends IService<StoreStaffTitle> {
+
+    /**
+     * 分页查询员工标题列表
+     * <p>
+     * 根据店铺ID查询员工标题列表,支持分页
+     * 只返回未删除的记录
+     * </p>
+     *
+     * @param page    分页页数,必须大于0
+     * @param size    分页条数,必须大于0且不超过100
+     * @param storeId 店铺ID,可选
+     * @return 员工标题列表分页结果
+     */
+    IPage<StoreStaffTitle> queryStaffTitleList(Integer page, Integer size, Integer storeId);
+
+    /**
+     * 新增员工标题
+     * <p>
+     * 新增员工标题,自动计算员工数量
+     * </p>
+     *
+     * @param storeStaffTitle 员工标题信息
+     * @return 新增结果,成功返回1,失败返回0
+     */
+    Integer addStaffTitle(StoreStaffTitle storeStaffTitle);
+
+    /**
+     * 更新员工标题
+     * <p>
+     * 更新员工标题信息,自动重新计算员工数量
+     * </p>
+     *
+     * @param storeStaffTitle 员工标题信息
+     * @return 更新结果,成功返回1,失败返回0
+     */
+    Integer updateStaffTitle(StoreStaffTitle storeStaffTitle);
+
+    /**
+     * 删除员工标题(逻辑删除)
+     * <p>
+     * 根据ID逻辑删除员工标题
+     * </p>
+     *
+     * @param id 员工标题ID,必须大于0
+     * @return 删除结果,成功返回1,失败返回0
+     */
+    Integer deleteStaffTitle(Integer id);
+
+    /**
+     * 查询员工标题详情
+     * <p>
+     * 根据ID查询员工标题详细信息
+     * </p>
+     *
+     * @param id 员工标题ID,必须大于0
+     * @return 员工标题详情,如果不存在则返回null
+     */
+    StoreStaffTitle getStaffTitleDetail(Integer id);
+}
+

+ 266 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreStaffConfigServiceImpl.java

@@ -24,6 +24,9 @@ import shop.alien.entity.store.StoreStaffFitnessCertification;
 import shop.alien.entity.store.StoreStaffFitnessCourse;
 import shop.alien.entity.store.StoreStaffFitnessExperience;
 import shop.alien.entity.store.vo.PerformanceScheduleVo;
+import shop.alien.entity.store.StoreComment;
+import shop.alien.entity.store.StoreStaffTitle;
+import shop.alien.entity.store.vo.StaffTitleGroupVo;
 import shop.alien.entity.store.vo.StoreStaffDetailVo;
 import shop.alien.entity.store.vo.StoreStaffDetailWithPerformanceVo;
 import shop.alien.entity.store.vo.StoreStaffFitnessDetailVo;
@@ -43,8 +46,11 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 
@@ -87,6 +93,10 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
 
     private final BarPerformanceMapper barPerformanceMapper;
 
+    private final StoreStaffTitleMapper storeStaffTitleMapper;
+
+    private final StoreCommentMapper storeCommentMapper;
+
     private final StoreStaffFitnessExperienceService storeStaffFitnessExperienceService;
 
     /**
@@ -1848,4 +1858,260 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
         log.info("查询员工职位统计成功,storeId={},职位数量:{}", storeId, result.size());
         return result;
     }
+
+    /**
+     * 员工列表查询(按标题分组)(用户端)
+     * <p>
+     * 根据店铺ID查询store_staff_title表中的记录,并通过staff_ids关联出store_staff_config
+     * 返回按标题分组的员工列表,每个标题下包含对应的员工信息
+     * 保留原有逻辑:今日是否有演出、点赞数、好评数等
+     * </p>
+     *
+     * @param storeId 店铺ID,必须大于0
+     * @return 按标题分组的员工列表
+     */
+    @Override
+    public List<StaffTitleGroupVo> queryStaffListByTitle(Integer storeId) {
+        log.info("查询员工列表(按标题分组),参数:storeId={}", storeId);
+
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            log.warn("查询员工列表(按标题分组)失败,店铺ID无效:storeId={}", storeId);
+            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
+        }
+
+        try {
+            // 1. 查询store_staff_title表中的记录
+            LambdaQueryWrapper<StoreStaffTitle> titleWrapper = new LambdaQueryWrapper<>();
+            titleWrapper.eq(StoreStaffTitle::getStoreId, storeId)
+                    .eq(StoreStaffTitle::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
+                    .orderByAsc(StoreStaffTitle::getCreatedTime);
+
+            List<StoreStaffTitle> titleList = storeStaffTitleMapper.selectList(titleWrapper);
+
+            if (titleList == null || titleList.isEmpty()) {
+                log.info("查询员工列表(按标题分组)成功,但未找到标题记录,storeId={}", storeId);
+                return new ArrayList<>();
+            }
+
+            // 2. 收集所有员工ID
+            List<Integer> allStaffIds = new ArrayList<>();
+            for (StoreStaffTitle title : titleList) {
+                if (StringUtils.isNotEmpty(title.getStaffIds())) {
+                    List<Integer> staffIds = parseStaffConfigIds(title.getStaffIds());
+                    allStaffIds.addAll(staffIds);
+                }
+            }
+
+            if (allStaffIds.isEmpty()) {
+                log.info("查询员工列表(按标题分组)成功,但未找到员工ID,storeId={}", storeId);
+                return new ArrayList<>();
+            }
+
+            // 3. 批量查询员工信息
+            List<StoreStaffConfig> allStaffList = storeStaffConfigMapper.selectBatchIds(allStaffIds);
+
+            // 4. 构建员工ID到员工对象的映射
+            Map<Integer, StoreStaffConfig> staffMap = allStaffList.stream()
+                    .filter(staff -> staff != null && CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag()))
+                    .collect(Collectors.toMap(StoreStaffConfig::getId, staff -> staff, (a, b) -> a));
+
+            // 5. 批量查询今日有演出的员工ID集合(性能优化)
+            Set<Integer> staffIdsWithPerformanceToday = queryStaffIdsWithPerformanceToday(allStaffIds);
+
+            // 6. 批量查询员工好评数(business_type=5, score>=4.5, business_id=员工ID)
+            Map<Integer, Integer> positiveCommentsCountMap = queryPositiveCommentsCountMap(allStaffIds, storeId);
+
+            // 7. 按标题分组构建结果
+            List<StaffTitleGroupVo> result = new ArrayList<>();
+            for (StoreStaffTitle title : titleList) {
+                StaffTitleGroupVo groupVo = new StaffTitleGroupVo();
+                groupVo.setTitleId(title.getId());
+                groupVo.setTitleName(title.getTitleName());
+                groupVo.setStaffCount(title.getStaffCount());
+
+                // 解析该标题下的员工ID
+                List<Integer> titleStaffIds = parseStaffConfigIds(title.getStaffIds());
+                List<StoreStaffConfig> titleStaffList = new ArrayList<>();
+
+                for (Integer staffId : titleStaffIds) {
+                    StoreStaffConfig staff = staffMap.get(staffId);
+                    if (staff != null) {
+                        // 填充今日是否有演出
+                        Boolean hasPerformanceToday = staffIdsWithPerformanceToday.contains(staffId);
+                        staff.setHasPerformanceToday(hasPerformanceToday);
+
+                        // 填充好评数
+                        Integer positiveCommentsCount = positiveCommentsCountMap.getOrDefault(staffId, 0);
+                        staff.setPositiveCommentsCount(positiveCommentsCount);
+
+                        titleStaffList.add(staff);
+                    }
+                }
+
+                groupVo.setStaffList(titleStaffList);
+                result.add(groupVo);
+            }
+
+            log.info("查询员工列表(按标题分组)成功,storeId={},标题数量:{}", storeId, result.size());
+            return result;
+        } catch (Exception e) {
+            log.error("查询员工列表(按标题分组)异常,storeId={},异常信息:{}", storeId, e.getMessage(), e);
+            throw new RuntimeException("查询员工列表(按标题分组)失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 批量查询员工好评数
+     * <p>
+     * 查询每个员工的好评数量(business_type=5, score>=4.5, business_id=员工ID)
+     * </p>
+     *
+     * @param staffIds 员工ID列表
+     * @param storeId  店铺ID
+     * @return 员工ID到好评数的映射
+     */
+    private Map<Integer, Integer> queryPositiveCommentsCountMap(List<Integer> staffIds, Integer storeId) {
+        Map<Integer, Integer> countMap = new HashMap<>();
+
+        if (staffIds == null || staffIds.isEmpty()) {
+            return countMap;
+        }
+
+        try {
+            // 查询好评(business_type=5, score>=4.5, business_id in staffIds)
+            LambdaQueryWrapper<StoreComment> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(StoreComment::getStoreId, storeId)
+                    .eq(StoreComment::getBusinessType, 5)
+                    .eq(StoreComment::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
+                    .isNull(StoreComment::getReplyId)
+                    .ge(StoreComment::getScore, 4.5)
+                    .in(StoreComment::getBusinessId, staffIds);
+
+            List<StoreComment> positiveComments = storeCommentMapper.selectList(queryWrapper);
+
+            if (positiveComments != null && !positiveComments.isEmpty()) {
+                // 按business_id分组统计
+                Map<Integer, Long> countMapLong = positiveComments.stream()
+                        .collect(Collectors.groupingBy(StoreComment::getBusinessId, Collectors.counting()));
+
+                // 转换为Integer
+                for (Map.Entry<Integer, Long> entry : countMapLong.entrySet()) {
+                    countMap.put(entry.getKey(), entry.getValue().intValue());
+                }
+            }
+        } catch (Exception e) {
+            log.error("批量查询员工好评数异常,异常信息:{}", e.getMessage(), e);
+        }
+
+        return countMap;
+    }
+
+    /**
+     * 根据标题ID查询员工列表(用户端)
+     * <p>
+     * 根据店铺ID和标题ID查询store_staff_title表中的记录,并通过staff_ids关联出store_staff_config
+     * 返回该标题下的员工列表
+     * 保留原有逻辑:今日是否有演出、点赞数、好评数等
+     * </p>
+     *
+     * @param storeId 店铺ID,必须大于0
+     * @param titleId 标题ID,必须大于0
+     * @return 员工列表
+     */
+    @Override
+    public List<StoreStaffConfig> queryStaffListByTitleId(Integer storeId, Integer titleId) {
+        log.info("根据标题ID查询员工列表,参数:storeId={}, titleId={}", storeId, titleId);
+
+        // 参数校验
+        if (storeId == null || storeId <= 0) {
+            log.warn("根据标题ID查询员工列表失败,店铺ID无效:storeId={}", storeId);
+            throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
+        }
+        if (titleId == null || titleId <= 0) {
+            log.warn("根据标题ID查询员工列表失败,标题ID无效:titleId={}", titleId);
+            throw new IllegalArgumentException("标题ID不能为空且必须大于0");
+        }
+
+        try {
+            // 1. 查询store_staff_title表中的记录
+            LambdaQueryWrapper<StoreStaffTitle> titleWrapper = new LambdaQueryWrapper<>();
+            titleWrapper.eq(StoreStaffTitle::getId, titleId)
+                    .eq(StoreStaffTitle::getStoreId, storeId)
+                    .eq(StoreStaffTitle::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);
+
+            StoreStaffTitle title = storeStaffTitleMapper.selectOne(titleWrapper);
+
+            if (title == null) {
+                log.warn("根据标题ID查询员工列表失败,标题记录不存在:storeId={}, titleId={}", storeId, titleId);
+                return new ArrayList<>();
+            }
+
+            // 2. 解析员工IDs
+            if (StringUtils.isEmpty(title.getStaffIds())) {
+                log.info("根据标题ID查询员工列表成功,但标题下无员工:storeId={}, titleId={}", storeId, titleId);
+                return new ArrayList<>();
+            }
+
+            List<Integer> staffIds = parseStaffConfigIds(title.getStaffIds());
+
+            if (staffIds.isEmpty()) {
+                log.info("根据标题ID查询员工列表成功,但解析员工ID为空:storeId={}, titleId={}", storeId, titleId);
+                return new ArrayList<>();
+            }
+
+            // 3. 批量查询员工信息
+            List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectBatchIds(staffIds);
+
+            if (staffList == null || staffList.isEmpty()) {
+                log.info("根据标题ID查询员工列表成功,但未找到员工记录:storeId={}, titleId={}", storeId, titleId);
+                return new ArrayList<>();
+            }
+
+            // 4. 过滤已删除的员工
+            List<StoreStaffConfig> validStaffList = staffList.stream()
+                    .filter(staff -> staff != null && CommonConstant.DELETE_FLAG_UNDELETE.equals(staff.getDeleteFlag()))
+                    .collect(Collectors.toList());
+
+            if (validStaffList.isEmpty()) {
+                log.info("根据标题ID查询员工列表成功,但有效员工为空:storeId={}, titleId={}", storeId, titleId);
+                return new ArrayList<>();
+            }
+
+            // 5. 批量查询今日有演出的员工ID集合(性能优化)
+            List<Integer> validStaffIds = validStaffList.stream()
+                    .map(StoreStaffConfig::getId)
+                    .filter(id -> id != null && id > 0)
+                    .collect(Collectors.toList());
+
+            Set<Integer> staffIdsWithPerformanceToday = queryStaffIdsWithPerformanceToday(validStaffIds);
+
+            // 6. 批量查询员工好评数
+            Map<Integer, Integer> positiveCommentsCountMap = queryPositiveCommentsCountMap(validStaffIds, storeId);
+
+            // 7. 填充字段
+            for (StoreStaffConfig staff : validStaffList) {
+                if (staff.getId() != null) {
+                    // 填充今日是否有演出
+                    Boolean hasPerformanceToday = staffIdsWithPerformanceToday.contains(staff.getId());
+                    staff.setHasPerformanceToday(hasPerformanceToday);
+
+                    // 填充好评数
+                    Integer positiveCommentsCount = positiveCommentsCountMap.getOrDefault(staff.getId(), 0);
+                    staff.setPositiveCommentsCount(positiveCommentsCount);
+                } else {
+                    staff.setHasPerformanceToday(false);
+                    staff.setPositiveCommentsCount(0);
+                }
+            }
+
+            log.info("根据标题ID查询员工列表成功,storeId={}, titleId={},员工数量:{}", 
+                    storeId, titleId, validStaffList.size());
+            return validStaffList;
+        } catch (Exception e) {
+            log.error("根据标题ID查询员工列表异常,storeId={}, titleId={},异常信息:{}", 
+                    storeId, titleId, e.getMessage(), e);
+            throw new RuntimeException("根据标题ID查询员工列表失败:" + e.getMessage(), e);
+        }
+    }
 }

+ 283 - 0
alien-store/src/main/java/shop/alien/store/service/impl/StoreStaffTitleServiceImpl.java

@@ -0,0 +1,283 @@
+package shop.alien.store.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import shop.alien.entity.store.StoreStaffTitle;
+import shop.alien.mapper.StoreStaffTitleMapper;
+import shop.alien.store.service.StoreStaffTitleService;
+import shop.alien.store.util.CommonConstant;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 员工标题服务实现类
+ *
+ * @author system
+ * @since 2025-01-XX
+ */
+@Slf4j
+@Service
+@RequiredArgsConstructor
+public class StoreStaffTitleServiceImpl extends ServiceImpl<StoreStaffTitleMapper, StoreStaffTitle>
+        implements StoreStaffTitleService {
+
+    private final StoreStaffTitleMapper storeStaffTitleMapper;
+
+    /**
+     * 分页查询员工标题列表
+     *
+     * @param page    分页页数,必须大于0
+     * @param size    分页条数,必须大于0且不超过100
+     * @param storeId 店铺ID,可选
+     * @return 员工标题列表分页结果
+     */
+    @Override
+    public IPage<StoreStaffTitle> queryStaffTitleList(Integer page, Integer size, Integer storeId) {
+        log.info("查询员工标题列表,参数:page={}, size={}, storeId={}", page, size, storeId);
+
+        // 参数校验
+        if (page == null || page < 1) {
+            log.warn("查询员工标题列表失败,分页页数无效:page={}", page);
+            throw new IllegalArgumentException("分页页数不能为空且必须大于0");
+        }
+        if (size == null || size < 1) {
+            log.warn("查询员工标题列表失败,分页条数无效:size={}", size);
+            throw new IllegalArgumentException("分页条数不能为空且必须大于0");
+        }
+        if (size > CommonConstant.MAX_PAGE_SIZE) {
+            log.warn("查询员工标题列表失败,分页条数超过最大值:size={}", size);
+            throw new IllegalArgumentException("分页条数不能超过" + CommonConstant.MAX_PAGE_SIZE);
+        }
+
+        try {
+            // 构建分页对象
+            IPage<StoreStaffTitle> staffTitlePage = new Page<>(page, size);
+
+            // 构建查询条件
+            LambdaQueryWrapper<StoreStaffTitle> queryWrapper = new LambdaQueryWrapper<>();
+            queryWrapper.eq(StoreStaffTitle::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE);
+
+            // 如果指定了店铺ID,则按店铺ID过滤
+            if (storeId != null && storeId > 0) {
+                queryWrapper.eq(StoreStaffTitle::getStoreId, storeId);
+            }
+
+            // 按创建时间降序排序
+            queryWrapper.orderByDesc(StoreStaffTitle::getCreatedTime);
+
+            // 执行查询
+            IPage<StoreStaffTitle> result = storeStaffTitleMapper.selectPage(staffTitlePage, queryWrapper);
+
+            log.info("查询员工标题列表成功,共{}条记录,当前页{}条",
+                    result.getTotal(), result.getRecords() != null ? result.getRecords().size() : 0);
+            return result;
+        } catch (Exception e) {
+            log.error("查询员工标题列表异常,异常信息:{}", e.getMessage(), e);
+            throw new RuntimeException("查询员工标题列表失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 新增员工标题
+     *
+     * @param storeStaffTitle 员工标题信息
+     * @return 新增结果,成功返回1,失败返回0
+     */
+    @Override
+    public Integer addStaffTitle(StoreStaffTitle storeStaffTitle) {
+        log.info("新增员工标题,参数:{}", storeStaffTitle);
+
+        // 参数校验
+        if (storeStaffTitle == null) {
+            log.warn("新增员工标题失败,参数为空");
+            throw new IllegalArgumentException("员工标题信息不能为空");
+        }
+        if (StringUtils.isEmpty(storeStaffTitle.getTitleName())) {
+            log.warn("新增员工标题失败,标题名称为空");
+            throw new IllegalArgumentException("标题名称不能为空");
+        }
+        if (StringUtils.isEmpty(storeStaffTitle.getStaffIds())) {
+            log.warn("新增员工标题失败,员工IDs为空");
+            throw new IllegalArgumentException("员工IDs不能为空");
+        }
+
+        try {
+            // 自动计算员工数量
+            int staffCount = calculateStaffCount(storeStaffTitle.getStaffIds());
+            storeStaffTitle.setStaffCount(staffCount);
+
+            // 设置创建时间
+            storeStaffTitle.setCreatedTime(new Date());
+            storeStaffTitle.setUpdatedTime(new Date());
+
+            // 执行新增
+            int result = storeStaffTitleMapper.insert(storeStaffTitle);
+
+            if (result > 0) {
+                log.info("新增员工标题成功,id={},标题名称={},员工数量={}",
+                        storeStaffTitle.getId(), storeStaffTitle.getTitleName(), staffCount);
+            } else {
+                log.warn("新增员工标题失败,插入记录数为0");
+            }
+
+            return result;
+        } catch (Exception e) {
+            log.error("新增员工标题异常,异常信息:{}", e.getMessage(), e);
+            throw new RuntimeException("新增员工标题失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 更新员工标题
+     *
+     * @param storeStaffTitle 员工标题信息
+     * @return 更新结果,成功返回1,失败返回0
+     */
+    @Override
+    public Integer updateStaffTitle(StoreStaffTitle storeStaffTitle) {
+        log.info("更新员工标题,参数:{}", storeStaffTitle);
+
+        // 参数校验
+        if (storeStaffTitle == null) {
+            log.warn("更新员工标题失败,参数为空");
+            throw new IllegalArgumentException("员工标题信息不能为空");
+        }
+        if (storeStaffTitle.getId() == null || storeStaffTitle.getId() <= 0) {
+            log.warn("更新员工标题失败,ID无效:id={}", storeStaffTitle.getId());
+            throw new IllegalArgumentException("员工标题ID不能为空且必须大于0");
+        }
+        if (StringUtils.isEmpty(storeStaffTitle.getTitleName())) {
+            log.warn("更新员工标题失败,标题名称为空");
+            throw new IllegalArgumentException("标题名称不能为空");
+        }
+
+        try {
+            // 如果更新了员工IDs,重新计算员工数量
+            if (StringUtils.isNotEmpty(storeStaffTitle.getStaffIds())) {
+                int staffCount = calculateStaffCount(storeStaffTitle.getStaffIds());
+                storeStaffTitle.setStaffCount(staffCount);
+            }
+
+            // 设置更新时间
+            storeStaffTitle.setUpdatedTime(new Date());
+
+            // 执行更新
+            int result = storeStaffTitleMapper.updateById(storeStaffTitle);
+
+            if (result > 0) {
+                log.info("更新员工标题成功,id={},标题名称={}",
+                        storeStaffTitle.getId(), storeStaffTitle.getTitleName());
+            } else {
+                log.warn("更新员工标题失败,更新记录数为0,id={}", storeStaffTitle.getId());
+            }
+
+            return result;
+        } catch (Exception e) {
+            log.error("更新员工标题异常,id={},异常信息:{}", storeStaffTitle.getId(), e.getMessage(), e);
+            throw new RuntimeException("更新员工标题失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 删除员工标题(逻辑删除)
+     *
+     * @param id 员工标题ID,必须大于0
+     * @return 删除结果,成功返回1,失败返回0
+     */
+    @Override
+    public Integer deleteStaffTitle(Integer id) {
+        log.info("删除员工标题,参数:id={}", id);
+
+        // 参数校验
+        if (id == null || id <= 0) {
+            log.warn("删除员工标题失败,ID无效:id={}", id);
+            throw new IllegalArgumentException("员工标题ID不能为空且必须大于0");
+        }
+
+        try {
+            // 逻辑删除(MyBatis-Plus会自动处理@TableLogic注解)
+            int result = storeStaffTitleMapper.deleteById(id);
+
+            if (result > 0) {
+                log.info("删除员工标题成功,id={}", id);
+            } else {
+                log.warn("删除员工标题失败,删除记录数为0,id={}", id);
+            }
+
+            return result;
+        } catch (Exception e) {
+            log.error("删除员工标题异常,id={},异常信息:{}", id, e.getMessage(), e);
+            throw new RuntimeException("删除员工标题失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 查询员工标题详情
+     *
+     * @param id 员工标题ID,必须大于0
+     * @return 员工标题详情,如果不存在则返回null
+     */
+    @Override
+    public StoreStaffTitle getStaffTitleDetail(Integer id) {
+        log.info("查询员工标题详情,参数:id={}", id);
+
+        // 参数校验
+        if (id == null || id <= 0) {
+            log.warn("查询员工标题详情失败,ID无效:id={}", id);
+            throw new IllegalArgumentException("员工标题ID不能为空且必须大于0");
+        }
+
+        try {
+            StoreStaffTitle result = storeStaffTitleMapper.selectById(id);
+
+            if (result == null) {
+                log.warn("查询员工标题详情失败,记录不存在:id={}", id);
+            } else {
+                log.info("查询员工标题详情成功,id={},标题名称={}", id, result.getTitleName());
+            }
+
+            return result;
+        } catch (Exception e) {
+            log.error("查询员工标题详情异常,id={},异常信息:{}", id, e.getMessage(), e);
+            throw new RuntimeException("查询员工标题详情失败:" + e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 计算员工数量
+     * <p>
+     * 根据员工IDs字符串(逗号分隔)计算员工数量
+     * </p>
+     *
+     * @param staffIds 员工IDs字符串(逗号分隔)
+     * @return 员工数量
+     */
+    private int calculateStaffCount(String staffIds) {
+        if (StringUtils.isEmpty(staffIds)) {
+            return 0;
+        }
+
+        try {
+            // 按逗号分割,过滤空字符串,计算数量
+            List<String> idList = Arrays.stream(staffIds.split(","))
+                    .map(String::trim)
+                    .filter(s -> !s.isEmpty())
+                    .collect(Collectors.toList());
+
+            return idList.size();
+        } catch (Exception e) {
+            log.error("计算员工数量异常,staffIds={},异常信息:{}", staffIds, e.getMessage(), e);
+            return 0;
+        }
+    }
+}
+