congming_huose-apk/common/components/DeviceRoomPicker.vue

169 lines
3.7 KiB
Vue
Raw Normal View History

<template>
<view v-if="visible" class="device-room-picker-mask" @tap="onMask">
<view class="device-room-picker-sheet" @tap.stop>
<view class="device-room-picker-head">
<text class="device-room-picker-title">{{ $i18n.t('room') }}</text>
<text class="device-room-picker-close" @tap="onClose">×</text>
</view>
<scroll-view scroll-y class="device-room-picker-scroll">
<view v-if="loading" class="device-room-picker-hint">{{ $i18n.t('loading') }}</view>
<view v-else-if="!list || !list.length" class="device-room-picker-hint">{{ $i18n.t('noData') }}</view>
<view
v-else
v-for="item in list"
:key="item.id"
class="device-room-picker-row"
:class="{ 'is-current': isCurrent(item) }"
@tap="onPick(item)"
>
<view class="device-room-picker-left">
<image
class="device-room-picker-thumb"
:src="roomThumbSrc(item)"
mode="aspectFill"
/>
<text class="device-room-picker-name">{{ item.name }}</text>
</view>
<text v-if="isCurrent(item)" class="device-room-picker-check"></text>
</view>
</scroll-view>
</view>
</view>
</template>
<script>
export default {
name: 'DeviceRoomPicker',
props: {
visible: { type: Boolean, default: false },
list: { type: Array, default: () => [] },
loading: { type: Boolean, default: false },
currentRoomId: { default: null }
},
data() {
return {
placeholderRoomImg: 'https://api.ccttiot.com/smartmeter/img/static/umA124Tcq2VMMgwye048'
}
},
methods: {
roomThumbSrc(item) {
if (!item) return this.placeholderRoomImg
const u = item.picture || item.roomPicture || item.photo || item.image
return u || this.placeholderRoomImg
},
isCurrent(item) {
if (this.currentRoomId === undefined || this.currentRoomId === null || this.currentRoomId === '') {
return false
}
return String(item.id) === String(this.currentRoomId)
},
onClose() {
this.$emit('close')
},
onMask() {
this.$emit('close')
},
onPick(item) {
this.$emit('select', item)
}
}
}
</script>
<style scoped>
.device-room-picker-mask {
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.45);
z-index: 10000;
display: flex;
align-items: flex-end;
justify-content: center;
}
.device-room-picker-sheet {
width: 100%;
max-height: 70vh;
background: #fff;
border-radius: 24rpx 24rpx 0 0;
padding-bottom: env(safe-area-inset-bottom);
box-sizing: border-box;
animation: appSheetSlideUp 0.42s cubic-bezier(0.25, 0.8, 0.25, 1);
}
.device-room-picker-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 28rpx 32rpx;
border-bottom: 1rpx solid #ececec;
}
.device-room-picker-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.device-room-picker-close {
font-size: 48rpx;
line-height: 1;
color: #999;
padding: 0 8rpx;
}
.device-room-picker-scroll {
max-height: 56vh;
}
.device-room-picker-hint {
padding: 48rpx 32rpx;
text-align: center;
color: #999;
font-size: 28rpx;
}
.device-room-picker-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 24rpx 32rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.device-room-picker-row.is-current {
background: #f7f8fa;
}
.device-room-picker-left {
display: flex;
align-items: center;
flex: 1;
min-width: 0;
}
.device-room-picker-thumb {
width: 88rpx;
height: 88rpx;
border-radius: 16rpx;
margin-right: 24rpx;
flex-shrink: 0;
background: #eee;
}
.device-room-picker-name {
font-size: 30rpx;
color: #333;
flex: 1;
min-width: 0;
}
.device-room-picker-check {
font-size: 32rpx;
color: #333;
}
</style>