|
|
@@ -67,16 +67,6 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
|
|
|
private final StoreStaffConfigMapper storeStaffConfigMapper;
|
|
|
|
|
|
- private final StoreDictionaryMapper storeDictionaryMapper;
|
|
|
-
|
|
|
- private final StoreStaffFitnessCourseMapper storeStaffFitnessCourseMapper;
|
|
|
-
|
|
|
- private final StoreStaffFitnessCertificationMapper storeStaffFitnessCertificationMapper;
|
|
|
-
|
|
|
- private final StoreStaffFitnessExperienceMapper storeStaffFitnessExperienceMapper;
|
|
|
-
|
|
|
- private final StoreStaffFitnessBaseMapper storeStaffFitnessBaseMapper;
|
|
|
-
|
|
|
private final StoreInfoMapper storeInfoMapper;
|
|
|
|
|
|
private final AliOSSUtil aliOSSUtil;
|
|
|
@@ -124,7 +114,6 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
int size = (query == null || query.getSize() == null) ? 10 : query.getSize();
|
|
|
Integer storeId = query == null ? null : query.getStoreId();
|
|
|
String status = query == null ? null : query.getStatus();
|
|
|
- Integer businessSection = query == null ? null : query.getBusinessSection();
|
|
|
Integer onlineStatus = query == null ? null : query.getOnlineStatus();
|
|
|
String staffPosition = query == null ? null : query.getStaffPosition();
|
|
|
|
|
|
@@ -134,7 +123,6 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
}
|
|
|
QueryWrapper<StoreStaffConfig> queryWrapper = new QueryWrapper<>();
|
|
|
queryWrapper.like(null != status && !status.isEmpty(), "status", status);
|
|
|
- queryWrapper.eq(businessSection != null, "business_section", businessSection);
|
|
|
queryWrapper.eq(onlineStatus != null, "online_status", onlineStatus);
|
|
|
queryWrapper.eq("store_id", storeId);
|
|
|
queryWrapper.eq(StringUtils.isNotEmpty(staffPosition), "staff_position", staffPosition);
|
|
|
@@ -165,20 +153,20 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // businessSection:优先用入参;更新场景若未传则继承库里
|
|
|
- Integer businessSection = storeStaffConfig.getBusinessSection();
|
|
|
- if (!isCreate && businessSection == null) {
|
|
|
- businessSection = existing.getBusinessSection();
|
|
|
- }
|
|
|
-
|
|
|
// 新增默认值
|
|
|
if (isCreate) {
|
|
|
applyCreateDefaults(storeStaffConfig);
|
|
|
+ // 新增员工时,检查门店是否有标题
|
|
|
+ if (storeStaffConfig.getStoreId() != null) {
|
|
|
+ StoreStaffTitle title = getTitleByStoreId(storeStaffConfig.getStoreId());
|
|
|
+ if (title == null) {
|
|
|
+ throw new RuntimeException("该门店还没有创建标题,请先创建标题");
|
|
|
+ }
|
|
|
+ // 设置员工的标题ID
|
|
|
+ storeStaffConfig.setTitleId(title.getId());
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 规范化擅长标签字段(proficient_id / proficient_projects)
|
|
|
- normalizeProficientFields(storeStaffConfig, businessSection);
|
|
|
-
|
|
|
// 先落库,再调用 AI 审核
|
|
|
int affected = isCreate
|
|
|
? insertStaff(storeStaffConfig)
|
|
|
@@ -189,11 +177,13 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
}
|
|
|
|
|
|
Integer staffId = isCreate ? storeStaffConfig.getId() : id;
|
|
|
- if (isFitnessBusinessSection(businessSection)) {
|
|
|
- saveOrUpdateFitnessDetails(staffId, storeStaffConfig);
|
|
|
+
|
|
|
+ // 新增员工成功后,更新标题的员工数量和 staff_ids
|
|
|
+ if (isCreate && storeStaffConfig.getTitleId() != null) {
|
|
|
+ updateTitleStaffCount(storeStaffConfig.getTitleId());
|
|
|
}
|
|
|
|
|
|
- // 新增 / 修改成功后,先将状态置为“审核中”(0),清空拒绝原因
|
|
|
+ // 新增 / 修改成功后,先将状态置为"审核中"(0),清空拒绝原因
|
|
|
StoreStaffConfig auditingUpdate = new StoreStaffConfig();
|
|
|
auditingUpdate.setId(staffId);
|
|
|
auditingUpdate.setStatus("0");
|
|
|
@@ -319,9 +309,6 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
if (staff == null) {
|
|
|
return null;
|
|
|
}
|
|
|
- if (isFitnessBusinessSection(staff.getBusinessSection())) {
|
|
|
- attachFitnessDetails(staff);
|
|
|
- }
|
|
|
return staff;
|
|
|
}
|
|
|
|
|
|
@@ -361,330 +348,13 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
// 因为实体类使用了 @TableLogic 注解
|
|
|
StoreStaffConfig staff = storeStaffConfigMapper.selectById(id);
|
|
|
int deleted = storeStaffConfigMapper.deleteById(id);
|
|
|
- if (deleted > 0 && staff != null && isFitnessBusinessSection(staff.getBusinessSection())) {
|
|
|
- cascadeDeleteFitnessDetails(id);
|
|
|
- }
|
|
|
- return deleted;
|
|
|
- }
|
|
|
|
|
|
- private void attachFitnessDetails(StoreStaffConfig staff) {
|
|
|
- Integer staffId = staff.getId();
|
|
|
- if (staffId == null) {
|
|
|
- return;
|
|
|
+ // 删除员工后,更新标题的员工数量和 staff_ids
|
|
|
+ if (deleted > 0 && staff != null && staff.getTitleId() != null) {
|
|
|
+ updateTitleStaffCount(staff.getTitleId());
|
|
|
}
|
|
|
|
|
|
- List<StoreStaffFitnessCourse> courses = storeStaffFitnessCourseMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreStaffFitnessCourse>()
|
|
|
- .eq(StoreStaffFitnessCourse::getStaffId, staffId)
|
|
|
- .eq(StoreStaffFitnessCourse::getDeleteFlag, 0)
|
|
|
- .orderByDesc(StoreStaffFitnessCourse::getId)
|
|
|
- );
|
|
|
- staff.setFitnessCourseList(courses);
|
|
|
- staff.setFitnessCourseGroupList(buildCourseGroups(courses));
|
|
|
-
|
|
|
- List<StoreStaffFitnessCertification> certAll = storeStaffFitnessCertificationMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreStaffFitnessCertification>()
|
|
|
- .eq(StoreStaffFitnessCertification::getStaffId, staffId)
|
|
|
- .eq(StoreStaffFitnessCertification::getDeleteFlag, 0)
|
|
|
- .orderByDesc(StoreStaffFitnessCertification::getId)
|
|
|
- );
|
|
|
- // 按 type 区分职业认证/荣誉奖项:1-认证 2-荣誉
|
|
|
- List<StoreStaffFitnessCertification> certList = certAll.stream()
|
|
|
- .filter(c -> c.getType() != null && c.getType() == 1)
|
|
|
- .collect(Collectors.toList());
|
|
|
- List<StoreStaffFitnessCertification> honorList = certAll.stream()
|
|
|
- .filter(c -> c.getType() != null && c.getType() == 2)
|
|
|
- .collect(Collectors.toList());
|
|
|
- staff.setFitnessCertificationList(certList);
|
|
|
- staff.setFitnessHonorList(honorList);
|
|
|
-
|
|
|
- List<StoreStaffFitnessExperience> experiences = storeStaffFitnessExperienceMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreStaffFitnessExperience>()
|
|
|
- .eq(StoreStaffFitnessExperience::getStaffId, staffId)
|
|
|
- .eq(StoreStaffFitnessExperience::getDeleteFlag, 0)
|
|
|
- .orderByDesc(StoreStaffFitnessExperience::getId)
|
|
|
- );
|
|
|
- staff.setFitnessExperienceList(experiences);
|
|
|
-
|
|
|
- StoreStaffFitnessBase base = storeStaffFitnessBaseMapper.selectOne(
|
|
|
- new LambdaQueryWrapper<StoreStaffFitnessBase>()
|
|
|
- .eq(StoreStaffFitnessBase::getStaffId, staffId)
|
|
|
- .eq(StoreStaffFitnessBase::getDeleteFlag, 0)
|
|
|
- .last("limit 1")
|
|
|
- );
|
|
|
- staff.setFitnessBase(base);
|
|
|
- }
|
|
|
-
|
|
|
- private void cascadeDeleteFitnessDetails(Integer staffId) {
|
|
|
- if (staffId == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- storeStaffFitnessCourseMapper.delete(new QueryWrapper<StoreStaffFitnessCourse>().eq("staff_id", staffId));
|
|
|
- storeStaffFitnessCertificationMapper.delete(new QueryWrapper<StoreStaffFitnessCertification>().eq("staff_id", staffId));
|
|
|
- storeStaffFitnessExperienceMapper.delete(new QueryWrapper<StoreStaffFitnessExperience>().eq("staff_id", staffId));
|
|
|
- storeStaffFitnessBaseMapper.delete(new QueryWrapper<StoreStaffFitnessBase>().eq("staff_id", staffId));
|
|
|
- }
|
|
|
-
|
|
|
- private void saveOrUpdateFitnessDetails(Integer staffId, StoreStaffConfig staff) {
|
|
|
- if (staffId == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 0) 兼容前端“课程类型分组”入参:优先使用分组字段,自动拍平成 fitnessCourseList 走现有落库逻辑
|
|
|
- if (staff.getFitnessCourseGroupList() != null) {
|
|
|
- staff.setFitnessCourseList(flattenCourseGroups(staff.getFitnessCourseGroupList()));
|
|
|
- }
|
|
|
-
|
|
|
- // 1) 课程信息:若前端传了列表(包括空列表),以传入为准覆盖
|
|
|
- if (staff.getFitnessCourseList() != null) {
|
|
|
- storeStaffFitnessCourseMapper.delete(new QueryWrapper<StoreStaffFitnessCourse>().eq("staff_id", staffId));
|
|
|
- // 课程类型存 dictDetail(名称)。如传 dictId,则在无歧义时自动转换为 dictDetail。
|
|
|
- java.util.Set<String> rawTypes = staff.getFitnessCourseList().stream()
|
|
|
- .filter(java.util.Objects::nonNull)
|
|
|
- .map(StoreStaffFitnessCourse::getCourseType)
|
|
|
- .filter(StringUtils::isNotEmpty)
|
|
|
- .map(String::trim)
|
|
|
- .collect(java.util.stream.Collectors.toSet());
|
|
|
- java.util.Map<String, String> dictIdToDetail = new java.util.HashMap<>();
|
|
|
- if (!rawTypes.isEmpty()) {
|
|
|
- List<StoreDictionary> dicts = storeDictionaryMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreDictionary>()
|
|
|
- .in(StoreDictionary::getTypeName, java.util.Arrays.asList("classOnLineType", "classOffLineType"))
|
|
|
- .in(StoreDictionary::getDictId, rawTypes)
|
|
|
- .eq(StoreDictionary::getDeleteFlag, 0)
|
|
|
- );
|
|
|
- // 仅在一个 dictId 唯一对应一个 dictDetail 时才转换(避免线上/线下 dictId 重复导致歧义)
|
|
|
- java.util.Map<String, java.util.Set<String>> tmp = new java.util.HashMap<>();
|
|
|
- for (StoreDictionary d : dicts) {
|
|
|
- if (StringUtils.isEmpty(d.getDictId()) || StringUtils.isEmpty(d.getDictDetail())) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- tmp.computeIfAbsent(d.getDictId(), k -> new java.util.HashSet<>()).add(d.getDictDetail());
|
|
|
- }
|
|
|
- for (java.util.Map.Entry<String, java.util.Set<String>> e : tmp.entrySet()) {
|
|
|
- if (e.getValue().size() == 1) {
|
|
|
- dictIdToDetail.put(e.getKey(), e.getValue().iterator().next());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- for (StoreStaffFitnessCourse course : staff.getFitnessCourseList()) {
|
|
|
- if (course == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- course.setId(null);
|
|
|
- course.setStaffId(staffId);
|
|
|
- if (course.getDeleteFlag() == null) {
|
|
|
- course.setDeleteFlag(0);
|
|
|
- }
|
|
|
- if (StringUtils.isNotEmpty(course.getCourseType())) {
|
|
|
- String ct = course.getCourseType().trim();
|
|
|
- // 若传的是 dictId 且能唯一映射,则替换为 dictDetail(名称)
|
|
|
- if (dictIdToDetail.containsKey(ct)) {
|
|
|
- course.setCourseType(dictIdToDetail.get(ct));
|
|
|
- } else {
|
|
|
- course.setCourseType(ct);
|
|
|
- }
|
|
|
- }
|
|
|
- // 价格字段归一化:0-固定价写 course_price;1-区间价写 min/max
|
|
|
- if (course.getCoursePriceType() != null) {
|
|
|
- if (course.getCoursePriceType() == 0) {
|
|
|
- course.setCourseMinPrice(null);
|
|
|
- course.setCourseMaxPrice(null);
|
|
|
- } else if (course.getCoursePriceType() == 1) {
|
|
|
- course.setCoursePrice(null);
|
|
|
- }
|
|
|
- }
|
|
|
- storeStaffFitnessCourseMapper.insert(course);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 2) 认证/荣誉:任意一个列表非 null,则覆盖保存(两类共用一张表)
|
|
|
- if (staff.getFitnessCertificationList() != null || staff.getFitnessHonorList() != null) {
|
|
|
- storeStaffFitnessCertificationMapper.delete(new QueryWrapper<StoreStaffFitnessCertification>().eq("staff_id", staffId));
|
|
|
-
|
|
|
- if (staff.getFitnessCertificationList() != null) {
|
|
|
- for (StoreStaffFitnessCertification cert : staff.getFitnessCertificationList()) {
|
|
|
- if (cert == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- StoreStaffFitnessCertification row = new StoreStaffFitnessCertification();
|
|
|
- row.setId(null);
|
|
|
- row.setStaffId(staffId);
|
|
|
- row.setType(1);
|
|
|
- row.setName(cert.getName());
|
|
|
- row.setImgUrls(cert.getImgUrls());
|
|
|
- row.setDeleteFlag(0);
|
|
|
- storeStaffFitnessCertificationMapper.insert(row);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- if (staff.getFitnessHonorList() != null) {
|
|
|
- for (StoreStaffFitnessCertification honor : staff.getFitnessHonorList()) {
|
|
|
- if (honor == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- StoreStaffFitnessCertification row = new StoreStaffFitnessCertification();
|
|
|
- row.setId(null);
|
|
|
- row.setStaffId(staffId);
|
|
|
- row.setType(2);
|
|
|
- row.setName(honor.getName());
|
|
|
- row.setImgUrls(honor.getImgUrls());
|
|
|
- row.setDeleteFlag(0);
|
|
|
- storeStaffFitnessCertificationMapper.insert(row);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 3) 从业经历:若前端传了列表(包括空列表),以传入为准覆盖
|
|
|
- if (staff.getFitnessExperienceList() != null) {
|
|
|
- storeStaffFitnessExperienceMapper.delete(new QueryWrapper<StoreStaffFitnessExperience>().eq("staff_id", staffId));
|
|
|
- for (StoreStaffFitnessExperience exp : staff.getFitnessExperienceList()) {
|
|
|
- if (exp == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- exp.setId(null);
|
|
|
- exp.setStaffId(staffId);
|
|
|
- if (exp.getDeleteFlag() == null) {
|
|
|
- exp.setDeleteFlag(0);
|
|
|
- }
|
|
|
- storeStaffFitnessExperienceMapper.insert(exp);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 4) 基本信息:若前端传了对象则 upsert,否则不动
|
|
|
- if (staff.getFitnessBase() != null) {
|
|
|
- StoreStaffFitnessBase base = staff.getFitnessBase();
|
|
|
- base.setStaffId(staffId);
|
|
|
- if (base.getDeleteFlag() == null) {
|
|
|
- base.setDeleteFlag(0);
|
|
|
- }
|
|
|
- StoreStaffFitnessBase existBase = storeStaffFitnessBaseMapper.selectOne(
|
|
|
- new LambdaQueryWrapper<StoreStaffFitnessBase>()
|
|
|
- .eq(StoreStaffFitnessBase::getStaffId, staffId)
|
|
|
- .eq(StoreStaffFitnessBase::getDeleteFlag, 0)
|
|
|
- .last("limit 1")
|
|
|
- );
|
|
|
- if (existBase == null) {
|
|
|
- base.setId(null);
|
|
|
- storeStaffFitnessBaseMapper.insert(base);
|
|
|
- } else {
|
|
|
- base.setId(existBase.getId());
|
|
|
- storeStaffFitnessBaseMapper.updateById(base);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 若 proficientProjects 未传,尝试根据 proficientId + businessSection 从字典表计算名称回填
|
|
|
- * 规则:proficient_tag.parent_id = business_section 主键id;proficient_id 存 proficient_tag.dict_id 逗号分隔
|
|
|
- */
|
|
|
- private void normalizeProficientFields(StoreStaffConfig staff, Integer businessSection) {
|
|
|
- if (staff == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
- if (StringUtils.isEmpty(staff.getProficientId()) || !StringUtils.isEmpty(staff.getProficientProjects()) || businessSection == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 查询经营板块(business_section),注意:staff.businessSection 存的是 dict_id
|
|
|
- StoreDictionary section = storeDictionaryMapper.selectOne(
|
|
|
- new LambdaQueryWrapper<StoreDictionary>()
|
|
|
- .eq(StoreDictionary::getTypeName, "business_section")
|
|
|
- .eq(StoreDictionary::getDictId, String.valueOf(businessSection))
|
|
|
- .eq(StoreDictionary::getDeleteFlag, 0)
|
|
|
- .isNull(StoreDictionary::getParentId)
|
|
|
- .last("limit 1")
|
|
|
- );
|
|
|
- if (section == null || section.getId() == null) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- List<String> dictIds = java.util.Arrays.stream(staff.getProficientId().split(","))
|
|
|
- .map(String::trim)
|
|
|
- .filter(s -> !s.isEmpty())
|
|
|
- .collect(Collectors.toList());
|
|
|
- if (dictIds.isEmpty()) {
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- List<StoreDictionary> tags = storeDictionaryMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreDictionary>()
|
|
|
- .eq(StoreDictionary::getTypeName, "proficient_tag")
|
|
|
- .eq(StoreDictionary::getParentId, section.getId())
|
|
|
- .in(StoreDictionary::getDictId, dictIds)
|
|
|
- .eq(StoreDictionary::getDeleteFlag, 0)
|
|
|
- );
|
|
|
-
|
|
|
- java.util.Map<String, String> idToName = tags.stream()
|
|
|
- .filter(d -> !StringUtils.isEmpty(d.getDictId()))
|
|
|
- .collect(Collectors.toMap(StoreDictionary::getDictId, StoreDictionary::getDictDetail, (a, b) -> a));
|
|
|
-
|
|
|
- List<String> namesInOrder = dictIds.stream()
|
|
|
- .map(idToName::get)
|
|
|
- .filter(s -> !StringUtils.isEmpty(s))
|
|
|
- .collect(Collectors.toList());
|
|
|
-
|
|
|
- if (!namesInOrder.isEmpty()) {
|
|
|
- staff.setProficientProjects(String.join(",", namesInOrder));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 判断该经营板块是否为“运动健身”
|
|
|
- * - 优先按常见 dict_id=7 判断
|
|
|
- * - 若不一致,再按字典表 dict_detail=运动健身 判断
|
|
|
- */
|
|
|
- private boolean isFitnessBusinessSection(Integer businessSection) {
|
|
|
- if (businessSection == null) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- if (businessSection == 7) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- StoreDictionary section = storeDictionaryMapper.selectOne(
|
|
|
- new LambdaQueryWrapper<StoreDictionary>()
|
|
|
- .eq(StoreDictionary::getTypeName, "business_section")
|
|
|
- .eq(StoreDictionary::getDictId, String.valueOf(businessSection))
|
|
|
- .eq(StoreDictionary::getDeleteFlag, 0)
|
|
|
- .last("limit 1")
|
|
|
- );
|
|
|
- return section != null && "运动健身".equals(section.getDictDetail());
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 将分组结构拍平成明细行结构(用于落库)
|
|
|
- */
|
|
|
- private List<StoreStaffFitnessCourse> flattenCourseGroups(List<StoreStaffFitnessCourseGroup> groups) {
|
|
|
- List<StoreStaffFitnessCourse> flat = new ArrayList<>();
|
|
|
- if (groups == null) {
|
|
|
- return flat;
|
|
|
- }
|
|
|
- for (StoreStaffFitnessCourseGroup g : groups) {
|
|
|
- if (g == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String courseType = StringUtils.isNotEmpty(g.getCourseType()) ? g.getCourseType().trim() : null;
|
|
|
- if (StringUtils.isEmpty(courseType) && StringUtils.isNotEmpty(g.getCourseTypeName())) {
|
|
|
- courseType = g.getCourseTypeName().trim();
|
|
|
- }
|
|
|
- if (g.getItems() == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- for (StoreStaffFitnessCourseItem item : g.getItems()) {
|
|
|
- if (item == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- StoreStaffFitnessCourse row = new StoreStaffFitnessCourse();
|
|
|
- row.setCourseType(courseType);
|
|
|
- row.setCourseName(item.getCourseName());
|
|
|
- row.setCoursePriceType(item.getCoursePriceType());
|
|
|
- row.setCoursePrice(item.getCoursePrice());
|
|
|
- row.setCourseMinPrice(item.getCourseMinPrice());
|
|
|
- row.setCourseMaxPrice(item.getCourseMaxPrice());
|
|
|
- flat.add(row);
|
|
|
- }
|
|
|
- }
|
|
|
- return flat;
|
|
|
+ return deleted;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -708,73 +378,6 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
lowerUrl.endsWith(".mov");
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 将明细行结构组装成分组结构(用于前端绑定)
|
|
|
- * - 优先按 courseType 分组(DB里可能存 dictDetail 或 dictId)
|
|
|
- * - courseTypeName:能从字典表解析到名称则回填,否则回填为原 courseType
|
|
|
- */
|
|
|
- private List<StoreStaffFitnessCourseGroup> buildCourseGroups(List<StoreStaffFitnessCourse> courses) {
|
|
|
- List<StoreStaffFitnessCourseGroup> groups = new ArrayList<>();
|
|
|
- if (courses == null || courses.isEmpty()) {
|
|
|
- return groups;
|
|
|
- }
|
|
|
-
|
|
|
- // 收集类型并尝试从字典表解析名称(兼容:DB存 dictId 或 dictDetail)
|
|
|
- java.util.Set<String> rawTypes = courses.stream()
|
|
|
- .filter(java.util.Objects::nonNull)
|
|
|
- .map(StoreStaffFitnessCourse::getCourseType)
|
|
|
- .filter(StringUtils::isNotEmpty)
|
|
|
- .map(String::trim)
|
|
|
- .collect(java.util.stream.Collectors.toSet());
|
|
|
-
|
|
|
- java.util.Map<String, String> typeToName = new java.util.HashMap<>();
|
|
|
- if (!rawTypes.isEmpty()) {
|
|
|
- List<StoreDictionary> dicts = storeDictionaryMapper.selectList(
|
|
|
- new LambdaQueryWrapper<StoreDictionary>()
|
|
|
- // 兼容历史:文档里是 classOnLineType/classOffLineType;部分环境可能是 courseType
|
|
|
- .in(StoreDictionary::getTypeName, java.util.Arrays.asList("classOnLineType", "classOffLineType", "courseType"))
|
|
|
- .and(w -> w.in(StoreDictionary::getDictId, rawTypes).or().in(StoreDictionary::getDictDetail, rawTypes))
|
|
|
- .eq(StoreDictionary::getDeleteFlag, 0)
|
|
|
- );
|
|
|
- for (StoreDictionary d : dicts) {
|
|
|
- if (d == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- if (StringUtils.isNotEmpty(d.getDictId()) && StringUtils.isNotEmpty(d.getDictDetail())) {
|
|
|
- // dictId -> name
|
|
|
- typeToName.putIfAbsent(d.getDictId().trim(), d.getDictDetail().trim());
|
|
|
- // name -> name(用于 DB 存 dictDetail 的场景)
|
|
|
- typeToName.putIfAbsent(d.getDictDetail().trim(), d.getDictDetail().trim());
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- java.util.Map<String, StoreStaffFitnessCourseGroup> map = new java.util.LinkedHashMap<>();
|
|
|
- for (StoreStaffFitnessCourse c : courses) {
|
|
|
- if (c == null) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- String ct = StringUtils.isNotEmpty(c.getCourseType()) ? c.getCourseType().trim() : "";
|
|
|
- StoreStaffFitnessCourseGroup g = map.computeIfAbsent(ct, k -> {
|
|
|
- StoreStaffFitnessCourseGroup ng = new StoreStaffFitnessCourseGroup();
|
|
|
- ng.setCourseType(k);
|
|
|
- ng.setCourseTypeName(typeToName.getOrDefault(k, k));
|
|
|
- ng.setItems(new ArrayList<>());
|
|
|
- return ng;
|
|
|
- });
|
|
|
-
|
|
|
- StoreStaffFitnessCourseItem item = new StoreStaffFitnessCourseItem();
|
|
|
- item.setCourseName(c.getCourseName());
|
|
|
- item.setCoursePriceType(c.getCoursePriceType());
|
|
|
- item.setCoursePrice(c.getCoursePrice());
|
|
|
- item.setCourseMinPrice(c.getCourseMinPrice());
|
|
|
- item.setCourseMaxPrice(c.getCourseMaxPrice());
|
|
|
- g.getItems().add(item);
|
|
|
- }
|
|
|
- groups.addAll(map.values());
|
|
|
- return groups;
|
|
|
- }
|
|
|
-
|
|
|
@Override
|
|
|
public Integer setTopStatus(Integer id, Integer topStatus) {
|
|
|
if (id == null || topStatus == null) {
|
|
|
@@ -802,6 +405,94 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
return storeStaffConfigMapper.update(null, lambdaUpdateWrapper);
|
|
|
}
|
|
|
|
|
|
+ @Override
|
|
|
+ public List<String> getStaffPositionList(Integer storeId) {
|
|
|
+ log.info("查询员工职位列表,storeId={}", storeId);
|
|
|
+
|
|
|
+ // 参数校验
|
|
|
+ if (storeId == null || storeId <= 0) {
|
|
|
+ log.warn("查询员工职位列表失败,店铺ID无效:storeId={}", storeId);
|
|
|
+ throw new IllegalArgumentException("店铺ID不能为空且必须大于0");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 构建查询条件:查询指定店铺下未删除的员工
|
|
|
+ LambdaQueryWrapper<StoreStaffConfig> queryWrapper = new LambdaQueryWrapper<>();
|
|
|
+ queryWrapper.eq(StoreStaffConfig::getStoreId, storeId)
|
|
|
+ .eq(StoreStaffConfig::getDeleteFlag, CommonConstant.DELETE_FLAG_UNDELETE)
|
|
|
+ // 只查询staff_position不为空的记录
|
|
|
+ .isNotNull(StoreStaffConfig::getStaffPosition)
|
|
|
+ .ne(StoreStaffConfig::getStaffPosition, "")
|
|
|
+ .select(StoreStaffConfig::getStaffPosition);
|
|
|
+
|
|
|
+ // 查询所有符合条件的员工
|
|
|
+ List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectList(queryWrapper);
|
|
|
+
|
|
|
+ // 提取所有不重复的职位名称
|
|
|
+ List<String> positionList = staffList.stream()
|
|
|
+ .map(StoreStaffConfig::getStaffPosition)
|
|
|
+ .filter(StringUtils::isNotEmpty)
|
|
|
+ .distinct()
|
|
|
+ .sorted()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ log.info("查询员工职位列表成功,storeId={},职位数量:{}", storeId, positionList.size());
|
|
|
+ return positionList;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据门店ID查询标题(一个门店只能有一个标题)
|
|
|
+ *
|
|
|
+ * @param storeId 门店ID
|
|
|
+ * @return 标题信息
|
|
|
+ */
|
|
|
+ private StoreStaffTitle getTitleByStoreId(Integer storeId) {
|
|
|
+ if (storeId == null) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 直接通过 store_id 查询标题
|
|
|
+ LambdaQueryWrapper<StoreStaffTitle> titleWrapper = new LambdaQueryWrapper<>();
|
|
|
+ titleWrapper.eq(StoreStaffTitle::getStoreId, storeId)
|
|
|
+ .eq(StoreStaffTitle::getDeleteFlag, 0)
|
|
|
+ .orderByDesc(StoreStaffTitle::getCreatedTime)
|
|
|
+ .last("limit 1");
|
|
|
+ return storeStaffTitleMapper.selectOne(titleWrapper);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 更新标题的员工数量和 staff_ids
|
|
|
+ *
|
|
|
+ * @param titleId 标题ID
|
|
|
+ */
|
|
|
+ private void updateTitleStaffCount(Integer titleId) {
|
|
|
+ if (titleId == null) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询该标题下的所有未删除员工
|
|
|
+ LambdaQueryWrapper<StoreStaffConfig> staffWrapper = new LambdaQueryWrapper<>();
|
|
|
+ staffWrapper.eq(StoreStaffConfig::getTitleId, titleId)
|
|
|
+ .eq(StoreStaffConfig::getDeleteFlag, 0)
|
|
|
+ .select(StoreStaffConfig::getId);
|
|
|
+ List<StoreStaffConfig> staffList = storeStaffConfigMapper.selectList(staffWrapper);
|
|
|
+
|
|
|
+ // 计算员工数量和 staff_ids
|
|
|
+ int staffCount = staffList.size();
|
|
|
+ String staffIds = staffList.stream()
|
|
|
+ .map(staff -> String.valueOf(staff.getId()))
|
|
|
+ .collect(Collectors.joining(","));
|
|
|
+
|
|
|
+ // 更新标题
|
|
|
+ LambdaUpdateWrapper<StoreStaffTitle> updateWrapper = new LambdaUpdateWrapper<>();
|
|
|
+ updateWrapper.eq(StoreStaffTitle::getId, titleId)
|
|
|
+ .set(StoreStaffTitle::getStaffIds, staffIds)
|
|
|
+ .set(StoreStaffTitle::getStaffCount, staffCount)
|
|
|
+ .set(StoreStaffTitle::getUpdatedTime, new Date());
|
|
|
+
|
|
|
+ storeStaffTitleMapper.update(null, updateWrapper);
|
|
|
+ log.info("StoreStaffConfigServiceImpl.updateTitleStaffCount 更新成功,titleId={}, staffCount={}", titleId, staffCount);
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* 员工列表查询(用户端)
|
|
|
* <p>
|
|
|
@@ -831,10 +522,10 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
|
|
|
// 执行查询
|
|
|
IPage<StoreStaffConfig> result = storeStaffConfigMapper.selectPage(staffPage, queryWrapper);
|
|
|
-
|
|
|
+
|
|
|
// 批量填充今日是否有演出字段(性能优化:批量查询)
|
|
|
fillHasPerformanceTodayBatch(result);
|
|
|
-
|
|
|
+
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
@@ -1263,20 +954,20 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
}
|
|
|
|
|
|
// 查询演出安排列表
|
|
|
- List<PerformanceScheduleVo> performanceScheduleList =
|
|
|
+ List<PerformanceScheduleVo> performanceScheduleList =
|
|
|
queryPerformanceScheduleList(id);
|
|
|
|
|
|
// 判断今日是否有演出
|
|
|
Boolean hasPerformanceToday = checkHasPerformanceToday(id);
|
|
|
|
|
|
// 构建返回对象
|
|
|
- StoreStaffDetailWithPerformanceVo result =
|
|
|
+ StoreStaffDetailWithPerformanceVo result =
|
|
|
new StoreStaffDetailWithPerformanceVo();
|
|
|
result.setStaffInfo(staffConfig);
|
|
|
result.setPerformanceScheduleList(performanceScheduleList);
|
|
|
result.setHasPerformanceToday(hasPerformanceToday);
|
|
|
|
|
|
- log.info("查询员工详情(包含演出列表)成功,id={},演出安排数量:{},今日是否有演出:{}",
|
|
|
+ log.info("查询员工详情(包含演出列表)成功,id={},演出安排数量:{},今日是否有演出:{}",
|
|
|
id, performanceScheduleList != null ? performanceScheduleList.size() : 0, hasPerformanceToday);
|
|
|
return result;
|
|
|
} catch (Exception e) {
|
|
|
@@ -1433,7 +1124,7 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
// 使用dailyStartTime和dailyEndTime
|
|
|
Date scheduleStart = combineDateAndLocalTime(currentDate, dailyStartTime);
|
|
|
Date scheduleEnd = combineDateAndLocalTime(currentDate, dailyEndTime);
|
|
|
-
|
|
|
+
|
|
|
// 如果结束时间小于或等于开始时间,说明跨天了
|
|
|
if (!scheduleEnd.after(scheduleStart)) {
|
|
|
java.util.Calendar endCal = java.util.Calendar.getInstance();
|
|
|
@@ -1506,7 +1197,7 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
// 使用dailyStartTime和dailyEndTime
|
|
|
Date scheduleStart = combineDateAndLocalTime(currentDate, dailyStartTime);
|
|
|
Date scheduleEnd = combineDateAndLocalTime(currentDate, dailyEndTime);
|
|
|
-
|
|
|
+
|
|
|
// 如果结束时间小于或等于开始时间,说明跨天了
|
|
|
if (!scheduleEnd.after(scheduleStart)) {
|
|
|
java.util.Calendar endCal = java.util.Calendar.getInstance();
|
|
|
@@ -1534,9 +1225,9 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
*/
|
|
|
private PerformanceScheduleVo buildPerformanceScheduleVo(
|
|
|
BarPerformance performance, Date startTime, Date endTime) {
|
|
|
- PerformanceScheduleVo schedule =
|
|
|
+ PerformanceScheduleVo schedule =
|
|
|
new PerformanceScheduleVo();
|
|
|
-
|
|
|
+
|
|
|
schedule.setPerformanceId(performance.getId());
|
|
|
schedule.setPerformanceName(performance.getPerformanceName());
|
|
|
|
|
|
@@ -1547,17 +1238,17 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
String dateStr = dateFormat.format(startTime);
|
|
|
String weekDayStr = getWeekDayStr(startTime);
|
|
|
String startTimeStr = timeFormat.format(startTime);
|
|
|
-
|
|
|
+
|
|
|
// 判断是否跨天
|
|
|
String endTimeStr;
|
|
|
java.util.Calendar startCal = java.util.Calendar.getInstance();
|
|
|
startCal.setTime(startTime);
|
|
|
java.util.Calendar endCal = java.util.Calendar.getInstance();
|
|
|
endCal.setTime(endTime);
|
|
|
-
|
|
|
+
|
|
|
boolean isNextDay = endCal.get(java.util.Calendar.DAY_OF_YEAR) > startCal.get(java.util.Calendar.DAY_OF_YEAR) ||
|
|
|
endCal.get(java.util.Calendar.YEAR) > startCal.get(java.util.Calendar.YEAR);
|
|
|
-
|
|
|
+
|
|
|
if (isNextDay) {
|
|
|
endTimeStr = "次日" + timeFormat.format(endTime);
|
|
|
} else {
|
|
|
@@ -1600,15 +1291,15 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
|
|
|
java.util.Calendar dateCal = java.util.Calendar.getInstance();
|
|
|
dateCal.setTime(date);
|
|
|
-
|
|
|
+
|
|
|
java.util.Calendar timeCal = java.util.Calendar.getInstance();
|
|
|
timeCal.setTime(timeSource);
|
|
|
-
|
|
|
+
|
|
|
dateCal.set(java.util.Calendar.HOUR_OF_DAY, timeCal.get(java.util.Calendar.HOUR_OF_DAY));
|
|
|
dateCal.set(java.util.Calendar.MINUTE, timeCal.get(java.util.Calendar.MINUTE));
|
|
|
dateCal.set(java.util.Calendar.SECOND, timeCal.get(java.util.Calendar.SECOND));
|
|
|
dateCal.set(java.util.Calendar.MILLISECOND, timeCal.get(java.util.Calendar.MILLISECOND));
|
|
|
-
|
|
|
+
|
|
|
return dateCal.getTime();
|
|
|
}
|
|
|
|
|
|
@@ -1629,10 +1320,10 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
java.time.Instant instant = date.toInstant();
|
|
|
java.time.ZoneId zoneId = java.time.ZoneId.systemDefault();
|
|
|
java.time.LocalDate localDate = instant.atZone(zoneId).toLocalDate();
|
|
|
-
|
|
|
+
|
|
|
// 合并日期和时间
|
|
|
java.time.LocalDateTime localDateTime = localDate.atTime(localTime);
|
|
|
-
|
|
|
+
|
|
|
// 转换回Date
|
|
|
return Date.from(localDateTime.atZone(zoneId).toInstant());
|
|
|
} catch (Exception e) {
|
|
|
@@ -2105,11 +1796,11 @@ public class StoreStaffConfigServiceImpl implements StoreStaffConfigService {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- log.info("根据标题ID查询员工列表成功,storeId={}, titleId={},员工数量:{}",
|
|
|
+ log.info("根据标题ID查询员工列表成功,storeId={}, titleId={},员工数量:{}",
|
|
|
storeId, titleId, validStaffList.size());
|
|
|
return validStaffList;
|
|
|
} catch (Exception e) {
|
|
|
- log.error("根据标题ID查询员工列表异常,storeId={}, titleId={},异常信息:{}",
|
|
|
+ log.error("根据标题ID查询员工列表异常,storeId={}, titleId={},异常信息:{}",
|
|
|
storeId, titleId, e.getMessage(), e);
|
|
|
throw new RuntimeException("根据标题ID查询员工列表失败:" + e.getMessage(), e);
|
|
|
}
|