rentease-app/pages/meter-readings/meter-readings.vue

168 lines
6.7 KiB
Vue

<template>
<view class="meter-readings-page">
<view class="custom-nav safe-area-top">
<view class="nav-content">
<view class="nav-back" @click="goBack">
<uni-icons type="left" size="20" color="#1E293B"></uni-icons>
</view>
<text class="nav-title">抄表记录</text>
<view class="nav-actions">
<view class="nav-btn" @click="addReading">
<uni-icons type="plus" size="20" color="#2563EB"></uni-icons>
</view>
</view>
</view>
</view>
<scroll-view scroll-y class="page-content" @scrolltolower="loadMore">
<view class="filter-section">
<view class="filter-tabs">
<view v-for="(tab, index) in filterTabs" :key="index" class="filter-tab" :class="{ active: currentFilter === tab.value }" @click="switchFilter(tab.value)">
<text>{{tab.label}}</text>
</view>
</view>
</view>
<view class="reading-list">
<view v-for="(item, index) in readingList" :key="index" class="reading-card">
<view class="reading-header">
<view class="room-info">
<text class="room-number">{{item.roomNumber || '-'}}</text>
<text class="reading-date">{{item.readingDate}}</text>
</view>
<view class="reading-type" :class="item.type">
<text>{{item.type === 'water' ? '水表' : '电表'}}</text>
</view>
</view>
<view class="reading-content">
<view class="reading-item">
<text class="item-label">本次读数</text>
<text class="item-value current">{{item.currentReading}}</text>
</view>
<view class="reading-item">
<text class="item-label">上次读数</text>
<text class="item-value">{{item.previousReading || '-'}}</text>
</view>
<view class="reading-item">
<text class="item-label">用量</text>
<text class="item-value usage">{{item.usage || calculateUsage(item)}} {{item.type === 'water' ? '吨' : '度'}}</text>
</view>
</view>
</view>
</view>
<view v-if="readingList.length === 0 && !isLoading" class="empty-state">
<text class="empty-text">暂无抄表记录</text>
<button class="add-btn" @click="addReading">添加记录</button>
</view>
<view class="safe-area-bottom" style="height: 40rpx;"></view>
</scroll-view>
</view>
</template>
<script>
import { meterReadingApi } from '../../api/index.js'
export default {
data() {
return {
currentFilter: 'all',
filterTabs: [
{ label: '全部', value: 'all' },
{ label: '水表', value: 'water' },
{ label: '电表', value: 'electricity' }
],
readingList: [],
isLoading: false,
page: 1,
pageSize: 10,
hasMore: true
}
},
onLoad() {
this.loadData()
},
onShow() {
this.loadData()
},
methods: {
async loadData() {
if (this.isLoading) return
this.isLoading = true
try {
const params = { page: this.page, pageSize: this.pageSize }
if (this.currentFilter !== 'all') {
params.type = this.currentFilter
}
const res = await meterReadingApi.list(params)
const list = res.data || []
if (this.page === 1) {
this.readingList = list
} else {
this.readingList = [...this.readingList, ...list]
}
this.hasMore = list.length >= this.pageSize
} catch (error) {
uni.showToast({ title: '加载失败', icon: 'none' })
} finally {
this.isLoading = false
}
},
loadMore() {
if (this.hasMore && !this.isLoading) {
this.page++
this.loadData()
}
},
switchFilter(value) {
this.currentFilter = value
this.page = 1
this.loadData()
},
addReading() {
uni.navigateTo({ url: '/pages/meter-reading-add/meter-reading-add' })
},
calculateUsage(item) {
if (item.currentReading && item.previousReading) {
return (parseFloat(item.currentReading) - parseFloat(item.previousReading)).toFixed(2)
}
return '-'
},
goBack() { uni.navigateBack() }
}
}
</script>
<style scoped>
.meter-readings-page { min-height: 100vh; background: #F8FAFC; display: flex; flex-direction: column; }
.custom-nav { background: #FFFFFF; border-bottom: 2rpx solid #F1F5F9; }
.nav-content { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 32rpx; }
.nav-back { width: 60rpx; height: 60rpx; display: flex; align-items: center; justify-content: center; }
.nav-title { font-size: 36rpx; font-weight: 700; color: #1E293B; }
.nav-actions { width: 60rpx; height: 60rpx; display: flex; align-items: center; justify-content: center; }
.page-content { flex: 1; padding: 24rpx 32rpx; }
.filter-section { margin-bottom: 24rpx; }
.filter-tabs { display: flex; gap: 16rpx; }
.filter-tab { padding: 16rpx 32rpx; background: #FFFFFF; border-radius: 12rpx; font-size: 28rpx; color: #64748B; }
.filter-tab.active { background: #2563EB; color: #FFFFFF; }
.reading-list { display: flex; flex-direction: column; gap: 24rpx; }
.reading-card { background: #FFFFFF; border-radius: 24rpx; padding: 32rpx; box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.04); }
.reading-header { display: flex; justify-content: space-between; align-items: center; margin-bottom: 24rpx; }
.room-info { display: flex; flex-direction: column; gap: 8rpx; }
.room-number { font-size: 32rpx; font-weight: 700; color: #1E293B; }
.reading-date { font-size: 24rpx; color: #94A3B8; }
.reading-type { padding: 8rpx 20rpx; border-radius: 8rpx; font-size: 24rpx; }
.reading-type.water { background: #DBEAFE; color: #2563EB; }
.reading-type.electricity { background: #FEF3C7; color: #D97706; }
.reading-content { display: flex; justify-content: space-around; padding-top: 24rpx; border-top: 2rpx solid #F1F5F9; }
.reading-item { display: flex; flex-direction: column; align-items: center; gap: 8rpx; }
.item-label { font-size: 24rpx; color: #94A3B8; }
.item-value { font-size: 32rpx; font-weight: 600; color: #1E293B; }
.item-value.current { color: #2563EB; }
.item-value.usage { color: #10B981; }
.empty-state { display: flex; flex-direction: column; align-items: center; padding: 120rpx 0; }
.empty-text { font-size: 28rpx; color: #94A3B8; margin-bottom: 32rpx; }
.add-btn { background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%); color: #FFFFFF; font-size: 28rpx; padding: 24rpx 64rpx; border-radius: 16rpx; border: none; }
</style>