feat(M08-B): 补微信转账预检
This commit is contained in:
+9
-1
@@ -4,7 +4,8 @@ import type {
|
||||
PageResult,
|
||||
SettlementStatus,
|
||||
TaskStatus,
|
||||
TransferMode
|
||||
TransferMode,
|
||||
WechatTransferPreflight
|
||||
} from './types';
|
||||
|
||||
const API_BASE = (import.meta.env.VITE_ADMIN_API_BASE_URL || '/admin-api').replace(/\/$/, '');
|
||||
@@ -143,6 +144,13 @@ export function executeWechatTransfer(
|
||||
);
|
||||
}
|
||||
|
||||
export function preflightWechatTransfer(session: ApiSession, settlementId: string) {
|
||||
return request<WechatTransferPreflight>(
|
||||
session,
|
||||
`/cleaning/settlements/${encodeURIComponent(settlementId)}/wechat-transfer/preflight`
|
||||
);
|
||||
}
|
||||
|
||||
export function syncWechatTransfer(session: ApiSession, settlementId: string, note?: string) {
|
||||
return request<{ settlement: CleaningSettlement; transferState: string; idempotent: boolean }>(
|
||||
session,
|
||||
|
||||
@@ -57,6 +57,14 @@
|
||||
>
|
||||
确认
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
:icon="ClipboardCheck"
|
||||
:disabled="row.status !== 'CONFIRMED'"
|
||||
@click="openPreflight(row)"
|
||||
>
|
||||
预检
|
||||
</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@@ -135,6 +143,34 @@
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="preflightDialog.open" title="微信转账预检" width="560px">
|
||||
<div v-if="preflightDialog.result" class="preflight-summary">
|
||||
<el-alert
|
||||
:title="preflightDialog.result.ready ? '真实转账前置条件已通过' : '仍有阻断项需要处理'"
|
||||
:type="preflightDialog.result.ready ? 'success' : 'warning'"
|
||||
show-icon
|
||||
:closable="false"
|
||||
/>
|
||||
<div class="preflight-meta">
|
||||
<span>结算单 {{ preflightDialog.result.settlement.settlementNo }}</span>
|
||||
<span>商户 {{ compactText(preflightDialog.result.account.merchantIdMasked) }}</span>
|
||||
<span>场景 {{ compactText(preflightDialog.result.credential.transferSceneId) }}</span>
|
||||
</div>
|
||||
<el-table :data="preflightDialog.result.checks" size="small" class="preflight-table">
|
||||
<el-table-column prop="key" label="检查项" width="170" />
|
||||
<el-table-column prop="status" label="状态" width="90">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="preflightTag(row.status)" effect="light">{{ row.status }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="message" label="说明" min-width="220" />
|
||||
</el-table>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="preflightDialog.open = false">关闭</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
||||
<el-dialog v-model="failureDialog.open" title="记录失败" width="420px">
|
||||
<el-form label-position="top">
|
||||
<el-form-item label="失败原因">
|
||||
@@ -159,19 +195,23 @@ import { reactive } from 'vue';
|
||||
import {
|
||||
BadgeCheck,
|
||||
CircleAlert,
|
||||
ClipboardCheck,
|
||||
FilePlus2,
|
||||
RefreshCw,
|
||||
Send
|
||||
} from '@lucide/vue';
|
||||
import { ElMessage } from 'element-plus';
|
||||
import { preflightWechatTransfer } from '../api';
|
||||
import { compactText, money, shortDate } from '../format';
|
||||
import type {
|
||||
CleaningSettlement,
|
||||
PageResult,
|
||||
SettlementStatus,
|
||||
TransferMode
|
||||
TransferMode,
|
||||
WechatTransferPreflight
|
||||
} from '../types';
|
||||
|
||||
defineProps<{
|
||||
const props = defineProps<{
|
||||
session: { token: string };
|
||||
loading: boolean;
|
||||
items: PageResult<CleaningSettlement>['items'];
|
||||
@@ -206,6 +246,13 @@ const transferDialog = reactive({
|
||||
mode: 'API' as TransferMode,
|
||||
note: ''
|
||||
});
|
||||
const preflightDialog = reactive<{
|
||||
open: boolean;
|
||||
result: WechatTransferPreflight | null;
|
||||
}>({
|
||||
open: false,
|
||||
result: null
|
||||
});
|
||||
const failureDialog = reactive({
|
||||
open: false,
|
||||
settlementId: '',
|
||||
@@ -221,6 +268,12 @@ function settlementTag(status: SettlementStatus) {
|
||||
return 'primary';
|
||||
}
|
||||
|
||||
function preflightTag(status: string) {
|
||||
if (status === 'PASS') return 'success';
|
||||
if (status === 'WARN') return 'warning';
|
||||
return 'danger';
|
||||
}
|
||||
|
||||
function submitGenerate() {
|
||||
emit('generate', {
|
||||
cleanerUserId: generateDialog.cleanerUserId,
|
||||
@@ -246,6 +299,15 @@ function submitTransfer() {
|
||||
transferDialog.open = false;
|
||||
}
|
||||
|
||||
async function openPreflight(row: CleaningSettlement) {
|
||||
try {
|
||||
preflightDialog.result = await preflightWechatTransfer(props.session, row.id);
|
||||
preflightDialog.open = true;
|
||||
} catch (error) {
|
||||
ElMessage.error(error instanceof Error ? error.message : '微信转账预检失败');
|
||||
}
|
||||
}
|
||||
|
||||
function openFailure(row: CleaningSettlement) {
|
||||
failureDialog.open = true;
|
||||
failureDialog.settlementId = row.id;
|
||||
|
||||
@@ -228,6 +228,33 @@ textarea {
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.preflight-summary {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
}
|
||||
|
||||
.preflight-meta {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, minmax(0, 1fr));
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.preflight-meta span {
|
||||
min-width: 0;
|
||||
padding: 8px 10px;
|
||||
overflow: hidden;
|
||||
color: #334155;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
background: #f5f8fb;
|
||||
border: 1px solid #e1e8f0;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.preflight-table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.el-button {
|
||||
border-radius: 8px;
|
||||
}
|
||||
@@ -296,4 +323,8 @@ textarea {
|
||||
.toolbar-actions {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.preflight-meta {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,3 +68,44 @@ export interface CleaningSettlement {
|
||||
note: string;
|
||||
createdAt: string;
|
||||
}
|
||||
|
||||
export type WechatTransferPreflightStatus = 'PASS' | 'WARN' | 'FAIL';
|
||||
|
||||
export interface WechatTransferPreflightCheck {
|
||||
key: string;
|
||||
status: WechatTransferPreflightStatus;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface WechatTransferPreflight {
|
||||
ready: boolean;
|
||||
settlement: {
|
||||
id: string;
|
||||
settlementNo: string;
|
||||
status: SettlementStatus;
|
||||
totalRewardCents: number;
|
||||
cleanerUserId: string;
|
||||
storeId: string | null;
|
||||
};
|
||||
account: {
|
||||
configured: boolean;
|
||||
id?: string;
|
||||
storeScoped?: boolean;
|
||||
merchantIdMasked?: string;
|
||||
credentialRefMasked?: string;
|
||||
authorizationStatus?: string;
|
||||
};
|
||||
credential: {
|
||||
configured: boolean;
|
||||
appIdPresent?: boolean;
|
||||
serialNoPresent?: boolean;
|
||||
transferSceneId?: string;
|
||||
reportInfoCount?: number;
|
||||
transferNotifyUrlConfigured?: boolean;
|
||||
platformCertificateCount?: number;
|
||||
};
|
||||
cleaner: {
|
||||
openidConfigured: boolean;
|
||||
};
|
||||
checks: WechatTransferPreflightCheck[];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user