功能添加
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 20s
Docker Build & Deploy / Deploy to Production (push) Successful in 5s

This commit is contained in:
孙诚
2025-12-26 15:21:31 +08:00
parent 7dfb6a5902
commit cb11d80d1f
26 changed files with 2208 additions and 841 deletions

View File

@@ -11,47 +11,74 @@
v-for="transaction in transactions"
:key="transaction.id"
>
<div
class="transaction-card"
@click="handleClick(transaction)"
>
<div class="card-left">
<div class="transaction-title">
<span class="reason">{{ transaction.reason || '(无摘要)' }}</span>
<div class="transaction-row">
<van-checkbox
v-if="showCheckbox"
:model-value="isSelected(transaction.id)"
@update:model-value="toggleSelection(transaction)"
class="checkbox-col"
/>
<div
class="transaction-card"
@click="handleClick(transaction)"
>
<div class="card-left">
<div class="transaction-title">
<span class="reason">{{ transaction.reason || '(无摘要)' }}</span>
</div>
<div class="transaction-info">
<div>交易时间: {{ formatDate(transaction.occurredAt) }}</div>
<div>
<span v-if="transaction.classify">
分类: {{ transaction.classify }}
</span>
<span v-if="transaction.upsetedClassify && transaction.upsetedClassify !== transaction.classify" style="color: #ff976a">
{{ transaction.upsetedClassify }}
</span>
</div>
<div v-if="transaction.card">
卡号: {{ transaction.card }}
</div>
<div v-if="transaction.importFrom">
来源: {{ transaction.importFrom }}
</div>
</div>
</div>
<div class="card-middle">
<van-tag
:type="getTypeTagType(transaction.type)"
size="medium"
>
{{ getTypeName(transaction.type) }}
</van-tag>
<template
v-if="Number.isFinite(transaction.upsetedType) && transaction.upsetedType !== transaction.type"
>
<van-tag
:type="getTypeTagType(transaction.upsetedType)"
size="medium"
>
{{ getTypeName(transaction.upsetedType) }}
</van-tag>
</template>
</div>
<div class="transaction-info">
<div>交易时间: {{ formatDate(transaction.occurredAt) }}</div>
<div v-if="transaction.classify">分类: {{ transaction.classify }}
<span v-if="transaction.subClassify">/ {{ transaction.subClassify }}</span>
</div>
<div v-if="transaction.card">
卡号: {{ transaction.card }}
</div>
<div v-if="transaction.importFrom">
来源: {{ transaction.importFrom }}
<div class="card-right">
<div class="transaction-amount">
<div :class="['amount', getAmountClass(transaction.type)]">
{{ formatAmount(transaction.amount, transaction.type) }}
</div>
<div class="balance" v-if="transaction.balance && transaction.balance > 0">
余额: {{ formatMoney(transaction.balance) }}
</div>
<div class="balance" v-if="transaction.refundAmount && transaction.refundAmount > 0">
退款: {{ formatMoney(transaction.refundAmount) }}
</div>
</div>
<van-icon name="arrow" size="16" color="#c8c9cc" />
</div>
</div>
<div class="card-right">
<div class="transaction-amount">
<div :class="['amount', getAmountClass(transaction.type)]">
{{ formatAmount(transaction.amount, transaction.type) }}
</div>
<div class="balance" v-if="transaction.balance && transaction.balance > 0">
余额: {{ formatMoney(transaction.balance) }}
</div>
<div class="balance" v-if="transaction.refundAmount && transaction.refundAmount > 0">
退款: {{ formatMoney(transaction.refundAmount) }}
</div>
</div>
<van-icon name="arrow" size="16" color="#c8c9cc" />
</div>
</div>
<template #right v-if="showDelete">
<van-button
@@ -76,7 +103,7 @@
<script setup>
import { defineEmits } from 'vue'
defineProps({
const props = defineProps({
transactions: {
type: Array,
default: () => []
@@ -92,10 +119,18 @@ defineProps({
showDelete: {
type: Boolean,
default: true
},
showCheckbox: {
type: Boolean,
default: false
},
selectedIds: {
type: Set,
default: () => new Set()
}
})
const emit = defineEmits(['load', 'click', 'delete'])
const emit = defineEmits(['load', 'click', 'delete', 'update:selectedIds'])
const onLoad = () => {
emit('load')
@@ -109,6 +144,20 @@ const handleDeleteClick = (transaction) => {
emit('delete', transaction)
}
const isSelected = (id) => {
return props.selectedIds.has(id)
}
const toggleSelection = (transaction) => {
const newSelectedIds = new Set(props.selectedIds)
if (newSelectedIds.has(transaction.id)) {
newSelectedIds.delete(transaction.id)
} else {
newSelectedIds.add(transaction.id)
}
emit('update:selectedIds', newSelectedIds)
}
// 获取交易类型名称
const getTypeName = (type) => {
const typeMap = {
@@ -168,6 +217,18 @@ const formatDate = (dateString) => {
width: 100%;
}
.transaction-row {
display: flex;
align-items: center;
width: 100%;
overflow: hidden;
}
.checkbox-col {
padding: 12px 8px;
flex-shrink: 0;
}
.transaction-card {
display: flex;
justify-content: space-between;
@@ -175,12 +236,27 @@ const formatDate = (dateString) => {
padding: 12px 16px;
cursor: pointer;
transition: background-color 0.3s;
flex: 1;
min-width: 0;
overflow: hidden;
position: relative;
}
.card-left {
flex: 1;
min-width: 0;
padding-right: 12px;
overflow: hidden;
}
.card-middle {
position: absolute;
top: 12px;
right: 20px;
display: flex;
align-items: center;
gap: 8px;
z-index: 1;
}
.card-right {
@@ -191,14 +267,13 @@ const formatDate = (dateString) => {
}
.transaction-title {
display: flex;
align-items: center;
font-weight: bold;
margin-bottom: 8px;
gap: 8px;
overflow: hidden;
}
.reason {
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
@@ -212,6 +287,14 @@ const formatDate = (dateString) => {
line-height: 1.6;
}
.original-info {
color: #ff976a;
font-style: italic;
display: flex;
align-items: center;
gap: 4px;
}
.transaction-amount {
text-align: right;
display: flex;
@@ -235,10 +318,6 @@ const formatDate = (dateString) => {
color: #07c160;
}
.amount.neutral {
color: #646566;
}
.balance {
font-size: 12px;
color: #969799;