288 lines
6.3 KiB
Plaintext
288 lines
6.3 KiB
Plaintext
<template>
|
|
<view class="finance-bill">
|
|
<!-- 头部筛选 -->
|
|
<view class="filter-card border-shadow">
|
|
<view class="filter-row">
|
|
<view class="filter-item">
|
|
<text class="filter-label">时间筛选:</text>
|
|
<view class="date-picker-wrap">
|
|
<text class="calendar-icon">📅</text>
|
|
<text class="date-placeholder">最近30天</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 内容区域 -->
|
|
<view class="content-card border-shadow">
|
|
<!-- 汇总选项卡 -->
|
|
<view class="tab-header">
|
|
<view
|
|
v-for="(item, index) in intervalOptions"
|
|
:key="index"
|
|
:class="['tab-item', currentTab === index ? 'active' : '']"
|
|
@click="handleTabChange(index)"
|
|
>
|
|
<text :class="['tab-txt', currentTab === index ? 'active-txt' : '']">{{ item.label }}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 表格区域 -->
|
|
<view class="table-container">
|
|
<view class="table-header">
|
|
<view class="th col-id"><text class="th-txt">序号</text></view>
|
|
<view class="th col-title"><text class="th-txt">账单周期</text></view>
|
|
<view class="th col-date"><text class="th-txt">具体日期/周期</text></view>
|
|
<view class="th col-income"><text class="th-txt">收入金额</text></view>
|
|
<view class="th col-expense"><text class="th-txt">支出金额</text></view>
|
|
<view class="th col-entry"><text class="th-txt">净入账</text></view>
|
|
<view class="th col-ops"><text class="th-txt">操作</text></view>
|
|
</view>
|
|
|
|
<view class="table-body">
|
|
<view v-if="loading" class="table-loading" style="padding: 40px; text-align: center;">
|
|
<text>加载中...</text>
|
|
</view>
|
|
<view v-else-if="tableData.length === 0" class="table-empty" style="padding: 40px; text-align: center;">
|
|
<text>暂无账单数据</text>
|
|
</view>
|
|
<view v-else class="table-row" v-for="(item, index) in tableData" :key="index">
|
|
<view class="td col-id"><text class="td-txt">{{ index + 1 }}</text></view>
|
|
<view class="td col-title text-left"><text class="td-txt">{{ intervalOptions[currentTab].label }}</text></view>
|
|
<view class="td col-date"><text class="td-txt">{{ item.date_group }}</text></view>
|
|
<view class="td col-income"><text class="td-txt red-txt">¥{{ item.income.toFixed(2) }}</text></view>
|
|
<view class="td col-expense"><text class="td-txt green-txt">¥{{ item.expense.toFixed(2) }}</text></view>
|
|
<view class="td col-entry"><text class="td-txt">¥{{ item.net_entry.toFixed(2) }}</text></view>
|
|
<view class="td col-ops">
|
|
<view class="ops-wrap">
|
|
<text class="op-link">查看流水</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup lang="uts">
|
|
import { ref, onMounted } from 'vue'
|
|
import { fetchFinanceBillSummary } from '@/services/admin/financeService.uts'
|
|
|
|
const currentTab = ref(0)
|
|
const loading = ref(false)
|
|
const tableData = ref<any[]>([])
|
|
|
|
const intervalOptions = [
|
|
{ label: '日账单', value: 'day' },
|
|
{ label: '周账单', value: 'week' },
|
|
{ label: '月账单', value: 'month' }
|
|
]
|
|
|
|
async function loadData() {
|
|
loading.value = true
|
|
const endTime = new Date().toISOString()
|
|
const startTime = new Date(Date.now() - 90 * 24 * 60 * 60 * 1000).toISOString() // 默认查最近90天
|
|
|
|
try {
|
|
const res = await fetchFinanceBillSummary(
|
|
startTime,
|
|
endTime,
|
|
intervalOptions[currentTab.value].value
|
|
)
|
|
tableData.value = res
|
|
} catch (e) {
|
|
uni.showToast({ title: '加载账单失败', icon: 'none' })
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
onMounted(() => {
|
|
loadData()
|
|
})
|
|
|
|
const handleTabChange = (index : number) => {
|
|
currentTab.value = index
|
|
loadData()
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.finance-bill {
|
|
padding: 20px;
|
|
background-color: #f5f7fa;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.border-shadow {
|
|
background-color: #fff;
|
|
border-radius: 4px;
|
|
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.05);
|
|
}
|
|
|
|
/* 筛选 */
|
|
.filter-card {
|
|
padding: 24px;
|
|
margin-bottom: 20px;
|
|
}
|
|
|
|
.filter-row {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.filter-item {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.filter-label {
|
|
font-size: 14px;
|
|
color: #333;
|
|
margin-right: 12px;
|
|
}
|
|
|
|
.date-picker-wrap {
|
|
width: 280px;
|
|
height: 36px;
|
|
border: 1px solid #dcdfe6;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
padding: 0 12px;
|
|
}
|
|
|
|
.calendar-icon {
|
|
font-size: 14px;
|
|
margin-right: 8px;
|
|
color: #c0c4cc;
|
|
}
|
|
|
|
.date-placeholder {
|
|
font-size: 14px;
|
|
color: #c0c4cc;
|
|
}
|
|
|
|
/* 内容卡片 */
|
|
.content-card {
|
|
padding: 0;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.tab-header {
|
|
display: flex;
|
|
flex-direction: row;
|
|
padding: 0 20px;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.tab-item {
|
|
padding: 16px 20px;
|
|
cursor: pointer;
|
|
position: relative;
|
|
}
|
|
|
|
.tab-item.active::after {
|
|
content: '';
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 20%;
|
|
right: 20%;
|
|
height: 2px;
|
|
background-color: #1890ff;
|
|
}
|
|
|
|
.tab-txt {
|
|
font-size: 14px;
|
|
color: #666;
|
|
}
|
|
|
|
.active-txt {
|
|
color: #1890ff;
|
|
font-weight: 500;
|
|
}
|
|
|
|
/* 表格样式 */
|
|
.table-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.table-header {
|
|
background-color: #e6f0ff;
|
|
display: flex;
|
|
flex-direction: row;
|
|
}
|
|
|
|
.th {
|
|
padding: 14px 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.th-txt {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #303133;
|
|
}
|
|
|
|
.table-row {
|
|
display: flex;
|
|
flex-direction: row;
|
|
border-bottom: 1px solid #f0f0f0;
|
|
}
|
|
|
|
.table-row:hover {
|
|
background-color: #fafafa;
|
|
}
|
|
|
|
.td {
|
|
padding: 16px 10px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.td-txt {
|
|
font-size: 14px;
|
|
color: #606266;
|
|
}
|
|
|
|
.col-id { width: 80px; }
|
|
.col-title { width: 150px; }
|
|
.col-date { width: 220px; }
|
|
.col-income { width: 180px; }
|
|
.col-expense { width: 180px; }
|
|
.col-entry { width: 180px; }
|
|
.col-ops { flex: 1; min-width: 150px; }
|
|
|
|
.text-left {
|
|
justify-content: flex-start;
|
|
}
|
|
|
|
.red-txt {
|
|
color: #f5222d;
|
|
}
|
|
|
|
.green-txt {
|
|
color: #52c41a;
|
|
}
|
|
|
|
.ops-wrap {
|
|
display: flex;
|
|
flex-direction: row;
|
|
align-items: center;
|
|
}
|
|
|
|
.op-link {
|
|
font-size: 14px;
|
|
color: #1890ff;
|
|
cursor: pointer;
|
|
}
|
|
</style>
|