You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

380 lines
8.6 KiB

<template>
<view class="container">
<!-- 顶部筛选标签 -->
<view class="filter-tabs">
<view
class="tab-item"
:class="{ active: activeTab === 'all' }"
@click="switchTab('all')"
>
全部
</view>
<view
class="tab-item"
:class="{ active: activeTab === 'generate' }"
@click="switchTab('generate')"
>
生成
</view>
<view
class="tab-item"
:class="{ active: activeTab === 'member' }"
@click="switchTab('member')"
>
会员
</view>
<view
class="tab-item"
:class="{ active: activeTab === 'other' }"
@click="switchTab('other')"
>
其他
</view>
</view>
<!-- 消费记录列表 -->
<view class="consumption-list">
<view
class="consumption-item"
v-for="item in filteredConsumptions"
:key="item.id"
>
<!-- 消费项目和金额 -->
<view class="item-header">
<view class="item-title">{{ item.title }}</view>
<view
class="item-amount"
:class="{
positive: item.amount > 0,
negative: item.amount < 0,
}"
>
{{ item.amount > 0 ? "+" : "-" }}¥{{
Math.abs(item.amount).toFixed(2)
}}
</view>
</view>
<!-- 消费详情 -->
<view class="item-details">
<view class="detail-row">
<text class="detail-label">消费编号:</text>
<text class="detail-value">{{ item.consumptionNumber }}</text>
</view>
<view class="detail-row">
<text class="detail-label">消费时间:</text>
<text class="detail-value">{{ item.consumptionTime }}</text>
</view>
<view class="balance-row">
<view class="balance-item">
<text class="balance-label">账前金额:</text>
<text class="balance-value">
¥{{ item.beforeBalance.toFixed(2) }}
</text>
</view>
<view class="balance-item">
<text class="balance-label">账后金额:</text>
<text class="balance-value">
¥{{ item.afterBalance.toFixed(2) }}
</text>
</view>
</view>
</view>
</view>
</view>
<!-- 空状态 -->
<view v-if="filteredConsumptions.length === 0" class="empty-state">
<u-icon name="file-text" size="60" color="#ccc"></u-icon>
<text class="empty-text">暂无消费记录</text>
</view>
<!-- 加载更多 -->
<view v-if="hasMore && filteredConsumptions.length > 0" class="load-more">
<u-button
type="default"
size="small"
:loading="loading"
@click="loadMore"
>
{{ loading ? "加载中..." : "加载更多" }}
</u-button>
</view>
</view>
</template>
<script setup>
import { computed, onMounted, ref } from "vue";
import { onShow } from "@dcloudio/uni-app";
import { useAuthStore, useUserStore } from "@/store";
import { regions } from "/static/json/regions.js";
import HeaderCustom from "/components/HeaderCustom/HeaderCustom.vue";
import RPC from "@/utils/request";
const authStore = useAuthStore();
const userStore = useUserStore();
// 响应式数据
const activeTab = ref("all");
const loading = ref(false);
const hasMore = ref(true);
const consumptions = ref([
{
id: 1,
title: "乘客电梯图纸生成",
amount: -30.0,
consumptionNumber: "CONS20230516024",
consumptionTime: "2025-05-16 14:30:22",
beforeBalance: 1250.0,
afterBalance: 1220.0,
type: "generate",
},
{
id: 2,
title: "货运电梯图纸生成",
amount: -45.0,
consumptionNumber: "CONS20230516024",
consumptionTime: "2025-05-16 14:30:22",
beforeBalance: 1295.0,
afterBalance: 1250.0,
type: "generate",
},
{
id: 3,
title: "包年会员订阅",
amount: -45.0,
consumptionNumber: "CONS20230516024",
consumptionTime: "2025-05-16 14:30:22",
beforeBalance: 1295.0,
afterBalance: 1250.0,
type: "member",
},
{
id: 4,
title: "账户充值",
amount: 1000.0,
consumptionNumber: "CONS20230516024",
consumptionTime: "2025-05-16 14:30:22",
beforeBalance: 1795.0,
afterBalance: 2795.0,
type: "other",
},
]);
// 计算过滤后的消费记录
const filteredConsumptions = computed(() => {
if (activeTab.value === "all") {
return consumptions.value;
}
return consumptions.value.filter((item) => item.type === activeTab.value);
});
// 切换标签
const switchTab = (tab) => {
activeTab.value = tab;
};
// 加载更多数据
const loadMore = async () => {
if (loading.value) return;
loading.value = true;
try {
// 模拟API调用
// const result = await RPC.get('/api/consumptions', {
// page: currentPage.value + 1,
// type: activeTab.value
// })
// 模拟加载延迟
await new Promise((resolve) => setTimeout(resolve, 1000));
// 模拟没有更多数据
hasMore.value = false;
uni.showToast({
title: "没有更多数据了",
icon: "none",
});
} catch (error) {
console.error("加载更多失败:", error);
uni.showToast({
title: "加载失败,请重试",
icon: "none",
});
} finally {
loading.value = false;
}
};
// 加载消费记录
const loadConsumptions = async () => {
try {
// 调用获取消费记录API
// const result = await RPC.get('/api/consumptions', {
// type: activeTab.value
// })
// consumptions.value = result.data
} catch (error) {
console.error("加载消费记录失败:", error);
uni.showToast({
title: "加载失败,请重试",
icon: "none",
});
}
};
// 下拉刷新
const onRefresh = async () => {
hasMore.value = true;
await loadConsumptions();
};
onMounted(() => {
loadConsumptions();
});
onShow(() => {
// 页面显示时刷新数据
loadConsumptions();
});
</script>
<style lang="scss" scoped>
.container {
font-size: 14px;
min-height: 100vh;
background-color: #f8f8f8;
}
.filter-tabs {
display: flex;
background: white;
padding: 0 16px;
border-bottom: 1px solid #e5e5e5;
.tab-item {
flex: 1;
text-align: center;
padding: 16px 0;
color: #666;
font-size: 14px;
position: relative;
&.active {
color: #4285f4;
font-weight: 500;
&::after {
content: "";
position: absolute;
bottom: 0;
left: 50%;
transform: translateX(-50%);
width: 20px;
height: 2px;
background: #4285f4;
border-radius: 1px;
}
}
}
}
.consumption-list {
padding: 16px;
.consumption-item {
background: white;
border-radius: 12px;
padding: 16px;
margin-bottom: 12px;
.item-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 12px;
.item-title {
font-size: 16px;
color: #333;
font-weight: 500;
}
.item-amount {
font-size: 16px;
font-weight: bold;
&.positive {
color: #52c41a;
}
&.negative {
color: #ff4d4f;
}
}
}
.item-details {
.detail-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 6px;
.detail-label {
color: #999;
font-size: 13px;
}
.detail-value {
color: #666;
font-size: 13px;
}
}
.balance-row {
display: flex;
justify-content: space-between;
margin-top: 8px;
.balance-item {
display: flex;
align-items: center;
gap: 4px;
.balance-label {
color: #999;
font-size: 13px;
}
.balance-value {
color: #333;
font-size: 13px;
font-weight: 500;
}
}
}
}
}
}
.empty-state {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 80px 20px;
.empty-text {
color: #999;
font-size: 14px;
margin-top: 16px;
}
}
.load-more {
padding: 20px;
text-align: center;
}
</style>