refactor(floating-list): 重构浮动列表界面并优化交互体验
- 重构拖拽手柄样式,使用新的渐变条形设计替代原有灰色线条 - 添加图标包装器容器,统一管理菜单项图标的显示和交互 - 集成动态图标切换功能,根据静音状态显示不同图标(音量高/静音) - 更新麦克风图标为更直观的麦克风/禁用麦克风图标 - 替换控制台图标为显示器图标,提高功能识别度 - 实现静音状态响应式更新,通过 isMuted 和 isTeacherMuted 状态追踪 - 调整菜单项点击逻辑,支持静音/取消静音双向切换 - 优化菜单项样式,添加悬停缩放效果和背景过渡动画 - 改进图标容器样式,增加圆角背景和阴影效果 - 调整文字颜色和阴影,提升在半透明背景下的可读性 - 重新组织CSS类结构,提高代码可维护性和复用性
This commit is contained in:
@ -1,35 +1,42 @@
|
||||
<template>
|
||||
<div class="menu-container">
|
||||
<div
|
||||
style="box-sizing: border-box; width: 100%; padding: 10px; cursor: pointer"
|
||||
@click="toggleFold()"
|
||||
@mousedown="handleMouseDown"
|
||||
@touchstart="handleTouchStart"
|
||||
>
|
||||
<div style="width: 100%; height: 6px; background: rgba(255, 255, 255, 0.6); border-radius: 4px"></div>
|
||||
<div class="drag-handle" @click="toggleFold()" @mousedown="handleMouseDown" @touchstart="handleTouchStart">
|
||||
<div class="drag-bar"></div>
|
||||
</div>
|
||||
<div style="width: calc(100% - 12px); height: 1px; margin: 9px 10px; background: rgba(180, 180, 180, 0.6)"></div>
|
||||
<!-- 会议控制按钮 -->
|
||||
<div class="menu-item" @click="muteAllStudents()">
|
||||
<icon-mdi-volume-high class="menu-icon"></icon-mdi-volume-high>
|
||||
<span class="menu-text">全员静音</span>
|
||||
</div>
|
||||
<div class="menu-item" @click="muteTeacher()">
|
||||
<icon-mdi-microphone-off class="menu-icon"></icon-mdi-microphone-off>
|
||||
<span class="menu-text">老师静音</span>
|
||||
</div>
|
||||
<div class="menu-item" @click="endClass()">
|
||||
<icon-mdi-school class="menu-icon"></icon-mdi-school>
|
||||
<span class="menu-text">下课</span>
|
||||
</div>
|
||||
<div class="menu-item" @click="openConsole()">
|
||||
<icon-mdi-console class="menu-icon"></icon-mdi-console>
|
||||
<span class="menu-text">控制台</span>
|
||||
<div class="menu-list">
|
||||
<!-- 会议控制按钮 -->
|
||||
<div class="menu-item" @click="muteAllStudents()">
|
||||
<div class="icon-wrapper">
|
||||
<icon-mdi-volume-high v-if="!isMuted" class="menu-icon"></icon-mdi-volume-high>
|
||||
<icon-mdi-volume-off v-else class="menu-icon muted"></icon-mdi-volume-off>
|
||||
</div>
|
||||
<span class="menu-text">全员静音</span>
|
||||
</div>
|
||||
<div class="menu-item" @click="muteTeacher()">
|
||||
<div class="icon-wrapper">
|
||||
<icon-mdi-microphone v-if="!isTeacherMuted" class="menu-icon"></icon-mdi-microphone>
|
||||
<icon-mdi-microphone-off v-else class="menu-icon muted"></icon-mdi-microphone-off>
|
||||
</div>
|
||||
<span class="menu-text">老师静音</span>
|
||||
</div>
|
||||
<div class="menu-item" @click="endClass()">
|
||||
<div class="icon-wrapper">
|
||||
<icon-mdi-school class="menu-icon"></icon-mdi-school>
|
||||
</div>
|
||||
<span class="menu-text">下课</span>
|
||||
</div>
|
||||
<div class="menu-item" @click="openConsole()">
|
||||
<div class="icon-wrapper">
|
||||
<icon-mdi-monitor class="menu-icon"></icon-mdi-monitor>
|
||||
</div>
|
||||
<span class="menu-text">控制台</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { emitTo } from '@tauri-apps/api/event';
|
||||
import { windowLabel } from '@/utils/tauri/windows-util';
|
||||
import { handleMouseDown, handleTouchStart } from '../move-window';
|
||||
@ -39,11 +46,19 @@
|
||||
|
||||
// 导入图标组件
|
||||
import IconMdiVolumeHigh from '~icons/mdi/volume-high';
|
||||
import IconMdiVolumeOff from '~icons/mdi/volume-off';
|
||||
import IconMdiMicrophone from '~icons/mdi/microphone';
|
||||
import IconMdiMicrophoneOff from '~icons/mdi/microphone-off';
|
||||
import IconMdiSchool from '~icons/mdi/school';
|
||||
import IconMdiConsole from '~icons/mdi/console';
|
||||
import IconMdiMonitor from '~icons/mdi/monitor';
|
||||
|
||||
const isFold = defineModel<boolean>();
|
||||
|
||||
/** 全员静音状态 */
|
||||
const isMuted = ref(false);
|
||||
/** 老师静音状态 */
|
||||
const isTeacherMuted = ref(false);
|
||||
|
||||
/**
|
||||
* 切换折叠状态
|
||||
*/
|
||||
@ -55,9 +70,10 @@
|
||||
*/
|
||||
function muteAllStudents() {
|
||||
playPromptTone();
|
||||
isMuted.value = !isMuted.value;
|
||||
// 发送事件给主窗口,让主窗口的 socket 处理
|
||||
emitTo(windowLabel.main, 'meeting-control', {
|
||||
action: 'mute_all_students',
|
||||
action: isMuted.value ? 'mute_all_students' : 'unmute_all_students',
|
||||
});
|
||||
}
|
||||
|
||||
@ -66,9 +82,10 @@
|
||||
*/
|
||||
function muteTeacher() {
|
||||
playPromptTone();
|
||||
isTeacherMuted.value = !isTeacherMuted.value;
|
||||
// 发送事件给主窗口,让主窗口的 socket 处理
|
||||
emitTo(windowLabel.main, 'meeting-control', {
|
||||
action: 'mute_teacher',
|
||||
action: isTeacherMuted.value ? 'mute_teacher' : 'unmute_teacher',
|
||||
});
|
||||
}
|
||||
|
||||
@ -107,73 +124,122 @@
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.time-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 10px;
|
||||
|
||||
.time-box {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-bottom: 2px;
|
||||
line-height: 1;
|
||||
|
||||
.time-text {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
text-shadow:
|
||||
1px 1px 2px #000000,
|
||||
0 0 4px #000000;
|
||||
}
|
||||
|
||||
.time-unit {
|
||||
margin-left: 2px;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
text-shadow:
|
||||
1px 1px 2px #000000,
|
||||
0 0 4px #000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-container {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
padding: 10px 0;
|
||||
padding: 4px 0;
|
||||
overflow: hidden;
|
||||
background: rgba(0, 0, 0, 0.2);
|
||||
border-radius: 6px;
|
||||
border-radius: 8px;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.menu-container .menu-item {
|
||||
/** 拖动区域 */
|
||||
.drag-handle {
|
||||
width: 100%;
|
||||
padding: 8px 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: background 0.2s;
|
||||
|
||||
.drag-bar {
|
||||
width: 32px;
|
||||
height: 4px;
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.3));
|
||||
border-radius: 2px;
|
||||
transition: all 0.3s;
|
||||
}
|
||||
|
||||
&:hover .drag-bar {
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.7), rgba(255, 255, 255, 0.5));
|
||||
}
|
||||
}
|
||||
.menu-list {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/** 菜单项 */
|
||||
.menu-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.icon-wrapper {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-bottom: 4px;
|
||||
border-radius: 8px;
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
transition: all 0.3s;
|
||||
|
||||
.menu-item:hover & {
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: #e0e0e0;
|
||||
transition: all 0.3s;
|
||||
|
||||
&.muted {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-text {
|
||||
font-size: 11px;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
font-weight: 500;
|
||||
letter-spacing: 0.5px;
|
||||
text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
font-size: 9px;
|
||||
color: #ff6b6b;
|
||||
margin-top: 2px;
|
||||
font-weight: 600;
|
||||
animation: fadeIn 0.3s ease;
|
||||
}
|
||||
}
|
||||
|
||||
.menu-container .menu-item .menu-icon {
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
color: #ffffff; // 白色图标,与深色背景形成对比
|
||||
}
|
||||
|
||||
.menu-container .menu-item .menu-text {
|
||||
font-size: 12px;
|
||||
color: #ffffff; // 白色文字
|
||||
text-shadow: 2px 2px 4px #000000;
|
||||
/** 淡入动画 */
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-4px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user