more-button.vue 3.24 KB
<template>
    <view class="more-actions">
        <!-- 点击按钮 -->
        <view class="trigger-btn" @click="toggleMenu" hover-class="btn-hover">
            <uni-icons type="more" size="28" color="#999" />
        </view>

        <!-- 手写下拉菜单 -->
        <view class="dropdown-menu" :class="{ show: showMenu }">
            <view class="menu-item" @click="handleNote">文字备注</view>
            <view class="menu-item" @click="handleVideoNote">视频备注</view>
            <view class="menu-item" @click="handleRest">组间休息</view>
            <view class="menu-item" @click="handleReplace">动作替换</view>
            <view class="menu-item danger" @click="handleDelete">删除动作</view>
        </view>
    </view>
</template>

<script setup>
import { ref, onMounted, onUnmounted } from 'vue'

const props = defineProps({
    exerciseId: [String, Number],
})

const showMenu = ref(false)

// 切换菜单显示
const toggleMenu = (e) => {
    e.stopPropagation() // 关键:阻止事件冒泡,防止document事件触发
    showMenu.value = !showMenu.value
}

// 点击页面其他地方关闭菜单
const closeMenu = (e) => {
    showMenu.value = false
}

// 注册/移除点击事件(修复:用uni的API,不要用原生document)
onMounted(() => {
    // uni-app 小程序不支持 document,用 uni.$on 或者自定义事件
    // 这里改用更安全的方式:页面点击时关闭
    uni.$on('page-click', closeMenu)
})
onUnmounted(() => {
    uni.$off('page-click', closeMenu)
})


// 菜单事件
const handleNote = () => {
    uni.showToast({ title: '文字备注', icon: 'none' })
    showMenu.value = false
}
const handleVideoNote = () => {
    uni.showToast({ title: '视频备注', icon: 'none' })
    showMenu.value = false
}
const handleRest = () => {
    uni.showToast({ title: '组间休息', icon: 'none' })
    showMenu.value = false
}
const handleReplace = () => {
    uni.showToast({ title: '动作替换', icon: 'none' })
    showMenu.value = false
}
const handleDelete = () => {
    uni.showModal({
        title: '确认删除',
        content: '确定要删除该动作吗?',
        success: (res) => {
            if (res.confirm) {
                uni.showToast({ title: '已删除' })
            }
            showMenu.value = false // 不管确认还是取消,都关闭菜单
        }
    })
}
</script>

<style scoped lang="scss">
.more-actions {
    position: relative;
    display: inline-block;
    margin-left: 10rpx;
    z-index: 1;
}

.trigger-btn {
    width: 60rpx;
    height: 60rpx;
    border-radius: 50%;
    border: 1rpx solid #dcdcdc;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.btn-hover {
    background-color: #eee;
}

/* 下拉菜单核心样式 */
.dropdown-menu {
    position: absolute;
    top: 70rpx;
    right: 0;
    background: #fff;
    border-radius: 10rpx;
    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.15);
    min-width: 200rpx;
    display: none;
    overflow: hidden;
}

.dropdown-menu.show {
    display: block;
}

.menu-item {
    padding: 24rpx 32rpx;
    font-size: 28rpx;
    color: #333;
    border-bottom: 1rpx solid #f0f0f0;
}

.menu-item:last-child {
    border-bottom: none;
}

.menu-item.danger {
    color: #ff4444;
}
</style>