Browse Source

增加动物笔记瀑布流接口

glx_phase2
glx 3 weeks ago
parent
commit
3bd113ade7
  1. 12
      src/main/java/com/youlai/boot/mini/controller/StrayAnimalController.java
  2. 2
      src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalMapper.java
  3. 19
      src/main/java/com/youlai/boot/mini/model/query/WaterfallQuery.java
  4. 3
      src/main/java/com/youlai/boot/mini/model/vo/StrayAnimalShortVO.java
  5. 28
      src/main/java/com/youlai/boot/mini/model/vo/WaterfallResult.java
  6. 5
      src/main/java/com/youlai/boot/mini/service/StrayAnimalService.java
  7. 52
      src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalServiceImpl.java
  8. 64
      src/main/resources/mapper/mini/MiniStrayAnimalMapper.xml

12
src/main/java/com/youlai/boot/mini/controller/StrayAnimalController.java

@ -14,6 +14,8 @@ import com.youlai.boot.mini.model.form.NoteCollectForm;
import com.youlai.boot.mini.model.form.NoteLikeForm; import com.youlai.boot.mini.model.form.NoteLikeForm;
import com.youlai.boot.mini.model.form.StrayAnimalForm; import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery; import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.query.WaterfallQuery;
import com.youlai.boot.mini.model.vo.WaterfallResult;
import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO;
import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO; import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO;
import com.youlai.boot.mini.model.vo.StrayAnimalShortVO; import com.youlai.boot.mini.model.vo.StrayAnimalShortVO;
@ -175,7 +177,15 @@ public class StrayAnimalController {
return Result.success(result); return Result.success(result);
} }
//获取流浪动物笔记瀑布流 @Operation(summary = "获取流浪动物笔记瀑布流")
@GetMapping(value = "/note/waterfall")
public Result<WaterfallResult<StrayAnimalShortVO>> getWaterfall(
@Valid WaterfallQuery query
) {
Long userId = SecurityUtils.getUserId();
WaterfallResult<StrayAnimalShortVO> result = strayAnimalService.getWaterfall(query, userId);
return Result.success(result);
}
//增加浏览量 //增加浏览量

2
src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalMapper.java

@ -30,4 +30,6 @@ public interface MiniStrayAnimalMapper extends BaseMapper<MiniStrayAnimal> {
StrayAnimalDetailsVO getStrayAnimalDetails(@Param("animalUuid") String animalUuid, @Param("miniUserId") Long miniUserId); StrayAnimalDetailsVO getStrayAnimalDetails(@Param("animalUuid") String animalUuid, @Param("miniUserId") Long miniUserId);
List<StrayAnimalNearbyVO> listByMapBounds(MapSearchDTO mapSearch); List<StrayAnimalNearbyVO> listByMapBounds(MapSearchDTO mapSearch);
List<StrayAnimalShortVO> getWaterfall(@Param("cursor") Long cursor, @Param("pageSize") Integer pageSize, @Param("animalType") String animalType, @Param("miniUserId") Long miniUserId);
} }

19
src/main/java/com/youlai/boot/mini/model/query/WaterfallQuery.java

@ -0,0 +1,19 @@
package com.youlai.boot.mini.model.query;
import com.youlai.boot.common.base.BaseQuery;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.Max;
import jakarta.validation.constraints.Min;
import lombok.Data;
@Data
@Schema(description = "瀑布流查询参数")
public class WaterfallQuery extends BaseQuery {
@Schema(description = "游标(上一页最后一条的ID,首次请求不传)", example = "100")
private Long cursor;
@Schema(description = "动物类型筛选(cat-猫 dog-狗 other-其他)", example = "cat")
private String animalType;
}

3
src/main/java/com/youlai/boot/mini/model/vo/StrayAnimalShortVO.java

@ -7,6 +7,9 @@ import lombok.Data;
@Data @Data
public class StrayAnimalShortVO { public class StrayAnimalShortVO {
@Schema(description = "笔记ID(仅用于瀑布流游标,前端不需要展示)", hidden = true)
private Long id;
@Schema(description = "作者uuid", example = "true") @Schema(description = "作者uuid", example = "true")
private String authorUuid; private String authorUuid;

28
src/main/java/com/youlai/boot/mini/model/vo/WaterfallResult.java

@ -0,0 +1,28 @@
package com.youlai.boot.mini.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import java.util.List;
@Data
@Schema(description = "瀑布流返回结果")
public class WaterfallResult<T> {
@Schema(description = "数据列表")
private List<T> list;
@Schema(description = "下一页游标(传null表示没有更多了)", example = "100")
private Long nextCursor;
@Schema(description = "是否最后一页", example = "false")
private Boolean isLastPage;
public static <T> WaterfallResult<T> of(List<T> list, Long nextCursor, boolean isLastPage) {
WaterfallResult<T> result = new WaterfallResult<>();
result.setList(list);
result.setNextCursor(nextCursor);
result.setIsLastPage(isLastPage);
return result;
}
}

5
src/main/java/com/youlai/boot/mini/service/StrayAnimalService.java

@ -9,8 +9,11 @@ import com.youlai.boot.mini.model.dto.MapSearchDTO;
import com.youlai.boot.mini.model.entity.MiniStrayAnimal; import com.youlai.boot.mini.model.entity.MiniStrayAnimal;
import com.youlai.boot.mini.model.form.NoteCollectForm; import com.youlai.boot.mini.model.form.NoteCollectForm;
import com.youlai.boot.mini.model.form.NoteLikeForm; import com.youlai.boot.mini.model.form.NoteLikeForm;
import com.youlai.boot.mini.model.form.NoteCollectForm;
import com.youlai.boot.mini.model.form.StrayAnimalForm; import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery; import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.query.WaterfallQuery;
import com.youlai.boot.mini.model.vo.WaterfallResult;
import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO; import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO;
import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO; import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO;
import com.youlai.boot.mini.model.vo.StrayAnimalNearbyVO; import com.youlai.boot.mini.model.vo.StrayAnimalNearbyVO;
@ -48,5 +51,7 @@ public interface StrayAnimalService extends IService<MiniStrayAnimal> {
Map<String, Object> toggleNoteLike(NoteLikeForm form, Long userId); Map<String, Object> toggleNoteLike(NoteLikeForm form, Long userId);
Map<String, Object> toggleNoteCollect(NoteCollectForm form, Long userId); Map<String, Object> toggleNoteCollect(NoteCollectForm form, Long userId);
WaterfallResult<StrayAnimalShortVO> getWaterfall(WaterfallQuery query, Long userId);
} }

52
src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalServiceImpl.java

@ -38,6 +38,7 @@ import com.youlai.boot.mini.model.entity.MiniStrayAnimalNote;
import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteMedia; import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteMedia;
import com.youlai.boot.mini.model.form.StrayAnimalForm; import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery; import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.query.WaterfallQuery;
import com.youlai.boot.mini.model.vo.*; import com.youlai.boot.mini.model.vo.*;
import com.youlai.boot.mini.service.MiniPointRecordService; import com.youlai.boot.mini.service.MiniPointRecordService;
import com.youlai.boot.mini.service.StrayAnimalService; import com.youlai.boot.mini.service.StrayAnimalService;
@ -774,4 +775,55 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M
return result; return result;
} }
@Override
public WaterfallResult<StrayAnimalShortVO> getWaterfall(WaterfallQuery query, Long userId) {
// 1. 设置默认值,查 N+1 条
int pageSize = query.getPageSize();
int querySize = pageSize + 1;
// 2. 从DB查询 N+1 条数据
List<StrayAnimalShortVO> list = miniStrayAnimalMapper.getWaterfall(
query.getCursor(),
querySize,
query.getAnimalType(),
userId
);
// 3. 设置默认图片(如果没有封面图)
if (list != null && !list.isEmpty()) {
list.forEach(item -> {
if (StrUtil.isBlank(item.getFirstImageUrl())) {
switch (item.getAnimalType()) {
case "cat":
item.setFirstImageUrl(getDefaultCatCoverHost() + "/default_cat.png");
break;
case "dog":
item.setFirstImageUrl(getDefaultCatCoverHost() + "/default_dog.png");
break;
default:
item.setFirstImageUrl(getDefaultCatCoverHost() + "/default_other.png");
break;
}
}
});
}
// 4. 计算下一页游标(N+1 方案:如果返回数量 > pageSize 说明有下一页,取前 pageSize 条)
Long nextCursor = null;
boolean isLastPage = true;
List<StrayAnimalShortVO> resultList = list;
if (list != null && !list.isEmpty()) {
if (list.size() > pageSize) {
// 取前 pageSize 条
resultList = list.subList(0, pageSize);
// 用第 pageSize 条的 id 作为游标
nextCursor = list.get(pageSize - 1).getId();
isLastPage = false;
}
}
return WaterfallResult.of(resultList, nextCursor, isLastPage);
}
} }

64
src/main/resources/mapper/mini/MiniStrayAnimalMapper.xml

@ -291,5 +291,69 @@
</if> </if>
</select> </select>
<!-- 瀑布流查询 -->
<select id="getWaterfall" resultType="com.youlai.boot.mini.model.vo.StrayAnimalShortVO" databaseId="mysql">
WITH first_image AS (
SELECT
m.note_id,
m.source_url,
ROW_NUMBER() OVER (
PARTITION BY m.note_id
ORDER BY m.id ASC
) AS rn
FROM mini_stray_animal_note_media m
WHERE m.media_type = 'image'
AND m.is_deleted = 0
)
SELECT
n.id,
u.uuid AS authorUuid,
u.nickname AS authorName,
u.avatar AS authorAvatar,
a.uuid AS animalUuid,
n.uuid AS animalNoteUuid,
a.animal_type,
fi.source_url AS firstImageUrl,
n.title,
n.content,
n.visibility,
n.view_count,
n.like_count,
n.comment_count,
n.collect_count,
<if test="miniUserId != null">
-- 当前用户是否点赞
EXISTS (
SELECT 1
FROM mini_stray_animal_note_like l
WHERE l.note_id = n.id
AND l.mini_user_id = #{miniUserId}
AND l.is_deleted = 0
) AS isLiked,
-- 当前用户是否收藏
EXISTS (
SELECT 1
FROM mini_stray_animal_note_collect c
WHERE c.note_id = n.id
AND c.mini_user_id = #{miniUserId}
AND c.is_deleted = 0
) AS isCollected,
</if>
a.audit_status
FROM mini_stray_animal a
INNER JOIN sys_user u ON a.mini_user_id = u.id
LEFT JOIN mini_stray_animal_note n ON n.stray_animal_id = a.id
LEFT JOIN first_image fi ON fi.note_id = n.id AND fi.rn = 1
WHERE n.is_deleted = 0
AND a.is_deleted = 0
<if test="cursor != null">
AND n.id &lt; #{cursor}
</if>
<if test="animalType != null and animalType != ''">
AND a.animal_type = #{animalType}
</if>
ORDER BY n.id DESC
LIMIT #{pageSize}
</select>
</mapper> </mapper>

Loading…
Cancel
Save