优化结构

This commit is contained in:
Yvan
2026-08-29 08:40:15 +08:00
parent b6d25c1a0f
commit 509df03d61
17 changed files with 234 additions and 40 deletions
@@ -265,6 +265,12 @@ const TARGETS = {
description: 'RabbitMQ 消息队列',
icon: Promotion
},
'mq/kafka': {
name: 'Kafka',
protocol: 'Kafka',
description: 'Apache Kafka 分布式事件队列',
icon: Promotion
},
'websocket/melody': {
name: 'WebSocket',
protocol: 'WS',
@@ -276,7 +282,7 @@ const TARGETS = {
const TARGET_ORDER = Object.keys(TARGETS)
const RECONNECT_INTERVAL_KEY = 'reconnect_interval'
const RECONNECT_DEFAULT_SECONDS = 5
const MQ_RECONNECT_TARGETS = new Set(['mq/emqx', 'mq/rabbitmq'])
const MQ_RECONNECT_TARGETS = new Set(['mq/emqx', 'mq/kafka', 'mq/rabbitmq'])
const RECONNECT_INTERVAL_FIELD = {
key: RECONNECT_INTERVAL_KEY,
label: '重连间隔(秒)',
@@ -291,6 +297,9 @@ const NUMBER_CONSTRAINTS = {
reconnect_interval: { min: 1, integer: true },
prefetch_count: { min: 0 },
heartbeat: { min: 0 },
min_bytes: { min: 1, integer: true },
max_bytes: { min: 1, integer: true },
max_wait: { min: 1 },
max_message_size: { min: 0 },
message_buffer_size: { min: 0 }
}
+9 -5
View File
@@ -78,7 +78,7 @@
<el-table-column label="订单与交易" min-width="285">
<template #default="scope">
<div class="order-cell">
<button type="button" class="order-link" @click="openDetail(scope.row)">{{ scope.row.tradeNo || '-' }}</button>
<span class="order-title-line"><button type="button" class="order-link" @click="openDetail(scope.row)">{{ scope.row.tradeNo || '-' }}</button><el-tag v-if="isDemoOrder(scope.row)" size="small" type="info" effect="plain">演示</el-tag></span>
<span v-if="scope.row.providerTradeNo">渠道单号 {{ scope.row.providerTradeNo }}</span>
<span>{{ scope.row.businessType || '-' }} · {{ scope.row.businessId || '-' }}</span>
</div>
@@ -140,6 +140,7 @@
<div class="mobile-order-meta"><span>{{ order.businessType || '-' }} · {{ order.businessId || '-' }}</span><span>{{ formatDateValue(order.createdAt) }}</span></div>
<div class="mobile-order-footer">
<div class="status-stack">
<el-tag v-if="isDemoOrder(order)" size="small" type="info" effect="plain">演示</el-tag>
<el-tag size="small" :type="paymentStatusType(order.paymentStatus)">{{ paymentStatusText(order.paymentStatus) }}</el-tag>
<el-tag size="small" :type="fulfillmentStatusType(order.fulfillmentStatus)" effect="plain">{{ fulfillmentStatusText(order.fulfillmentStatus, order) }}</el-tag>
<el-tag v-if="order.refundStatus !== 'none'" size="small" :type="refundStatusType(order.refundStatus)" effect="plain">{{ refundStatusText(order.refundStatus) }}</el-tag>
@@ -165,6 +166,7 @@
<template v-if="detail">
<div class="detail-toolbar">
<div class="detail-statuses">
<el-tag v-if="isDemoOrder(detail)" type="info" effect="plain">演示订单</el-tag>
<el-tag :type="paymentStatusType(detail.paymentStatus)">{{ paymentStatusText(detail.paymentStatus) }}</el-tag>
<el-tag :type="fulfillmentStatusType(detail.fulfillmentStatus)" effect="plain">{{ fulfillmentStatusText(detail.fulfillmentStatus, detail) }}</el-tag>
<el-tag :type="refundStatusType(detail.refundStatus)" effect="plain">{{ refundStatusText(detail.refundStatus) }}</el-tag>
@@ -288,7 +290,7 @@ const providerNames = Object.fromEntries(providerOptions.map((item) => [item.val
Object.assign(providerNames, { admin: '后台人工操作', client: '客户端', system: '系统任务', internal: '内部支付' })
const paymentStatusOptions = Object.entries(PAYMENT_STATUS_META).map(([value, item]) => ({ value, label: item.label }))
const refundStatusOptions = Object.entries(REFUND_STATUS_META).map(([value, item]) => ({ value, label: item.label }))
const ZERO_DECIMAL_CURRENCIES = new Set(['BIF', 'CLP', 'DJF', 'GNF', 'ISK', 'JPY', 'KMF', 'KRW', 'PYG', 'RWF', 'UGX', 'UYI', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'])
const ZERO_DECIMAL_CURRENCIES = new Set(['BIF', 'CLP', 'DJF', 'GNF', 'ISK', 'JPY', 'KMF', 'KRW', 'POINT', 'PYG', 'RWF', 'UGX', 'UYI', 'VND', 'VUV', 'XAF', 'XOF', 'XPF'])
const THREE_DECIMAL_CURRENCIES = new Set(['BHD', 'IQD', 'JOD', 'KWD', 'LYD', 'OMR', 'TND'])
const FOUR_DECIMAL_CURRENCIES = new Set(['CLF', 'UYW'])
const MAX_SAFE_MINOR_AMOUNT = Number.MAX_SAFE_INTEGER
@@ -456,9 +458,10 @@ function refundStatusType(status) { return REFUND_STATUS_META[status]?.type || '
function paymentModeText(mode) { return mode === 'internal' ? '内部支付' : mode === 'external' ? '外部渠道' : mode || '-' }
function formatDateValue(value) { return value ? formatDate(value) || '-' : '-' }
function remainingRefundAmount(order) { return Math.max(0, Number(order?.amount || 0) - Number(order?.refundedAmount || 0)) }
function canRefund(order) { return ['paid', 'partially_refunded'].includes(order?.paymentStatus) && ['none', 'partial', 'failed'].includes(order?.refundStatus) && remainingRefundAmount(order) > 0 }
function canFulfill(order) { return order?.paymentStatus === 'paid' && ['pending', 'processing', 'failed'].includes(order?.fulfillmentStatus) }
function canSync(order) { return ['initialized', 'pending', 'paid', 'partially_refunded', 'refunded', 'failed'].includes(order?.paymentStatus) }
function isDemoOrder(order) { return order?.businessType === 'demo_subscription' && String(order?.tradeNo || '').startsWith('DEMO-PAY-') }
function canRefund(order) { return !isDemoOrder(order) && ['paid', 'partially_refunded'].includes(order?.paymentStatus) && ['none', 'partial', 'failed'].includes(order?.refundStatus) && remainingRefundAmount(order) > 0 }
function canFulfill(order) { return !isDemoOrder(order) && order?.paymentStatus === 'paid' && ['pending', 'processing', 'failed'].includes(order?.fulfillmentStatus) }
function canSync(order) { return !isDemoOrder(order) && ['initialized', 'pending', 'paid', 'partially_refunded', 'refunded', 'failed'].includes(order?.paymentStatus) }
function fulfillmentActionText(order) { return ['processing', 'failed'].includes(order?.fulfillmentStatus) ? '重试发货' : '执行发货' }
function isIssueOrder(order) { return order?.paymentStatus === 'failed' || order?.fulfillmentStatus === 'failed' || order?.refundStatus === 'failed' || Boolean(order?.lastError) }
function rowClassName({ row }) { return isIssueOrder(row) ? 'is-payment-issue' : '' }
@@ -645,6 +648,7 @@ onMounted(load)
.issue-count { color: var(--el-color-danger) !important; }
.order-cell, .business-cell, .provider-cell, .amount-cell { display: grid; min-width: 0; gap: 5px; }
.order-link { overflow: hidden; padding: 0; border: 0; background: transparent; color: var(--el-color-primary); font: inherit; font-weight: 500; text-align: left; text-overflow: ellipsis; white-space: nowrap; cursor: pointer; }
.order-title-line { display: flex; align-items: center; gap: 6px; min-width: 0; }
.order-cell > span, .business-cell small, .provider-cell small, .amount-cell small { overflow: hidden; color: var(--el-text-color-secondary); font-size: 11px; text-overflow: ellipsis; white-space: nowrap; }
.business-cell > span, .provider-cell > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.amount-cell { justify-items: end; }