consumer-app/components/DetailActionBar/DetailActionBar.vue

284 lines
6.6 KiB
Vue
Raw Permalink Normal View History

2026-03-02 07:32:41 +00:00
<template>
<view class="detail-action-bar">
<!-- <view class="action-item" @click="handleContact">
<image class="action-icon" src="/static/service/phone_icon.png" mode="aspectFill"></image>
<text class="action-text">联系</text>
</view> -->
<view class="action-item" @click="handleLike">
<image class="action-icon" src="/static/service/like_icon.png" mode="aspectFill"></image>
<text class="action-text">点赞</text>
</view>
<button class="action-item share-button" open-type="share" @click="handleShareClick">
<image class="action-icon" src="/static/service/share_icon.png" mode="aspectFill"></image>
<text class="action-text">分享</text>
</button>
<view class="action-item" @click="handleCollect">
<image class="action-icon" src="/static/service/collect_icon.png" mode="aspectFill"></image>
<text class="action-text">收藏</text>
</view>
</view>
</template>
<script>
import { setMemberLike, setMemberCollect, createMemberShare } from '@/api/service.js'
export default {
name: 'DetailActionBar',
props: {
// 是否已点赞
liked: {
type: Boolean,
default: false
},
// 是否已收藏
collected: {
type: Boolean,
default: false
},
// 联系电话(用于联系功能)
contactPhone: {
type: String,
default: ''
},
// 内容ID
id: {
type: [String, Number],
default: null
},
// 点赞类型
zanType: {
type: [String, Number],
default: null
},
// 内容类型(用于收藏接口)
type: {
type: [String, Number],
default: null
}
},
data() {
return {
isLiked: this.liked,
isCollected: this.collected,
likeLoading: false,
collectLoading: false
}
},
watch: {
liked(newVal) {
this.isLiked = newVal
},
collected(newVal) {
this.isCollected = newVal
}
},
methods: {
// 处理联系
handleContact() {
if (this.contactPhone) {
uni.makePhoneCall({
phoneNumber: this.contactPhone,
fail: (err) => {
console.error('拨打电话失败:', err)
uni.showToast({
title: '拨打电话失败',
icon: 'none'
})
}
})
} else {
this.$emit('contact')
}
},
// 处理点赞
async handleLike() {
if (this.likeLoading) return
const newLikedState = !this.isLiked
try {
this.likeLoading = true
// 先更新UI状态提供即时反馈
this.isLiked = newLikedState
const res = await setMemberLike({
zanId: this.id,
zanType: this.zanType,
status: newLikedState ? 1 : 2 ,//赞状态不能为空 1 赞,2 取消赞
})
if (res) {
uni.showToast({
title: newLikedState ? '点赞成功' : '取消点赞',
icon: 'success',
duration: 1500
})
}
} catch (error) {
console.error('点赞操作失败:', error)
// 操作失败,恢复原状态
this.isLiked = !newLikedState
uni.showToast({
title: '操作失败,请重试',
icon: 'none',
duration: 2000
})
} finally {
this.likeLoading = false
}
},
// 处理分享点击(用于非微信小程序平台)
handleShareClick() {
// #ifdef MP-WEIXIN
// 微信小程序中button 的 open-type="share" 会自动触发分享
// 不需要额外处理
// #endif
// #ifndef MP-WEIXIN
// 其他平台,触发分享事件
this.$emit('share')
// #endif
},
// 分享成功后调用接口(由页面调用)
async handleShareSuccess() {
try {
const res = await createMemberShare({
shareId: this.id,
shareContentType: this.type
})
if (res) {
console.log('分享记录创建成功')
}
} catch (error) {
console.error('创建分享记录失败:', error)
// 分享记录失败不影响用户体验,只记录错误
}
},
// 处理收藏
async handleCollect() {
if (this.collectLoading) return
const newCollectedState = !this.isCollected
try {
this.collectLoading = true
// 先更新UI状态提供即时反馈
this.isCollected = newCollectedState
const res = await setMemberCollect({
collectId: this.id,
collectType: this.type,
status: newCollectedState ? 1 : 2 ,//收藏状态不能为空 1 收藏,2 取消收藏
})
if (res) {
uni.showToast({
title: newCollectedState ? '收藏成功' : '取消收藏',
icon: 'success',
duration: 1500
})
}
} catch (error) {
console.error('收藏操作失败:', error)
// 操作失败,恢复原状态
this.isCollected = !newCollectedState
uni.showToast({
title: '操作失败,请重试',
icon: 'none',
duration: 2000
})
} finally {
this.collectLoading = false
}
}
}
}
</script>
<style lang="scss" scoped>
.detail-action-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background-color: #ffffff;
border-top: 1rpx solid #e2e8f1;
padding: 20rpx 0;
padding-bottom: calc(20rpx + env(safe-area-inset-bottom));
display: flex;
align-items: center;
justify-content: space-around;
z-index: 100;
box-shadow: 0 -2rpx 10rpx rgba(0, 0, 0, 0.05);
.action-item {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
flex: 1;
padding: 10rpx 0;
&.share-button {
background: transparent;
border: none;
outline: none;
line-height: normal;
margin: 0;
padding: 10rpx 0;
&::after {
border: none;
}
}
.action-icon {
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 8rpx;
transition: transform 0.2s;
&.active {
transform: scale(1.1);
}
.icon-text {
font-size: 48rpx;
line-height: 1;
}
}
.action-text {
font-family: PingFang-SC, PingFang-SC;
font-size: 24rpx;
color: #666666;
transition: color 0.2s;
&.active {
color: #004294;
font-weight: 500;
}
}
&:active {
opacity: 0.7;
}
}
}
</style>