From 8dd9360a0e4cfd22ea9e261bec3821eff3f57fe8 Mon Sep 17 00:00:00 2001
From: cloudroam <cloudroam>
Date: 星期二, 12 八月 2025 10:10:07 +0800
Subject: [PATCH] add:分享功能

---
 sub-pages/mine/index.vue |  325 ++++++++++++++++++++++++++++++++++++++++++++++--------
 1 files changed, 276 insertions(+), 49 deletions(-)

diff --git a/sub-pages/mine/index.vue b/sub-pages/mine/index.vue
index 6b913e7..2b980a3 100644
--- a/sub-pages/mine/index.vue
+++ b/sub-pages/mine/index.vue
@@ -3,9 +3,10 @@
     <view class="profile-section" :style="backgroundStyle">
       <up-sticky bgColor="#000">
         <view class="top-bar">
-          <up-icon name="list" size="60rpx" color="#D0E1E9" @click="onSettingClick" />
+          <up-icon name="setting" size="60rpx" color="#D0E1E9" @click="onSettingClick" />
+<!--          <up-icon name="list" size="60rpx" color="#D0E1E9" @click="showUnderDevelopment" />-->
           <view class="top-bar-right">
-            <up-icon name="share" size="60rpx" color="#D0E1E9" />
+<!--            <up-icon name="share" size="60rpx" color="#D0E1E9" @click="showUnderDevelopment" />-->
           </view>
         </view>
       </up-sticky>
@@ -21,45 +22,45 @@
             </view>
           </view>
           <view class="user-info">
-            <view class="username">影途 {{ userStore?.userInfo?.customerDTO?.name }}</view>
-            <view class="user-id">影途号:{{ userStore?.userInfo?.customerDTO?.id }}</view>
+            <view class="username">影游四方 {{ userStore?.userInfo?.customerDTO?.name }}</view>
+            <view class="user-id">影游四方号:{{ userStore?.userInfo?.customerDTO?.id }}</view>
             <view class="location">IP 属地:{{ userStore.address?.ad_info?.province }}</view>
           </view>
         </view>
 
-        <view class="edit-profile">点击这里,填写简介</view>
+<!--        <view class="edit-profile" >点击这里,填写简介</view>-->
 
         <view class="stats">
           <view class="stat-row">
-            <view class="stat-item">
-              <text class="number">0</text>
-              <text class="label">关注</text>
-            </view>
-            <view class="stat-item">
-              <text class="number">0</text>
-              <text class="label">粉丝</text>
-            </view>
-            <view class="stat-item">
+<!--            <view class="stat-item">-->
+<!--              <text class="number">0</text>-->
+<!--              <text class="label">关注</text>-->
+<!--            </view>-->
+<!--            <view class="stat-item">-->
+<!--              <text class="number">0</text>-->
+<!--              <text class="label">粉丝</text>-->
+<!--            </view>-->
+<!--            <view class="stat-item">
               <text class="number">1</text>
               <text class="label">获赞与收藏</text>
-            </view>
+            </view> -->
           </view>
           <view class="action-buttons">
-            <up-button text="编辑资料" size="mini" type="info" plain hairline
+            <up-button text="编辑资料" size="mini" type="info" plain hairline @click="navigateTo('/sub-pages/mine/profile-edit')"
               :custom-style="{ backgroundColor: 'transparent', borderColor: '#B1ABA9' }" />
-            <up-icon name="setting" size="40rpx" @click="gotoUrl('/sub-pages/mine/settings')" />
+<!--            <up-icon name="setting" size="40rpx" @click="navigateTo('/sub-pages/mine/settings')" />-->
           </view>
         </view>
       </view>
 
-      <scroll-view class="function-cards" scroll-x show-scrollbar="false">
-        <view class="card" v-for="item in cardList" :key="item.title">
-          <view class="card-content">
-            <text class="card-title">{{ item.title }}</text>
-            <text class="card-subtitle">{{ item.subtitle }}</text>
-          </view>
-        </view>
-      </scroll-view>
+<!--      <scroll-view class="function-cards" scroll-x show-scrollbar="false">-->
+<!--        <view class="card" v-for="item in cardList" :key="item.title"  @click="showUnderDevelopment">-->
+<!--          <view class="card-content">-->
+<!--            <text class="card-title">{{ item.title }}</text>-->
+<!--            <text class="card-subtitle">{{ item.subtitle }}</text>-->
+<!--          </view>-->
+<!--        </view>-->
+<!--      </scroll-view>-->
     </view>
 
     <view class="tab-section">
@@ -68,31 +69,82 @@
           activeStyle="color: #2979ff" />
       </up-sticky>
 
+
+<!--      <swiper class="swiper-box" :current="current" @change="onSwiperChange" duration="300">-->
+<!--        <swiper-item v-for="(item, index) in tabList" :key="index">-->
+<!--          <view v-if="!userStore.hasLogin" class="empty-state">-->
+<!--            <text class="empty-text">请登录后查看{{ item.name }}</text>-->
+<!--          </view>-->
+<!--          <view v-else-if="getCurrentList.length === 0" class="empty-state">-->
+<!--            <text class="empty-text">暂无{{ item.name }}内容</text>-->
+<!--          </view>-->
+<!--          <view v-else class="list-view">-->
+<!--            <up-waterfall v-model="getCurrentList">-->
+<!--              <template #left="{ leftList }">-->
+<!--                <FlowCard-->
+<!--                    v-for="(item, index) in leftList"-->
+<!--                    :key="index"-->
+<!--                    :item="item"-->
+<!--                    @click="handleDetailClick"-->
+<!--                />-->
+<!--              </template>-->
+<!--              <template #right="{ rightList }">-->
+<!--                <FlowCard-->
+<!--                    v-for="(item, index) in rightList"-->
+<!--                    :key="index"-->
+<!--                    :item="item"-->
+<!--                    @click="handleDetailClick"-->
+<!--                />-->
+<!--              </template>-->
+<!--            </up-waterfall>-->
+<!--            <up-loadmore :status="loading ? 'loading' : 'nomore'" :line="true" />-->
+<!--          </view>-->
+<!--        </swiper-item>-->
+<!--      </swiper>-->
       <swiper class="swiper-box" :current="current" @change="onSwiperChange" duration="300">
         <swiper-item v-for="(item, index) in tabList" :key="index">
-          <view class="empty-state">
-            <image class="empty-icon"
-              src="https://ai-public.mastergo.com/ai/img_res/fc3cb775274ef0f5e58ac01687a9c121.jpg" mode="aspectFit" />
-            <text class="empty-text">快去发布你的笔记吧</text>
-            <up-button class="publish-btn" size="mini" type="warning" shape="circle">去发布</up-button>
-          </view>
+          <scroll-view scroll-y style="height: 60vh; min-height: 400rpx; background: #fff;">
+            <view class="list-view">
+              <up-waterfall v-model="getCurrentList">
+                <template #left="{ leftList }">
+                  <FlowCard
+                      v-for="(item, index) in leftList"
+                      :key="index"
+                      :item="item"
+                      @click="handleDetailClick"
+                  />
+                </template>
+                <template #right="{ rightList }">
+                  <FlowCard
+                      v-for="(item, index) in rightList"
+                      :key="index"
+                      :item="item"
+                      @click="handleDetailClick"
+                  />
+                </template>
+              </up-waterfall>
+              <up-loadmore :status="current.value === 0 ? collectStatus : likeStatus" :line="true" />
+            </view>
+          </scroll-view>
         </swiper-item>
       </swiper>
     </view>
 
     <common-footer flg="0" />
-    <setting-popup v-model="settingShow" />
+<!--    <setting-popup v-model="settingShow" />-->
   </view>
 </template>
 
 <script setup lang="ts">
 import { ref, computed, watch } from 'vue';
-import { onShow } from '@dcloudio/uni-app'
+import { onShow, onPullDownRefresh, onReachBottom } from '@dcloudio/uni-app'
 import SettingPopup from '@/components/setting/setting-popup.vue';
 import { usePlatformLoginType } from '@/composables/usePlatformLoginType'
 import { useUserStore } from '@/store/user'
 import { useLocation } from '@/composables/useLocation'
 import { useNavigator } from '@/composables/useNavigator'
+import { FilmWorks } from '@/types/index'
+import{ getFilmCollectList, getFilmLikeList} from '@/sub-pages/utils/api'
 
 const { apitype } = usePlatformLoginType()
 const userStore = useUserStore()
@@ -100,23 +152,52 @@
 const {getLocation,province } = useLocation()
 
 
-const gotoUrl = (url: string) => {
-  navigateTo(url)
-}
-
 watch(
   () => userStore.userInfo,      // 监听 userInfo 这个响应式属性
   (newVal, oldVal) => {
     console.log('userInfo 发生变化:', newVal)
+    if (newVal && userStore.hasLogin) {
+      fetchList();
+    } else {
+      // 用户未登录,清空列表
+      likeList.value = [];
+      collectList.value = [];
+    }
   },
   { deep: true } // 如果 userInfo 是对象,需要深度监听其属性变化
 )
 
 onShow(() => {
-  console.log('我的')
   getLocation()
+  if (userStore.hasLogin) {
+    // 强制刷新用户信息
+    userStore.getCurrentInfo().then(() => {
+      fetchList();
+    });
+  }else {
+    // 用户未登录,清空列表
+    likeList.value = [];
+    collectList.value = [];
+  }
 });
 
+onPullDownRefresh(async () => {
+  if (current.value === 0) {
+    collectPage.value = 1;
+    collectList.value = [];
+    collectStatus.value = 'loadmore';
+  } else {
+    likePage.value = 1;
+    likeList.value = [];
+    likeStatus.value = 'loadmore';
+  }
+  await fetchList(true);
+  uni.stopPullDownRefresh();
+});
+
+onReachBottom(() => {
+  fetchList();
+});
 
 
 // 当前 tab 索引
@@ -128,9 +209,20 @@
 // 控制设置弹窗显示
 const settingShow = ref(false);
 
+const likeList = ref<FilmWorks[]>([]);
+const collectList = ref<FilmWorks[]>([]);
+const loading = ref(false);
+const noMore = ref(false);
+// 分页相关状态
+const collectPage = ref(1);
+const collectSize = 10;
+const collectStatus = ref('loadmore');
+const likePage = ref(1);
+const likeSize = 10;
+const likeStatus = ref('loadmore');
 // tab 列表
 const tabList = ref([
-  { name: '笔记' },
+  // { name: '笔记' },
   { name: '收藏' },
   { name: '赞过' },
 ]);
@@ -151,17 +243,142 @@
 });
 
 // 方法定义
-function onSettingClick() {
-  settingShow.value = true;
+const onSettingClick= ()=> {
+  // settingShow.value = true;
+  uni.navigateTo({ url: '/sub-pages/mine/settings' })
 }
 
-function onTabChange(item: { index: number }) {
+const onTabChange=(item: { index: number })=> {
+  // 如果切到相同的 tab,直接返回,避免重复触发
+  if (current.value === item.index) return;
   current.value = item.index;
+  // 切换tab时重置对应列表和页码,防止数据重复
+  if (current.value === 0) {
+    collectPage.value = 1;
+    collectList.value = [];
+    collectStatus.value = 'loadmore';
+  } else {
+    likePage.value = 1;
+    likeList.value = [];
+    likeStatus.value = 'loadmore';
+  }
+  if (userStore.hasLogin) {
+    fetchList(true); // 强制刷新
+  }
 }
 
-function onSwiperChange(e: any) {
+const onSwiperChange=(e: any) => {
   current.value = e.detail.current;
+  onTabChange({ index: e.detail.current });
 }
+
+const handleDetailClick = (item: FilmWorks) => {
+  navigateTo(`/sub-pages/film-list/film-detail?id=${item.id}`);
+};
+
+const getCurrentList = computed(() => {
+  return current.value === 0 ? collectList.value : likeList.value;
+});
+const fetchList = async (isRefresh = false) => {
+  if (!userStore.hasLogin) return;
+  // 并发加载守卫:防止切换或多事件同时触发导致重复请求
+  if (loading.value) return;
+  loading.value = true;
+  try {
+    if (current.value === 0) {
+      // 收藏分页
+      if (isRefresh) {
+        collectPage.value = 1;
+        collectList.value = [];
+        collectStatus.value = 'loadmore';
+      }
+      if (collectStatus.value === 'nomore') return;
+      const res = await getFilmCollectList({
+        userId: userStore.userInfo?.customerDTO?.id,
+        current: collectPage.value,
+        size: collectSize
+      });
+      if (res && res.length > 0) {
+        // 去重
+        const existingIds = new Set(collectList.value.map(item => item.id));
+        const uniqueRecords = res.filter(item => !existingIds.has(item.id));
+        if (uniqueRecords.length > 0) {
+          collectList.value = [...collectList.value, ...uniqueRecords];
+        }
+        if (res.length < collectSize) {
+          collectStatus.value = 'nomore';
+        }
+        // 无论是否有去重,当前页已消费,推进页码,避免下一次重复拉取相同页
+        collectPage.value++;
+      } else {
+        collectStatus.value = 'nomore';
+      }
+    } else {
+      // 点赞分页
+      if (isRefresh) {
+        likePage.value = 1;
+        likeList.value = [];
+        likeStatus.value = 'loadmore';
+      }
+      if (likeStatus.value === 'nomore') return;
+      const res = await getFilmLikeList({
+        userId: userStore.userInfo?.customerDTO?.id,
+        current: likePage.value,
+        size: likeSize
+      });
+      if (res && res.length > 0) {
+        // 去重
+        const existingIds = new Set(likeList.value.map(item => item.id));
+        const uniqueRecords = res.filter(item => !existingIds.has(item.id));
+        if (uniqueRecords.length > 0) {
+          likeList.value = [...likeList.value, ...uniqueRecords];
+        }
+        if (res.length < likeSize) {
+          likeStatus.value = 'nomore';
+        }
+        // 同理,推进页码,避免重复拉取相同页
+        likePage.value++;
+      } else {
+        likeStatus.value = 'nomore';
+      }
+    }
+  } catch (error) {
+    console.error('获取列表失败:', error);
+    uni.showToast({ title: '获取数据失败', icon: 'none' });
+  } finally {
+    loading.value = false;
+  }
+};
+const goToProfile=  ()=> {
+  navigateTo('/sub-pages/mine/edit-profile');
+};
+
+const showUnderDevelopment = () => {
+  uni.showToast({
+    title: '功能正在开发中',
+    icon: 'none'
+  });
+}
+
+defineExpose({
+  onShareAppMessage() {
+    return {
+      title: '影视地标推荐',
+      path: '/pages/home/home',
+      imageUrl: '', // 可以设置默认分享图片
+      desc: '发现全球影视拍摄地,探索电影背后的故事'
+    }
+  },
+  // 分享到朋友圈
+  onShareTimeline() {
+    return {
+      title: '影视地标推荐',
+      query: '',
+      imageUrl: '', // 可以设置默认分享图片
+      desc: '发现全球影视拍摄地,探索电影背后的故事'
+    }
+  }
+})
 </script>
 
 
@@ -328,7 +545,7 @@
 
 .card {
   display: inline-block;
-  width: 180rpx;
+  width: 100%;
   height: 80rpx;
   margin-left: 20rpx;
   background-color: rgba(60, 60, 60, 0.4);
@@ -427,11 +644,21 @@
   border-radius: 32rpx !important;
   padding: 0 48rpx !important;
 }
+.swiper-box {
+  min-height: calc(100vh - 200rpx);
+  /*padding: 20rpx 0;*/
+}
+
+.list-view {
+  /*padding: 0 20rpx;*/
+  background-color: #fff;
+}
 </style>
 <style lang="scss" scoped>
-.swiper-box {
-  // min-height: 600rpx;
-  /* 或 100vh,或具体 px */
-  min-height: 800px;
-}
+//.swiper-box {
+//  // min-height: 600rpx;
+//  /* 或 100vh,或具体 px */
+//  min-height: 800px;
+//}
+
 </style>
\ No newline at end of file

--
Gitblit v1.9.3