168 lines
6.7 KiB
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>
|