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 | 308 ++++++++++++++++++++++++++++++++++++++++++++------
1 files changed, 268 insertions(+), 40 deletions(-)
diff --git a/sub-pages/mine/index.vue b/sub-pages/mine/index.vue
index cb9b46d..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 @click="navigateTo('/sub-pages/mine/profile-edit')"
:custom-style="{ backgroundColor: 'transparent', borderColor: '#B1ABA9' }" />
- <up-icon name="setting" size="40rpx" @click="navigateTo('/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()
@@ -104,12 +156,47 @@
() => userStore.userInfo, // 监听 userInfo 这个响应式属性
(newVal, oldVal) => {
console.log('userInfo 发生变化:', newVal)
+ if (newVal && userStore.hasLogin) {
+ fetchList();
+ } else {
+ // 用户未登录,清空列表
+ likeList.value = [];
+ collectList.value = [];
+ }
},
{ deep: true } // 如果 userInfo 是对象,需要深度监听其属性变化
)
onShow(() => {
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();
});
@@ -122,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: '赞过' },
]);
@@ -146,21 +244,141 @@
// 方法定义
const onSettingClick= ()=> {
- settingShow.value = true;
+ // settingShow.value = true;
+ uni.navigateTo({ url: '/sub-pages/mine/settings' })
}
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); // 强制刷新
+ }
}
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>
@@ -327,7 +545,7 @@
.card {
display: inline-block;
- width: 180rpx;
+ width: 100%;
height: 80rpx;
margin-left: 20rpx;
background-color: rgba(60, 60, 60, 0.4);
@@ -426,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