Browse Source

增加首页接口

glx
glx 1 day ago
parent
commit
78a3dc661e
  1. 2
      .gitignore
  2. 29
      src/main/java/com/youlai/boot/mini/controller/HomePageController.java
  3. 6
      src/main/java/com/youlai/boot/mini/mapper/MiniStrayAnimalMapper.java
  4. 3
      src/main/java/com/youlai/boot/mini/model/query/StrayAnimalQuery.java
  5. 15
      src/main/java/com/youlai/boot/mini/model/vo/HomeStatsVO.java
  6. 30
      src/main/java/com/youlai/boot/mini/model/vo/TaskVO.java
  7. 4
      src/main/java/com/youlai/boot/mini/service/MiniPointRecordService.java
  8. 6
      src/main/java/com/youlai/boot/mini/service/StrayAnimalService.java
  9. 80
      src/main/java/com/youlai/boot/mini/service/impl/MiniPointRecordServiceImpl.java
  10. 31
      src/main/java/com/youlai/boot/mini/service/impl/StrayAnimalServiceImpl.java
  11. 76
      src/main/resources/mapper/mini/MiniStrayAnimalMapper.xml

2
.gitignore

@ -19,3 +19,5 @@ docker/xxljob/logs
application-youlai.yml
.claude
CLAUDE.md
docs
.mcp.json

29
src/main/java/com/youlai/boot/mini/controller/HomePageController.java

@ -1,9 +1,18 @@
package com.youlai.boot.mini.controller;
import com.youlai.boot.common.result.PageResult;
import com.youlai.boot.common.result.Result;
import com.youlai.boot.framework.security.util.SecurityUtils;
import com.youlai.boot.mini.model.dto.MapSearchDTO;
import com.youlai.boot.mini.model.query.StrayAnimalQuery;
import com.youlai.boot.mini.model.vo.HomeStatsVO;
import com.youlai.boot.mini.model.vo.StrayAnimalShortVO;
import com.youlai.boot.mini.model.vo.TaskVO;
import com.youlai.boot.mini.service.MiniPointRecordService;
import com.youlai.boot.mini.service.StrayAnimalService;
import java.util.List;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
@ -16,6 +25,7 @@ import org.springframework.web.bind.annotation.*;
public class HomePageController {
private final StrayAnimalService strayAnimalService;
private final MiniPointRecordService miniPointRecordService;
@Operation(summary = "根据地图边界获取流浪动物信息(不需要登录)")
@RequestMapping(value = "/listByBounds", method = RequestMethod.GET)
@ -23,5 +33,24 @@ public class HomePageController {
return Result.success(strayAnimalService.listByMapBounds(mapSearch));
}
@Operation(summary = "首页获取最新登记动物列表")
@GetMapping(value = "/listAnimal")
public PageResult<StrayAnimalShortVO> listAnimal(StrayAnimalQuery queryParams) {
return PageResult.success(strayAnimalService.getHomePageList(queryParams));
}
@Operation(summary = "首页统计数据:已登记动物数 + 爱心用户数")
@GetMapping(value = "/stats")
public Result<HomeStatsVO> stats() {
return Result.success(strayAnimalService.getHomeStats());
}
@Operation(summary = "首页任务列表(需登录)")
@GetMapping(value = "/tasks")
public Result<List<TaskVO>> tasks() {
Long userId = SecurityUtils.getUserId();
return Result.success(miniPointRecordService.listHomeTasks(userId));
}
}

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

@ -6,6 +6,8 @@ import com.youlai.boot.mini.model.dto.MapSearchDTO;
import com.youlai.boot.mini.model.entity.MiniStrayAnimal;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.query.StrayAnimalQuery;
import com.youlai.boot.mini.model.vo.HomeStatsVO;
import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO;
import com.youlai.boot.mini.model.vo.StrayAnimalNearbyVO;
import com.youlai.boot.mini.model.vo.StrayAnimalShortVO;
@ -27,7 +29,11 @@ public interface MiniStrayAnimalMapper extends BaseMapper<MiniStrayAnimal> {
IPage<StrayAnimalShortVO> getAnimalPage(Page<StrayAnimalShortVO> page, @Param("queryParams") OwnStrayAnimalQuery queryParams);
IPage<StrayAnimalShortVO> getHomePageList(Page<StrayAnimalShortVO> page, @Param("queryParams") StrayAnimalQuery queryParams);
StrayAnimalDetailsVO getStrayAnimalDetails(@Param("animalUuid") String animalUuid, @Param("miniUserId") Long miniUserId);
List<StrayAnimalNearbyVO> listByMapBounds(MapSearchDTO mapSearch);
HomeStatsVO countHomeStats();
}

3
src/main/java/com/youlai/boot/mini/model/query/StrayAnimalQuery.java

@ -17,4 +17,7 @@ public class StrayAnimalQuery extends BaseQuery {
@Schema(description = "截止登记时间,毫秒级时间戳", example = "1776426078459")
private Long createEndTimestamp;
@Schema(description = "可见性范围:public-公开,private-仅自己,friends-仅好友", example = "public")
private String visibility;
}

15
src/main/java/com/youlai/boot/mini/model/vo/HomeStatsVO.java

@ -0,0 +1,15 @@
package com.youlai.boot.mini.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "首页统计数据")
public class HomeStatsVO {
@Schema(description = "已登记动物总数")
private Long animalCount;
@Schema(description = "爱心用户数(登记过动物的去重用户数)")
private Long caringUserCount;
}

30
src/main/java/com/youlai/boot/mini/model/vo/TaskVO.java

@ -0,0 +1,30 @@
package com.youlai.boot.mini.model.vo;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
@Data
@Schema(description = "首页任务")
public class TaskVO {
@Schema(description = "规则编码")
private String ruleCode;
@Schema(description = "任务名称")
private String ruleName;
@Schema(description = "奖励积分")
private Integer points;
@Schema(description = "限制周期")
private String limitPeriod;
@Schema(description = "周期内限制次数")
private Integer limitCount;
@Schema(description = "当前周期已完成次数")
private Integer currentCount;
@Schema(description = "是否已完成")
private Boolean completed;
}

4
src/main/java/com/youlai/boot/mini/service/MiniPointRecordService.java

@ -5,6 +5,9 @@ import com.baomidou.mybatisplus.extension.service.IService;
import com.youlai.boot.mini.model.entity.MiniPointRecord;
import com.youlai.boot.mini.model.query.MyPointRecordQuery;
import com.youlai.boot.mini.model.vo.MyPointRecordVO;
import com.youlai.boot.mini.model.vo.TaskVO;
import java.util.List;
public interface MiniPointRecordService extends IService<MiniPointRecord> {
@ -16,4 +19,5 @@ public interface MiniPointRecordService extends IService<MiniPointRecord> {
Integer deductPoint(Long userId, String ruleCode, String bizId);
List<TaskVO> listHomeTasks(Long userId);
}

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

@ -9,6 +9,8 @@ import com.youlai.boot.mini.model.dto.MapSearchDTO;
import com.youlai.boot.mini.model.entity.MiniStrayAnimal;
import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.query.StrayAnimalQuery;
import com.youlai.boot.mini.model.vo.HomeStatsVO;
import com.youlai.boot.mini.model.vo.SaveStrayAnimalVO;
import com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO;
import com.youlai.boot.mini.model.vo.StrayAnimalNearbyVO;
@ -41,5 +43,9 @@ public interface StrayAnimalService extends IService<MiniStrayAnimal> {
IPage<StrayAnimalShortVO> getOthersCreatedPage(String authorUuid, OwnStrayAnimalQuery queryParams);
List<StrayAnimalNearbyVO> listByMapBounds(MapSearchDTO mapSearch);
IPage<StrayAnimalShortVO> getHomePageList(StrayAnimalQuery queryParams);
HomeStatsVO getHomeStats();
}

80
src/main/java/com/youlai/boot/mini/service/impl/MiniPointRecordServiceImpl.java

@ -15,6 +15,7 @@ import com.youlai.boot.mini.model.entity.MiniPointRule;
import com.youlai.boot.admin.model.form.AdjustUserPointForm;
import com.youlai.boot.mini.model.query.MyPointRecordQuery;
import com.youlai.boot.mini.model.vo.MyPointRecordVO;
import com.youlai.boot.mini.model.vo.TaskVO;
import com.youlai.boot.mini.service.MiniPointAccountService;
import com.youlai.boot.mini.service.MiniPointRecordService;
import lombok.RequiredArgsConstructor;
@ -29,6 +30,8 @@ import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;
@ -322,4 +325,81 @@ public class MiniPointRecordServiceImpl extends ServiceImpl<MiniPointRecordMappe
}
}
@Override
public List<TaskVO> listHomeTasks(Long userId) {
List<MiniPointRule> rules = pointManageService.list(new LambdaQueryWrapper<MiniPointRule>()
.eq(MiniPointRule::getStatus, false)
.gt(MiniPointRule::getPoints, 0)
.eq(MiniPointRule::getDeleted, 0));
LocalDate now = LocalDate.now();
List<TaskVO> tasks = new ArrayList<>();
for (MiniPointRule rule : rules) {
TaskVO vo = new TaskVO();
vo.setRuleCode(rule.getRuleCode());
vo.setRuleName(rule.getRuleName());
vo.setPoints(rule.getPoints());
vo.setLimitPeriod(rule.getLimitPeriod());
vo.setLimitCount(rule.getLimitCount());
int currentCount = getTaskProgress(rule, userId, now);
vo.setCurrentCount(currentCount);
vo.setCompleted(rule.getLimitPeriod() != null
&& rule.getLimitCount() != null
&& currentCount >= rule.getLimitCount());
tasks.add(vo);
}
return tasks;
}
private int getTaskProgress(MiniPointRule rule, Long userId, LocalDate now) {
String ruleCode = rule.getRuleCode();
if ("SIGN_IN_BASE".equals(ruleCode)) {
String dayKey = String.format(CommonConstants.SIGN_DAY_KEY, userId,
now.format(DateTimeFormatter.ofPattern("yyyyMMdd")));
return Boolean.TRUE.equals(redisTemplate.hasKey(dayKey)) ? 1 : 0;
}
String limitPeriod = rule.getLimitPeriod();
if (limitPeriod == null) {
return 0;
}
String bizPrefix = ruleCode.toLowerCase();
String periodKey;
switch (limitPeriod) {
case "ALL":
periodKey = "all";
break;
case "DAY":
periodKey = now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
break;
case "WEEK":
LocalDate monday = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
periodKey = monday.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
break;
case "MONTH":
periodKey = now.format(DateTimeFormatter.ofPattern("yyyyMM"));
break;
case "YEAR":
periodKey = String.valueOf(now.getYear());
break;
default:
return 0;
}
String countKey = String.format(CommonConstants.REWARD_COUNT_KEY, bizPrefix,
limitPeriod.toLowerCase(), userId, periodKey);
try {
String countStr = redisTemplate.opsForValue().get(countKey);
return countStr != null ? Integer.parseInt(countStr) : 0;
} catch (Exception e) {
log.warn("读取任务进度Redis失败, key={}", countKey, e);
return 0;
}
}
}

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

@ -31,6 +31,7 @@ import com.youlai.boot.mini.model.entity.MiniStrayAnimalNote;
import com.youlai.boot.mini.model.entity.MiniStrayAnimalNoteMedia;
import com.youlai.boot.mini.model.form.StrayAnimalForm;
import com.youlai.boot.mini.model.query.OwnStrayAnimalQuery;
import com.youlai.boot.mini.model.query.StrayAnimalQuery;
import com.youlai.boot.mini.model.vo.*;
import com.youlai.boot.mini.service.MiniPointRecordService;
import com.youlai.boot.mini.service.StrayAnimalService;
@ -565,6 +566,36 @@ public class StrayAnimalServiceImpl extends ServiceImpl<MiniStrayAnimalMapper, M
return getAnimalPage(queryParams);
}
@Override
public IPage<StrayAnimalShortVO> getHomePageList(StrayAnimalQuery queryParams) {
Page<StrayAnimalShortVO> page = new Page<>(queryParams.getPageNum(), queryParams.getPageSize());
IPage<StrayAnimalShortVO> result = this.miniStrayAnimalMapper.getHomePageList(page, queryParams);
if (result.getTotal() > 0) {
result.getRecords().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;
}
}
});
}
return result;
}
@Override
public HomeStatsVO getHomeStats() {
return miniStrayAnimalMapper.countHomeStats();
}
private IPage<StrayAnimalShortVO> getAnimalPage(OwnStrayAnimalQuery queryParams) {
// 参数构建
int pageNum = queryParams.getPageNum();

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

@ -207,6 +207,82 @@
</select>
<select id="getHomePageList" 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
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,
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
AND n.visibility = 'public'
<!-- 动物类型 -->
<if test="queryParams.animalType != null and queryParams.animalType != ''">
AND a.animal_type = #{queryParams.animalType}
</if>
<!-- 时间范围 -->
<if test="queryParams.createStartTimestamp != null">
AND a.create_timestamp >= #{queryParams.createStartTimestamp}
</if>
<if test="queryParams.createEndTimestamp != null">
AND #{queryParams.createEndTimestamp} >= a.create_timestamp
</if>
</where>
ORDER BY a.id DESC
</select>
<select id="countHomeStats" resultType="com.youlai.boot.mini.model.vo.HomeStatsVO">
SELECT
COUNT(*) AS animalCount,
COUNT(DISTINCT mini_user_id) AS caringUserCount
FROM mini_stray_animal
WHERE is_deleted = 0
</select>
<select id="getStrayAnimalDetails" resultType="com.youlai.boot.mini.model.vo.StrayAnimalDetailsVO">
SELECT
su.uuid AS authorUuid,

Loading…
Cancel
Save