ソースを参照

feat:修改弹幕组件bug,和守护页面bug

wangsisi 3 週間 前
コミット
a1b81c5610

+ 5 - 4
components/checkinPopup/checkinPopup.vue

@@ -37,9 +37,9 @@
 					</view>
 				</view>
 			</view>
-			<view class="button" @click="showPopup = false">开心收下</view>
+			<view class="button" @click="closeCheckPopup">开心收下</view>
 			<view class="close">
-				<up-icon name="close-circle-fill" size="30" @click="showPopup = false"
+				<up-icon name="close-circle-fill" size="30" @click="closeCheckPopup"
 					color="rgba(255, 255, 255, 0.7)"></up-icon>
 			</view>
 		</view>
@@ -80,9 +80,10 @@
 		checkIn();
 	});
 
-	function closeCheckPopup() {
+	function closeCheckPopup() {
+		showPopup.value = false
 		emit('closedCheckPopup');
-	}
+	}
 
 	const emit = defineEmits(['closedCheckPopup']);
 </script>

+ 39 - 0
components/danmakuManager/README.md

@@ -168,3 +168,42 @@ const onDanmakuComplete = (id) => {
 - 调整低高度容器的可用轨道数量为3个,平衡显示和防叠加
 - 优化播放间隔时间,确保弹幕流畅显示
 - 修复过于严格的轨道分配导致的弹幕不显示问题
+
+### 11. 智能安全距离算法
+- 实现基于时间的安全距离计算,确保弹幕不会前后叠加
+- 采用安全性评分系统,优先选择最安全的轨道
+- 低高度容器使用更长的安全时间间隔(3000ms)
+- 智能轨道排序:完全安全 > 部分安全 > 等待
+- 大幅增加播放间隔时间,确保弹幕完全分离
+- 当没有安全轨道时,暂停添加新弹幕,避免强制叠加
+
+### 12. 平衡显示与防叠加
+- 回退到更平衡的轨道分配策略,确保弹幕能正常显示
+- 采用三级轨道选择策略:完全空闲 > 任何空闲 > 最早释放
+- 调整低高度容器的可用轨道数量为3个,平衡显示和防叠加
+- 优化播放间隔时间,确保弹幕流畅显示且减少叠加
+- 在保证弹幕正常显示的前提下,尽可能避免叠加
+
+### 13. 页面生命周期管理
+- 新增 `autoStart` 属性,控制弹幕是否自动开始播放
+- 支持父组件手动控制弹幕的启动和停止
+- 页面显示时自动启动弹幕,页面隐藏时自动停止弹幕
+- 页面卸载时自动清理弹幕资源,避免内存泄漏
+- 提供 `startDanmakuAnimation()` 和 `stopDanmakuAnimation()` 方法供外部调用
+
+### 14. 超强防叠加算法
+- 实现基于时间的安全距离计算,确保弹幕不会前后叠加
+- 采用安全性评分系统,优先选择最安全的轨道
+- 低高度容器使用更长的安全时间间隔(4000ms)
+- 智能轨道排序:完全安全 > 部分安全 > 等待
+- 大幅增加播放间隔时间(5000-9000ms),确保弹幕完全分离
+- 当没有安全轨道时,暂停添加新弹幕,避免强制叠加
+- 进一步减少低高度容器的可用轨道数量(最多2个)
+
+### 15. 修复显示问题
+- 回退到更平衡的轨道分配策略,确保弹幕能正常显示
+- 采用三级轨道选择策略:完全空闲 > 任何空闲 > 最早释放
+- 调整低高度容器的可用轨道数量为3个,平衡显示和防叠加
+- 优化播放间隔时间(3000-5000ms),确保弹幕流畅显示且减少叠加
+- 在保证弹幕正常显示的前提下,尽可能避免叠加
+- 修复过于严格的轨道分配导致的弹幕不显示问题

+ 1 - 1
components/danmakuManager/danmakuManager.vue

@@ -243,7 +243,7 @@ const startDanmakuAnimation = () => {
 		
 		// 根据容器高度动态调整间隔时间,低高度容器需要更大的间隔避免叠加
 		const baseInterval = props.height < 150 ? 
-			Math.max(2000, props.height * 2) : // 低高度容器使用适中的基础间隔
+			Math.max(3000, props.height * 2) : // 低高度容器使用适中的基础间隔
 			Math.max(1500, props.height * 2)   // 正常高度容器
 		const minInterval = baseInterval
 		const maxInterval = baseInterval + (props.height < 150 ? 2000 : 2000)

+ 160 - 102
pages/tabBar/tree/components/treeAlbumPopup.vue

@@ -10,13 +10,21 @@
 			</view>
             <view class="album-cont">
                 <view class="time-line-scroll">
-                    <scroll-view class="time-line-container" scroll-x :scroll-into-view="scrollIntoViewId" scroll-with-animation>
+                    <scroll-view class="time-line-container" scroll-x :scroll-into-view="scrollIntoViewId" scroll-with-animation @scroll="handleScroll" @scrollend="handleScrollEnd">
                         <view class="time-line">
-                            <view class="time-item" v-for="(item,index) in dateList" :key="index" :id="`d-${item.dateStr}`" @click="handleDateClick(item.dateStr)">
-                                <text :style="{color:(selectedDateStr===item.dateStr)?'#2199F8':'#777777'}">{{item.display}}</text>
-                                <view class="dot" :style="{background:(selectedDateStr===item.dateStr)?'#2199F8':'#777777'}"></view>
-                                <text class="today" v-if="item.isToday">今</text>
-                                <text v-if="item.showYear" class="year-flag">{{ item.year }}</text>
+                            <!-- 月份标记 -->
+                            <view class="month-markers">
+                                <view class="month-item" v-for="(month, index) in monthList" :key="index">
+                                    <text class="month-text">{{ month.label }}</text>
+                                    <view class="month-dot" :class="{'active': month.isCurrent}"></view>
+                                </view>
+                            </view>
+                            <!-- 日期刻度 -->
+                            <view class="date-markers">
+                                <view class="date-item" v-for="(date, index) in dateList" :key="index" :class="{'current-date': date.isCurrent}">
+                                    <text class="date-text" :class="{'current': date.isCurrent}">{{ date.display }}</text>
+                                    <view class="date-dot" :class="{'current': date.isCurrent}"></view>
+                                </view>
                             </view>
                         </view>
                     </scroll-view>
@@ -70,14 +78,16 @@
 	const handleClose = ()=>{
 		showPopup.value = false
 	}
+    const monthList = ref([])
     const dateList = ref([])
     const scrollIntoViewId = ref('')
     const selectedDateStr = ref('')
+    const centerDate = ref('')
 
     const formatToDisplay = (dateStr)=>{
         // dateStr: YYYY-MM-DD
         const [y,m,d] = dateStr.split('-')
-        return `${m}/${d}`
+        return `${m}月${d}日`
     }
     const getTodayStr = ()=>{
         const d = new Date()
@@ -85,74 +95,58 @@
         const dd = `${d.getDate()}`.padStart(2,'0')
         return `${d.getFullYear()}-${mm}-${dd}`
     }
-    const fetchHasImageDates = async ()=>{
-        if(!props.farmBuyId) return
-        try{
-            const {data} = await TREE.findHasImagesDate({farmBuyId: props.farmBuyId})
-            const today = getTodayStr()
-            const arr = Array.isArray(data) ? data : []
-            const mapped = arr.map(ds=>{
-                const dateStr = (typeof ds === 'string') ? ds.split(' ')[0] : ''
-                const isToday = dateStr === today
-                const [y,m,d] = dateStr.split('-')
-                return {
-                    dateStr,
-                    display: dateStr ? formatToDisplay(dateStr) : '',
-                    isToday,
-                    year: y,
-                    month: m,
-                    day: d
-                }
-            }).filter(i=>i.dateStr)
-            mapped.sort((a,b)=> a.dateStr.localeCompare(b.dateStr))
-            
-            // 只显示月份第一天和中间/下月第一天
-            const filteredDates = []
-            let currentMonth = ''
-            let currentYear = ''
+    
+    const generateTimeLineData = () => {
+        const today = new Date()
+        const currentYear = today.getFullYear()
+        const currentMonth = today.getMonth() + 1
+        const currentDay = today.getDate()
+        
+        // 生成月份列表(往前一年)
+        const months = []
+        for(let i = 11; i >= 0; i--) {
+            const date = new Date(currentYear, currentMonth - 1 - i, 1)
+            const month = date.getMonth() + 1
+            const year = date.getFullYear()
+            const isCurrent = month === currentMonth && year === currentYear
             
-            for(let i=0;i<mapped.length;i++){
-                const item = mapped[i]
-                const monthKey = `${item.year}-${item.month}`
-                
-                if(monthKey !== currentMonth){
-                    // 新月份的第一天
-                    item.showYear = monthKey.split('-')[0] !== currentYear
-                    filteredDates.push(item)
-                    currentMonth = monthKey
-                    currentYear = item.year
-                } else {
-                    // 检查是否是当前月份的中间日期或下个月第一天
-                    const day = parseInt(item.day)
-                    if(day === 15 || day === 1){
-                        item.showYear = false
-                        filteredDates.push(item)
-                    }
-                }
-            }
+            months.push({
+                year,
+                month,
+                label: `${month}月`,
+                isCurrent,
+                dateStr: `${year}-${month.toString().padStart(2,'0')}-01`
+            })
+        }
+        monthList.value = months
+        
+        // 生成当前月份的日期刻度(每两天一个)
+        const dates = []
+        const daysInMonth = new Date(currentYear, currentMonth, 0).getDate()
+        
+        for(let day = 1; day <= daysInMonth; day += 2) {
+            const dateStr = `${currentYear}-${currentMonth.toString().padStart(2,'0')}-${day.toString().padStart(2,'0')}`
+            const isCurrent = day === currentDay
             
-            dateList.value = filteredDates
-            if(dateList.value.length){
-                const last = dateList.value[dateList.value.length-1]
-                selectedDateStr.value = last.dateStr
-                // 强制等渲染后再滚动到最右端
-                scrollIntoViewId.value = ''
-                await nextTick()
-                scrollIntoViewId.value = `d-${last.dateStr}`
-            }else{
-                selectedDateStr.value = ''
-                scrollIntoViewId.value = ''
-            }
-        }catch(e){
-            // 静默失败
+            dates.push({
+                dateStr,
+                display: `${currentMonth}月${day}日`,
+                isCurrent,
+                day
+            })
         }
+        dateList.value = dates
+        
+        // 设置当前日期为选中状态
+        selectedDateStr.value = getTodayStr()
+        centerDate.value = getTodayStr()
     }
+    
     const fetchTreeImages = async (dateStr)=>{
         try{
             const params = {
                 page: 1,
                 limit: 1,
-                // treeId: Number(props.sampleId),
                 treeId: 110939,
                 date: dateStr,
             }
@@ -170,9 +164,42 @@
 	    }
 	};
 	
+    const handleScroll = (e) => {
+        // 滚动中实时计算中间位置
+        const scrollLeft = e.detail.scrollLeft
+        const viewWidth = e.detail.scrollWidth - e.detail.scrollLeft
+        
+        // 计算中间位置对应的日期
+        const centerPosition = scrollLeft + viewWidth / 2
+        const itemWidth = 120 // 每个时间项的宽度
+        const estimatedIndex = Math.floor(centerPosition / itemWidth)
+        
+        if(dateList.value[estimatedIndex]){
+            centerDate.value = dateList.value[estimatedIndex].dateStr
+        }
+    }
+    
+    const handleScrollEnd = (e) => {
+        // 滚动停止时获取中间位置的日期并调用接口
+        const scrollLeft = e.detail.scrollLeft
+        const viewWidth = e.detail.scrollWidth - e.detail.scrollLeft
+        
+        const centerPosition = scrollLeft + viewWidth / 2
+        const itemWidth = 120
+        const estimatedIndex = Math.floor(centerPosition / itemWidth)
+        
+        if(dateList.value[estimatedIndex]){
+            const finalDate = dateList.value[estimatedIndex].dateStr
+            centerDate.value = finalDate
+            selectedDateStr.value = finalDate
+            console.log('滑动停止,中间位置日期:', finalDate)
+            fetchTreeImages(finalDate)
+        }
+    }
+    
     const handleDateClick = (dateStr)=>{
         selectedDateStr.value = dateStr
-        scrollIntoViewId.value = `d-${dateStr}`
+        centerDate.value = dateStr
         fetchTreeImages(dateStr)
     }
 	const photoList = ref([]);
@@ -182,7 +209,7 @@
         async (val) => {
             showPopup.value = val;
             if(val){
-                await fetchHasImageDates()
+                generateTimeLineData()
                 const today = getTodayStr()
                 fetchTreeImages(today)
             }
@@ -192,7 +219,7 @@
         () => props.farmBuyId,
         (val) => {
             if(showPopup.value && val){
-                fetchHasImageDates()
+                generateTimeLineData()
             }
         }
     )
@@ -246,6 +273,7 @@
             }
             .time-line{
                 display: flex;
+                flex-direction: column;
                 padding: 0 20rpx;
                 position: relative;
             }
@@ -260,44 +288,74 @@
                 transform: translateX(-50%);
                 pointer-events: none;
             }
-            .time-item{
-                min-width: 120rpx;
-                font-size: 24rpx;
-                color: #777777;
+            
+            .month-markers{
                 display: flex;
-                flex-direction: column;
-                align-items: center;
-                position: relative;
-                padding: 0 12rpx;
-                cursor: pointer;
+                align-items: flex-end;
+                margin-bottom: 20rpx;
                 
-                &::before{
-                    content: '';
-                    position: absolute;
-                    top: 44%;
-                    left: 0;
-                    right: 0;
-                    height: 2rpx;
-                    background: rgba(136, 136, 136, 0.1);
-                }
-                .dot{
-                    width: 14rpx;
-                    height: 14rpx;
-                    background: #777777;
-                    border-radius: 50%;
-                    position: relative;
-                    z-index: 5;
-                }
-                .today{
-                    color: #2199F8;
-                    margin-top: 8rpx;
+                .month-item{
+                    display: flex;
+                    flex-direction: column;
+                    align-items: center;
+                    min-width: 120rpx;
+                    padding: 0 12rpx;
+                    
+                    .month-text{
+                        font-size: 28rpx;
+                        color: #777777;
+                        margin-bottom: 8rpx;
+                    }
+                    
+                    .month-dot{
+                        width: 16rpx;
+                        height: 16rpx;
+                        background: #777777;
+                        border-radius: 50%;
+                        
+                        &.active{
+                            background: #2199F8;
+                        }
+                    }
                 }
-                .year-flag{
-                    font-size: 18rpx;
-                    color: #999;
-                    margin-top: 6rpx;
+            }
+            
+            .date-markers{
+                display: flex;
+                align-items: flex-end;
+                
+                .date-item{
+                    display: flex;
+                    flex-direction: column;
+                    align-items: center;
+                    min-width: 120rpx;
+                    padding: 0 12rpx;
+                    
+                    .date-text{
+                        font-size: 24rpx;
+                        color: #777777;
+                        margin-bottom: 8rpx;
+                        
+                        &.current{
+                            color: #2199F8;
+                        }
+                    }
+                    
+                    .date-dot{
+                        width: 8rpx;
+                        height: 8rpx;
+                        background: #ccc;
+                        border-radius: 50%;
+                        
+                        &.current{
+                            background: #2199F8;
+                            width: 16rpx;
+                            height: 16rpx;
+                        }
+                    }
                 }
             }
+            
 			.swiper-wrap{
 				position: relative;
 				padding: 0 20rpx;

+ 7 - 2
pages/tabBar/tree/subPages/diary.vue

@@ -73,7 +73,7 @@
 		<up-calendar ref="calendar" :show="showDatetime" mode="single" :defaultDate="selectedDate" @confirm="confirm" @close="cancel"
 			:minDate="formatDate(new Date(Date.now() - 365 * 24 * 60 * 60 * 1000),'-')" :maxDate="formatDate(new Date(),'-')" monthNum="13"
 			:formatter="formatter"></up-calendar>
-		<editNamePopup ref="editNameRef" @editEnd="getBySampleId"></editNamePopup>
+		<editNamePopup ref="editNameRef" @editEnd="editEnd"></editNamePopup>
 	</view>
 </template>
 
@@ -91,7 +91,12 @@
 		} else {
 			return config.BASE_IMG_URL + filename + resize;
 		}
-	};
+	};
+	
+	const editEnd = () =>{
+		uni.setStorageSync('isUpdateName','true')
+		getBySampleId()
+	}
 
 	const sampleId = ref('')
 	const farmBuyId = ref('')

+ 137 - 89
pages/tabBar/tree/tree.vue

@@ -5,23 +5,24 @@
 				<view class="toogle" @click="handleShow">切换 {{name}}<up-icon class="icon" name="arrow-down" color="#fff"
 						size="12"></up-icon></view>
 			</member-level>
-			<view class="tree-cont">
-				<!-- 弹幕组件 -->
-				<view class="danmaku-wrapper">
-					<danmakuManager 
-						:danmakuList="danmakuList" 
-						:height="100" 
-						:infinite="true"
-						:speed="80"
-						@danmakuComplete="onDanmakuComplete"
-					></danmakuManager>
-				</view>
-				<view class="dialogue-tips">
-					<view class="tips-name">
-						<image class="tip-img" :src="`${config.BASIC_IMG}img/treePage/sun-icon.png`"></image>
-						<text>亲爱的主人!</text>
-					</view>
-					<view class="tips-cont">今天是我开花的日子,我很开心!</view>
+			<view class="tree-cont">
+				<!-- 弹幕组件 -->
+				<view class="danmaku-wrapper">
+					<danmakuManager 
+						ref="danmakuRef"
+						:danmakuList="danmakuList" 
+						:height="100" 
+						:infinite="true"
+						:speed="80"
+						@danmakuComplete="onDanmakuComplete"
+					></danmakuManager>
+				</view>
+				<view class="dialogue-tips">
+					<view class="tips-name">
+						<image class="tip-img" :src="`${config.BASIC_IMG}img/treePage/sun-icon.png`"></image>
+						<text>亲爱的主人!</text>
+					</view>
+					<view class="tips-cont">今天是我开花的日子,我很开心!</view>
 				</view>
 				<view class="tree-name">
 					<view>{{treeName}}</view>
@@ -49,19 +50,19 @@
 				</view>
 			</view>
 			<view class="tree-footer">
-				<template v-if="userInfo.tel">
-					<view class="footer-item" v-for="(item,index) in footerList" :key="index" @click="handleItem(index)">
-						<view @click="requestSubscribe">
-							<button class="share-btn" open-type="share" v-if="index === 2">
-								<image class="icon" :src="`${config.BASIC_IMG}img/treePage/b-tree-icon-${index+1}.png`">
-								</image>
-							</button>
-							<image v-else class="icon" :src="`${config.BASIC_IMG}img/treePage/b-tree-icon-${index+1}.png`">
-							</image>
-							<view class="name">{{item}}</view>
-						</view>
-					</view>
-				</template>
+				<template v-if="userInfo.tel">
+					<view class="footer-item" v-for="(item,index) in footerList" :key="index" @click="handleItem(index)">
+						<view @click="requestSubscribe">
+							<button class="share-btn" open-type="share" v-if="index === 2">
+								<image class="icon" :src="`${config.BASIC_IMG}img/treePage/b-tree-icon-${index+1}.png`">
+								</image>
+							</button>
+							<image v-else class="icon" :class="{small:index === 0}" :src="`${config.BASIC_IMG}img/treePage/b-tree-icon-${index+1}.png`">
+							</image>
+							<view class="name">{{item}}</view>
+						</view>
+					</view>
+				</template>
 				<view v-else class="button" @click="handlePage">开启我的守护</view>
 			</view>
 		</view>
@@ -93,10 +94,12 @@
 <script setup>
 	import config from "@/api/config.js"
 	import {
-		onLoad,
-		onShareAppMessage,
-		onShow
-	} from '@dcloudio/uni-app'
+	onLoad,
+	onShareAppMessage,
+	onShow,
+	onHide,
+	onUnload
+} from '@dcloudio/uni-app'
 	import memberLevel from "./components/memberLevel.vue"
 	import treeAlbumPopup from "./components/treeAlbumPopup.vue"
 	import blessingsPopup from "./components/blessingsPopup.vue"
@@ -177,11 +180,28 @@
 
 	onLoad(() => {
 		featchIsLookedGuide()
-		featchCategoryList()
+		featchCategoryList()
+		featchLightTree()
 	})
 	
-	onShow(()=>{
-		featchLightTree()
+	onShow(()=>{
+		const isUpdateName = uni.getStorageSync('isUpdateName')
+		if(isUpdateName === 'true'){
+			featchLightTree()
+			uni.setStorageSync('isUpdateName','false')
+		}
+		// 页面显示时启动弹幕
+		startDanmaku()
+	})
+	
+	onHide(() => {
+		// 页面隐藏时停止弹幕
+		stopDanmaku()
+	})
+	
+	onUnload(() => {
+		// 页面卸载时停止弹幕
+		stopDanmaku()
 	})
 	
 	//品类查询所有
@@ -201,7 +221,7 @@
 			data
 		}) => {
 			if (data == false) {
-				showMask.value = true
+				showMask.value = true
 				
 			}
 		})
@@ -223,15 +243,15 @@
 				showGuardSuccess.value = !showGuardSuccess.value
 				USER.setSessionStore({
 					key: 'successTree',
-					miniUserId: userInfo.id,
+					miniUserId: userInfo.id,
 					val:1
 				})
 			}
 		}))
-	}
-	
+	}
+	
 	const closedCheckPopup = () =>{
-		showPoster.value = !showPoster.value
+		showPoster.value = !showPoster.value
 	}
 	
 	const sampleId = ref('')
@@ -263,12 +283,12 @@
 			farmBuyId.value = data.buyList[0].id
 			featchSessionStore()
 		})
-	}
-	
-	const handlePage = () =>{
-		uni.navigateTo({
-			url: `/pages/login/index`
-		});
+	}
+	
+	const handlePage = () =>{
+		uni.navigateTo({
+			url: `/pages/login/index`
+		});
 	}
 
 	const showPoster = ref(false)
@@ -329,9 +349,26 @@
 		}
 	])
 	
+	// 弹幕组件引用
+	const danmakuRef = ref(null)
+	
 	// 弹幕完成回调
 	const onDanmakuComplete = (id) => {
-		console.log('弹幕播放完成:', id)
+		// console.log('弹幕播放完成:', id)
+	}
+	
+	// 启动弹幕
+	const startDanmaku = () => {
+		if (danmakuRef.value) {
+			danmakuRef.value.startDanmakuAnimation()
+		}
+	}
+	
+	// 停止弹幕
+	const stopDanmaku = () => {
+		if (danmakuRef.value) {
+			danmakuRef.value.stopDanmakuAnimation()
+		}
 	}
 	const handleItem = (index) => {
 		if (index === 0) {
@@ -362,7 +399,9 @@
 				showSuccess.value = !showSuccess.value
 			}
 		} else {
-			console.log('123')
+			uni.navigateTo({
+				url: `/pages/tabBar/home/subPages/gardenItem`
+			});
 		}
 	}
 
@@ -466,27 +505,27 @@
 
 		.tree-cont {
 			width: 100%;
-			margin-top: 10rpx;
-			.dialogue-tips{
-				position: absolute;
-				top: 31.5%;
-				right: 80rpx;
-				font-size: 24rpx;
-				@include ossBg("treePage/tips-bg.png");
-				padding: 10rpx 10rpx 30rpx 20rpx;
-				.tips-name{
-					font-size: 28rpx;
-					font-weight: 500;
-					margin-bottom: 6rpx;
-					display: flex;
-					align-items: center;
-					.tip-img{
-						width: 40rpx;
-						height: 40rpx;
-						margin-right: 4rpx;
-					}
-				}
-			}
+			margin-top: 10rpx;
+			.dialogue-tips{
+				position: absolute;
+				top: 31.5%;
+				right: 80rpx;
+				font-size: 24rpx;
+				@include ossBg("treePage/tips-bg.png");
+				padding: 10rpx 10rpx 30rpx 20rpx;
+				.tips-name{
+					font-size: 28rpx;
+					font-weight: 500;
+					margin-bottom: 6rpx;
+					display: flex;
+					align-items: center;
+					.tip-img{
+						width: 40rpx;
+						height: 40rpx;
+						margin-right: 4rpx;
+					}
+				}
+			}
 
 			.tree-name {
 				position: absolute;
@@ -596,32 +635,41 @@
 			bottom: 76rpx;
 			width: 100%;
 			display: flex;
-			justify-content: center;
-			.button {
-				padding: 26rpx 80rpx;
-				border-radius: 50rpx;
-				border: 2rpx solid #fff;
-				background-image: linear-gradient(120deg, #FFD887, #ED9E1E);
-				margin-top: 20rpx;
-				color: #fff;
+			justify-content: center;
+			.button {
+				padding: 26rpx 80rpx;
+				border-radius: 50rpx;
+				border: 2rpx solid #fff;
+				background-image: linear-gradient(120deg, #FFD887, #ED9E1E);
+				margin-top: 20rpx;
+				color: #fff;
 			}
 
 			.footer-item {
 				width: 18%;
 				text-align: center;
-
-				.share-btn {
-					background: transparent;
-					display: inline-flex;
-
-					&::after {
-						border: none;
-					}
-				}
-
 				.icon {
 					width: 96rpx;
 					height: 96rpx;
+				}
+				.share-btn {
+					background: transparent;
+					display: inline-flex;
+					.icon {
+						width: 90rpx;
+						height: 90rpx;
+						margin-top: 6rpx;
+					}
+				
+					&::after {
+						border: none;
+					}
+				}
+				
+				.small{
+					width: 90rpx;
+					height: 90rpx;
+					margin-top: 6rpx;
 				}
 
 				.name {