| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915 |
- package com.ylx.massage.service.impl;
- import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
- import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
- import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
- import com.ylx.common.core.domain.model.WxLoginUser;
- import com.ylx.common.exception.ServiceException;
- import com.ylx.massage.domain.MomentMedia;
- import com.ylx.massage.domain.TechnicianMoment;
- import com.ylx.massage.domain.TJs;
- import com.ylx.massage.domain.dto.MomentAuditDTO;
- import com.ylx.massage.domain.dto.MomentManageQueryDTO;
- import com.ylx.massage.domain.dto.PublishMomentDTO;
- import com.ylx.massage.domain.dto.EditMomentDTO;
- import com.ylx.massage.domain.vo.MomentDetailVO;
- import com.ylx.massage.domain.vo.MomentListVO;
- import com.ylx.massage.domain.vo.MomentManageVO;
- import com.ylx.massage.domain.vo.MomentMediaVO;
- import com.ylx.massage.domain.vo.MomentSimpleDetailVO;
- import com.ylx.massage.domain.vo.MyMomentVO;
- import com.ylx.massage.mapper.MomentMediaMapper;
- import com.ylx.massage.mapper.TechnicianMomentMapper;
- import com.ylx.massage.mapper.TJsMapper;
- import com.ylx.massage.service.ITechnicianMomentService;
- import lombok.extern.slf4j.Slf4j;
- import org.apache.commons.lang3.StringUtils;
- import org.springframework.beans.BeanUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import java.math.BigDecimal;
- import java.time.LocalDateTime;
- import java.util.ArrayList;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Map;
- import java.util.stream.Collectors;
- /**
- * 技师动态服务实现类
- */
- @Service
- @Slf4j
- public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMapper, TechnicianMoment> implements ITechnicianMomentService {
- @Autowired
- private TechnicianMomentMapper momentMapper;
- @Autowired
- private MomentMediaMapper mediaMapper;
- @Autowired
- private TJsMapper tJsMapper;
- /**
- * 查询推荐动态列表(不分地区,按日期倒序,同一天按浏览量倒序)
- *
- * @param pageNum 页码,默认1
- * @param pageSize 每页数量,默认10
- * @return R<List<MomentListVO>> 动态列表
- */
- @Override
- public List<MomentListVO> getRecommendedMoments(Integer pageNum, Integer pageSize) {
- Page<TechnicianMoment> page = new Page<>(pageNum, pageSize);
- List<TechnicianMoment> moments = momentMapper.selectRecommendedMoments(page);
- if (moments == null || moments.isEmpty()) {
- return new ArrayList<>();
- }
- // 查询技师信息
- List<String> technicianIds = moments.stream().map(TechnicianMoment::getTechnicianId).collect(Collectors.toList());
- Map<String, TJs> technicianMap = getTechnicianMap(technicianIds);
- // 组装VO
- return moments.stream().map(moment -> {
- MomentListVO vo = new MomentListVO();
- BeanUtils.copyProperties(moment, vo);
- TJs technician = technicianMap.get(moment.getTechnicianId());
- if (technician != null) {
- vo.setTechnicianNickName(technician.getcNickName());
- vo.setTechnicianAvatar(technician.getcPortrait());
- vo.setTechnicianStatus(getTechnicianStatus(technician));
- }
- return vo;
- }).collect(Collectors.toList());
- }
- /**
- * 查询同城动态列表(按城市和发布时间倒序)
- */
- @Override
- public List<MomentListVO> getSameCityMoments(String cityCode, Integer pageNum, Integer pageSize) {
- Page<TechnicianMoment> page = new Page<>(pageNum, pageSize);
- List<TechnicianMoment> moments = momentMapper.selectSameCityMoments(page, cityCode);
- if (moments == null || moments.isEmpty()) {
- return new ArrayList<>();
- }
- // 查询技师信息
- List<String> technicianIds = moments.stream().map(TechnicianMoment::getTechnicianId).collect(Collectors.toList());
- Map<String, TJs> technicianMap = getTechnicianMap(technicianIds);
- // 组装VO
- return moments.stream().map(moment -> {
- MomentListVO vo = new MomentListVO();
- BeanUtils.copyProperties(moment, vo);
- TJs technician = technicianMap.get(moment.getTechnicianId());
- if (technician != null) {
- vo.setTechnicianNickName(technician.getcNickName());
- vo.setTechnicianAvatar(technician.getcPortrait());
- vo.setTechnicianStatus(getTechnicianStatus(technician));
- }
- return vo;
- }).collect(Collectors.toList());
- }
- /**
- * 查询附近动态列表(10km内,按日期倒序,同一天按距离排序)
- *
- * @param longitude 经度
- * @param latitude 纬度
- * @param pageNum 页码,默认1
- * @param pageSize 每页数量,默认10
- * @return R<List<MomentListVO>> 动态列表
- */
- @Override
- public List<MomentListVO> getNearbyMoments(BigDecimal longitude, BigDecimal latitude, Integer pageNum, Integer pageSize) {
- if (latitude == null || longitude == null) {
- throw new ServiceException("地理位置信息不能为空");
- }
- Page<TechnicianMoment> page = new Page<>(pageNum, pageSize);
- List<TechnicianMoment> moments = momentMapper.selectNearbyMoments(page, longitude, latitude);
- if (moments == null || moments.isEmpty()) {
- return new ArrayList<>();
- }
- // 查询技师信息
- List<String> technicianIds = moments.stream()
- .map(TechnicianMoment::getTechnicianId)
- .collect(Collectors.toList());
- Map<String, TJs> technicianMap = getTechnicianMap(technicianIds);
- // 组装VO(需要计算距离)
- return moments.stream().map(moment -> {
- MomentListVO vo = new MomentListVO();
- BeanUtils.copyProperties(moment, vo);
- TJs technician = technicianMap.get(String.valueOf(moment.getTechnicianId()));
- if (technician != null) {
- vo.setTechnicianNickName(technician.getcNickName());
- vo.setTechnicianAvatar(technician.getcPortrait());
- vo.setTechnicianStatus(getTechnicianStatus(technician));
- // 计算距离
- if (moment.getLatitude() != null && moment.getLongitude() != null) {
- double distance = calculateDistance(
- latitude.doubleValue(), longitude.doubleValue(),
- moment.getLatitude().doubleValue(), moment.getLongitude().doubleValue()
- );
- vo.setDistance(Math.round(distance * 100.0) / 100.0); // 保留两位小数
- }
- }
- return vo;
- }).collect(Collectors.toList());
- }
- /**
- * 查询动态详情(浏览量+1)
- *
- * @param momentId 动态ID
- * @return MomentDetailVO 动态详情
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public MomentDetailVO getMomentDetail(Long momentId, BigDecimal longitude, BigDecimal latitude) {
- if (momentId == null) {
- throw new ServiceException("动态ID不能为空");
- }
- // 查询动态信息
- TechnicianMoment moment = momentMapper.selectById(momentId);
- if (moment == null) {
- throw new ServiceException("动态不存在");
- }
- // 增加浏览量
- momentMapper.incrementViewCount(momentId);
- moment.setViewCount(moment.getViewCount() + 1);
- // 查询技师信息
- TJs technician = tJsMapper.selectById(moment.getTechnicianId());
- // 查询媒体列表
- List<MomentMedia> mediaList = mediaMapper.selectMediaListByMomentId(momentId);
- List<MomentMediaVO> mediaVOList = mediaList.stream().map(media -> {
- MomentMediaVO mediaVO = new MomentMediaVO();
- BeanUtils.copyProperties(media, mediaVO);
- return mediaVO;
- }).collect(Collectors.toList());
- // 组装VO
- MomentDetailVO vo = new MomentDetailVO();
- BeanUtils.copyProperties(moment, vo);
- if (technician != null) {
- vo.setTechnicianNickName(technician.getcNickName());
- vo.setTechnicianAvatar(technician.getcPortrait());
- vo.setTechnicianStatus(getTechnicianStatus(technician));
- }
- vo.setMediaList(mediaVOList);
- // 计算距离(如果有位置信息)
- if (moment.getLatitude() != null && moment.getLongitude() != null) {
- // 传入用户位置,计算用户与技师之间的距离
- double distance = calculateDistance(
- latitude.doubleValue(), longitude.doubleValue(),
- moment.getLatitude().doubleValue(), moment.getLongitude().doubleValue()
- );
- vo.setDistance(Math.round(distance * 100.0) / 100.0); // 保留两位小数
- }
- return vo;
- }
- /**
- * 批量查询技师信息
- *
- * @param technicianIds 技师ID列表
- * @return Map<String, TJs> 技师ID-技师实体映射
- */
- private Map<String, TJs> getTechnicianMap(List<String> technicianIds) {
- List<String> ids = technicianIds.stream()
- .map(String::valueOf)
- .collect(Collectors.toList());
- return tJsMapper.selectBatchIds(ids).stream().collect(Collectors.toMap(TJs::getId, t -> t));
- }
- /**
- * 获取技师状态
- * 1-可服务(当前时间技师空闲)
- * 2-可预约(当前时间技师"已接单-服务中")
- */
- private Integer getTechnicianStatus(TJs technician) {
- if (technician.getnStatus() != null && technician.getnStatus() == 0) {
- return 1; // 可服务
- } else if (technician.getnStatus() != null && technician.getnStatus() == 1) {
- return 2; // 可预约(服务中)
- }
- return null;
- }
- /**
- * 计算两点之间的距离(单位:km)
- *
- * @param lat1 纬度1(用户纬度)
- * @param lon1 经度1(用户经度)
- * @param lat2 纬度2(技师纬度)
- * @param lon2 经度2(技师经度)
- * @return double 距离(单位:km)
- *
- * 使用Haversine公式
- */
- private double calculateDistance(double lat1, double lon1, double lat2, double lon2) {
- final double R = 6371; // 地球半径,单位km
- double dLat = Math.toRadians(lat2 - lat1);
- double dLon = Math.toRadians(lon2 - lon1);
- double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
- Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
- Math.sin(dLon / 2) * Math.sin(dLon / 2);
- double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
- return R * c;
- }
- /**
- * 发布动态或保存草稿
- *
- * @param dto 发布动态请求对象
- * @param openId 技师OpenID
- * @return Long 动态ID
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Long publishMoment(PublishMomentDTO dto, String openId) {
- // 1. 参数校验
- if (dto == null) {
- throw new ServiceException("发布动态信息不能为空");
- }
- if (openId == null || openId.trim().isEmpty()) {
- throw new ServiceException("openId不能为空");
- }
- // 2. 根据openId查询技师信息
- LambdaQueryWrapper<TJs> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(TJs::getcOpenId, openId);
- TJs technician = tJsMapper.selectOne(queryWrapper);
- if (technician == null) {
- throw new ServiceException("技师信息不存在");
- }
- // 3. 校验媒体类型和媒体文件
- if (dto.getMediaType() == null) {
- throw new ServiceException("媒体类型不能为空");
- }
- if (dto.getMediaType() == 1) {
- // 图片类型
- if (dto.getImageUrls() == null || dto.getImageUrls().isEmpty()) {
- throw new ServiceException("图片不能为空");
- }
- if (dto.getImageUrls().size() > 9) {
- throw new ServiceException("最多只能上传9张图片");
- }
- } else if (dto.getMediaType() == 2) {
- // 视频类型
- if (dto.getVideoUrl() == null || dto.getVideoUrl().trim().isEmpty()) {
- throw new ServiceException("视频不能为空");
- }
- } else {
- throw new ServiceException("媒体类型不正确");
- }
- // 4. 校验可见范围
- if (dto.getVisibleRange() == null || dto.getVisibleRange() != 1) {
- throw new ServiceException("可见范围只能选择公开");
- }
- // 5. 创建动态对象
- TechnicianMoment moment = new TechnicianMoment();
- moment.setTechnicianId(technician.getId());
- moment.setTitle(dto.getTitle());
- moment.setContent(dto.getContent());
- moment.setMediaType(dto.getMediaType());
- moment.setVisibleRange(dto.getVisibleRange());
- moment.setLatitude(dto.getLatitude());
- moment.setLongitude(dto.getLongitude());
- moment.setLocation(dto.getLocation());
- moment.setAddress(dto.getAddress());
- // 设置封面图
- if (dto.getMediaType() == 1) {
- // 图片类型,默认取第一张作为封面
- if (dto.getImageUrls() != null && !dto.getImageUrls().isEmpty()) {
- moment.setCoverUrl(dto.getImageUrls().get(0));
- }
- } else if (dto.getMediaType() == 2) {
- // 视频类型,使用视频URL作为封面
- moment.setCoverUrl(dto.getVideoUrl());
- }
- // 6. 设置审核状态和发布时间
- if (dto.getIsDraft() != null && dto.getIsDraft() == 1) {
- // 保存草稿
- moment.setAuditStatus(0);
- moment.setPublishTime(null);
- } else {
- // 立即发布,进入待审核状态
- moment.setAuditStatus(1);
- moment.setPublishTime(LocalDateTime.now());
- }
- // 7. 设置初始状态
- moment.setStatus(1); // 正常
- moment.setViewCount(0);
- moment.setCreateTime(LocalDateTime.now());
- moment.setUpdateTime(LocalDateTime.now());
- // 8. 保存动态到数据库
- int insertResult = momentMapper.insert(moment);
- if (insertResult <= 0) {
- throw new ServiceException("发布动态失败");
- }
- Long momentId = moment.getId();
- // 9. 保存媒体信息到媒体表
- if (dto.getMediaType() == 1) {
- // 保存图片
- if (dto.getImageUrls() != null && !dto.getImageUrls().isEmpty()) {
- for (int i = 0; i < dto.getImageUrls().size(); i++) {
- MomentMedia media = new MomentMedia();
- media.setMomentId(momentId);
- media.setMediaUrl(dto.getImageUrls().get(i));
- media.setMediaType(1); // 图片
- media.setSortOrder(i + 1);
- media.setCreateTime(LocalDateTime.now());
- //获取文件的格式
- String fileFormat = dto.getImageUrls().get(i).substring(dto.getImageUrls().get(i).lastIndexOf(".") + 1);
- media.setFileFormat(fileFormat);
- mediaMapper.insert(media);
- }
- }
- } else if (dto.getMediaType() == 2) {
- // 保存视频
- MomentMedia media = new MomentMedia();
- media.setMomentId(momentId);
- media.setMediaUrl(dto.getVideoUrl());
- media.setMediaType(2); // 视频
- media.setSortOrder(1);
- media.setCreateTime(LocalDateTime.now());
- mediaMapper.insert(media);
- }
- log.info("发布动态成功,动态ID:{},技师ID:{},是否草稿:{}", momentId, technician.getId(), dto.getIsDraft());
- return momentId;
- }
- /**
- * 编辑动态
- *
- * @param dto 编辑动态请求对象
- * @param openId 技师OpenID
- * @return Long 动态ID
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Long editMoment(EditMomentDTO dto, String openId) {
- // 1. 参数校验
- if (dto == null) {
- throw new ServiceException("编辑动态信息不能为空");
- }
- if (openId == null || openId.trim().isEmpty()) {
- throw new ServiceException("openId不能为空");
- }
- if (dto.getMomentId() == null) {
- throw new ServiceException("动态ID不能为空");
- }
- // 2. 根据openId查询技师信息
- LambdaQueryWrapper<TJs> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(TJs::getcOpenId, openId);
- TJs technician = tJsMapper.selectOne(queryWrapper);
- if (technician == null) {
- throw new ServiceException("技师信息不存在");
- }
- // 3. 查询动态信息
- TechnicianMoment moment = momentMapper.selectById(dto.getMomentId());
- if (moment == null) {
- throw new ServiceException("动态不存在");
- }
- // 4. 验证动态是否属于当前技师
- if (!moment.getTechnicianId().equals(technician.getId())) {
- throw new ServiceException("无权编辑此动态");
- }
- // 5. 验证动态状态是否允许编辑(只能编辑草稿和审核拒绝的动态)
- if (moment.getAuditStatus() == null ||
- (moment.getAuditStatus() != 0 && moment.getAuditStatus() != 3)) {
- throw new ServiceException("只能编辑草稿或审核拒绝的动态");
- }
- // 6. 校验媒体类型和媒体文件
- if (dto.getMediaType() == null) {
- throw new ServiceException("媒体类型不能为空");
- }
- if (dto.getMediaType() == 1) {
- // 图片类型
- if (dto.getImageUrls() == null || dto.getImageUrls().isEmpty()) {
- throw new ServiceException("图片不能为空");
- }
- if (dto.getImageUrls().size() > 9) {
- throw new ServiceException("最多只能上传9张图片");
- }
- } else if (dto.getMediaType() == 2) {
- // 视频类型
- if (dto.getVideoUrl() == null || dto.getVideoUrl().trim().isEmpty()) {
- throw new ServiceException("视频不能为空");
- }
- } else {
- throw new ServiceException("媒体类型不正确");
- }
- // 7. 校验可见范围
- if (dto.getVisibleRange() == null || dto.getVisibleRange() != 1) {
- throw new ServiceException("可见范围只能选择公开");
- }
- // 8. 更新动态对象
- moment.setTitle(dto.getTitle());
- moment.setContent(dto.getContent());
- moment.setMediaType(dto.getMediaType());
- moment.setVisibleRange(dto.getVisibleRange());
- moment.setLongitude(dto.getLongitude());
- moment.setLatitude(dto.getLatitude());
- moment.setLocation(dto.getLocation());
- moment.setAddress(dto.getAddress());
- // 设置封面图
- if (dto.getMediaType() == 1) {
- // 图片类型,默认取第一张作为封面
- if (dto.getImageUrls() != null && !dto.getImageUrls().isEmpty()) {
- moment.setCoverUrl(dto.getImageUrls().get(0));
- }
- } else if (dto.getMediaType() == 2) {
- // 视频类型,使用视频封面URL(如果提供了)或视频URL作为封面
- if (dto.getVideoCoverUrl() != null && !dto.getVideoCoverUrl().trim().isEmpty()) {
- moment.setCoverUrl(dto.getVideoCoverUrl());
- } else {
- moment.setCoverUrl(dto.getVideoUrl());
- }
- }
- // 9. 设置审核状态和发布时间
- if (dto.getIsDraft() != null && dto.getIsDraft() == 1) {
- // 保存草稿
- moment.setAuditStatus(0); // 草稿
- moment.setPublishTime(null);
- moment.setRejectReason(null); // 清空拒绝原因
- } else {
- // 提交发布,进入待审核状态
- moment.setAuditStatus(1);
- if (moment.getPublishTime() == null) {
- moment.setPublishTime(LocalDateTime.now());
- }
- moment.setRejectReason(null); // 清空拒绝原因
- }
- moment.setUpdateTime(LocalDateTime.now());
- // 10. 更新动态到数据库
- int updateResult = momentMapper.updateById(moment);
- if (updateResult <= 0) {
- throw new ServiceException("编辑动态失败");
- }
- Long momentId = moment.getId();
- // 11. 删除旧的媒体信息
- LambdaQueryWrapper<MomentMedia> mediaWrapper = new LambdaQueryWrapper<>();
- mediaWrapper.eq(MomentMedia::getMomentId, momentId);
- mediaMapper.delete(mediaWrapper);
- // 12. 保存新的媒体信息到媒体表
- if (dto.getMediaType() == 1) {
- // 保存图片
- if (dto.getImageUrls() != null && !dto.getImageUrls().isEmpty()) {
- for (int i = 0; i < dto.getImageUrls().size(); i++) {
- MomentMedia media = new MomentMedia();
- media.setMomentId(momentId);
- media.setMediaUrl(dto.getImageUrls().get(i));
- media.setMediaType(1); // 图片
- media.setSortOrder(i + 1);
- media.setCreateTime(LocalDateTime.now());
- // 获取文件的格式
- String fileFormat = dto.getImageUrls().get(i).substring(dto.getImageUrls().get(i).lastIndexOf(".") + 1);
- media.setFileFormat(fileFormat);
- mediaMapper.insert(media);
- }
- }
- } else if (dto.getMediaType() == 2) {
- // 保存视频
- MomentMedia media = new MomentMedia();
- media.setMomentId(momentId);
- media.setMediaUrl(dto.getVideoUrl());
- media.setMediaType(2); // 视频
- media.setSortOrder(1);
- media.setCreateTime(LocalDateTime.now());
- mediaMapper.insert(media);
- }
- log.info("编辑动态成功,动态ID:{},技师ID:{},是否草稿:{}", momentId, technician.getId(), dto.getIsDraft());
- return momentId;
- }
- /**
- * 查询草稿箱列表
- *
- * @param openId 技师OpenID
- * @param pageNum 页码
- * @param pageSize 每页数量
- * @return List<MomentListVO> 草稿列表
- */
- @Override
- public Page<MomentListVO> getDraftMoments(String openId, Integer pageNum, Integer pageSize) {
- if (openId == null || openId.trim().isEmpty()) {
- throw new ServiceException("openId不能为空");
- }
- // 1. 根据openId查询技师信息
- LambdaQueryWrapper<TJs> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(TJs::getcOpenId, openId);
- TJs technician = tJsMapper.selectOne(queryWrapper);
- if (technician == null) {
- throw new ServiceException("技师信息不存在");
- }
- // 2. 查询该技师的草稿列表
- Page<TechnicianMoment> page = new Page<>(pageNum, pageSize);
- LambdaQueryWrapper<TechnicianMoment> momentWrapper = new LambdaQueryWrapper<>();
- momentWrapper.eq(TechnicianMoment::getTechnicianId, technician.getId())
- .eq(TechnicianMoment::getAuditStatus, 0) // 草稿状态
- .eq(TechnicianMoment::getStatus, 1) // 正常状态
- .orderByDesc(TechnicianMoment::getCreateTime);
- Page<TechnicianMoment> momentPage = momentMapper.selectPage(page, momentWrapper);
- List<TechnicianMoment> moments = momentPage.getRecords();
- Page<MomentListVO> voPage = new Page<>(pageNum, pageSize);
- if (moments == null || moments.isEmpty()) {
- // 草稿列表为空时,返回空Page对象
- return voPage;
- }
- // 3. 组装VO
- List<MomentListVO> collect = moments.stream().map(moment -> {
- MomentListVO vo = new MomentListVO();
- BeanUtils.copyProperties(moment, vo);
- vo.setTechnicianNickName(technician.getcNickName());
- vo.setTechnicianAvatar(technician.getcPortrait());
- vo.setTechnicianStatus(getTechnicianStatus(technician));
- // 草稿的发布时间使用创建时间
- vo.setPublishTime(moment.getCreateTime());
- return vo;
- }).collect(Collectors.toList());
- //返回Page对象
- voPage.setTotal(momentPage.getTotal());
- voPage.setRecords(collect);
- return voPage;
- }
- /**
- * 查询我的动态列表(已发布的动态:审核中+审核通过)
- *
- * @param openId 技师OpenID
- * @param pageNum 页码
- * @param pageSize 每页数量
- * @return Page<MyMomentVO> 我的动态列表
- */
- @Override
- public Page<MyMomentVO> getMyMoments(String openId, Integer pageNum, Integer pageSize) {
- // 1. 参数校验
- if (openId == null || openId.trim().isEmpty()) {
- throw new ServiceException("openId不能为空");
- }
- // 2. 根据openId查询技师信息
- LambdaQueryWrapper<TJs> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(TJs::getcOpenId, openId);
- TJs technician = tJsMapper.selectOne(queryWrapper);
- if (technician == null) {
- throw new ServiceException("技师信息不存在");
- }
- // 3. 查询该技师的已发布动态(待审核、审核通过)
- Page<TechnicianMoment> page = new Page<>(pageNum, pageSize);
- LambdaQueryWrapper<TechnicianMoment> momentWrapper = new LambdaQueryWrapper<>();
- momentWrapper.eq(TechnicianMoment::getTechnicianId, technician.getId())
- .in(TechnicianMoment::getAuditStatus, 1, 2) // 1-待审核, 2-审核通过
- .eq(TechnicianMoment::getStatus, 1) // 正常状态
- .orderByDesc(TechnicianMoment::getPublishTime);
- Page<TechnicianMoment> momentPage = momentMapper.selectPage(page, momentWrapper);
- // 4. 组装分页返回结果
- Page<MyMomentVO> voPage = new Page<>(pageNum, pageSize);
- voPage.setTotal(momentPage.getTotal());
- voPage.setCurrent(momentPage.getCurrent());
- voPage.setSize(momentPage.getSize());
- List<TechnicianMoment> moments = momentPage.getRecords();
- if (moments == null || moments.isEmpty()) {
- voPage.setRecords(new ArrayList<>());
- return voPage;
- }
- // 5. 组装VO列表
- List<MyMomentVO> voList = moments.stream().map(moment -> {
- MyMomentVO vo = new MyMomentVO();
- vo.setId(moment.getId());
- vo.setTitle(moment.getTitle());
- vo.setAuditStatus(moment.getAuditStatus());
- vo.setCoverUrl(moment.getCoverUrl());
- vo.setPublishTime(moment.getPublishTime());
- vo.setViewCount(moment.getViewCount());
- return vo;
- }).collect(Collectors.toList());
- voPage.setRecords(voList);
- log.info("查询我的动态列表成功,技师ID:{},页码:{},每页数量:{},总记录数:{}", technician.getId(), pageNum, pageSize, voPage.getTotal());
- return voPage;
- }
- /**
- * 根据技师ID查询动态列表(已发布的动态:审核中+审核通过)
- *
- * @param technicianId 技师ID
- * @return List<MomentListVO> 动态列表
- */
- @Override
- public List<MomentListVO> getMomentsByTechnicianId(String technicianId) {
- // 1. 参数校验
- if (technicianId == null || technicianId.trim().isEmpty()) {
- throw new ServiceException("技师ID不能为空");
- }
- // 2. 查询该技师的已发布动态(待审核、审核通过)
- LambdaQueryWrapper<TechnicianMoment> momentWrapper = new LambdaQueryWrapper<>();
- momentWrapper.eq(TechnicianMoment::getTechnicianId, technicianId)
- .in(TechnicianMoment::getAuditStatus, 1, 2) // 1-待审核, 2-审核通过
- .eq(TechnicianMoment::getStatus, 1) // 正常状态
- .orderByDesc(TechnicianMoment::getPublishTime);
- List<TechnicianMoment> moments = momentMapper.selectList(momentWrapper);
- if (moments == null || moments.isEmpty()) {
- return new ArrayList<>();
- }
- // 3. 组装VO列表
- List<MomentListVO> voList = moments.stream().map(moment -> {
- MomentListVO vo = new MomentListVO();
- vo.setId(moment.getId());
- vo.setTitle(moment.getTitle());
- vo.setAuditStatus(moment.getAuditStatus());
- vo.setCoverUrl(moment.getCoverUrl());
- vo.setPublishTime(moment.getPublishTime());
- vo.setViewCount(moment.getViewCount());
- return vo;
- }).collect(Collectors.toList());
- log.info("根据技师ID查询动态列表成功,技师ID:{},记录数:{}", technicianId, voList.size());
- return voList;
- }
- /**
- * 查询待审核动态列表(管理后台)
- *
- * @param queryDTO 查询参数
- * @return Page<MomentManageVO> 分页结果
- */
- @Override
- public Page<MomentManageVO> getMomentManageList(MomentManageQueryDTO queryDTO) {
- // 1. 参数处理
- Integer pageNum = queryDTO.getPageNum() != null ? queryDTO.getPageNum() : 1;
- Integer pageSize = queryDTO.getPageSize() != null ? queryDTO.getPageSize() : 10;
- String technicianName = queryDTO.getTechnicianName();
- Integer auditStatus = queryDTO.getAuditStatus();
- String startTime = queryDTO.getStartTime();
- if(StringUtils.isNotBlank(startTime)){
- startTime = startTime + " 00:00:00";
- }
- String endTime = queryDTO.getEndTime();
- if(StringUtils.isNotBlank(endTime)){
- endTime = endTime + " 23:59:59";
- }
- // 2. 构建查询条件
- LambdaQueryWrapper<TechnicianMoment> queryWrapper = new LambdaQueryWrapper<>();
- queryWrapper.eq(TechnicianMoment::getStatus, 1); // 只查询正常状态的动态
- // 如果传入了审核状态,则按照审核状态查询
- if (auditStatus != null) {
- queryWrapper.eq(TechnicianMoment::getAuditStatus, auditStatus);
- } else {
- // 默认查询全部的动态(待审核、审核通过、审核拒绝)
- queryWrapper.in(TechnicianMoment::getAuditStatus, 1, 2, 3);
- }
- // 技师姓名查询
- if (technicianName != null && !technicianName.trim().isEmpty()) {
- //根据技师姓名查询技师的ID
- LambdaQueryWrapper<TJs> jsQueryWrapper = new LambdaQueryWrapper<>();
- jsQueryWrapper.like(TJs::getcNickName, technicianName);
- List<TJs> technicians = tJsMapper.selectList(jsQueryWrapper);
- if (technicians == null || technicians.isEmpty()) {
- throw new ServiceException("技师不存在");
- }
- // 构建查询条件,查询所有匹配的技师的动态
- queryWrapper.in(TechnicianMoment::getTechnicianId, technicians.stream().map(TJs::getId).collect(Collectors.toList()));
- }
- // 时间范围查询
- if (startTime != null && !startTime.trim().isEmpty()) {
- queryWrapper.ge(TechnicianMoment::getPublishTime, startTime);
- }
- if (endTime != null && !endTime.trim().isEmpty()) {
- queryWrapper.le(TechnicianMoment::getPublishTime, endTime);
- }
- // 按创建时间倒序排序
- queryWrapper.orderByDesc(TechnicianMoment::getCreateTime);
- // 3. 分页查询
- Page<TechnicianMoment> page = new Page<>(pageNum, pageSize);
- Page<TechnicianMoment> momentPage = momentMapper.selectPage(page, queryWrapper);
- // 4. 组装VO
- Page<MomentManageVO> voPage = new Page<>(pageNum, pageSize);
- voPage.setTotal(momentPage.getTotal());
- voPage.setCurrent(momentPage.getCurrent());
- voPage.setSize(momentPage.getSize());
- List<TechnicianMoment> moments = momentPage.getRecords();
- if (moments == null || moments.isEmpty()) {
- voPage.setRecords(new ArrayList<>());
- return voPage;
- }
- // 5. 批量查询技师信息
- List<String> technicianIds = moments.stream()
- .map(TechnicianMoment::getTechnicianId)
- .collect(Collectors.toList());
- Map<String, TJs> technicianMap = getTechnicianMap(technicianIds);
- // 6. 组装VO列表
- List<MomentManageVO> voList = moments.stream().map(moment -> {
- MomentManageVO vo = new MomentManageVO();
- BeanUtils.copyProperties(moment, vo);
- // 设置技师信息
- TJs technician = technicianMap.get(moment.getTechnicianId());
- if (technician != null) {
- // 设置技师姓名
- vo.setTechnicianName(technician.getcName());
- // 设置技师昵称
- vo.setTechnicianNickname(technician.getcNickName());
- }
- return vo;
- }).collect(Collectors.toList());
- voPage.setRecords(voList);
- log.info("查询动态管理列表,页码:{},每页数量:{},总记录数:{}", pageNum, pageSize, voPage.getTotal());
- return voPage;
- }
- /**
- * 审核动态(通过/拒绝)
- *
- * @param momentId 动态ID
- * @param auditStatus 审核状态:2-通过,3-拒绝
- * @param rejectReason 拒绝原因(拒绝时必填)
- * @return 是否成功
- */
- @Override
- @Transactional(rollbackFor = Exception.class)
- public Boolean auditMoment(MomentAuditDTO dto) {
- // 1. 参数校验
- if (dto.getMomentId() == null) {
- throw new ServiceException("动态ID不能为空");
- }
- if (dto.getAuditStatus() == null || (dto.getAuditStatus() != 2 && dto.getAuditStatus() != 3)) {
- throw new ServiceException("审核状态不正确");
- }
- if (dto.getAuditStatus() == 3 && (dto.getRejectReason() == null || dto.getRejectReason().trim().isEmpty())) {
- throw new ServiceException("拒绝时必须填写拒绝原因");
- }
- // 2. 查询动态信息
- TechnicianMoment moment = momentMapper.selectById(dto.getMomentId());
- if (moment == null) {
- throw new ServiceException("动态不存在");
- }
- // 3. 校验动态状态
- if (moment.getStatus() != 1) {
- throw new ServiceException("动态已删除,无法审核");
- }
- if (moment.getAuditStatus() != 1) {
- throw new ServiceException("只能审核待审核状态的动态");
- }
- // 4. 更新审核状态
- moment.setAuditStatus(dto.getAuditStatus());
- moment.setRejectReason(dto.getRejectReason());
- moment.setUpdateTime(LocalDateTime.now());
- int updateResult = momentMapper.updateById(moment);
- if (updateResult <= 0) {
- throw new ServiceException("审核失败");
- }
- log.info("审核动态成功,动态ID:{},审核结果:{},拒绝原因:{}", dto.getMomentId(), dto.getAuditStatus(), dto.getRejectReason());
- return true;
- }
- /**
- * 根据动态ID查询动态简要详情(包含媒体URL列表)
- *
- * @param momentId 动态ID
- * @return MomentSimpleDetailVO动态简要详情
- */
- @Override
- public MomentSimpleDetailVO getMomentSimpleDetail(Long momentId) {
- // 1. 参数校验
- if (momentId == null) {
- throw new ServiceException("动态ID不能为空");
- }
- // 2. 查询动态信息
- Map<String, Object> result = momentMapper.selectMomentSimpleDetail(momentId);
- if (result == null || result.isEmpty()) {
- throw new ServiceException("动态不存在");
- }
- // 3. 组装VO
- MomentSimpleDetailVO vo = new MomentSimpleDetailVO();
- vo.setId(((Number) result.get("id")).longValue());
- vo.setTitle((String) result.get("title"));
- vo.setContent((String) result.get("content"));
- vo.setMediaType((Integer) result.get("media_type"));
- vo.setAuditStatus((Integer) result.get("audit_status"));
- vo.setRejectReason((String) result.get("reject_reason"));
- // 4. 处理媒体URL列表
- String mediaUrlsStr = (String) result.get("media_urls");
- if (mediaUrlsStr != null && !mediaUrlsStr.trim().isEmpty()) {
- // 将逗号分隔的字符串转换为List
- List<String> mediaUrls = Arrays.asList(mediaUrlsStr.split(","));
- vo.setMediaUrls(mediaUrls);
- } else {
- vo.setMediaUrls(new ArrayList<>());
- }
- log.info("查询动态简要详情成功,动态ID:{}", momentId);
- return vo;
- }
- }
|