370 lines
13 KiB
Vue
370 lines
13 KiB
Vue
<template>
|
||
<div class="reststop-list-page" :style="{ paddingBottom: `${safeHeight}px` }">
|
||
<!-- 共享休息站列表 -->
|
||
<div class="reststops-section">
|
||
<div class="reststops-list" v-if="reststopList.length > 0">
|
||
<div class="reststop-item" v-for="(item, index) in reststopList" :key="index" @click="goToDetail(item)">
|
||
<div class="reststop-header">
|
||
<div class="reststop-name">{{ item.reststopName }}</div>
|
||
<div class="reststop-status" :class="[
|
||
item.doorLockStatus === 'unlocked' ? 'status-available' : 'status-occupied'
|
||
]">
|
||
{{ getDoorLockStatusText(item.doorLockStatus) }}
|
||
</div>
|
||
</div>
|
||
|
||
<div class="reststop-info">
|
||
<div class="info-row">
|
||
<div class="info-item">
|
||
<span class="info-icon">🕒</span>
|
||
<span class="info-text">剩余时间:{{ item.remainingTime || '0分钟' }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-icon">⭐</span>
|
||
<span class="info-text">评分:{{ item.rating || '暂无' }}</span>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="info-row">
|
||
<div class="info-item">
|
||
<span class="info-icon">🧹</span>
|
||
<span class="info-text">保洁状态:{{ getCleaningStatusText(item.cleaningStatus) }}</span>
|
||
</div>
|
||
<div class="info-item">
|
||
<span class="info-icon">📋</span>
|
||
<span class="info-text">订单:{{ getOrderStatusText(item.orderStatus) }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="reststop-footer">
|
||
<div class="action-btn" :class="[
|
||
item.orderStatus === 'active' ? 'action-active' :
|
||
(item.orderStatus === 'completed' || item.orderStatus === 'cancelled' ? 'action-normal' : 'action-disabled')
|
||
]" @click.stop="handleAction(item)">
|
||
{{
|
||
item.orderStatus === 'active' ? '使用中' :
|
||
(item.orderStatus === 'completed' || item.orderStatus === 'cancelled' ? '查看详情' : '不可用')
|
||
}}
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- 空状态 -->
|
||
<div class="empty-state" v-else>
|
||
<div class="empty-icon">🏠</div>
|
||
<div class="empty-title">暂无休息站</div>
|
||
<div class="empty-desc">附近暂无可用的共享休息站</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</template>
|
||
|
||
<script>
|
||
export default {
|
||
data() {
|
||
return {
|
||
safeHeight: "",
|
||
reststopList: [],
|
||
defaultCover: 'https://picsum.photos/seed/reststop-default/400/300.jpg'
|
||
};
|
||
},
|
||
onLoad() {
|
||
let systemInfo = uni.getSystemInfoSync();
|
||
let height = systemInfo.safeAreaInsets.bottom;
|
||
this.safeHeight = Number(height);
|
||
|
||
this.loadReststopList();
|
||
},
|
||
onPullDownRefresh() {
|
||
this.loadReststopList();
|
||
},
|
||
onReachBottom() {
|
||
this.loadMoreReststops();
|
||
},
|
||
methods: {
|
||
// 加载休息站列表
|
||
async loadReststopList() {
|
||
try {
|
||
// 这里调用实际接口获取休息站列表
|
||
// const res = await this.$api.getReststopList({
|
||
// page: 1,
|
||
// pageSize: 10
|
||
// });
|
||
|
||
// 模拟数据
|
||
const mockData = [
|
||
{
|
||
id: 1,
|
||
reststopName: "昆明服务区A区-01号休息站",
|
||
doorLockStatus: "unlocked", // unlocked: 未锁定, locked: 已锁定
|
||
orderStatus: "active", // active: 进行中, completed: 已完成, cancelled: 已取消
|
||
orderTime: "2024-03-20 14:30:00",
|
||
remainingTime: "45分钟",
|
||
renewalStatus: "available", // available: 可续费, unavailable: 不可续费
|
||
cleaningStatus: "clean", // clean: 干净, cleaning: 清洁中, dirty: 待清洁
|
||
emergencyContact: "13800138000",
|
||
rating: 4.8,
|
||
location: "昆明服务区A区东侧"
|
||
},
|
||
{
|
||
id: 2,
|
||
reststopName: "昆明服务区B区-02号休息站",
|
||
doorLockStatus: "locked",
|
||
orderStatus: "active",
|
||
orderTime: "2024-03-20 13:45:00",
|
||
remainingTime: "120分钟",
|
||
renewalStatus: "available",
|
||
cleaningStatus: "clean",
|
||
emergencyContact: "13900139000",
|
||
rating: 4.5,
|
||
location: "昆明服务区B区西侧"
|
||
},
|
||
{
|
||
id: 3,
|
||
reststopName: "曲靖服务区-03号休息站",
|
||
doorLockStatus: "locked",
|
||
orderStatus: "completed",
|
||
orderTime: "2024-03-20 10:00:00",
|
||
remainingTime: "已结束",
|
||
renewalStatus: "unavailable",
|
||
cleaningStatus: "cleaning",
|
||
emergencyContact: "13700137000",
|
||
rating: 4.9,
|
||
location: "曲靖服务区南区"
|
||
}
|
||
];
|
||
|
||
this.reststopList = mockData;
|
||
uni.stopPullDownRefresh();
|
||
|
||
} catch (error) {
|
||
console.error('加载休息站列表失败:', error);
|
||
uni.showToast({
|
||
title: '加载失败,请重试',
|
||
icon: 'none'
|
||
});
|
||
uni.stopPullDownRefresh();
|
||
}
|
||
},
|
||
|
||
// 加载更多休息站
|
||
loadMoreReststops() {
|
||
console.log('加载更多休息站');
|
||
},
|
||
|
||
// 跳转到休息站详情
|
||
goToDetail(item) {
|
||
uni.navigateTo({
|
||
url: `/pages/sharedRestStop/detail?id=${item.id}`
|
||
});
|
||
},
|
||
|
||
// 处理按钮点击
|
||
handleAction(item) {
|
||
if (item.orderStatus === 'completed' || item.orderStatus === 'cancelled') {
|
||
uni.navigateTo({
|
||
url: `/pages/sharedRestStop/detail?id=${item.id}`
|
||
});
|
||
} else {
|
||
uni.showToast({
|
||
title: '当前订单进行中',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
},
|
||
|
||
// 获取门锁状态文本
|
||
getDoorLockStatusText(status) {
|
||
const statusMap = {
|
||
'unlocked': '可使用',
|
||
'locked': '使用中'
|
||
};
|
||
return statusMap[status] || '未知';
|
||
},
|
||
|
||
// 获取保洁状态文本
|
||
getCleaningStatusText(status) {
|
||
const statusMap = {
|
||
'clean': '已清洁',
|
||
'cleaning': '清洁中',
|
||
'dirty': '待清洁'
|
||
};
|
||
return statusMap[status] || '未知';
|
||
},
|
||
|
||
// 获取订单状态文本
|
||
getOrderStatusText(status) {
|
||
const statusMap = {
|
||
'active': '进行中',
|
||
'completed': '已完成',
|
||
'cancelled': '已取消'
|
||
};
|
||
return statusMap[status] || '无订单';
|
||
},
|
||
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style scoped lang="less">
|
||
.reststop-list-page {
|
||
width: 100vw;
|
||
min-height: 100vh;
|
||
background: #f8fafc;
|
||
overflow-y: scroll;
|
||
|
||
.reststops-section {
|
||
padding: 40rpx 32rpx;
|
||
|
||
.reststops-list {
|
||
.reststop-item {
|
||
background: white;
|
||
border-radius: 24rpx;
|
||
margin-bottom: 32rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||
overflow: hidden;
|
||
transition: all 0.3s ease;
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.12);
|
||
}
|
||
|
||
.reststop-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 24rpx;
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
|
||
.reststop-name {
|
||
font-size: 30rpx;
|
||
font-weight: 600;
|
||
color: #1f2937;
|
||
flex: 1;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.reststop-status {
|
||
padding: 8rpx 12rpx;
|
||
border-radius: 16rpx;
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
|
||
&.status-available {
|
||
background: #dcfce7;
|
||
color: #15803d;
|
||
}
|
||
|
||
&.status-occupied {
|
||
background: #fef3c7;
|
||
color: #92400e;
|
||
}
|
||
}
|
||
}
|
||
|
||
.reststop-info {
|
||
padding: 24rpx;
|
||
|
||
.info-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 20rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.info-item {
|
||
display: flex;
|
||
align-items: center;
|
||
flex: 1;
|
||
|
||
.info-icon {
|
||
font-size: 24rpx;
|
||
margin-right: 12rpx;
|
||
width: 32rpx;
|
||
text-align: center;
|
||
}
|
||
|
||
.info-text {
|
||
font-size: 24rpx;
|
||
color: #6b7280;
|
||
line-height: 1.4;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.reststop-footer {
|
||
padding: 0 24rpx 24rpx;
|
||
display: flex;
|
||
justify-content: flex-end;
|
||
|
||
.action-btn {
|
||
padding: 12rpx 24rpx;
|
||
border-radius: 40rpx;
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
transition: all 0.3s ease;
|
||
|
||
&.action-normal {
|
||
background: linear-gradient(135deg, #22c55e, #16a34a);
|
||
color: white;
|
||
|
||
&:active {
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
|
||
&.action-active {
|
||
background: linear-gradient(135deg, #f59e0b, #d97706);
|
||
color: white;
|
||
|
||
&:active {
|
||
opacity: 0.9;
|
||
}
|
||
}
|
||
|
||
&.action-disabled {
|
||
background: #f3f4f6;
|
||
color: #9ca3af;
|
||
border: 2rpx solid #e5e7eb;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.empty-state {
|
||
text-align: center;
|
||
padding: 200rpx 40rpx;
|
||
|
||
.empty-icon {
|
||
font-size: 120rpx;
|
||
margin-bottom: 32rpx;
|
||
opacity: 0.3;
|
||
}
|
||
|
||
.empty-title {
|
||
font-size: 32rpx;
|
||
color: #6b7280;
|
||
margin-bottom: 16rpx;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.empty-desc {
|
||
font-size: 26rpx;
|
||
color: #9ca3af;
|
||
line-height: 1.5;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.reststop-list-page::-webkit-scrollbar {
|
||
display: none;
|
||
}
|
||
</style> |