美化样式
This commit is contained in:
@ -291,10 +291,10 @@ export class MeetingWebSocketGateway implements OnGatewayConnection, OnGatewayDi
|
||||
const validSocketIds: string[] = [];
|
||||
for (const result of validationResults) {
|
||||
if (result.isValid && result.sockets) {
|
||||
this.server?.to(result.oldSocketId).emit('message', {
|
||||
type: 'sev_device_conflict',
|
||||
data: { fromRoomId: roomId, reason: '您已在其他设备进入相同入口', targetUid: shortUid },
|
||||
} satisfies SucceedMessage);
|
||||
// this.server?.to(result.oldSocketId).emit('message', {
|
||||
// type: 'sev_device_conflict',
|
||||
// data: { fromRoomId: roomId, reason: '您已在其他设备进入相同入口', targetUid: shortUid },
|
||||
// } satisfies SucceedMessage);
|
||||
result.sockets.forEach((s) => s.disconnect(true));
|
||||
validSocketIds.push(result.oldSocketId);
|
||||
}
|
||||
|
||||
@ -1,12 +1,4 @@
|
||||
/**
|
||||
* 统一按钮样式规范
|
||||
* 适用于项目中所有的按钮组件
|
||||
*/
|
||||
|
||||
/* ========================================
|
||||
会议室控制栏按钮 (.control-btn)
|
||||
用于底部控制栏的功能按钮(上课/下课、静音、视频等)
|
||||
======================================== */
|
||||
// 会议室控制栏按钮 (.control-btn) 用于底部控制栏的功能按钮(上课/下课、静音、视频等)
|
||||
.control-btn {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@ -19,12 +11,11 @@
|
||||
line-height: 1.5;
|
||||
color: var(--el-color-primary);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
border: 1px solid var(--el-color-primary-light-7);
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s ease;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
svg {
|
||||
width: 24px;
|
||||
@ -90,8 +81,8 @@
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background: linear-gradient(135deg, #5568d3 0%, #63408a 100%);
|
||||
transform: translateY(-3px);
|
||||
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
@ -100,12 +91,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
视频用户控制按钮 (.control-icon-btn)
|
||||
用于视频卡片右上角的图标按钮(设为主讲、禁麦、禁视频、踢人等)
|
||||
======================================== */
|
||||
// 视频用户控制按钮 (.control-icon-btn) 用于视频卡片右上角的图标按钮(设为主讲、禁麦、禁视频、踢人等)
|
||||
.control-icon-btn {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 32px;
|
||||
@ -113,13 +102,11 @@
|
||||
padding: 0;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background: rgba(0, 0, 0, 0.6);
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
transition: all 0.3s ease;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 18px;
|
||||
@ -177,24 +164,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
窗口控制按钮 (.operating-button)
|
||||
用于窗口标题栏的控制按钮(最小化、最大化、关闭、返回等)
|
||||
======================================== */
|
||||
// 窗口控制按钮 (.operating-button) 用于窗口标题栏的控制按钮(最小化、最大化、关闭、返回等)
|
||||
.operating-button {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
margin-right: 15px;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background-color: var(--button-bg);
|
||||
border-radius: 50%;
|
||||
transition: all 0.2s ease;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
flex-shrink: 0;
|
||||
|
||||
svg {
|
||||
width: 12px;
|
||||
@ -203,8 +186,8 @@
|
||||
}
|
||||
|
||||
&:hover {
|
||||
transform: scale(1.15);
|
||||
filter: brightness(1.1);
|
||||
transform: scale(1.15);
|
||||
}
|
||||
|
||||
&:active {
|
||||
@ -244,62 +227,53 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
Element Plus 按钮覆盖样式
|
||||
用于登录页面等使用 el-button 的场景
|
||||
======================================== */
|
||||
.el-button {
|
||||
&.login-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
background: linear-gradient(93deg, #74e8ff 0%, #306fff 100%);
|
||||
border: transparent;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
// Element Plus 按钮覆盖样式 用于登录页面等使用 el-button 的场景
|
||||
.el-button.login-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
background: linear-gradient(93deg, #74e8ff 0%, #306fff 100%);
|
||||
border: transparent;
|
||||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover:not(:disabled) {
|
||||
background: linear-gradient(93deg, #5dd6ff 0%, #2560e8 100%);
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 4px 16px 0 rgba(48, 111, 255, 0.3);
|
||||
}
|
||||
&:hover:not(:disabled) {
|
||||
background: linear-gradient(93deg, #5dd6ff 0%, #2560e8 100%);
|
||||
box-shadow: 0 4px 16px 0 rgba(48, 111, 255, 0.3);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
&:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
}
|
||||
&:active:not(:disabled) {
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
&:disabled {
|
||||
opacity: 0.6;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
&:disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
黑名单解除按钮 (.remove-btn)
|
||||
用于黑名单列表中的解除按钮
|
||||
======================================== */
|
||||
// 黑名单解除按钮 (.remove-btn) 用于黑名单列表中的解除按钮
|
||||
.remove-btn {
|
||||
padding: 4px 12px;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, #5568d3 0%, #63408a 100%);
|
||||
transform: translateY(-1px);
|
||||
box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
|
||||
transform: translateY(-1px);
|
||||
}
|
||||
|
||||
&:active {
|
||||
@ -307,9 +281,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* ========================================
|
||||
响应式适配
|
||||
======================================== */
|
||||
// 响应式适配
|
||||
@media (max-width: 768px) {
|
||||
.control-btn {
|
||||
min-width: 56px;
|
||||
|
||||
@ -564,7 +564,7 @@
|
||||
.loading-text {
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
color: #999;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -149,14 +149,28 @@
|
||||
<span class="btn-text">离开</span>
|
||||
</button>
|
||||
</div>
|
||||
<el-drawer v-model="blacklistVisible" title="黑名单" size="30%">
|
||||
<div v-if="blacklist.length === 0" class="empty">暂无黑名单</div>
|
||||
<ul v-else class="blacklist">
|
||||
<li v-for="item in blacklist" :key="item.shortUid" class="blacklist-item">
|
||||
<span class="user-info">{{ item.userName }} (ID: {{ item.shortUid }})</span>
|
||||
<button class="remove-btn" @click="removeFromBlacklist(item.shortUid)">解除</button>
|
||||
</li>
|
||||
</ul>
|
||||
<el-drawer v-model="blacklistVisible" title="黑名单" size="30%" closeOnClickModal>
|
||||
<div v-if="blacklist.length === 0" class="empty">
|
||||
<icon-mdi-account-off class="empty-icon"></icon-mdi-account-off>
|
||||
<span class="empty-text">暂无黑名单</span>
|
||||
</div>
|
||||
<el-scrollbar v-else class="blacklist-scrollbar">
|
||||
<ul class="blacklist">
|
||||
<li v-for="item in blacklist" :key="item.shortUid" class="blacklist-item">
|
||||
<div class="user-avatar">
|
||||
<icon-mdi-account class="avatar-icon"></icon-mdi-account>
|
||||
</div>
|
||||
<div class="user-details">
|
||||
<span class="user-name">{{ item.userName }}</span>
|
||||
<span class="user-id">ID: {{ item.shortUid }}</span>
|
||||
</div>
|
||||
<button class="remove-btn" @click="removeFromBlacklist(item.shortUid)">
|
||||
<icon-mdi-delete class="remove-icon"></icon-mdi-delete>
|
||||
<span>解除</span>
|
||||
</button>
|
||||
</li>
|
||||
</ul>
|
||||
</el-scrollbar>
|
||||
</el-drawer>
|
||||
<!-- 学生列表排序弹窗 -->
|
||||
<student-sort-dialog v-model="studentSortDialogVisible" :roomId="courseRoomId" :students="studentListForSort"></student-sort-dialog>
|
||||
@ -168,6 +182,8 @@
|
||||
import { playPromptTone } from '@/utils/prompt-tone';
|
||||
import { useResizeObserver } from '@vueuse/core';
|
||||
import IconMdiAccount from '~icons/mdi/account';
|
||||
import IconMdiAccountOff from '~icons/mdi/account-off';
|
||||
import IconMdiDelete from '~icons/mdi/delete';
|
||||
import IconMdiExitToApp from '~icons/mdi/exit-to-app';
|
||||
import IconMdiLoading from '~icons/mdi/loading';
|
||||
import IconMdiMicrophone from '~icons/mdi/microphone';
|
||||
@ -1078,7 +1094,7 @@
|
||||
.loading-text {
|
||||
margin-top: 20px;
|
||||
font-size: 16px;
|
||||
color: #999;
|
||||
color: #999999;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1397,4 +1413,142 @@
|
||||
|
||||
// 使用统一按钮样式,移除重复的 .control-btn 定义
|
||||
}
|
||||
|
||||
// 黑名单抽屉样式
|
||||
:deep(.el-drawer__header) {
|
||||
padding-bottom: 16px;
|
||||
margin-bottom: 16px;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
|
||||
.el-drawer__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
}
|
||||
|
||||
:deep(.el-drawer__body) {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 60px 20px;
|
||||
color: #909399;
|
||||
|
||||
.empty-icon {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin-bottom: 16px;
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.blacklist-scrollbar {
|
||||
max-height: calc(100vh - 120px);
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.blacklist {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
list-style: none;
|
||||
|
||||
.blacklist-item {
|
||||
display: flex;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #e4e7ed;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
|
||||
transition: all 0.3s ease;
|
||||
|
||||
&:hover {
|
||||
background: #f5f7fa;
|
||||
border-color: #667eea;
|
||||
box-shadow: 0 4px 16px rgba(102, 126, 234, 0.2);
|
||||
transform: translateX(4px);
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
border-radius: 50%;
|
||||
|
||||
.avatar-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.user-details {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
|
||||
.user-name {
|
||||
overflow: hidden;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
color: #303133;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.user-id {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
}
|
||||
|
||||
.remove-btn {
|
||||
display: flex;
|
||||
gap: 4px;
|
||||
align-items: center;
|
||||
padding: 6px 12px;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
background: linear-gradient(135deg, #f56c6c 0%, #e74c3c 100%);
|
||||
border: none;
|
||||
border-radius: 6px;
|
||||
transition: all 0.3s ease;
|
||||
|
||||
.remove-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%);
|
||||
box-shadow: 0 4px 12px rgba(245, 108, 108, 0.4);
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -109,8 +109,8 @@
|
||||
|
||||
<style scoped lang="scss">
|
||||
.student-sort-container {
|
||||
padding: 10px 0;
|
||||
position: relative;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.slick-list {
|
||||
@ -123,16 +123,17 @@
|
||||
align-items: center;
|
||||
padding: 12px 16px;
|
||||
margin-bottom: 8px;
|
||||
background: #f5f7fa;
|
||||
border-radius: 8px;
|
||||
cursor: move;
|
||||
border: 2px solid transparent;
|
||||
user-select: none;
|
||||
background: #f5f7fa;
|
||||
border: 1px solid #409eff;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 6px 16px rgba(54, 137, 246, 0.12);
|
||||
|
||||
.drag-handle {
|
||||
margin-right: 12px;
|
||||
font-size: 20px;
|
||||
color: #909399;
|
||||
margin-right: 12px;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
@ -142,12 +143,12 @@
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
background: #409eff;
|
||||
color: #fff;
|
||||
border-radius: 50%;
|
||||
font-weight: bold;
|
||||
margin-right: 12px;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #ffffff;
|
||||
background: #409eff;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.student-name {
|
||||
@ -164,7 +165,7 @@
|
||||
|
||||
.dialog-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 16px;
|
||||
justify-content: center;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user