You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
besure_app/src/components/dashboard/ModeSwitchPopup.vue

165 lines
3.4 KiB
Vue

<template>
<view>
<view class="mode-switch-btn" @click="openPopup">
<uni-icons type="settings" size="28" color="#1a3a5c" />
</view>
<view v-if="showModePopup" class="popup-overlay" @click="showModePopup = false">
<view
class="popup-content"
:class="{ 'popup-enter': showModePopup }"
:style="{ top: popupTop + 'px', right: popupRight + 'px' }"
@click.stop
>
<view
class="popup-item"
:class="{ active: currentMode === 'production' }"
@click="switchMode('production')"
>
<text class="popup-icon">📋</text>
<text class="popup-text">{{ t('dashboard.production') }}</text>
</view>
<view
class="popup-item"
:class="{ active: currentMode === 'quality' }"
@click="switchMode('quality')"
>
<text class="popup-icon">🛡️</text>
<text class="popup-text">{{ t('dashboard.quality') }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
import { getCurrentInstance } from 'vue'
const { t } = useI18n()
const instance = getCurrentInstance()
const props = defineProps({
currentMode: {
type: String,
default: 'production'
}
})
const emit = defineEmits(['modeChange'])
const showModePopup = ref(false)
const popupTop = ref(0)
const popupRight = ref(0)
function openPopup() {
const query = uni.createSelectorQuery().in(instance.proxy)
query.select('.mode-switch-btn').boundingClientRect((rect) => {
if (rect) {
const { windowWidth } = uni.getSystemInfoSync()
popupTop.value = rect.bottom + 8
popupRight.value = windowWidth - rect.right
}
showModePopup.value = true
}).exec()
}
function switchMode(mode) {
showModePopup.value = false
emit('modeChange', mode)
}
</script>
<style lang="scss" scoped>
.mode-switch-btn {
width: 64rpx;
height: 64rpx;
// background: linear-gradient(135deg, #1a3a5c 0%, #2d5a87 100%);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
// box-shadow: 0 4rpx 12rpx rgba(26, 58, 92, 0.3);
&:active {
transform: scale(0.95);
}
}
.popup-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
animation: overlayFadeIn 0.25s ease-out;
}
.popup-content {
position: fixed;
width: 200rpx;
background: linear-gradient(180deg, #1a3a5c 0%, #2d5a87 100%);
border-radius: 16rpx;
overflow: hidden;
box-shadow: 0 8rpx 32rpx rgba(26, 58, 92, 0.4);
transform-origin: top right;
&.popup-enter {
animation: popupSlideIn 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
}
@keyframes overlayFadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes popupSlideIn {
from {
opacity: 0;
transform: scale(0.6) translateY(-20rpx);
}
to {
opacity: 1;
transform: scale(1) translateY(0);
}
}
.popup-item {
display: flex;
align-items: center;
padding: 24rpx 20rpx;
justify-content: center;
gap: 12rpx;
&:active {
background: rgba(255, 255, 255, 0.1);
}
&.active {
background: rgba(255, 255, 255, 0.2);
}
&:not(:last-child) {
border-bottom: 1rpx solid rgba(255, 255, 255, 0.1);
}
}
.popup-icon {
font-size: 36rpx;
}
.popup-text {
font-size: 28rpx;
color: #ffffff;
font-weight: 500;
}
</style>