Jelajahi Sumber

开发动态相关的接口

jinshihui 1 bulan lalu
induk
melakukan
82e1c9ec3e

+ 10 - 8
nightFragrance-admin/src/main/java/com/ylx/web/controller/common/CommonController.java

@@ -122,8 +122,9 @@ public class CommonController {
      */
     @ApiOperation("通用上传请求(多个)")
     @PostMapping("/uploads")
-    public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception {
+    public AjaxResult uploadFiles(List<MultipartFile> file) throws Exception {
         try {
+            log.info("上传文件数量:{}", file.size());
             // 上传文件路径
             String filePath = RuoYiConfig.getUploadPath();
             log.info("上传文件路径:{}", filePath);
@@ -132,22 +133,23 @@ public class CommonController {
             List<String> fileNames = new ArrayList<String>();
             List<String> newFileNames = new ArrayList<String>();
             List<String> originalFilenames = new ArrayList<String>();
-            for (MultipartFile file : files) {
+            for (MultipartFile fileItem : file) {
                 // 上传并返回新文件名称
-                String fileName = FileUploadUtils.upload(filePath, file);
+                String fileName = FileUploadUtils.upload(filePath, fileItem);
                 String url = serverConfig.getUrl() + fileName;
                 urls.add(url);
                 fileNames.add(fileName);
                 newFileNames.add(FileUtils.getName(fileName));
-                originalFilenames.add(file.getOriginalFilename());
+                originalFilenames.add(fileItem.getOriginalFilename());
             }
             AjaxResult ajax = AjaxResult.success();
-            ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
-            ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
-            ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
-            ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
+            ajax.put("url", StringUtils.join(urls, FILE_DELIMETER));
+            ajax.put("fileName", StringUtils.join(fileNames, FILE_DELIMETER));
+            ajax.put("newFileName", StringUtils.join(newFileNames, FILE_DELIMETER));
+            ajax.put("originalFilename", StringUtils.join(originalFilenames, FILE_DELIMETER));
             return ajax;
         } catch (Exception e) {
+            e.printStackTrace();
             return AjaxResult.error(e.getMessage());
         }
     }

+ 61 - 9
nightFragrance-admin/src/main/java/com/ylx/web/controller/massage/TechnicianMomentController.java

@@ -1,5 +1,6 @@
 package com.ylx.web.controller.massage;
 
+import com.alibaba.fastjson.JSON;
 import com.ylx.common.annotation.Log;
 import com.ylx.common.core.controller.BaseController;
 import com.ylx.common.core.domain.R;
@@ -8,10 +9,12 @@ import com.ylx.common.enums.BusinessType;
 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.MomentSimpleDetailVO;
+import com.ylx.massage.domain.vo.MyMomentVO;
 import com.ylx.massage.service.ITechnicianMomentService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -47,7 +50,7 @@ public class TechnicianMomentController extends BaseController {
      * @param pageSize 每页数量,默认10
      * @return R<List<MomentListVO>> 动态列表
      */
-    @GetMapping("/recommended")
+    /*@GetMapping("/recommended")
     @ApiOperation("获取推荐动态列表")
     public R<List<MomentListVO>> getRecommendedMoments(
             @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
@@ -59,7 +62,7 @@ public class TechnicianMomentController extends BaseController {
             log.error("获取推荐动态列表失败", e);
             return R.fail("获取推荐动态列表失败:" + e.getMessage());
         }
-    }
+    }*/
 
     /**
      * 获取同城商户动态列表
@@ -71,7 +74,7 @@ public class TechnicianMomentController extends BaseController {
      * @param pageSize 每页数量,默认10
      * @return R<List<MomentListVO>> 动态列表
      */
-    @GetMapping("/sameCity")
+    /*@GetMapping("/sameCity")
     @ApiOperation("获取同城商户动态列表")
     public R<List<MomentListVO>> getSameCityMoments(
             @ApiParam("城市编码") @RequestParam String cityCode,
@@ -87,7 +90,7 @@ public class TechnicianMomentController extends BaseController {
             log.error("获取同城商户动态列表失败", e);
             return R.fail("获取同城商户动态列表失败:" + e.getMessage());
         }
-    }
+    }*/
 
     /**
      * 获取附近动态列表
@@ -100,7 +103,7 @@ public class TechnicianMomentController extends BaseController {
      * @param pageSize  每页数量,默认10
      * @return 动态列表
      */
-    @GetMapping("/nearby")
+    /*@GetMapping("/nearby")
     @ApiOperation("获取附近动态列表")
     public R<List<MomentListVO>> getNearbyMoments(
             @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
@@ -117,10 +120,10 @@ public class TechnicianMomentController extends BaseController {
             log.error("获取附近动态列表失败", e);
             return R.fail("获取附近动态列表失败:" + e.getMessage());
         }
-    }
+    }*/
 
     /**
-     * 统一查询接口
+     * 获取推荐、同城、附近动态列表接口
      * 根据queryType参数决定查询类型:1-推荐,2-同城,3-附近
      *
      * @param queryType 查询类型:1-推荐,2-同城,3-附近
@@ -132,7 +135,7 @@ public class TechnicianMomentController extends BaseController {
      * @return R<List<MomentListVO>> 动态列表
      */
     @GetMapping("/list")
-    @ApiOperation("统一查询接口")
+    @ApiOperation("获取推荐、同城、附近动态列表接口")
     public R<List<MomentListVO>> getMomentList(
             @ApiParam("查询类型:1-推荐,2-同城,3-附近") @RequestParam Integer queryType,
             @ApiParam("城市编码") @RequestParam(required = false) String cityCode,
@@ -208,10 +211,10 @@ public class TechnicianMomentController extends BaseController {
     @ApiOperation("发布动态或保存草稿")
     public R<Long> publishMoment(@Valid @RequestBody PublishMomentDTO dto) {
         try {
+            log.info("发布动态或保存草稿的请求参数:{}", JSON.toJSONString(dto));
             // 获取当前登录用户信息
             WxLoginUser wxLoginUser = getWxLoginUser();
             String openId = wxLoginUser.getCOpenid();
-            log.info("发布动态,openId:{},标题:{},媒体类型:{},是否草稿:{}", openId, dto.getTitle(), dto.getMediaType(), dto.getIsDraft());
 
             Long momentId = momentService.publishMoment(dto, openId);
             return R.ok(momentId, dto.getIsDraft() != null && dto.getIsDraft() == 1 ? "保存草稿成功" : "发布成功,等待审核");
@@ -221,6 +224,55 @@ public class TechnicianMomentController extends BaseController {
         }
     }
 
+    /**
+     * 编辑动态
+     *
+     * @param dto 编辑动态请求对象
+     * @return R 动态ID
+     */
+    @PostMapping("/edit")
+    @ApiOperation("编辑动态")
+    public R<Long> editMoment(@Valid @RequestBody EditMomentDTO dto) {
+        try {
+            log.info("编辑动态的请求参数:{}", JSON.toJSONString(dto));
+            // 获取当前登录用户信息
+            WxLoginUser wxLoginUser = getWxLoginUser();
+            String openId = wxLoginUser.getCOpenid();
+
+            Long momentId = momentService.editMoment(dto, openId);
+            return R.ok(momentId, dto.getIsDraft() != null && dto.getIsDraft() == 1 ? "保存草稿成功" : "提交成功,等待审核");
+        } catch (Exception e) {
+            log.error("编辑动态失败", e);
+            return R.fail("编辑动态失败:" + e.getMessage());
+        }
+    }
+
+    /**
+     * 查询我的动态列表(已发布的动态:审核中+审核通过)
+     *
+     * @param pageNum  页码
+     * @param pageSize 每页数量
+     * @return R 我的动态列表
+     */
+    @GetMapping("/my")
+    @ApiOperation("查询我的动态列表")
+    public R<Page<MyMomentVO>> getMyMoments(
+            @ApiParam("页码") @RequestParam(defaultValue = "1") Integer pageNum,
+            @ApiParam("每页数量") @RequestParam(defaultValue = "10") Integer pageSize) {
+        try {
+            // 获取当前登录用户信息
+            WxLoginUser wxLoginUser = getWxLoginUser();
+            String openId = wxLoginUser.getCOpenid();
+            log.info("查询我的动态列表,openId:{},页码:{},每页数量:{}", openId, pageNum, pageSize);
+
+            Page<MyMomentVO> page = momentService.getMyMoments(openId, pageNum, pageSize);
+            return R.ok(page);
+        } catch (Exception e) {
+            log.error("查询我的动态列表失败", e);
+            return R.fail("查询我的动态列表失败:" + e.getMessage());
+        }
+    }
+
     /**
      * 查询草稿箱列表
      *

+ 18 - 6
nightFragrance-massage/src/main/java/com/ylx/massage/domain/TechnicianMoment.java

@@ -65,15 +65,30 @@ public class TechnicianMoment {
     private String cityCode;
 
     /**
-     * 纬度
+     * 地址名称
      */
-    private BigDecimal latitude;
+    private String location;
+
+    /**
+     * 完整的详细地址信息
+     */
+    private String address;
 
     /**
      * 经度
      */
     private BigDecimal longitude;
 
+    /**
+     * 纬度
+     */
+    private BigDecimal latitude;
+
+    /**
+     * 距离(单位:米)
+     */
+    //private Double distance;
+
     /**
      * 创建时间
      */
@@ -99,9 +114,6 @@ public class TechnicianMoment {
      */
     private Integer visibleRange;
 
-    /**
-     * 发布地址
-     */
-    private String address;
+
 
 }

+ 104 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/EditMomentDTO.java

@@ -0,0 +1,104 @@
+package com.ylx.massage.domain.dto;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 编辑动态请求DTO
+ */
+@Data
+@ApiModel("编辑动态请求")
+public class EditMomentDTO {
+
+    /**
+     * 动态ID
+     */
+    @ApiModelProperty(value = "动态ID", required = true)
+    @NotNull(message = "动态ID不能为空")
+    private Long momentId;
+
+    /**
+     * 动态标题
+     */
+    @ApiModelProperty(value = "动态标题", required = true)
+    @NotBlank(message = "动态标题不能为空")
+    private String title;
+
+    /**
+     * 动态内容
+     */
+    @ApiModelProperty(value = "动态内容", required = true)
+    @NotBlank(message = "动态内容不能为空")
+    @Size(max = 1000, message = "动态内容不能超过1000个字符")
+    private String content;
+
+    /**
+     * 媒体类型:1-图片,2-视频
+     */
+    @ApiModelProperty(value = "媒体类型:1-图片,2-视频", required = true)
+    @NotNull(message = "媒体类型不能为空")
+    private Integer mediaType;
+
+    /**
+     * 图片URL列表(最多9张)
+     */
+    @ApiModelProperty("图片URL列表,最多9张")
+    @Size(max = 9, message = "最多只能上传9张图片")
+    private List<String> imageUrls;
+
+    /**
+     * 视频URL
+     */
+    @ApiModelProperty("视频URL")
+    private String videoUrl;
+
+    /**
+     * 视频封面URL
+     */
+    @ApiModelProperty("视频封面URL")
+    private String videoCoverUrl;
+
+    /**
+     * 可见范围:1-公开
+     */
+    @ApiModelProperty(value = "可见范围:1-公开", required = true)
+    @NotNull(message = "可见范围不能为空")
+    private Integer visibleRange;
+
+    /**
+     * 纬度
+     */
+    @ApiModelProperty("纬度")
+    private BigDecimal latitude;
+
+    /**
+     * 经度
+     */
+    @ApiModelProperty("经度")
+    private BigDecimal longitude;
+
+    /**
+     * 地址名称
+     */
+    @ApiModelProperty("地址名称")
+    private String location;
+
+    /**
+     * 详细地址信息
+     */
+    @ApiModelProperty("详细地址信息")
+    private String address;
+
+    /**
+     * 是否保存为草稿:0-立即发布,1-保存草稿
+     */
+    @ApiModelProperty("是否保存为草稿:0-立即发布,1-保存草稿")
+    private Integer isDraft;
+}

+ 8 - 2
nightFragrance-massage/src/main/java/com/ylx/massage/domain/dto/PublishMomentDTO.java

@@ -78,9 +78,15 @@ public class PublishMomentDTO {
     private BigDecimal longitude;
 
     /**
-     * 发布地址
+     * 地址名称
      */
-    @ApiModelProperty("发布地址")
+    @ApiModelProperty("地址名称")
+    private String location;
+
+    /**
+     * 详细地址信息
+     */
+    @ApiModelProperty("详细地址信息")
     private String address;
 
 

+ 51 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/domain/vo/MyMomentVO.java

@@ -0,0 +1,51 @@
+package com.ylx.massage.domain.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 我的动态列表VO
+ */
+@Data
+@ApiModel("我的动态列表")
+public class MyMomentVO {
+
+    /**
+     * 动态ID
+     */
+    @ApiModelProperty("动态ID")
+    private Long id;
+
+    /**
+     * 动态标题
+     */
+    @ApiModelProperty("动态标题")
+    private String title;
+
+    /**
+     * 审核状态:1-待审核,2-审核通过,3-审核拒绝
+     */
+    @ApiModelProperty("审核状态:1-待审核,2-审核通过,3-审核拒绝")
+    private Integer auditStatus;
+
+    /**
+     * 动态封面图URL
+     */
+    @ApiModelProperty("动态封面图URL")
+    private String coverUrl;
+
+    /**
+     * 发布时间
+     */
+    @ApiModelProperty("发布时间")
+    private LocalDateTime publishTime;
+
+    /**
+     * 浏览量
+     */
+    @ApiModelProperty("浏览量")
+    private Integer viewCount;
+}

+ 19 - 0
nightFragrance-massage/src/main/java/com/ylx/massage/service/ITechnicianMomentService.java

@@ -65,6 +65,15 @@ public interface ITechnicianMomentService extends IService<com.ylx.massage.domai
      */
     Long publishMoment(PublishMomentDTO dto, String openId);
 
+    /**
+     * 编辑动态或保存为草稿
+     *
+     * @param dto      编辑动态请求对象
+     * @param openId   技师OpenID
+     * @return 动态ID
+     */
+    Long editMoment(com.ylx.massage.domain.dto.EditMomentDTO dto, String openId);
+
     /**
      * 查询草稿箱列表
      *
@@ -75,6 +84,16 @@ public interface ITechnicianMomentService extends IService<com.ylx.massage.domai
      */
     List<MomentListVO> getDraftMoments(String openId, Integer pageNum, Integer pageSize);
 
+    /**
+     * 查询我的动态列表(已发布的动态:审核中+审核通过)
+     *
+     * @param openId   技师OpenID
+     * @param pageNum  页码
+     * @param pageSize 每页数量
+     * @return 我的动态列表
+     */
+    com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.ylx.massage.domain.vo.MyMomentVO> getMyMoments(String openId, Integer pageNum, Integer pageSize);
+
     /**
      * 查询待审核动态列表(管理后台)
      *

+ 227 - 6
nightFragrance-massage/src/main/java/com/ylx/massage/service/impl/TechnicianMomentServiceImpl.java

@@ -11,11 +11,13 @@ 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;
@@ -289,7 +291,7 @@ public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMap
             throw new ServiceException("发布动态信息不能为空");
         }
         if (openId == null || openId.trim().isEmpty()) {
-            throw new ServiceException("技师信息不能为空");
+            throw new ServiceException("openId不能为空");
         }
 
         // 2. 根据openId查询技师信息
@@ -335,8 +337,8 @@ public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMap
         moment.setVisibleRange(dto.getVisibleRange());
         moment.setLatitude(dto.getLatitude());
         moment.setLongitude(dto.getLongitude());
+        moment.setLocation(dto.getLocation());
         moment.setAddress(dto.getAddress());
-        moment.setCityCode(dto.getCityCode());
 
         // 设置封面图
         if (dto.getMediaType() == 1) {
@@ -345,8 +347,8 @@ public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMap
                 moment.setCoverUrl(dto.getImageUrls().get(0));
             }
         } else if (dto.getMediaType() == 2) {
-            // 视频类型,使用视频封面
-            moment.setCoverUrl(dto.getVideoCoverUrl());
+            // 视频类型,使用视频URL作为封面
+            moment.setCoverUrl(dto.getVideoUrl());
         }
 
         // 6. 设置审核状态和发布时间
@@ -355,8 +357,8 @@ public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMap
             moment.setAuditStatus(0); // 草稿
             moment.setPublishTime(null);
         } else {
-            // 立即发布,进入审核状态
-            moment.setAuditStatus(1); // 审核中
+            // 立即发布,进入审核状态
+            moment.setAuditStatus(1);
             moment.setPublishTime(LocalDateTime.now());
         }
 
@@ -405,6 +407,163 @@ public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMap
         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;
+    }
+
     /**
      * 查询草稿箱列表
      *
@@ -454,6 +613,68 @@ public class TechnicianMomentServiceImpl extends ServiceImpl<TechnicianMomentMap
         }).collect(Collectors.toList());
     }
 
+    /**
+     * 查询我的动态列表(已发布的动态:审核中+审核通过)
+     *
+     * @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;
+    }
+
     /**
      * 查询动态列表(管理后台)
      *