创建会议修正
This commit is contained in:
@@ -1,6 +1,9 @@
|
||||
<template>
|
||||
<!-- 消息会议卡片 -->
|
||||
<view :class="['meeting-card', meeting.status ? `meeting-card--${meeting.status}` : '']">
|
||||
<view v-if="loading" class="meeting-card meeting-card--loading">
|
||||
<text class="meeting-card-loading">加载中...</text>
|
||||
</view>
|
||||
<view v-else-if="meeting" :class="['meeting-card', meeting.status ? `meeting-card--${meeting.status}` : '']">
|
||||
<view class="meeting-card-header">
|
||||
<view class="meeting-card-title">{{ meeting.meetingName || '未命名会议' }}</view>
|
||||
<view class="meeting-card-status">
|
||||
@@ -29,36 +32,76 @@
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="meeting-card meeting-card--error">
|
||||
<text class="meeting-card-error">会议信息加载失败</text>
|
||||
</view>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import type { VideoMeetingVO } from '../../../types/workcase/chatRoom'
|
||||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||||
import { workcaseChatAPI } from '../../../api/workcase'
|
||||
|
||||
interface Props {
|
||||
meeting: VideoMeetingVO
|
||||
meetingId: string
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
console.log("meeting", JSON.stringify(props.meeting))
|
||||
const emit = defineEmits<{
|
||||
join: [meetingId: string]
|
||||
}>()
|
||||
|
||||
// 会议详情(从API获取的实时数据)
|
||||
const meeting = ref<VideoMeetingVO | null>(null)
|
||||
const loading = ref(false)
|
||||
|
||||
// 当前时间,每秒更新
|
||||
const currentTime = ref(Date.now())
|
||||
let timer: ReturnType<typeof setInterval> | null = null
|
||||
let timeTimer: ReturnType<typeof setInterval> | null = null
|
||||
let refreshTimer: ReturnType<typeof setInterval> | null = null
|
||||
|
||||
// 获取会议详情
|
||||
async function fetchMeetingInfo() {
|
||||
if (!props.meetingId) return
|
||||
|
||||
try {
|
||||
loading.value = true
|
||||
const result = await workcaseChatAPI.getMeetingInfo(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 = setInterval(() => {
|
||||
timeTimer = setInterval(() => {
|
||||
currentTime.value = Date.now()
|
||||
}, 1000)
|
||||
|
||||
// 每30秒刷新会议状态
|
||||
refreshTimer = setInterval(() => {
|
||||
fetchMeetingInfo()
|
||||
}, 30000)
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
if (timer !== null) {
|
||||
clearInterval(timer)
|
||||
timer = null
|
||||
if (timeTimer !== null) {
|
||||
clearInterval(timeTimer)
|
||||
timeTimer = null
|
||||
}
|
||||
if (refreshTimer !== null) {
|
||||
clearInterval(refreshTimer)
|
||||
refreshTimer = null
|
||||
}
|
||||
})
|
||||
|
||||
@@ -82,32 +125,26 @@ function formatDateTime(dateStr?: string): string {
|
||||
* 计算倒计时文本
|
||||
*/
|
||||
const countdownText = computed((): string => {
|
||||
const meeting = props.meeting
|
||||
if (!meeting) {
|
||||
if (!meeting.value || !meeting.value.startTime || !meeting.value.endTime) {
|
||||
return ''
|
||||
}
|
||||
|
||||
// 检查必要字段
|
||||
if (!meeting.startTime || !meeting.endTime) {
|
||||
return ''
|
||||
}
|
||||
|
||||
|
||||
// advance 默认为 0
|
||||
const advanceMinutes = meeting.advance || 0
|
||||
const advanceMinutes = meeting.value.advance || 0
|
||||
|
||||
const now = currentTime.value
|
||||
// iOS和小程序兼容性处理
|
||||
const startTime = new Date(meeting.startTime.replace(' ', 'T')).getTime()
|
||||
const endTime = new Date(meeting.endTime.replace(' ', 'T')).getTime()
|
||||
|
||||
const startTime = new Date(meeting.value.startTime.replace(' ', 'T')).getTime()
|
||||
const endTime = new Date(meeting.value.endTime.replace(' ', 'T')).getTime()
|
||||
|
||||
// 检查时间解析是否有效
|
||||
if (isNaN(startTime) || isNaN(endTime)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
|
||||
const advanceTime = startTime - advanceMinutes * 60 * 1000
|
||||
|
||||
if (meeting.status === 'ended') {
|
||||
if (meeting.value.status === 'ended') {
|
||||
return '会议已结束'
|
||||
}
|
||||
|
||||
@@ -131,7 +168,7 @@ const countdownText = computed((): string => {
|
||||
return '可以入会'
|
||||
} else if (now < endTime) {
|
||||
// 会议进行中
|
||||
if (meeting.status === 'ongoing') {
|
||||
if (meeting.value.status === 'ongoing') {
|
||||
return '会议进行中'
|
||||
} else {
|
||||
return '可以入会'
|
||||
@@ -146,30 +183,25 @@ const countdownText = computed((): string => {
|
||||
* 是否可以加入会议
|
||||
*/
|
||||
const canJoinMeeting = computed((): boolean => {
|
||||
const meeting = props.meeting
|
||||
if (!meeting) {
|
||||
return false
|
||||
}
|
||||
|
||||
if (!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
|
||||
// iOS和小程序兼容性处理
|
||||
const startTime = new Date(meeting.startTime.replace(' ', 'T')).getTime()
|
||||
const endTime = new Date(meeting.endTime.replace(' ', 'T')).getTime()
|
||||
|
||||
const startTime = new Date(meeting.value.startTime.replace(' ', 'T')).getTime()
|
||||
const endTime = new Date(meeting.value.endTime.replace(' ', 'T')).getTime()
|
||||
|
||||
// 检查时间解析是否有效
|
||||
if (isNaN(startTime) || isNaN(endTime)) {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
const advanceTime = startTime - advanceMinutes * 60 * 1000
|
||||
|
||||
// 在允许入会的时间窗口内(提前入会时间 ~ 结束时间)
|
||||
@@ -180,8 +212,10 @@ const canJoinMeeting = computed((): boolean => {
|
||||
* 按钮文本
|
||||
*/
|
||||
const buttonText = computed((): string => {
|
||||
const meeting = props.meeting
|
||||
if (meeting.status === 'ended') {
|
||||
if (!meeting.value) {
|
||||
return '加载中'
|
||||
}
|
||||
if (meeting.value.status === 'ended') {
|
||||
return '会议已结束'
|
||||
}
|
||||
if (!canJoinMeeting.value) {
|
||||
@@ -195,12 +229,12 @@ const buttonText = computed((): string => {
|
||||
*/
|
||||
function handleJoinMeeting() {
|
||||
console.log('[MeetingCard] handleJoinMeeting 被点击', {
|
||||
meetingId: props.meeting.meetingId,
|
||||
meetingId: props.meetingId,
|
||||
canJoin: canJoinMeeting.value,
|
||||
meeting: props.meeting
|
||||
meeting: meeting.value
|
||||
})
|
||||
|
||||
if (!props.meeting.meetingId) {
|
||||
if (!props.meetingId) {
|
||||
console.error('[MeetingCard] 会议ID不存在')
|
||||
uni.showToast({
|
||||
title: '会议ID不存在',
|
||||
@@ -211,14 +245,14 @@ function handleJoinMeeting() {
|
||||
|
||||
if (!canJoinMeeting.value) {
|
||||
console.warn('[MeetingCard] 不允许加入会议', {
|
||||
status: props.meeting.status,
|
||||
status: meeting.value?.status,
|
||||
canJoin: canJoinMeeting.value
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
console.log('[MeetingCard] 触发join事件, meetingId:', props.meeting.meetingId)
|
||||
emit('join', props.meeting.meetingId)
|
||||
console.log('[MeetingCard] 触发join事件, meetingId:', props.meetingId)
|
||||
emit('join', props.meetingId)
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
.meeting-create-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
background-color: #fff;
|
||||
padding: 32rpx;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: #fff;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding: 24rpx 32rpx;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.form-item.required .label-text::after {
|
||||
content: ' *';
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.required-star {
|
||||
color: #f56c6c;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 16rpx 24rpx;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.picker-display {
|
||||
padding: 16rpx 24rpx;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.picker-display .placeholder {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.form-tip text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.form-footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #ebeef5;
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 24rpx 0;
|
||||
border-radius: 8rpx;
|
||||
font-size: 32rpx;
|
||||
text-align: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #f5f7fa;
|
||||
color: #606266;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-submit[loading] {
|
||||
opacity: 0.7;
|
||||
}
|
||||
@@ -114,8 +114,8 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, computed } from 'vue'
|
||||
import { onLoad } from '@dcloudio/uni-app'
|
||||
import { workcaseChatAPI } from '../../api/workcase/workcaseChat'
|
||||
import type { CreateMeetingParam } from '../../types/workcase/chatRoom'
|
||||
import { workcaseChatAPI } from '../../../api/workcase/workcaseChat'
|
||||
import type { CreateMeetingParam } from '../../../types/workcase/chatRoom'
|
||||
|
||||
// 路由参数
|
||||
const roomId = ref('')
|
||||
@@ -328,120 +328,5 @@ function handleCancel() {
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.meeting-create-page {
|
||||
min-height: 100vh;
|
||||
background-color: #f5f7fa;
|
||||
padding-bottom: 120rpx;
|
||||
}
|
||||
|
||||
.page-header {
|
||||
background-color: #fff;
|
||||
padding: 32rpx;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.page-title {
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.form-container {
|
||||
background-color: #fff;
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
padding: 24rpx 32rpx;
|
||||
border-bottom: 1px solid #ebeef5;
|
||||
}
|
||||
|
||||
.form-item.required .label-text::after {
|
||||
content: ' *';
|
||||
color: #f56c6c;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 28rpx;
|
||||
color: #606266;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.required-star {
|
||||
color: #f56c6c;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 16rpx 24rpx;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.picker-display {
|
||||
padding: 16rpx 24rpx;
|
||||
border: 1px solid #dcdfe6;
|
||||
border-radius: 8rpx;
|
||||
font-size: 28rpx;
|
||||
color: #303133;
|
||||
}
|
||||
|
||||
.picker-display .placeholder {
|
||||
color: #c0c4cc;
|
||||
}
|
||||
|
||||
.form-tip {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.form-tip text {
|
||||
font-size: 24rpx;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.form-footer {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 24rpx 32rpx;
|
||||
background-color: #fff;
|
||||
border-top: 1px solid #ebeef5;
|
||||
box-shadow: 0 -2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.btn {
|
||||
flex: 1;
|
||||
padding: 24rpx 0;
|
||||
border-radius: 8rpx;
|
||||
font-size: 32rpx;
|
||||
text-align: center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.btn-cancel {
|
||||
background-color: #f5f7fa;
|
||||
color: #606266;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.btn-submit {
|
||||
background-color: #409eff;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.btn-submit[loading] {
|
||||
opacity: 0.7;
|
||||
}
|
||||
@import url('./MeetingCreate.scss')
|
||||
</style>
|
||||
Reference in New Issue
Block a user