feat(phase2e-2): 会议首页落地 "创建 / 加入" 双入口
问题 - tabBar "会议" 指向 pages/meeting/index,但该页仍是占位的 "视频会议功能开发中…",用户从底部 tab 进入无入口按钮, 必须手改 URL 到 /pages/meeting/create 或 /join 才能进会议 修复 - 重写 pages/meeting/index.vue 为真实的 Meeting Hub: · 顶部 hero 标题 + 描述 · "创建即时会议" 主按钮(蓝色渐变卡片,跳 /pages/meeting/create) · "加入会议" 次按钮(卡片,跳 /pages/meeting/join) · 提示文案说明入会流程与主持人能力 - 保留 CustomTabBar 底栏 current=2 验证 - Playwright 截图确认布局、两个入口按钮视觉与点击区域均正常 Made-with: Cursor
This commit is contained in:
@@ -1,16 +1,59 @@
|
|||||||
<!--
|
<!--
|
||||||
会议页面(占位)
|
会议首页(Meeting Hub)
|
||||||
|
|
||||||
设计系统:design-system/echochat/MASTER.md
|
职责:
|
||||||
TabBar 页面,Phase 3(会议模块)中实现具体功能
|
- 作为 tabBar "会议" 的统一入口,提供创建 / 加入 / 最近会议跳转
|
||||||
|
- 不直接承载 mediasoup 连接,只做导航与轻量查询
|
||||||
|
|
||||||
|
数据流:
|
||||||
|
- 点击「创建即时会议」→ /pages/meeting/create
|
||||||
|
- 点击「加入会议」→ /pages/meeting/join
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<view class="page-wrapper">
|
<view class="page">
|
||||||
<view class="placeholder-content">
|
<view class="hero">
|
||||||
<text class="placeholder-icon">🎥</text>
|
<view class="hero-icon">🎥</view>
|
||||||
<text class="placeholder-title">会议</text>
|
<text class="hero-title">视频会议</text>
|
||||||
<text class="placeholder-desc">视频会议功能开发中…</text>
|
<text class="hero-desc">创建或加入会议,进行高清音视频协作</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
|
<view class="actions">
|
||||||
|
<view class="action-card primary" @click="goCreate">
|
||||||
|
<view class="action-icon">
|
||||||
|
<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<polygon points="23 7 16 12 23 17 23 7"></polygon>
|
||||||
|
<rect x="1" y="5" width="15" height="14" rx="2" ry="2"></rect>
|
||||||
|
</svg>
|
||||||
|
</view>
|
||||||
|
<view class="action-text">
|
||||||
|
<text class="action-title">创建即时会议</text>
|
||||||
|
<text class="action-desc">立即发起一场新会议并邀请成员</text>
|
||||||
|
</view>
|
||||||
|
<view class="action-arrow">›</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="action-card" @click="goJoin">
|
||||||
|
<view class="action-icon alt">
|
||||||
|
<svg viewBox="0 0 24 24" width="28" height="28" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||||
|
<path d="M14 9l6 6-6 6"></path>
|
||||||
|
<path d="M4 4v7a4 4 0 0 0 4 4h12"></path>
|
||||||
|
</svg>
|
||||||
|
</view>
|
||||||
|
<view class="action-text">
|
||||||
|
<text class="action-title">加入会议</text>
|
||||||
|
<text class="action-desc">输入 9 位会议号加入已有会议</text>
|
||||||
|
</view>
|
||||||
|
<view class="action-arrow">›</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<view class="tips">
|
||||||
|
<text class="tips-title">提示</text>
|
||||||
|
<text class="tips-line">• 入会前会先进入设备预览页选择摄像头 / 麦克风</text>
|
||||||
|
<text class="tips-line">• 主持人可在会议中邀请成员、管理权限、结束会议</text>
|
||||||
|
<text class="tips-line">• 支持静音、关闭摄像头、实时聊天等常用操作</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
<CustomTabBar :current="2" />
|
<CustomTabBar :current="2" />
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
@@ -20,39 +63,140 @@ import CustomTabBar from '@/components/CustomTabBar.vue'
|
|||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MeetingIndex',
|
name: 'MeetingIndex',
|
||||||
components: { CustomTabBar }
|
components: { CustomTabBar },
|
||||||
|
methods: {
|
||||||
|
goCreate() {
|
||||||
|
uni.navigateTo({ url: '/pages/meeting/create' })
|
||||||
|
},
|
||||||
|
goJoin() {
|
||||||
|
uni.navigateTo({ url: '/pages/meeting/join' })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.page-wrapper {
|
.page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background-color: #F8FAFC;
|
background: linear-gradient(180deg, #EEF4FF 0%, #F8FAFC 40%);
|
||||||
padding-bottom: 120rpx;
|
padding: 48rpx 32rpx 180rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-content {
|
.hero {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
|
padding: 20rpx 8rpx 40rpx;
|
||||||
|
}
|
||||||
|
.hero-icon {
|
||||||
|
font-size: 72rpx;
|
||||||
|
line-height: 1;
|
||||||
|
margin-bottom: 16rpx;
|
||||||
|
}
|
||||||
|
.hero-title {
|
||||||
|
font-size: 44rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: #0F172A;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
}
|
||||||
|
.hero-desc {
|
||||||
|
font-size: 26rpx;
|
||||||
|
color: #64748B;
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-top: 8rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.action-card {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 24rpx;
|
||||||
|
padding: 28rpx 28rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
box-shadow: 0 4rpx 16rpx rgba(15, 23, 42, 0.05);
|
||||||
|
transition: transform 0.12s ease, box-shadow 0.12s ease;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.action-card:active {
|
||||||
|
transform: translateY(1rpx);
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(15, 23, 42, 0.08);
|
||||||
|
}
|
||||||
|
.action-card.primary {
|
||||||
|
background: linear-gradient(135deg, #3B82F6 0%, #2563EB 100%);
|
||||||
|
box-shadow: 0 6rpx 20rpx rgba(59, 130, 246, 0.28);
|
||||||
|
}
|
||||||
|
.action-card.primary .action-title,
|
||||||
|
.action-card.primary .action-desc,
|
||||||
|
.action-card.primary .action-arrow {
|
||||||
|
color: #FFFFFF;
|
||||||
|
}
|
||||||
|
.action-card.primary .action-desc { color: rgba(255, 255, 255, 0.82); }
|
||||||
|
|
||||||
|
.action-icon {
|
||||||
|
width: 88rpx;
|
||||||
|
height: 88rpx;
|
||||||
|
border-radius: 20rpx;
|
||||||
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding-top: 300rpx;
|
background: rgba(255, 255, 255, 0.22);
|
||||||
|
color: #FFFFFF;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
.action-icon.alt {
|
||||||
|
background: rgba(59, 130, 246, 0.12);
|
||||||
|
color: #2563EB;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-icon {
|
.action-text {
|
||||||
font-size: 80rpx;
|
flex: 1;
|
||||||
margin-bottom: 24rpx;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6rpx;
|
||||||
|
min-width: 0;
|
||||||
}
|
}
|
||||||
|
.action-title {
|
||||||
.placeholder-title {
|
font-size: 30rpx;
|
||||||
font-size: 36rpx;
|
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: #1E293B;
|
color: #0F172A;
|
||||||
margin-bottom: 12rpx;
|
}
|
||||||
|
.action-desc {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #64748B;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
.action-arrow {
|
||||||
|
font-size: 40rpx;
|
||||||
|
color: #CBD5E1;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.placeholder-desc {
|
.tips {
|
||||||
font-size: 28rpx;
|
margin-top: 48rpx;
|
||||||
color: #94A3B8;
|
padding: 24rpx 28rpx;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
border-radius: 16rpx;
|
||||||
|
border: 1rpx solid rgba(59, 130, 246, 0.08);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 8rpx;
|
||||||
|
}
|
||||||
|
.tips-title {
|
||||||
|
font-size: 26rpx;
|
||||||
|
font-weight: 600;
|
||||||
|
color: #0F172A;
|
||||||
|
margin-bottom: 4rpx;
|
||||||
|
}
|
||||||
|
.tips-line {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #475569;
|
||||||
|
line-height: 1.7;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user