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.
165 lines
3.4 KiB
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>
|