tanlie hace 2 semanas
padre
commit
7ab02fbc79

+ 25 - 14
wishing-platform/platform-service/platform-service-mobile/src/main/java/cn/qinys/platform/mobile/controller/UserWishController.java

@@ -2,9 +2,12 @@ package cn.qinys.platform.mobile.controller;
 
 import cn.qinys.platform.base.response.Result;
 import cn.qinys.platform.mobile.req.WishCreateReq;
+import cn.qinys.platform.mobile.req.WishPageReq;
 import cn.qinys.platform.mobile.resp.WishDetailResp;
 import cn.qinys.platform.mobile.resp.WishListResp;
+import cn.qinys.platform.mobile.resp.WishPageResp;
 import cn.qinys.platform.mobile.service.UserWishService;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
 import org.springframework.web.bind.annotation.*;
@@ -16,39 +19,45 @@ public class UserWishController {
     @Resource
     private UserWishService wishService;
 
-    /** 创建愿望 */
+    /**
+     * 创建愿望
+     */
     @PostMapping("/create")
     public Result<WishDetailResp> create(@RequestBody @Valid WishCreateReq req) {
         WishDetailResp resp = wishService.create(req);
         return new Result<>(resp);
     }
 
-    /** 许愿树下的公开愿望列表 */
+    /**
+     * 许愿树下的公开愿望列表
+     */
     @GetMapping("/tree/{treeId}")
-    public Result<WishListResp> listByTree(@PathVariable Long treeId,
-                                           @RequestParam(defaultValue = "1") Integer page,
-                                           @RequestParam(defaultValue = "20") Integer pageSize) {
-        WishListResp resp = wishService.listByTree(treeId, page, pageSize);
+    public Result<Page<WishPageResp>> listByTree(@PathVariable Integer treeId, WishPageReq req) {
+        Page<WishPageResp> resp = wishService.pageByTree(treeId, req);
         return new Result<>(resp);
     }
 
-    /** 我的愿望列表 */
+    /**
+     * 我的愿望列表
+     */
     @GetMapping("/my")
-    public Result<WishListResp> myList(@RequestHeader(value = "X-User-Id", defaultValue = "anonymous") String userId,
-                                       @RequestParam(defaultValue = "1") Integer page,
-                                       @RequestParam(defaultValue = "20") Integer pageSize) {
-        WishListResp resp = wishService.listMyWishes(userId, page, pageSize);
+    public Result<Page<WishPageResp>> myWishPage(WishPageReq req) {
+        Page<WishPageResp> resp = wishService.pageByUser(req);
         return new Result<>(resp);
     }
 
-    /** 愿望详情 */
+    /**
+     * 愿望详情
+     */
     @GetMapping("/{id}")
     public Result<WishDetailResp> detail(@PathVariable Long id) {
         WishDetailResp resp = wishService.getDetail(id);
         return resp != null ? new Result<>(resp) : new Result<>(404, "愿望不存在");
     }
 
-    /** 删除愿望 */
+    /**
+     * 删除愿望
+     */
     @DeleteMapping("/{id}")
     public Result<Boolean> delete(@PathVariable Long id,
                                   @RequestHeader(value = "X-User-Id", defaultValue = "anonymous") String userId) {
@@ -56,7 +65,9 @@ public class UserWishController {
         return ok ? new Result<>(true) : new Result<>(404, "删除失败,愿望不存在或无权操作");
     }
 
-    /** 点赞愿望 */
+    /**
+     * 点赞愿望
+     */
     @PostMapping("/{id}/like")
     public Result<Integer> like(@PathVariable Long id) {
         int count = wishService.like(id);

+ 11 - 0
wishing-platform/platform-service/platform-service-mobile/src/main/java/cn/qinys/platform/mobile/mapper/UserWishMapper.java

@@ -1,10 +1,21 @@
 package cn.qinys.platform.mobile.mapper;
 
 import cn.qinys.platform.entity.wishing.UserWish;
+import cn.qinys.platform.mobile.resp.WishDetailResp;
+import cn.qinys.platform.mobile.resp.WishPageResp;
+import com.baomidou.mybatisplus.core.conditions.Wrapper;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
 
 @Mapper
 public interface UserWishMapper extends BaseMapper<UserWish> {
 
+
+    @Select("SELECT * FROM user_wish ${ew.customSqlSegment}")
+    Page<WishPageResp> selectWishPage(Page<UserWish> page, @Param(Constants.WRAPPER) Wrapper<UserWish> wrapper);
+
 }

+ 19 - 0
wishing-platform/platform-service/platform-service-mobile/src/main/java/cn/qinys/platform/mobile/req/WishPageReq.java

@@ -0,0 +1,19 @@
+package cn.qinys.platform.mobile.req;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author lie tan
+ * @description
+ * @date 2026-06-07 16:04
+ **/
+@Data
+public class WishPageReq implements Serializable {
+
+    private Integer page = 1;
+
+    private Integer pageSize = 20;
+
+}

+ 47 - 0
wishing-platform/platform-service/platform-service-mobile/src/main/java/cn/qinys/platform/mobile/resp/WishPageResp.java

@@ -0,0 +1,47 @@
+package cn.qinys.platform.mobile.resp;
+
+import com.alibaba.fastjson2.JSON;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Data
+public class WishPageResp implements Serializable {
+
+    private Integer id;
+
+    private Integer treeId;
+
+    private String treeName;
+
+    private String userId;
+
+    private String content;
+
+    private String images;
+
+    private String address;
+
+    private Boolean isPublic;
+
+    private String tags;
+
+    private Integer likes;
+
+    private Integer status;
+
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createdAt;
+
+    public List<String> getImages() {
+        return JSON.parseArray(images, String.class);
+    }
+
+    public List<String> getTags() {
+        return JSON.parseArray(tags, String.class);
+    }
+
+}

+ 5 - 2
wishing-platform/platform-service/platform-service-mobile/src/main/java/cn/qinys/platform/mobile/service/UserWishService.java

@@ -1,14 +1,17 @@
 package cn.qinys.platform.mobile.service;
 
 import cn.qinys.platform.mobile.req.WishCreateReq;
+import cn.qinys.platform.mobile.req.WishPageReq;
 import cn.qinys.platform.mobile.resp.WishDetailResp;
 import cn.qinys.platform.mobile.resp.WishListResp;
+import cn.qinys.platform.mobile.resp.WishPageResp;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 
 public interface UserWishService {
 
-    WishListResp listByTree(Long treeId, Integer page, Integer pageSize);
+    Page<WishPageResp> pageByTree(Integer treeId, WishPageReq req);
 
-    WishListResp listMyWishes(String userId, Integer page, Integer pageSize);
+    Page<WishPageResp> pageByUser(WishPageReq req);
 
     WishDetailResp getDetail(Long id);
 

+ 24 - 29
wishing-platform/platform-service/platform-service-mobile/src/main/java/cn/qinys/platform/mobile/service/impl/UserWishServiceImpl.java

@@ -1,14 +1,18 @@
 package cn.qinys.platform.mobile.service.impl;
+
 import cn.qinys.platform.base.security.utils.CurrentUtils;
 import cn.qinys.platform.entity.wishing.UserWish;
 import cn.qinys.platform.entity.wishing.WishingTree;
 import cn.qinys.platform.mobile.mapper.UserWishMapper;
 import cn.qinys.platform.mobile.mapper.WishingTreeMapper;
 import cn.qinys.platform.mobile.req.WishCreateReq;
+import cn.qinys.platform.mobile.req.WishPageReq;
 import cn.qinys.platform.mobile.resp.WishDetailResp;
 import cn.qinys.platform.mobile.resp.WishListResp;
+import cn.qinys.platform.mobile.resp.WishPageResp;
 import cn.qinys.platform.mobile.service.UserWishService;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.fasterxml.jackson.core.JsonProcessingException;
 import com.fasterxml.jackson.core.type.TypeReference;
@@ -28,40 +32,30 @@ public class UserWishServiceImpl implements UserWishService {
     private UserWishMapper wishMapper;
 
     @Resource
-    private WishingTreeMapper wishingTreeMapper;
+    private WishingTreeMapper treeMapper;
 
     private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     @Override
-    public WishListResp listByTree(Long treeId, Integer page, Integer pageSize) {
-        Page<UserWish> mpPage = wishMapper.selectPage(
-                new Page<>(page, pageSize),
-                new LambdaQueryWrapper<UserWish>()
-                        .eq(UserWish::getTreeId, treeId)
-                        .eq(UserWish::getIsPublic, 1)
-                        .eq(UserWish::getStatus, 0)
-                        .orderByDesc(UserWish::getCreatedAt)
-        );
-
-        WishListResp resp = new WishListResp();
-        resp.setList(mpPage.getRecords().stream().map(this::toDetailResp).toList());
-        resp.setTotal(mpPage.getTotal());
-        return resp;
+    public Page<WishPageResp> pageByTree(Integer treeId, WishPageReq req) {
+        Page<UserWish> pageResp = new Page<>(req.getPage(), req.getPageSize());
+        QueryWrapper<UserWish> wrapper = new QueryWrapper<>();
+        wrapper.eq("tree_id", treeId)
+                .eq("is_public", 1)
+                .eq("is_deleted", 0)
+                .orderByDesc("created_at");
+        return wishMapper.selectWishPage(pageResp, wrapper);
     }
 
     @Override
-    public WishListResp listMyWishes(String userId, Integer page, Integer pageSize) {
-        Page<UserWish> mpPage = wishMapper.selectPage(
-                new Page<>(page, pageSize),
-                new LambdaQueryWrapper<UserWish>()
-                        .eq(UserWish::getUserId, userId)
-                        .orderByDesc(UserWish::getCreatedAt)
-        );
-
-        WishListResp resp = new WishListResp();
-        resp.setList(mpPage.getRecords().stream().map(this::toDetailResp).toList());
-        resp.setTotal(mpPage.getTotal());
-        return resp;
+    public Page<WishPageResp> pageByUser(WishPageReq req) {
+        String userId = CurrentUtils.getCurrentUserId();
+        Page<UserWish> pageResp = new Page<>(req.getPage(), req.getPageSize());
+        QueryWrapper<UserWish> wrapper = new QueryWrapper<>();
+        wrapper.eq("user_id", userId)
+                .eq("is_deleted", 0)
+                .orderByDesc("created_at");
+        return wishMapper.selectWishPage(pageResp, wrapper);
     }
 
     @Override
@@ -72,7 +66,7 @@ public class UserWishServiceImpl implements UserWishService {
 
     @Override
     public WishDetailResp create(WishCreateReq req) {
-        WishingTree tree = wishingTreeMapper.selectById(req.getTreeId());
+        WishingTree tree = treeMapper.selectById(req.getTreeId());
 
         UserWish wish = new UserWish();
         wish.setTreeId(req.getTreeId());
@@ -143,7 +137,8 @@ public class UserWishServiceImpl implements UserWishService {
     private List<String> parseJsonList(String json) {
         if (json == null || json.isBlank()) return new ArrayList<>();
         try {
-            return OBJECT_MAPPER.readValue(json, new TypeReference<List<String>>() {});
+            return OBJECT_MAPPER.readValue(json, new TypeReference<List<String>>() {
+            });
         } catch (Exception e) {
             log.error("parseJsonList error", e);
             return new ArrayList<>();

+ 27 - 12
wishing-tree-h5/src/api/wish.ts

@@ -11,23 +11,28 @@ import { request } from './request'
 
 const USE_MOCK = false
 
+/**
+ * 许愿树下的公开愿望列表(分页)
+ */
 export async function fetchTreeWishes(treeId: number, page = 1, pageSize = 20) {
   if (USE_MOCK) return getWishesByTree(treeId, page, pageSize)
 
-  const res = await request<{ list: Wish[]; total: number }>(
+  const res = await request<{ records: Wish[]; total: number }>(
     `/mobile/wish/tree/${treeId}?page=${page}&pageSize=${pageSize}`,
   )
-  return { list: res.data.list, total: res.data.total }
+  return { list: res.data.records, total: res.data.total }
 }
 
-export async function fetchMyWishes(userId: string, page = 1, pageSize = 20) {
-  if (USE_MOCK) return getMyWishesMock(userId, page, pageSize)
+/**
+ * 我的愿望列表(分页,基于 token 识别用户)
+ */
+export async function fetchMyWishes(page = 1, pageSize = 20) {
+  if (USE_MOCK) return getMyWishesMock('', page, pageSize)
 
-  const res = await request<{ list: Wish[]; total: number }>(
+  const res = await request<{ records: Wish[]; total: number }>(
     `/mobile/wish/my?page=${page}&pageSize=${pageSize}`,
-    { headers: { 'X-User-Id': userId } },
   )
-  return { list: res.data.list, total: res.data.total }
+  return { list: res.data.records, total: res.data.total }
 }
 
 export async function fetchWishDetail(id: number) {
@@ -37,14 +42,24 @@ export async function fetchWishDetail(id: number) {
   return res.data
 }
 
-export async function submitWish(data: Omit<Wish, 'id' | 'status' | 'likes' | 'createdAt'>) {
-  if (USE_MOCK) return createWishMock(data)
+/**
+ * 创建愿望(用户信息由后端从 token 获取)
+ */
+export async function submitWish(data: {
+  treeId: number
+  content: string
+  images: string[]
+  lng: number
+  lat: number
+  address: string
+  isPublic: boolean
+  tags: string[]
+}) {
+  if (USE_MOCK) return createWishMock(data as any)
 
-  const { userId, ...body } = data as any
   const res = await request<Wish>('/mobile/wish/create', {
     method: 'POST',
-    body: JSON.stringify(body),
-    headers: { 'X-User-Id': userId || 'anonymous' },
+    body: JSON.stringify(data),
   })
   return res.data
 }

+ 0 - 2
wishing-tree-h5/src/views/MakeWishView.vue

@@ -105,8 +105,6 @@ async function submitWish() {
   try {
     await submitWishApi({
       treeId: tree.value.id,
-      treeName: tree.value.name,
-      userId: userStore.phone,
       content: content.value,
       images: images.value,
       lng: locationStore.lng || 0,

+ 46 - 23
wishing-tree-h5/src/views/MyWishesView.vue

@@ -9,27 +9,31 @@
     </div>
 
     <template v-else>
-      <van-tabs v-model:active="activeTab" sticky>
-        <van-tab title="全部愿望">
-          <van-pull-refresh v-model="refreshing" @refresh="loadWishes">
-            <wish-card
-              v-for="wish in wishes"
-              :key="wish.id"
-              :wish="wish"
-              @click="goWish(wish.id)"
-            />
-            <van-empty v-if="wishes.length === 0" description="你还没有许过愿望哦">
-              <van-button type="primary" round to="/">去许愿</van-button>
-            </van-empty>
-          </van-pull-refresh>
-        </van-tab>
-      </van-tabs>
+      <van-pull-refresh v-model="refreshing" @refresh="onRefresh">
+        <van-list
+          v-model:loading="loading"
+          :finished="finished"
+          finished-text="没有更多了"
+          @load="loadWishes"
+        >
+          <wish-card
+            v-for="wish in wishes"
+            :key="wish.id"
+            :wish="wish"
+            @click="goWish(wish.id)"
+          />
+        </van-list>
+      </van-pull-refresh>
+
+      <van-empty v-if="!loading && wishes.length === 0" description="你还没有许过愿望哦">
+        <van-button type="primary" round to="/">去许愿</van-button>
+      </van-empty>
     </template>
   </div>
 </template>
 
 <script setup lang="ts">
-import { ref, onMounted } from 'vue'
+import { ref } from 'vue'
 import { useRouter } from 'vue-router'
 import { useUserStore } from '@/stores/user'
 import { fetchMyWishes } from '@/api/wish'
@@ -40,21 +44,40 @@ const router = useRouter()
 const userStore = useUserStore()
 
 const wishes = ref<Wish[]>([])
-const activeTab = ref(0)
+const loading = ref(false)
+const finished = ref(false)
 const refreshing = ref(false)
+let page = 1
 
 async function loadWishes() {
-  if (!userStore.phone) return
-  const result = await fetchMyWishes(userStore.phone)
-  wishes.value = result.list
-  refreshing.value = false
+  loading.value = true
+  try {
+    const result = await fetchMyWishes(page, 20)
+    if (refreshing.value) {
+      wishes.value = result.list
+    } else {
+      wishes.value = [...wishes.value, ...result.list]
+    }
+    finished.value = result.list.length < 20
+    page++
+  } catch {
+    finished.value = true
+  } finally {
+    loading.value = false
+    refreshing.value = false
+  }
+}
+
+async function onRefresh() {
+  refreshing.value = true
+  page = 1
+  finished.value = false
+  await loadWishes()
 }
 
 function goWish(id: number) {
   router.push(`/wish/${id}`)
 }
-
-onMounted(loadWishes)
 </script>
 
 <style scoped>