hookehuyr

feat(相册): 将家庭相册功能提取为独立组件

将原本在Dashboard页面中的家庭相册功能提取为独立的FamilyAlbum组件
优化代码结构,提高可维护性和复用性
...@@ -11,6 +11,7 @@ declare module 'vue' { ...@@ -11,6 +11,7 @@ declare module 'vue' {
11 AppHeader: typeof import('./src/components/AppHeader.vue')['default'] 11 AppHeader: typeof import('./src/components/AppHeader.vue')['default']
12 BackToTop: typeof import('./src/components/BackToTop.vue')['default'] 12 BackToTop: typeof import('./src/components/BackToTop.vue')['default']
13 BottomNav: typeof import('./src/components/BottomNav.vue')['default'] 13 BottomNav: typeof import('./src/components/BottomNav.vue')['default']
14 + FamilyAlbum: typeof import('./src/components/FamilyAlbum.vue')['default']
14 GlassCard: typeof import('./src/components/GlassCard.vue')['default'] 15 GlassCard: typeof import('./src/components/GlassCard.vue')['default']
15 NavBar: typeof import('./src/components/navBar.vue')['default'] 16 NavBar: typeof import('./src/components/navBar.vue')['default']
16 NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet'] 17 NutActionSheet: typeof import('@nutui/nutui-taro')['ActionSheet']
......
1 +<template>
2 + <view>
3 + <!-- Family album -->
4 + <view class="p-5 mt-4 mb-6 bg-white rounded-xl shadow-md mx-4">
5 + <view class="flex justify-between items-center mb-2">
6 + <h2 class="font-medium text-lg">多彩瞬间</h2>
7 + <view class="text-blue-500 flex items-center text-xs" @click="openAlbumList">
8 + 查看更多
9 + </view>
10 + </view>
11 + <p class="text-sm text-gray-500 mb-3">记录每一个家庭活动瞬间</p>
12 + <view class="grid grid-cols-2 gap-3">
13 + <view
14 + v-for="(item, index) in albumData"
15 + :key="index"
16 + class="rounded-lg overflow-hidden h-32 relative cursor-pointer"
17 + @click="handleMediaClick(item, albumData)"
18 + >
19 + <image
20 + :src="item.type === 'video' ? item.thumbnail : item.url"
21 + alt="家庭活动照片"
22 + class="w-full h-full object-cover rounded-lg"
23 + />
24 + <!-- 视频标识 -->
25 + <view
26 + v-if="item.type === 'video'"
27 + class="absolute top-2 left-2 px-2 py-1 bg-black bg-opacity-70 rounded text-white text-xs"
28 + >
29 + 视频
30 + </view>
31 + </view>
32 + </view>
33 + </view>
34 +
35 + <!-- 图片预览 -->
36 + <nut-image-preview
37 + v-model:show="previewVisible"
38 + :images="previewImages"
39 + :init-no="previewIndex"
40 + :show-index="false"
41 + @close="closePreview"
42 + />
43 +
44 + <!-- 视频播放器 -->
45 + <view
46 + v-if="videoVisible"
47 + class="fixed inset-0 bg-black"
48 + style="z-index: 9999;"
49 + @click="closeVideo"
50 + >
51 + <!-- 关闭按钮 -->
52 + <view
53 + @click.stop="closeVideo"
54 + class="absolute top-4 right-4 w-10 h-10 bg-black bg-opacity-50 rounded-full flex items-center justify-center"
55 + style="z-index: 10000;"
56 + >
57 + <Close size="24" class="text-white" />
58 + </view>
59 +
60 + <!-- 视频播放器 -->
61 + <video
62 + v-if="currentVideo"
63 + :id="'family-album-video-' + videoId"
64 + :src="currentVideo.url"
65 + :poster="currentVideo.thumbnail"
66 + :controls="true"
67 + :autoplay="false"
68 + :show-center-play-btn="true"
69 + :show-play-btn="true"
70 + :object-fit="'contain'"
71 + :show-fullscreen-btn="true"
72 + style="width: 100vw; height: 50vh; position: absolute; top: 20vh; left: 0;"
73 + @click.stop
74 + @play="handleVideoPlay"
75 + @pause="handleVideoPause"
76 + @error="handleVideoError"
77 + @fullscreenchange="handleFullscreenChange"
78 + />
79 + </view>
80 + </view>
81 +</template>
82 +
83 +<script setup>
84 +import { ref } from 'vue';
85 +import Taro from '@tarojs/taro';
86 +import { Close } from '@nutui/icons-vue-taro';
87 +import { useMediaPreview } from '@/composables/useMediaPreview';
88 +
89 +// 使用媒体预览 composable
90 +const {
91 + previewVisible,
92 + previewImages,
93 + previewIndex,
94 + videoVisible,
95 + currentVideo,
96 + videoId,
97 + handleMediaClick,
98 + closePreview,
99 + closeVideo,
100 + handleVideoPlay,
101 + handleVideoPause,
102 + handleFullscreenChange,
103 + handleVideoError
104 +} = useMediaPreview();
105 +
106 +// 家庭相册数据
107 +const albumData = ref([
108 + {
109 + type: 'image',
110 + url: 'https://cdn.ipadbiz.cn/hager/0513-1_FsxMk28AGz6N_D1zZFFOl_EaRdss.png',
111 + },
112 + {
113 + type: 'video',
114 + url: 'https://vjs.zencdn.net/v/oceans.mp4',
115 + thumbnail: 'https://cdn.ipadbiz.cn/hager/0513-1_FsxMk28AGz6N_D1zZFFOl_EaRdss.png',
116 + }
117 +]);
118 +
119 +/**
120 + * 打开相册列表页面
121 + */
122 +const openAlbumList = () => {
123 + Taro.navigateTo({ url: '/pages/AlbumList/index' });
124 +};
125 +</script>
126 +
127 +<style lang="less" scoped>
128 +// 组件样式
129 +</style>
...\ No newline at end of file ...\ No newline at end of file
...@@ -138,36 +138,7 @@ ...@@ -138,36 +138,7 @@
138 <RankingCard ref="rankingCardRef" :onViewMore="openFamilyRank" /> 138 <RankingCard ref="rankingCardRef" :onViewMore="openFamilyRank" />
139 139
140 <!-- Family album --> 140 <!-- Family album -->
141 - <view class="p-5 mt-4 mb-6 bg-white rounded-xl shadow-md mx-4"> 141 + <FamilyAlbum />
142 - <view class="flex justify-between items-center mb-2">
143 - <h2 class="font-medium text-lg">多彩瞬间</h2>
144 - <view class="text-blue-500 flex items-center text-xs" @click="openAlbumList">
145 - 查看更多
146 - </view>
147 - </view>
148 - <p class="text-sm text-gray-500 mb-3">记录每一个家庭活动瞬间</p>
149 - <view class="grid grid-cols-2 gap-3">
150 - <view
151 - v-for="(item, index) in albumData"
152 - :key="index"
153 - class="rounded-lg overflow-hidden h-32 relative cursor-pointer"
154 - @click="handleMediaClick(item, albumData)"
155 - >
156 - <image
157 - :src="item.type === 'video' ? item.thumbnail : item.url"
158 - alt="家庭活动照片"
159 - class="w-full h-full object-cover rounded-lg"
160 - />
161 - <!-- 视频标识 -->
162 - <view
163 - v-if="item.type === 'video'"
164 - class="absolute top-2 left-2 px-2 py-1 bg-black bg-opacity-70 rounded text-white text-xs"
165 - >
166 - 视频
167 - </view>
168 - </view>
169 - </view>
170 - </view>
171 142
172 <BottomNav /> 143 <BottomNav />
173 144
...@@ -180,65 +151,21 @@ ...@@ -180,65 +151,21 @@
180 @click="handleAdClick" 151 @click="handleAdClick"
181 /> 152 />
182 153
183 - <!-- 图片预览 -->
184 - <nut-image-preview
185 - v-model:show="previewVisible"
186 - :images="previewImages"
187 - :init-no="previewIndex"
188 - :show-index="false"
189 - @close="closePreview"
190 - />
191 -
192 - <!-- 视频播放器 -->
193 - <view
194 - v-if="videoVisible"
195 - class="fixed inset-0 bg-black"
196 - style="z-index: 9999;"
197 - @click="closeVideo"
198 - >
199 - <!-- 关闭按钮 -->
200 - <view
201 - @click.stop="closeVideo"
202 - class="absolute top-4 right-4 w-10 h-10 bg-black bg-opacity-50 rounded-full flex items-center justify-center"
203 - style="z-index: 10000;"
204 - >
205 - <Close size="24" class="text-white" />
206 - </view>
207 154
208 - <!-- 视频播放器 -->
209 - <video
210 - v-if="currentVideo"
211 - :id="'dashboard-video-' + videoId"
212 - :src="currentVideo.url"
213 - :poster="currentVideo.thumbnail"
214 - :controls="true"
215 - :autoplay="false"
216 - :show-center-play-btn="true"
217 - :show-play-btn="true"
218 - :object-fit="'contain'"
219 - :show-fullscreen-btn="true"
220 - style="width: 100vw; height: 50vh; position: absolute; top: 20vh; left: 0;"
221 - @click.stop
222 - @play="handleVideoPlay"
223 - @pause="handleVideoPause"
224 - @error="handleVideoError"
225 - @fullscreenchange="handleFullscreenChange"
226 - />
227 - </view>
228 </view> 155 </view>
229 </template> 156 </template>
230 157
231 <script setup> 158 <script setup>
232 import { ref, computed, onMounted } from 'vue'; 159 import { ref, computed, onMounted } from 'vue';
233 import Taro, { useDidShow, useReady } from '@tarojs/taro'; 160 import Taro, { useDidShow, useReady } from '@tarojs/taro';
234 -import { Setting, Photograph, Close, Category } from '@nutui/icons-vue-taro'; 161 +import { Setting, Photograph, Category } from '@nutui/icons-vue-taro';
235 import BottomNav from '../../components/BottomNav.vue'; 162 import BottomNav from '../../components/BottomNav.vue';
236 import TotalPointsDisplay from '@/components/TotalPointsDisplay.vue'; 163 import TotalPointsDisplay from '@/components/TotalPointsDisplay.vue';
237 import PointsCollector from '@/components/PointsCollector.vue' 164 import PointsCollector from '@/components/PointsCollector.vue'
238 import WeRunAuth from '@/components/WeRunAuth.vue' 165 import WeRunAuth from '@/components/WeRunAuth.vue'
239 import RankingCard from '@/components/RankingCard.vue' 166 import RankingCard from '@/components/RankingCard.vue'
240 import AdOverlay from '@/components/AdOverlay.vue' 167 import AdOverlay from '@/components/AdOverlay.vue'
241 -import { useMediaPreview } from '@/composables/useMediaPreview'; 168 +import FamilyAlbum from '@/components/FamilyAlbum.vue';
242 // 默认家庭封面图 169 // 默认家庭封面图
243 const defaultFamilyCover = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png'; 170 const defaultFamilyCover = 'https://cdn.ipadbiz.cn/lls_prog/images/default-family-cover.png';
244 // 默认头像 171 // 默认头像
...@@ -260,35 +187,7 @@ const familySlogn = ref('') ...@@ -260,35 +187,7 @@ const familySlogn = ref('')
260 const familyCover = ref('') 187 const familyCover = ref('')
261 const familyOwner = ref(false); 188 const familyOwner = ref(false);
262 189
263 -// 使用媒体预览 composable 190 +
264 -const {
265 - previewVisible,
266 - previewImages,
267 - previewIndex,
268 - videoVisible,
269 - currentVideo,
270 - videoId,
271 - handleMediaClick,
272 - closePreview,
273 - closeVideo,
274 - handleVideoPlay,
275 - handleVideoPause,
276 - handleFullscreenChange,
277 - handleVideoError
278 -} = useMediaPreview();
279 -
280 -// 家庭相册数据
281 -const albumData = ref([
282 - {
283 - type: 'image',
284 - url: 'https://cdn.ipadbiz.cn/hager/0513-1_FsxMk28AGz6N_D1zZFFOl_EaRdss.png',
285 - },
286 - {
287 - type: 'video',
288 - url: 'https://vjs.zencdn.net/v/oceans.mp4',
289 - thumbnail: 'https://cdn.ipadbiz.cn/hager/0513-1_FsxMk28AGz6N_D1zZFFOl_EaRdss.png',
290 - }
291 -]);
292 191
293 // 广告遮罩层数据 192 // 广告遮罩层数据
294 const adObj = ref({}) 193 const adObj = ref({})
...@@ -364,9 +263,7 @@ const goToProfile = () => { ...@@ -364,9 +263,7 @@ const goToProfile = () => {
364 Taro.navigateTo({ url: '/pages/EditFamily/index' }); 263 Taro.navigateTo({ url: '/pages/EditFamily/index' });
365 }; 264 };
366 265
367 -const openAlbumList = () => { 266 +
368 - Taro.navigateTo({ url: '/pages/AlbumList/index' });
369 -};
370 267
371 /** 268 /**
372 * 打开拍照上传页面 269 * 打开拍照上传页面
......