Files
SmartParks_uniapp/pages/sys/workbench/meet/meet.vue

439 lines
8.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="meet-container">
<!-- tab栏 -->
<view class="meet-tabs">
<view v-for="(tab, idx) in tabs" :key="idx" :class="['meet-tab', {active: idx === activeTab}]"
@click="changeTab(idx)">
{{ tab }}
<view v-if="idx === activeTab" class="tab-underline"></view>
</view>
</view>
<view class="meet-list-container">
<scroll-view
v-for="(tab, idx) in tabs"
:key="idx"
v-show="idx === activeTab"
class="meet-list-scroll"
scroll-y
:refresher-enabled="false">
<view class="empty-content" v-if="tabData[idx].length ===0">
<image src="/static/ic_meet_01.png" class="empty-img"></image>
<view class="empty-txt">暂无预约</view>
<button class="empty-btn" @click="createMeet">发起预约</button>
</view>
<!-- 列表区 -->
<view v-else class="meet-list">
<view v-for="(item, index) in tabData[idx]" :key="index" class="meet-card" @click="showVisitorDetail(item)">
<view class="card-row">
<view class="card-type">{{ item.visitorUnit }}</view>
<view class="card-status" :class="getStatusColor(item.serveStatus)">
{{ getStatusLabel(item.serveStatus) }}</view>
</view>
<view class="card-info">{{ item.visitorName }}
<text class="card-phone">{{ item.visitorPhone }}</text>
<text class="card-divider"></text>
<text class="card-address">{{ item.visitorUnit }}</text>
</view>
<view class="card-time">{{ item.createTime }}</view>
</view>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
tabs: ['我发起的', '邀请我的'],
activeTab: 0,
tabData: [
[],
[]
], // 每个tab的数据
tabLoaded: [false, false], // 每个tab是否已加载
loading: false
}
},
computed: {
list() {
return this.tabData[this.activeTab];
}
},
created() {
this.loadAllTabsData(); // 预加载所有标签页数据
},
methods: {
goBack() {
uni.navigateBack();
},
createMeet(){
uni.navigateTo({
url: '/pages/sys/workbench/meet/createMeet'
});
},
async changeTab(idx) {
this.activeTab = idx;
// 移除切换标签时的加载逻辑,避免重复调用接口
/*
if (!this.tabLoaded[idx]) {
await this.loadTabData(idx);
}
*/
},
async loadTabData(idx) {
this.loading = true;
// 模拟接口请求不同tab返回不同mock数据
let params = {}
if (idx === 0) {
params = {
}
}
let data = [];
let res = await this.$u.api.getMeetings(params);
if (res.code == '200') {
data = res.rows
}
this.$set(this.tabData, idx, data);
this.$set(this.tabLoaded, idx, true);
this.loading = false;
},
getStatusLabel(status) {
const statusMap = {
0: '待确认',
1: '已确认',
2: '已取消',
3: '已完成'
};
return statusMap[status] || '';
},
getStatusColor(status) {
const statusMap = {
0: '待确认',
1: 'orange',
2: '已取消',
3: '已完成'
};
return statusMap[status] || '';
},
// 添加预加载所有标签页数据的方法
async loadAllTabsData() {
// 并行加载所有标签页数据,提高加载速度
const loadPromises = [0, 1].map((index) => {
return this.loadTabData(index);
});
await Promise.all(loadPromises);
// 标记所有标签页已加载
this.tabLoaded = [true, true];
}
}
}
</script>
<style scoped>
.meet-container {
height: 100vh;
background: #f7f7f7;
display: flex;
flex-direction: column;
overflow: hidden;
}
.empty-content{
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
margin-top: 168rpx;
}
.empty-img{
width: 440rpx;
height: 398rpx;
}
.empty-txt{
color: #737373;
font-size: 28rpx;
margin-top: 64rpx;
}
.empty-btn {
width: 70vw;
height: 80rpx;
background: #0090FF;
color: #fff;
font-size: 32rpx;
border: none;
border-radius: 40rpx;
margin: 140rpx auto 0 auto;
display: block;
box-shadow: 0 18rpx 24rpx rgba(0, 0, 0, 0.18);
font-weight: bold;
}
.meet-tabs {
display: flex;
align-items: center;
justify-content: space-around;
background: #fff;
height: 80rpx;
border-bottom: 1px solid #f0f0f0;
flex-shrink: 0;
/* 防止被压缩 */
}
.meet-tab {
flex: 1;
text-align: center;
font-size: 30rpx;
color: #888;
position: relative;
font-weight: 500;
padding: 0 0 10rpx 0;
/* tab点击事件 */
cursor: pointer;
}
.meet-tab.active {
color: #2186FF;
font-weight: bold;
}
.tab-underline {
width: 60rpx;
height: 6rpx;
background: #2186FF;
border-radius: 3rpx;
margin: 0 auto;
margin-top: 8rpx;
}
.meet-list-container {
flex: 1;
position: relative;
margin: 25rpx 0 0 0;
padding: 0 35rpx;
padding-bottom: 200rpx;
/* 为底部按钮留出空间 */
}
.meet-list-scroll {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
padding: 0 35rpx;
overflow-y: auto;
padding-bottom: 200rpx;
/* 为底部按钮留出空间 */
height: calc(100vh - 80rpx - 32rpx - 80rpx); /* 减去顶部tab区域和底部按钮高度 */
box-sizing: border-box;
}
.meet-list {
margin: 25rpx 0 0 0;
padding: 0 35rpx;
flex: 1;
/* 占据所有剩余空间 */
overflow-y: auto;
/* 内容超出时,开启垂直滚动 */
padding-bottom: 200rpx;
/* 为底部按钮留出空间 */
}
.meet-card {
background: #fff;
border-radius: 16rpx;
margin-bottom: 24rpx;
padding: 20rpx 40rpx 70rpx 12rpx;
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
}
.card-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 28rpx;
}
.card-type {
font-weight: 600;
font-size: 26rpx;
padding: 10rpx 45rpx 10rpx 12rpx;
border-radius: 15rpx;
color: #fff;
background: linear-gradient(90deg, #007CFF 0%, #FFFFFF 100%);
display: inline-block;
}
.card-status {
font-size: 28rpx;
}
.card-status.orange {
color: #F3831F;
}
.card-status.green {
color: #07C78E;
}
.card-status.gray {
color: #8F8F8F;
}
.card-info {
font-size: 26rpx;
color: #333;
margin-bottom: 8rpx;
margin-left: 8rpx;
display: flex;
align-items: center;
}
.card-phone {
margin: 0 8rpx 0 8rpx;
}
.card-divider {
width: 1rpx;
height: 40rpx;
background: #DCDCDC;
display: inline-block;
margin: 0 12rpx;
vertical-align: middle;
content: '';
}
.card-address {
margin-left: 0;
}
.card-time {
font-size: 28rpx;
color: #626262;
margin-left: 8rpx;
}
.meet-btn {
width: 90vw;
height: 80rpx;
background: #0090FF;
color: #fff;
font-size: 32rpx;
border: none;
border-radius: 40rpx;
margin: 60rpx auto 0 auto;
display: block;
font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
}
.meet-btn-fixed {
position: fixed;
left: 0;
right: 0;
bottom: 100rpx;
margin: 0 auto;
width: 90vw;
height: 80rpx;
background: #0090FF;
color: #fff;
font-size: 32rpx;
border: none;
border-radius: 40rpx;
display: block;
font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
z-index: 99;
}
.meet-detail-mask {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.meet-detail-dialog {
width: 80vw;
background: #fff;
border-radius: 36rpx;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.12);
padding: 48rpx 36rpx 36rpx 36rpx;
position: relative;
display: flex;
flex-direction: column;
align-items: center;
}
.meet-detail-title-row {
width: 100%;
display: flex;
align-items: center;
justify-content: center;
position: relative;
margin-bottom: 52rpx;
}
.meet-detail-title {
font-size: 36rpx;
color: #000;
}
.meet-detail-close {
position: absolute;
right: 0;
top: 0;
width: 22rpx;
height: 22rpx;
}
.meet-detail-info {
width: 100%;
font-size: 28rpx;
color: #222;
margin-bottom: 80rpx;
display: flex;
flex-direction: column;
gap: 28rpx;
position: relative;
}
.meet-detail-status-img {
position: absolute;
right: 0;
bottom: -40rpx;
width: 160rpx;
height: 160rpx;
z-index: 1;
pointer-events: none;
}
.meet-detail-btn {
width: 320rpx;
height: 80rpx;
background: linear-gradient(90deg, #0090FF 0%, #2E9FFF 100%);
color: #fff;
font-size: 32rpx;
border: none;
border-radius: 40rpx;
margin-bottom: 30rpx;
display: block;
font-weight: bold;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.18);
}
</style>