feat(M08-B): 补结算批量同步
This commit is contained in:
@@ -131,6 +131,7 @@
|
||||
@confirm="handleConfirmSettlement"
|
||||
@transfer="handleTransfer"
|
||||
@sync-transfer="handleSyncTransfer"
|
||||
@sync-transfer-many="handleSyncTransferMany"
|
||||
@failure="handleFailure"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@@ -478,6 +479,15 @@ async function handleSyncTransfer(input: { settlementId: string; note?: string }
|
||||
}, '已同步微信状态');
|
||||
}
|
||||
|
||||
async function handleSyncTransferMany(input: { settlementIds: string[]; note?: string }) {
|
||||
await runAction(async () => {
|
||||
for (const settlementId of input.settlementIds) {
|
||||
await syncWechatTransfer(session.value, settlementId, input.note);
|
||||
}
|
||||
await Promise.all([loadSettlements(), loadStatistics()]);
|
||||
}, `已批量同步 ${input.settlementIds.length} 个结算单`);
|
||||
}
|
||||
|
||||
async function handleFailure(
|
||||
input: { settlementId: string; error: string; payoutReference?: string; note?: string }
|
||||
) {
|
||||
|
||||
@@ -34,6 +34,13 @@
|
||||
<el-button :icon="Search" @click="submitFilters">筛选</el-button>
|
||||
</div>
|
||||
<div class="toolbar-actions">
|
||||
<el-button
|
||||
:icon="RefreshCw"
|
||||
:disabled="selectedSyncableCount === 0"
|
||||
@click="submitBatchSync"
|
||||
>
|
||||
批量同步
|
||||
</el-button>
|
||||
<el-button :icon="Download" :disabled="items.length === 0" @click="exportSettlements">
|
||||
导出
|
||||
</el-button>
|
||||
@@ -49,7 +56,14 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<el-table :data="items" :loading="loading" class="data-table" row-key="id">
|
||||
<el-table
|
||||
:data="items"
|
||||
:loading="loading"
|
||||
class="data-table"
|
||||
row-key="id"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column type="selection" width="44" :selectable="canSelectSettlement" />
|
||||
<el-table-column prop="settlementNo" label="结算单" min-width="190" fixed>
|
||||
<template #default="{ row }">
|
||||
<div class="stack">
|
||||
@@ -347,7 +361,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, reactive, watch } from 'vue';
|
||||
import { computed, reactive, ref, watch } from 'vue';
|
||||
import {
|
||||
BadgeCheck,
|
||||
CircleAlert,
|
||||
@@ -398,6 +412,7 @@ const emit = defineEmits<{
|
||||
confirm: [{ settlementId: string; note?: string }];
|
||||
transfer: [{ settlementId: string; mode: TransferMode; note?: string }];
|
||||
'sync-transfer': [{ settlementId: string; note?: string }];
|
||||
'sync-transfer-many': [{ settlementIds: string[]; note?: string }];
|
||||
failure: [{ settlementId: string; error: string; payoutReference?: string; note?: string }];
|
||||
}>();
|
||||
|
||||
@@ -409,6 +424,7 @@ const statusOptions = [
|
||||
{ label: '取消', value: 'CANCELLED' }
|
||||
];
|
||||
const filterDraft = reactive({ storeId: props.filters.storeId, cleanerUserId: props.filters.cleanerUserId });
|
||||
const selectedSettlements = ref<CleaningSettlement[]>([]);
|
||||
const generateDialog = reactive({ open: false, cleanerUserId: '', storeId: '', note: '' });
|
||||
const transferDialog = reactive({
|
||||
open: false,
|
||||
@@ -462,6 +478,9 @@ const candidateDialog = reactive<{
|
||||
});
|
||||
const candidatePageRewardCents = computed(() => candidateDialog.items
|
||||
.reduce((sum, item) => sum + item.rewardCents, 0));
|
||||
const selectedSyncableSettlements = computed(() => selectedSettlements.value
|
||||
.filter((settlement) => settlement.status === 'CONFIRMED'));
|
||||
const selectedSyncableCount = computed(() => selectedSyncableSettlements.value.length);
|
||||
|
||||
function settlementTag(status: SettlementStatus) {
|
||||
if (status === 'PAID') return 'success';
|
||||
@@ -476,6 +495,14 @@ function preflightTag(status: string) {
|
||||
return 'danger';
|
||||
}
|
||||
|
||||
function canSelectSettlement(row: CleaningSettlement) {
|
||||
return row.status === 'CONFIRMED';
|
||||
}
|
||||
|
||||
function handleSelectionChange(rows: CleaningSettlement[]) {
|
||||
selectedSettlements.value = rows;
|
||||
}
|
||||
|
||||
function cleanerLabel(cleaner: ManagedUser) {
|
||||
const name = cleaner.nickname || `ID ${cleaner.id}`;
|
||||
const phone = cleaner.maskedPhone ? ` · ${cleaner.maskedPhone}` : '';
|
||||
@@ -519,6 +546,18 @@ function submitTransfer() {
|
||||
transferDialog.open = false;
|
||||
}
|
||||
|
||||
function submitBatchSync() {
|
||||
const settlementIds = selectedSyncableSettlements.value.map((settlement) => settlement.id);
|
||||
if (!settlementIds.length) {
|
||||
ElMessage.warning('请选择待发放结算单');
|
||||
return;
|
||||
}
|
||||
emit('sync-transfer-many', {
|
||||
settlementIds,
|
||||
note: '后台批量同步微信转账状态'
|
||||
});
|
||||
}
|
||||
|
||||
async function openPreflight(row: CleaningSettlement) {
|
||||
try {
|
||||
preflightDialog.result = await preflightWechatTransfer(props.session, row.id);
|
||||
|
||||
Reference in New Issue
Block a user