创建会议修正

This commit is contained in:
2025-12-27 19:23:33 +08:00
parent 50df8495c7
commit 750c112eac
12 changed files with 448 additions and 343 deletions

View File

@@ -683,8 +683,9 @@ const subscribeToRoom = (roomId: string) => {
roomSubscription = stompClient.subscribe(`/topic/chat/${roomId}`, (message: any) => {
const chatMessage = JSON.parse(message.body) as ChatRoomMessageVO
// 避免重复添加自己发送的消息
if (chatMessage.senderId !== loginDomain.user.userId) {
// 避免重复添加自己发送的普通消息
// 但会议消息meet类型始终添加因为它是系统生成的通知
if (chatMessage.messageType === 'meet' || chatMessage.senderId !== loginDomain.user.userId) {
messages.value.push(chatMessage)
scrollToBottom()
}

View File

@@ -1,6 +1,9 @@
<template>
<!-- 消息会议卡片 -->
<div class="meeting-card" :class="`meeting-card--${meeting.status}`">
<div v-if="loading" class="meeting-card meeting-card--loading">
<div class="meeting-card-loading">加载中...</div>
</div>
<div v-else-if="meeting" class="meeting-card" :class="`meeting-card--${meeting.status}`">
<div class="meeting-card-header">
<div class="meeting-card-title">{{ meeting.meetingName }}</div>
<div class="meeting-card-status">
@@ -28,15 +31,19 @@
</ElButton>
</div>
</div>
<div v-else class="meeting-card meeting-card--error">
<div class="meeting-card-error">会议信息加载失败</div>
</div>
</template>
<script setup lang="ts">
import { ElButton, ElMessage } from 'element-plus'
import type { VideoMeetingVO } from '@/types'
import { computed, ref, onMounted, onUnmounted } from 'vue'
import { workcaseChatAPI } from '@/api/workcase'
interface Props {
meeting: VideoMeetingVO
meetingId: string
}
const props = defineProps<Props>()
@@ -44,20 +51,56 @@ const emit = defineEmits<{
join: [meetingId: string]
}>()
// 会议详情从API获取的实时数据
const meeting = ref<VideoMeetingVO | null>(null)
const loading = ref(false)
// 当前时间,每秒更新
const currentTime = ref(Date.now())
let timer: number | null = null
let timeTimer: number | null = null
let refreshTimer: number | null = null
// 获取会议详情
async function fetchMeetingInfo() {
if (!props.meetingId) return
try {
loading.value = true
const result = await workcaseChatAPI.getVideoMeetingInfo(props.meetingId)
if (result.success && result.data) {
meeting.value = result.data
console.log('[MeetingCard] 获取会议信息成功:', result.data)
} else {
console.error('[MeetingCard] 获取会议信息失败:', result.message)
}
} catch (error) {
console.error('[MeetingCard] 获取会议信息异常:', error)
} finally {
loading.value = false
}
}
onMounted(() => {
// 初始加载会议信息
fetchMeetingInfo()
// 每秒更新当前时间
timer = window.setInterval(() => {
timeTimer = window.setInterval(() => {
currentTime.value = Date.now()
}, 1000)
// 每30秒刷新会议状态
refreshTimer = window.setInterval(() => {
fetchMeetingInfo()
}, 30000)
})
onUnmounted(() => {
if (timer) {
clearInterval(timer)
if (timeTimer) {
clearInterval(timeTimer)
}
if (refreshTimer) {
clearInterval(refreshTimer)
}
})
@@ -78,24 +121,23 @@ function formatDateTime(dateStr?: string): string {
* 计算倒计时文本
*/
const countdownText = computed(() => {
const { meeting } = props
if (!meeting || !meeting.startTime || !meeting.endTime) {
if (!meeting.value || !meeting.value.startTime || !meeting.value.endTime) {
return ''
}
const advanceMinutes = meeting.advance || 0
const advanceMinutes = meeting.value.advance || 0
const now = currentTime.value
const startTime = new Date(meeting.startTime).getTime()
const endTime = new Date(meeting.endTime).getTime()
const startTime = new Date(meeting.value.startTime).getTime()
const endTime = new Date(meeting.value.endTime).getTime()
// 检查时间解析是否有效
if (isNaN(startTime) || isNaN(endTime)) {
return ''
}
const advanceTime = startTime - advanceMinutes * 60 * 1000
if (meeting.status === 'ended') {
if (meeting.value.status === 'ended') {
return '会议已结束'
}
@@ -119,7 +161,7 @@ const countdownText = computed(() => {
return '可以入会'
} else if (now < endTime) {
// 会议进行中
if (meeting.status === 'ongoing') {
if (meeting.value.status === 'ongoing') {
return '会议进行中'
} else {
return '可以入会'
@@ -134,25 +176,24 @@ const countdownText = computed(() => {
* 是否可以加入会议
*/
const canJoinMeeting = computed(() => {
const { meeting } = props
if (!meeting || !meeting.startTime || !meeting.endTime) {
if (!meeting.value || !meeting.value.startTime || !meeting.value.endTime) {
return false
}
if (meeting.status === 'ended') {
if (meeting.value.status === 'ended') {
return false
}
const advanceMinutes = meeting.advance || 0
const advanceMinutes = meeting.value.advance || 0
const now = currentTime.value
const startTime = new Date(meeting.startTime).getTime()
const endTime = new Date(meeting.endTime).getTime()
const startTime = new Date(meeting.value.startTime).getTime()
const endTime = new Date(meeting.value.endTime).getTime()
// 检查时间解析是否有效
if (isNaN(startTime) || isNaN(endTime)) {
return false
}
const advanceTime = startTime - advanceMinutes * 60 * 1000
// 在允许入会的时间窗口内(提前入会时间 ~ 结束时间)
@@ -163,8 +204,10 @@ const canJoinMeeting = computed(() => {
* 按钮文本
*/
const buttonText = computed(() => {
const { meeting } = props
if (meeting.status === 'ended') {
if (!meeting.value) {
return '加载中'
}
if (meeting.value.status === 'ended') {
return '会议已结束'
}
if (!canJoinMeeting.value) {
@@ -177,7 +220,7 @@ const buttonText = computed(() => {
* 加入会议
*/
async function handleJoinMeeting() {
if (!props.meeting.meetingId) {
if (!props.meetingId) {
ElMessage.error('会议ID不存在')
return
}
@@ -187,9 +230,9 @@ async function handleJoinMeeting() {
}
// 发出事件让父组件处理
emit('join', props.meeting.meetingId)
emit('join', props.meetingId)
}
</script>
<style scoped lang="scss">
@import './MeetingCard.scss';
@import url('./MeetingCard.scss');
</style>

View File

@@ -36,7 +36,7 @@
<div class="message-content-wrapper">
<!-- 会议消息卡片 -->
<template v-if="message.messageType === 'meet'">
<MeetingCard :meeting="getMeetingData(message.contentExtra)" @join="handleJoinMeeting" />
<MeetingCard :meetingId="getMeetingId(message.contentExtra)" @join="handleJoinMeeting" />
<div class="message-time">{{ formatTime(message.sendTime) }}</div>
</template>
@@ -186,7 +186,9 @@ const showMeetingCreate = ref(false)
// 打开创建会议对话框或直接emit事件给父组件处理
const handleStartMeeting = () => {
// emit事件给父组件让父组件处理会议逻辑
emit('start-meeting')
// emit('start-meeting')
showMeetingCreate.value = true
}
// 会议创建成功回调
@@ -322,11 +324,13 @@ const handleJoinMeeting = async (meetingId: string) => {
}
// 获取会议数据将contentExtra转换为VideoMeetingVO
function getMeetingData(contentExtra: Record<string, any> | undefined): VideoMeetingVO {
if (!contentExtra) {
return {} as VideoMeetingVO
// 从消息extra中提取meetingId
function getMeetingId(contentExtra: Record<string, any> | undefined): string {
if (!contentExtra || !contentExtra.meetingId) {
console.warn('[ChatRoom] contentExtra中没有meetingId:', contentExtra)
return ''
}
return contentExtra as VideoMeetingVO
return contentExtra.meetingId as string
}
// Markdown渲染函数