peixue-dev/peidu/uniapp/user-package/pages/timecard/usage.vue

258 lines
5.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="usage-page">
<!-- 统计信息 -->
<view class="statistics-card">
<view class="stat-item">
<text class="stat-value">{{ totalUsage }}</text>
<text class="stat-label">累计使用(小时)</text>
</view>
<view class="stat-item">
<text class="stat-value">{{ usageCount }}</text>
<text class="stat-label">使用次数</text>
</view>
</view>
<!-- 使用记录列表 -->
<view class="usage-list">
<view v-if="list.length === 0" class="empty-state">
<text class="empty-icon">📭</text>
<text class="empty-text">暂无使用记录</text>
</view>
<view v-else>
<view v-for="item in list" :key="item.id" class="usage-item">
<view class="item-header">
<text class="usage-date">{{ item.usageDate }}</text>
<text class="usage-hours">-{{ item.usageHours }}小时</text>
</view>
<view class="item-content">
<view class="content-row">
<text class="label">服务类型:</text>
<text class="value">{{ item.serviceType || '陪读服务' }}</text>
</view>
<view class="content-row" v-if="item.serviceContent">
<text class="label">服务内容:</text>
<text class="value">{{ item.serviceContent }}</text>
</view>
<view class="content-row" v-if="item.startTime && item.endTime">
<text class="label">服务时间:</text>
<text class="value">{{ formatTime(item.startTime) }} - {{ formatTime(item.endTime) }}</text>
</view>
<view class="content-row" v-if="item.orderId">
<text class="label">订单编号:</text>
<text class="value link" @click="goOrder(item.orderId)">{{ item.orderId }}</text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import { parseId, validateId } from '@/utils/params.js'
export default {
data() {
return {
cardId: null,
list: [],
totalUsage: 0,
usageCount: 0,
page: 1,
size: 20,
loading: false,
finished: false
}
},
onLoad(options) {
this.cardId = parseId(options.id)
if (!validateId(this.cardId, '次卡ID')) {
setTimeout(() => uni.navigateBack(), 1500)
return
}
this.loadUsageList()
},
onReachBottom() {
if (!this.loading && !this.finished) {
this.page++
this.loadUsageList()
}
},
methods: {
async loadUsageList() {
if (this.loading) return
this.loading = true
try {
const res = await this.$http.get('/api/timecard/usage/list', {
params: {
timeCardId: this.cardId,
page: this.page,
size: this.size
}
})
if (res.code === 200) {
const records = res.data.records
if (this.page === 1) {
this.list = records
this.calculateStatistics()
} else {
this.list = [...this.list, ...records]
}
if (records.length < this.size) {
this.finished = true
}
}
} catch (e) {
console.error('加载使用记录失败:', e)
const errorMsg = e.message || e.msg || '加载使用记录失败,请稍后重试'
uni.showToast({
title: errorMsg,
icon: 'none',
duration: 2000
})
} finally {
this.loading = false
}
},
calculateStatistics() {
// 计算总使用时长小时数不涉及金额使用parseFloat是安全的
this.totalUsage = this.list.reduce((sum, item) => sum + parseFloat(item.usageHours || 0), 0).toFixed(1)
this.usageCount = this.list.length
},
formatTime(datetime) {
if (!datetime) return ''
return datetime.substring(11, 16)
},
goOrder(orderId) {
uni.navigateTo({
url: `/pages/order/detail?id=${orderId}`
})
}
}
}
</script>
<style lang="scss" scoped>
@import '@/static/css/common.scss';
.usage-page {
min-height: 100vh;
background: $bg-color;
}
.statistics-card {
background: linear-gradient(135deg, #4a9b9f 0%, #3d8185 100%);
padding: 60rpx 40rpx;
display: flex;
justify-content: space-around;
.stat-item {
flex: 1;
text-align: center;
.stat-value {
display: block;
font-size: 48rpx;
font-weight: bold;
color: #fff;
margin-bottom: 16rpx;
}
.stat-label {
display: block;
font-size: 28rpx;
color: rgba(255, 255, 255, 0.8);
}
}
}
.usage-list {
padding: 20rpx 30rpx;
}
.empty-state {
text-align: center;
padding: 120rpx 0;
.empty-image {
width: 300rpx;
height: 300rpx;
margin-bottom: 40rpx;
}
.empty-text {
display: block;
font-size: 28rpx;
color: #999;
}
}
.usage-item {
background: #fff;
border-radius: 16rpx;
padding: 30rpx;
margin-bottom: 20rpx;
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f0f0f0;
.usage-date {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.usage-hours {
font-size: 36rpx;
font-weight: bold;
color: #4a9b9f;
}
}
.item-content {
.content-row {
display: flex;
margin-bottom: 16rpx;
&:last-child {
margin-bottom: 0;
}
.label {
font-size: 28rpx;
color: #999;
min-width: 160rpx;
}
.value {
flex: 1;
font-size: 28rpx;
color: #333;
&.link {
color: #4a9b9f;
text-decoration: underline;
}
}
}
}
}
</style>