解决了/transfers按钮显示及交互的相关问题

This commit is contained in:
2025-08-12 16:38:44 +08:00
parent 99feae7c59
commit 81506b4a8f

View File

@@ -5,9 +5,6 @@
<div class="nav-center"> <div class="nav-center">
<h1 class="nav-title">货款管理</h1> <h1 class="nav-title">货款管理</h1>
</div> </div>
<div class="nav-right">
<!-- 移除发起转账按钮 -->
</div>
</nav> </nav>
<!-- 待转账 --> <!-- 待转账 -->
@@ -69,6 +66,17 @@
已回款 已回款
</el-tag> </el-tag>
</div> </div>
<!-- 回款确认按钮 -->
<div v-if="!allocation.return_date && canConfirmReturn(allocation)" class="return-action">
<el-button
type="success"
size="small"
@click="showReturnConfirmDialog(allocation)"
>
确认收到回款
</el-button>
</div>
</div> </div>
<!-- 超时警告 --> <!-- 超时警告 -->
@@ -122,7 +130,7 @@
@click="statusFilter = ''" @click="statusFilter = ''"
> >
<span class="filter-text">全部</span> <span class="filter-text">全部</span>
<span class="filter-count">{{ totalCount }}</span> <span class="filter-count">{{ pagination.total }}</span>
</div> </div>
<div <div
class="filter-item" class="filter-item"
@@ -195,7 +203,7 @@
</div> </div>
<!-- 确认收款操作按钮 --> <!-- 确认收款操作按钮 -->
<div <div
v-if="transfer.status === 'confirmed' && transfer.to_user_id !== userStore.user.id" v-if="transfer.status === 'confirmed' && transfer.to_user_id === userStore.user.id"
class="transfer-actions" class="transfer-actions"
> >
<el-button <el-button
@@ -223,6 +231,20 @@
<el-empty :description="statusFilter === 'pending' ? '暂无待确认的转账' : '暂无转账记录'" /> <el-empty :description="statusFilter === 'pending' ? '暂无待确认的转账' : '暂无转账记录'" />
</div> </div>
</div> </div>
<!-- 分页 -->
<div class="pagination" v-if="pagination.total > 0">
<el-pagination
v-model:current-page="pagination.page"
v-model:page-size="pagination.limit"
:page-sizes="[10, 20, 50]"
:total="pagination.total"
:layout="paginationLayout"
:small="isMobile"
@size-change="loadTransferHistory"
@current-change="loadTransferHistory"
/>
</div>
</el-card> </el-card>
</div> </div>
@@ -292,6 +314,45 @@
</span> </span>
</template> </template>
</el-dialog> </el-dialog>
<!-- 回款确认对话框 -->
<el-dialog
v-model="showReturnDialog"
title="确认回款"
width="90%"
:style="{ maxWidth: '500px' }"
>
<el-form :model="returnForm" label-width="100px">
<el-form-item label="回款金额">
<el-input-number
v-model="returnForm.returnAmount"
:min="0"
:precision="2"
controls-position="right"
/>
</el-form-item>
<el-form-item label="备注说明">
<el-input
v-model="returnForm.description"
type="textarea"
:rows="3"
/>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="showReturnDialog = false">取消</el-button>
<el-button
type="success"
@click="confirmReturn"
:loading="confirmLoading"
>
确认回款
</el-button>
</span>
</template>
</el-dialog>
</div> </div>
</template> </template>
@@ -311,24 +372,11 @@ const userStore = useUserStore()
const loading = ref(false) const loading = ref(false)
const submitLoading = ref(false) const submitLoading = ref(false)
const confirmLoading = ref(false) const confirmLoading = ref(false)
const showCreateTransfer = ref(false)
const showVoucherDialog = ref(false) const showVoucherDialog = ref(false)
const showReturnDialog = ref(false)
const statusFilter = ref('') const statusFilter = ref('')
const currentTransfer = ref({}) const currentTransfer = ref({})
const currentAllocation = ref({}) const currentAllocation = ref({})
const confirmFormRef = ref(null)
const confirmForm = reactive({
confirmedAmount: '',
remarks: ''
})
const confirmRules = {
confirmedAmount: [
{ required: true, message: '请输入实际收到的金额', trigger: 'blur' },
{ type: 'number', min: 0, message: '金额必须大于0', trigger: 'blur' }
]
}
const pendingTransfers = ref([]) const pendingTransfers = ref([])
const pendingAllocations = ref([]) const pendingAllocations = ref([])
@@ -336,26 +384,48 @@ const allTransferHistory = ref([])
const filteredTransferHistory = ref([]) const filteredTransferHistory = ref([])
const userList = ref([]) const userList = ref([])
// 移动端检测 const pagination = reactive({
page: 1,
limit: 10,
total: 0
})
const returnForm = reactive({
returnAmount: '',
description: ''
})
// 移动端检测和分页布局
const windowWidth = ref(window.innerWidth) const windowWidth = ref(window.innerWidth)
const isMobile = computed(() => { const isMobile = computed(() => {
return windowWidth.value <= 768 return windowWidth.value <= 768
}) })
const paginationLayout = computed(() => {
if (windowWidth.value <= 480) {
return 'prev, pager, next'
} else if (windowWidth.value <= 768) {
return 'total, prev, pager, next'
} else {
return 'total, sizes, prev, pager, next, jumper'
}
})
// 计算属性 // 计算属性
const totalCount = computed(() => allTransferHistory.value.length)
const pendingCount = computed(() => { const pendingCount = computed(() => {
return allTransferHistory.value.filter(t => return allTransferHistory.value.filter(t =>
t.status === 'pending' && t.status === 'pending' &&
t.to_user_id === userStore.user.id t.to_user_id === userStore.user.id
).length ).length
}) })
const confirmedCount = computed(() => { const confirmedCount = computed(() => {
return allTransferHistory.value.filter(t => return allTransferHistory.value.filter(t =>
t.status === 'confirmed' t.status === 'confirmed'
).length ).length
}) })
const rejectedCount = computed(() => { const rejectedCount = computed(() => {
return allTransferHistory.value.filter(t => return allTransferHistory.value.filter(t =>
t.status === 'rejected' t.status === 'rejected'
@@ -382,22 +452,11 @@ onUnmounted(() => {
// 监听状态筛选 // 监听状态筛选
watch(statusFilter, () => { watch(statusFilter, () => {
filteredTransferHistory.value = filterTransfers(allTransferHistory.value) pagination.page = 1
loadTransferHistory()
}) })
// 方法 // 方法
const filterTransfers = (transfers) => {
if (!statusFilter.value) return transfers
return transfers.filter(transfer => {
if (statusFilter.value === 'pending') {
return transfer.status === 'pending' &&
transfer.to_user_id === userStore.user.id
}
return transfer.status === statusFilter.value
})
}
const loadPendingTransfers = async () => { const loadPendingTransfers = async () => {
try { try {
const response = await api.get('/transfers/pending', { const response = await api.get('/transfers/pending', {
@@ -431,10 +490,21 @@ const loadPendingAllocations = async () => {
const loadTransferHistory = async () => { const loadTransferHistory = async () => {
try { try {
loading.value = true loading.value = true
const response = await api.get(`/transfers/user/${userStore.user.id}`) const params = {
page: pagination.page,
limit: pagination.limit
}
if (statusFilter.value) {
params.status = statusFilter.value
}
const response = await api.get(`/transfers/user/${userStore.user.id}`, { params })
if (response.data.success) { if (response.data.success) {
allTransferHistory.value = response.data.data.transfers || [] allTransferHistory.value = response.data.data.transfers || []
filteredTransferHistory.value = filterTransfers(allTransferHistory.value) filteredTransferHistory.value = allTransferHistory.value
pagination.total = response.data.data.pagination?.total || 0
console.log(allTransferHistory.value)
} }
} catch (error) { } catch (error) {
console.error('加载转账记录失败:', error) console.error('加载转账记录失败:', error)
@@ -504,7 +574,8 @@ const getStatusText = (status) => {
confirmed: '已确认', confirmed: '已确认',
rejected: '已拒绝', rejected: '已拒绝',
received: '已收款', received: '已收款',
not_received: '未收到款' not_received: '未收到款',
cancelled: '已取消'
} }
return texts[status] || '未知' return texts[status] || '未知'
} }
@@ -560,36 +631,31 @@ const canConfirmReturn = (allocation) => {
return now >= canReturnTime return now >= canReturnTime
} }
const confirmReturn = async (allocation) => { const showReturnConfirmDialog = (allocation) => {
currentAllocation.value = allocation
returnForm.returnAmount = allocation.amount
returnForm.description = `匹配订单 ${allocation.matching_order_id} 回款确认`
showReturnDialog.value = true
}
const confirmReturn = async () => {
try { try {
await ElMessageBox.confirm(
`确定已收到¥${allocation.amount}回款吗?`,
'确认回款',
{
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning'
}
)
confirmLoading.value = true confirmLoading.value = true
const response = await api.post(`/matching/confirm-return/${allocation.id}`, { const response = await api.post(`/matching/confirm-return/${currentAllocation.value.id}`, {
returnAmount: allocation.amount, returnAmount: returnForm.returnAmount,
description: `匹配订单 ${allocation.matching_order_id} 回款确认` description: returnForm.description
}) })
if (response.data.success) { if (response.data.success) {
ElMessage.success('回款确认成功') ElMessage.success('回款确认成功')
showReturnDialog.value = false
await loadPendingAllocations() await loadPendingAllocations()
await loadTransferHistory() await loadTransferHistory()
} }
} catch (error) { } catch (error) {
if (error !== 'cancel') { console.error('确认回款失败:', error)
console.error('确认回款失败:', error) ElMessage.error(error.response?.data?.message || '确认回款失败')
const errorMsg = error.response?.data?.message || '确认回款失败'
ElMessage.error(errorMsg)
}
} finally { } finally {
confirmLoading.value = false confirmLoading.value = false
} }
@@ -777,7 +843,7 @@ const confirmNotReceived = async (transferId) => {
.transfer-item.confirmed { .transfer-item.confirmed {
border-color: #67c23a; border-color: #67c23a;
background: #f0f9ff; background: #f0f9eb;
} }
.transfer-item.rejected { .transfer-item.rejected {
@@ -917,30 +983,32 @@ const confirmNotReceived = async (transferId) => {
font-weight: 500; font-weight: 500;
} }
.return-time-status { .return-info {
font-size: 13px; margin-top: 8px;
font-weight: 500; padding-top: 8px;
margin-top: 4px; border-top: 1px dashed #ebeef5;
} }
.return-time-status.can-return { .return-time.can-return {
color: #67c23a; color: #67c23a;
font-weight: 500;
} }
.return-time-status.waiting { .return-time.waiting {
color: #e6a23c; color: #e6a23c;
} }
.return-time-status.normal { .return-status.can-return {
color: #909399; color: #67c23a;
font-weight: 500;
} }
.transfer-header .el-tag { .return-status.waiting {
margin-left: 8px; color: #e6a23c;
font-size: 11px; }
height: 20px;
line-height: 18px; .return-action {
padding: 0 6px; margin-top: 10px;
} }
.empty-state { .empty-state {
@@ -1033,15 +1101,8 @@ const confirmNotReceived = async (transferId) => {
} }
} }
} }
.confirm-form {
margin-top: 20px;
padding: 16px;
background-color: #f8f9fa;
border-radius: 8px;
}
/* 移动端适配 */
@media (max-width: 768px) { @media (max-width: 768px) {
.status-filter-nav { .status-filter-nav {
overflow-x: auto; overflow-x: auto;
@@ -1049,7 +1110,7 @@ const confirmNotReceived = async (transferId) => {
padding-bottom: 5px; padding-bottom: 5px;
.filter-item { .filter-item {
min-width: 80px; min-width: 80px; // 在移动端保持最小宽度
flex: none; flex: none;
padding: 6px 0; padding: 6px 0;
@@ -1117,4 +1178,11 @@ const confirmNotReceived = async (transferId) => {
border-radius: 12px 12px 0 0 !important; border-radius: 12px 12px 0 0 !important;
} }
} }
.pagination {
margin-top: 20px;
display: flex;
justify-content: center;
}
</style> </style>