fix(phase2e-2): 会议内聊天面板 UI 布局优化
问题修复: - 原遮罩式抽屉覆盖底部 toolbar,导致按钮不可点击 - 发送按钮过小不显眼 - 聊天面板打开时视频区被遮挡出现大片空白 改进: - room.vue 主区改为 flex-row 布局:视频列 + 聊天列并排,聊天打开时视频自动收窄 - ChatPanel 去除全屏遮罩,作为侧边栏嵌入 chat-col,保留过渡动画 - 发送按钮增加纸飞机图标并采用渐变背景,hover / active / disabled 状态清晰 - msg-list 使用 flex:1 + min-height:0 + height:0 修复 scroll-view 高度撑破问题,保证输入区始终固定在底部 - 小屏(<750px)自动回退为全屏浮层,避免挤压视频 Made-with: Cursor
This commit is contained in:
@@ -11,8 +11,7 @@
|
|||||||
- 发送通过 @send 事件回传,成功/失败由父层决定是否 toast
|
- 发送通过 @send 事件回传,成功/失败由父层决定是否 toast
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<view v-if="visible" class="panel-root" @click.self="close">
|
<view v-if="visible" class="panel" :class="{ show }">
|
||||||
<view class="panel" :class="{ show }">
|
|
||||||
<view class="header">
|
<view class="header">
|
||||||
<view class="title-area">
|
<view class="title-area">
|
||||||
<text class="title">会议聊天</text>
|
<text class="title">会议聊天</text>
|
||||||
@@ -81,13 +80,16 @@
|
|||||||
@input="onDraftInput"
|
@input="onDraftInput"
|
||||||
@confirm="onSend"
|
@confirm="onSend"
|
||||||
/>
|
/>
|
||||||
<button class="btn-send" :disabled="!canSend || sending" @click="onSend">
|
<button class="btn-send" :disabled="!canSend || sending" :class="{ active: canSend && !sending }" @click="onSend">
|
||||||
<text v-if="!sending">发送</text>
|
<svg v-if="!sending" viewBox="0 0 24 24" width="22" height="22" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<text v-else>发送中</text>
|
<line x1="22" y1="2" x2="11" y2="13"></line>
|
||||||
|
<polygon points="22 2 15 22 11 13 2 9 22 2"></polygon>
|
||||||
|
</svg>
|
||||||
|
<text v-if="!sending" class="btn-send-label">发送</text>
|
||||||
|
<text v-else class="btn-send-label">发送中</text>
|
||||||
</button>
|
</button>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
@@ -222,28 +224,15 @@ const close = () => emit('close')
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.panel-root {
|
/* 面板作为并排侧边栏:父容器 .chat-col 控制宽度/显隐动画 */
|
||||||
position: fixed;
|
|
||||||
inset: 0;
|
|
||||||
z-index: 205;
|
|
||||||
background: rgba(0, 0, 0, 0.45);
|
|
||||||
display: flex;
|
|
||||||
justify-content: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.panel {
|
.panel {
|
||||||
width: 640rpx;
|
width: 100%;
|
||||||
max-width: 92vw;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background: #1F2937;
|
background: #1F2937;
|
||||||
color: #F3F4F6;
|
color: #F3F4F6;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
transform: translateX(100%);
|
|
||||||
transition: transform 0.24s ease;
|
|
||||||
box-shadow: -4rpx 0 24rpx rgba(0, 0, 0, 0.4);
|
|
||||||
}
|
}
|
||||||
.panel.show { transform: translateX(0); }
|
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@@ -269,7 +258,9 @@ const close = () => emit('close')
|
|||||||
.btn-close:hover { background: rgba(255, 255, 255, 0.08); }
|
.btn-close:hover { background: rgba(255, 255, 255, 0.08); }
|
||||||
|
|
||||||
.msg-list {
|
.msg-list {
|
||||||
flex: 1;
|
flex: 1 1 0;
|
||||||
|
min-height: 0;
|
||||||
|
height: 0;
|
||||||
padding: 16rpx 24rpx 24rpx;
|
padding: 16rpx 24rpx 24rpx;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
@@ -284,10 +275,14 @@ const close = () => emit('close')
|
|||||||
.load-more:hover { color: rgba(255, 255, 255, 0.8); }
|
.load-more:hover { color: rgba(255, 255, 255, 0.8); }
|
||||||
|
|
||||||
.empty {
|
.empty {
|
||||||
padding: 100rpx 0 80rpx;
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: rgba(255, 255, 255, 0.45);
|
color: rgba(255, 255, 255, 0.45);
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
|
padding: 40rpx 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.msg-row {
|
.msg-row {
|
||||||
@@ -382,18 +377,30 @@ const close = () => emit('close')
|
|||||||
.btn-send {
|
.btn-send {
|
||||||
all: unset;
|
all: unset;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
padding: 14rpx 28rpx;
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 8rpx;
|
||||||
|
padding: 16rpx 28rpx;
|
||||||
background: #3B82F6;
|
background: #3B82F6;
|
||||||
color: #FFFFFF;
|
color: #FFFFFF;
|
||||||
font-size: 26rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
border-radius: 14rpx;
|
border-radius: 14rpx;
|
||||||
transition: background-color 0.15s ease;
|
box-shadow: 0 4rpx 14rpx rgba(59, 130, 246, 0.35);
|
||||||
|
transition: background-color 0.15s ease, transform 0.08s ease, box-shadow 0.15s ease;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
|
min-height: 64rpx;
|
||||||
}
|
}
|
||||||
|
.btn-send svg { display: block; }
|
||||||
|
.btn-send .btn-send-label { font-size: 26rpx; font-weight: 600; }
|
||||||
.btn-send:hover { background: #2563EB; }
|
.btn-send:hover { background: #2563EB; }
|
||||||
|
.btn-send:active { transform: translateY(1rpx); }
|
||||||
.btn-send[disabled] {
|
.btn-send[disabled] {
|
||||||
background: rgba(59, 130, 246, 0.35);
|
background: rgba(59, 130, 246, 0.28);
|
||||||
|
color: rgba(255, 255, 255, 0.55);
|
||||||
|
box-shadow: none;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
.btn-send.active {
|
||||||
|
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -34,8 +34,9 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 视频网格 -->
|
<!-- 主区:左视频 + 右侧聊天面板(仅 chatVisible 时侧栏展开) -->
|
||||||
<view class="body">
|
<view class="body">
|
||||||
|
<view class="video-col">
|
||||||
<VideoGrid :tiles="tiles">
|
<VideoGrid :tiles="tiles">
|
||||||
<template #tile="{ tile }">
|
<template #tile="{ tile }">
|
||||||
<VideoTile
|
<VideoTile
|
||||||
@@ -51,6 +52,21 @@
|
|||||||
</template>
|
</template>
|
||||||
</VideoGrid>
|
</VideoGrid>
|
||||||
</view>
|
</view>
|
||||||
|
<view class="chat-col" :class="{ open: chatVisible }">
|
||||||
|
<ChatPanel
|
||||||
|
:visible="chatVisible"
|
||||||
|
:messages="chatMessages"
|
||||||
|
:current-user-id="myUserId"
|
||||||
|
:display-name-map="displayNameMap"
|
||||||
|
:has-more="chatHasMore"
|
||||||
|
:loading-more="chatLoadingMore"
|
||||||
|
@close="closeChat"
|
||||||
|
@send="onChatSend"
|
||||||
|
@load-more="onChatLoadMore"
|
||||||
|
@request-initial-load="onChatRequestInitialLoad"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<!-- 底部工具条 -->
|
<!-- 底部工具条 -->
|
||||||
<MeetingToolbar
|
<MeetingToolbar
|
||||||
@@ -92,20 +108,6 @@
|
|||||||
@close="inviteVisible = false"
|
@close="inviteVisible = false"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<!-- 聊天面板 -->
|
|
||||||
<ChatPanel
|
|
||||||
:visible="chatVisible"
|
|
||||||
:messages="chatMessages"
|
|
||||||
:current-user-id="myUserId"
|
|
||||||
:display-name-map="displayNameMap"
|
|
||||||
:has-more="chatHasMore"
|
|
||||||
:loading-more="chatLoadingMore"
|
|
||||||
@close="closeChat"
|
|
||||||
@send="onChatSend"
|
|
||||||
@load-more="onChatLoadMore"
|
|
||||||
@request-initial-load="onChatRequestInitialLoad"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 离会确认弹窗 -->
|
<!-- 离会确认弹窗 -->
|
||||||
<view v-if="leaveDialogVisible" class="leave-mask" @click.self="leaveDialogVisible = false">
|
<view v-if="leaveDialogVisible" class="leave-mask" @click.self="leaveDialogVisible = false">
|
||||||
<view class="leave-modal">
|
<view class="leave-modal">
|
||||||
@@ -633,6 +635,31 @@ onUnload(() => {
|
|||||||
min-height: 0;
|
min-height: 0;
|
||||||
background: #0B1220;
|
background: #0B1220;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.video-col {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
display: flex;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.chat-col {
|
||||||
|
width: 0;
|
||||||
|
min-height: 0;
|
||||||
|
flex-shrink: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
transition: width 0.24s ease;
|
||||||
|
border-left: 1rpx solid rgba(255, 255, 255, 0.06);
|
||||||
|
background: #1F2937;
|
||||||
|
}
|
||||||
|
.chat-col.open { width: 640rpx; }
|
||||||
|
|
||||||
|
@media (max-width: 750px) {
|
||||||
|
/* 小屏幕:聊天面板改为全屏浮层,避免挤压视频 */
|
||||||
|
.chat-col { position: fixed; top: 0; right: 0; bottom: 0; z-index: 205; }
|
||||||
|
.chat-col.open { width: 100vw; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 离会弹窗 */
|
/* 离会弹窗 */
|
||||||
|
|||||||
Reference in New Issue
Block a user