consumer-app/components/DetailActionBar/DetailActionBar.vue

289 lines
6.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<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"
:class="{ active: isLiked }"
:src="isLiked ? '/static/service/like_icon_active.png' : '/static/service/like_icon.png'"
mode="aspectFill"
></image>
<text class="action-text" :class="{ active: isLiked }">点赞</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"
:class="{ active: isCollected }"
:src="isCollected ? '/static/service/collect_icon_active.png' : '/static/service/collect_icon.png'"
mode="aspectFill"
></image>
<text class="action-text" :class="{ active: isCollected }">收藏</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);
}
}
.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>