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

---
 sub-pages/film-list/film-detail.vue |  280 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 274 insertions(+), 6 deletions(-)

diff --git a/sub-pages/film-list/film-detail.vue b/sub-pages/film-list/film-detail.vue
index afeab9e..87a5965 100644
--- a/sub-pages/film-list/film-detail.vue
+++ b/sub-pages/film-list/film-detail.vue
@@ -1,6 +1,7 @@
 <template>
     <view>
         <view class="page">
+
             <up-sticky bgColor="#fff">
                 <view class="card-footer">
                     <view class="user-info">
@@ -10,8 +11,8 @@
                         </view>
                     </view>
                     <view class="opera-info">
-                        <button class="custom-btn">关注</button>
-                        <up-icon name="/static/common/share2.png" size="40rpx" color="#999" />
+<!--                        <button class="custom-btn">关注</button>-->
+                        <up-icon name="/static/common/share2.png" size="40rpx" color="#999" @click="openSharePopup" />
                     </view>
                 </view>
             </up-sticky>
@@ -44,14 +45,14 @@
                         <!-- <view v-html="filmInfo.filmContent||'暂无'" class="rich" style="overflow: scroll;"></view> -->
                     </view>
                     <view class="annotation content-item">
-                        <text>{{ formatRelativeTime(filmInfo?.createTime) }} 美国</text>
+<!--                        <text>{{ formatRelativeTime(filmInfo?.createTime) }} 美国</text>-->
                     </view>
                 </view>
 
                 <up-line></up-line>
 
                 <view class="comment">
-                    <view class="writer-view" @click="showCommentLayer">
+                    <view class="writer-view" @click="() => showCommentLayer()">
                         <up-icon name="chat-fill" size="60rpx" />
                         <view class="comment-operation">
                             <up-text size="12px" text="说点什么......" margin="0 0 0 20rpx" color="#B9B9B9" />
@@ -86,7 +87,7 @@
             <!-- 固定底部输入框 -->
             <view class="comment-box">
                 <view class="input-row">
-                    <view class="comment-input" @click="showCommentLayer">
+                    <view class="comment-input" @click="() => showCommentLayer()">
                         <up-text size="12px" text="说点什么......" margin="0 0 0 20rpx" color="#B9B9B9" />
                     </view>
 <!--                    <up-icon name="heart" size="60rpx" color="#B9B9B9" label="11" />-->
@@ -116,10 +117,19 @@
                     <!-- <up-icon name="chat" size="60rpx" color="#B9B9B9" label="33" /> -->
                 </view>
             </view>
+
+
         </view>
 
         <comment-popup v-model="commentShow" :film-id="filmInfo?.id" :parent-id="commentParendId"
             @success="handleCommentSuccess" />
+
+        <!-- 自定义分享弹窗 -->
+        <share-popup
+            v-model:show="showSharePopup"
+            :share-data="shareData"
+        />
+
     </view>
 </template>
 
@@ -130,6 +140,8 @@
 import { onLoad } from '@dcloudio/uni-app'
 import { useGlobal } from '@/composables/useGlobal'
 const { $http, $message, $store } = useGlobal()
+// 在 film-detail.vue 的 script setup 部分添加
+import { useUserStore } from '@/store/user'
 
 import { FilmInfo, FilmPicture, CommentDTO } from '@/types/index'
 import { formatRelativeTime } from '@/utils/time'
@@ -151,6 +163,45 @@
 
 const liked = ref(false)      // 是否已点赞
 const collected = ref(false)  // 是否已收藏
+
+const sharePopupShow = ref(false)
+
+import SharePopup from '@/components/share-popup.vue'
+
+// 分享弹窗控制
+const showSharePopup = ref(false)
+
+const shareData = ref({
+  title: '',
+  desc: '',
+  image: '',
+  url: ''
+})
+
+// 打开分享弹窗
+const openSharePopup = () => {
+  // 设置分享内容
+  shareData.value = {
+    title: filmInfo.value?.coverTitle || '分享内容',
+    desc: filmInfo.value?.filmContent?.substring(0, 50) || '',
+    image: filmPictureList.value[0] || '',
+    // url: `http://您的域名/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`
+    url: `/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`
+  }
+  showSharePopup.value = true
+}
+
+
+// 复制链接
+const copyLink = () => {
+  sharePopupShow.value = false
+  uni.setClipboardData({
+    // data: `http://14.103.144.28/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`,
+    // 此处应该是一个小程序的外链
+    data: `http://14.103.144.28/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`,
+    success: () => $message.showToast('链接已复制')
+  })
+}
 
 
 onLoad((options: any) => {
@@ -207,8 +258,26 @@
 }
 
 // film-detail.vue
-const showCommentLayer = (parentId?: number) => {
+// const showCommentLayer = (parentId?: number | string) => {
+//   console.log('点击了评论按钮',parentId)
+//   if (typeof parentId === 'object') {
+//     parentId = ''
+//   }
+//   commentShow.value = true
+//   // 如果有parentId,说明是回复评论,需要设置parentId
+//   // 如果没有parentId,说明是直接评论,不需要设置parentId
+//   commentParendId.value = parentId ? String(parentId) : ''
+// }
+// 修改 showCommentLayer 函数
+const showCommentLayer = async (parentId?: number | string) => {
+  // 检查是否登录
+  const isLoggedIn = await checkLogin()
+  if (!isLoggedIn) return
+
   console.log('点击了评论按钮',parentId)
+  if (typeof parentId === 'object') {
+    parentId = ''
+  }
   commentShow.value = true
   // 如果有parentId,说明是回复评论,需要设置parentId
   // 如果没有parentId,说明是直接评论,不需要设置parentId
@@ -315,7 +384,62 @@
     }
 }
 
+// const toggleLike = async () => {
+//   console.log("toggleLike",filmInfo.value)
+//   if (!filmInfo.value) return
+//
+//   const api = liked.value ? '/v2/film-likes/filmLikes/edit' : '/v2/film-likes/filmLikes/edit'
+//
+//   try {
+//     const res = await $http.request('post', api, {
+//       data: { filmId: filmInfo.value.id }
+//     })
+//
+//     if (res.code === 0) {
+//       // 更新本地状态
+//       liked.value = !liked.value
+//       filmInfo.value.voLikeCount += liked.value ? 1 : -1
+//
+//       // 提示信息
+//       $message.showToast(liked.value ? '点赞成功' : '取消点赞')
+//     }
+//   } catch (error) {
+//     console.error('点赞失败:', error)
+//     $message.showToast('操作失败')
+//   }
+// }
+//
+// const toggleFavorite = async () => {
+//   console.log("toggleFavorite",filmInfo.value)
+//   if (!filmInfo.value) return
+//
+//   const api = collected.value ? '/v2/film-collects/filmCollects/edit' : '/v2/film-collects/filmCollects/edit'
+//
+//   try {
+//     const res = await $http.request('post', api, {
+//       data: { filmId: filmInfo.value.id }
+//     })
+//
+//     if (res.code === 0) {
+//       // 更新本地状态
+//       collected.value = !collected.value
+//       filmInfo.value.voCollectCount += collected.value ? 1 : -1
+//
+//       // 提示信息
+//       $message.showToast(collected.value ? '收藏成功' : '取消收藏')
+//     }
+//   } catch (error) {
+//     console.error('收藏失败:', error)
+//     $message.showToast('操作失败')
+//   }
+// }
+
+// 修改 toggleLike 函数
 const toggleLike = async () => {
+  // 检查是否登录
+  const isLoggedIn = await checkLogin()
+  if (!isLoggedIn) return
+
   console.log("toggleLike",filmInfo.value)
   if (!filmInfo.value) return
 
@@ -340,7 +464,12 @@
   }
 }
 
+// 修改 toggleFavorite 函数
 const toggleFavorite = async () => {
+  // 检查是否登录
+  const isLoggedIn = await checkLogin()
+  if (!isLoggedIn) return
+
   console.log("toggleFavorite",filmInfo.value)
   if (!filmInfo.value) return
 
@@ -364,6 +493,57 @@
     $message.showToast('操作失败')
   }
 }
+
+
+const checkLogin = async () => {
+  const userStore = useUserStore()
+  try {
+    await userStore.getCurrentInfo()
+    if (userStore.hasLogin) {
+      return true
+    } else {
+      showLoginModal()
+      return false
+    }
+  } catch (err) {
+    console.error('验证登录状态失败:', err)
+    showLoginModal()
+    return false
+  }
+}
+
+const showLoginModal = () => {
+  uni.showModal({
+    title: '登录提示',
+    content: '该操作需要登录,是否前往登录?',
+    confirmText: '去登录',
+    success: (res) => {
+      if(res.confirm) uni.navigateTo({ url: '/pages/login/login' })
+    }
+  })
+}
+
+// 小程序分享配置
+defineExpose({
+  onShareAppMessage() {
+    return {
+      title: filmInfo.value?.coverTitle || '分享内容',
+      path: `/sub-pages/film-list/film-detail?id=${filmInfo.value?.id}`,
+      imageUrl: filmPictureList.value[0] || '',
+      desc: filmInfo.value?.filmContent?.substring(0, 50) || ''
+    }
+  },
+  // 分享到朋友圈
+  onShareTimeline() {
+    return {
+      title: filmInfo.value?.coverTitle || '分享内容',
+      query: `id=${filmInfo.value?.id}`,
+      imageUrl: filmPictureList.value[0] || '',
+      desc: filmInfo.value?.filmContent?.substring(0, 50) || ''
+    }
+  }
+})
+
 </script>
 
 
@@ -593,4 +773,92 @@
     padding-bottom: 180rpx;
     /* 留出评论区高度,避免遮挡 */
 }
+
+.share-popup {
+  background: #fff;
+  padding: 30rpx;
+  border-top-left-radius: 20rpx;
+  border-top-right-radius: 20rpx;
+  min-height: 300rpx;
+}
+.share-title {
+  text-align: center;
+  font-size: 32rpx;
+  margin-bottom: 30rpx;
+  color: #333;
+}
+.share-options {
+  display: flex;
+  justify-content: space-around;
+  margin-bottom: 30rpx;
+  padding: 20rpx 0;
+}
+.share-btn {
+  display: flex;
+  flex-direction: column;
+  align-items: center;
+  width: 120rpx;
+}
+.share-icon {
+  width: 80rpx;
+  height: 80rpx;
+  margin-bottom: 10rpx;
+}
+.share-btn text {
+  font-size: 24rpx;
+  color: #666;
+  margin-top: 10rpx;
+}
+.share-cancel {
+  text-align: center;
+  color: #888;
+  font-size: 28rpx;
+  padding: 20rpx 0;
+  border-top: 1px solid #eee;
+  margin-top: 20rpx;
+}
+</style>
+
+<style lang="scss" scoped>
+// 分享按钮样式
+.share-btn {
+  background: none;
+  border: none;
+  padding: 0;
+  margin: 0;
+  line-height: normal;
+  
+  &::after {
+    border: none;
+  }
+}
+
+// 分享弹窗样式
+.share-popup {
+  position: fixed;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  z-index: 9999;
+  
+  .share-mask {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(0, 0, 0, 0.5);
+  }
+  
+  .share-content {
+    position: absolute;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: #fff;
+    border-radius: 20rpx 20rpx 0 0;
+    padding: 30rpx;
+  }
+}
 </style>
\ No newline at end of file

--
Gitblit v1.9.3