diff --git a/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx b/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx index 6d8f1161..774872b9 100644 --- a/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx +++ b/apps/frontend/src/pages/admin/AdminKuaishouIndustryPage.tsx @@ -120,6 +120,8 @@ export default function AdminKuaishouIndustryPage() { const [actionLoading, setActionLoading] = useState('') const [consumingVoucherId, setConsumingVoucherId] = useState(null) const [vouchers, setVouchers] = useState([]) + const [selectedVoucher, setSelectedVoucher] = + useState(null) const [voucherTotal, setVoucherTotal] = useState(0) const [voucherFilters, setVoucherFilters] = useState({ oid: '', @@ -341,15 +343,21 @@ export default function AdminKuaishouIndustryPage() { ) } + const isSelected = selectedVoucher?.id === row.id return ( - ) }, }, ], - [consumingVoucherId, isSupportOnly, shopNameBySellerId], + [consumingVoucherId, isSupportOnly, selectedVoucher?.id, shopNameBySellerId], ) const refundColumns = useMemo>>( @@ -425,7 +433,14 @@ export default function AdminKuaishouIndustryPage() { page: filters.page, pageSize: filters.pageSize, }) - setVouchers(response.data.items) + const items = response.data.items + setVouchers(items) + setSelectedVoucher((current) => { + if (!current) { + return null + } + return items.find((item) => item.id === current.id) || current + }) setVoucherTotal(response.data.pagination.total) } catch (error) { showError(error instanceof Error ? error.message : '查询电子凭证失败') @@ -435,18 +450,8 @@ export default function AdminKuaishouIndustryPage() { } function selectVoucher(row: AdminKuaishouIndustryVoucher) { - setToolForm((current) => ({ - ...current, - sellerId: row.sellerId, - oid: row.oid, - orderId: row.oid, - taskId: row.taskId || '', - voucherCode: row.voucherCode, - eticketType: row.eticketType || current.eticketType || '', - serialNum: row.consumeSerialNum || current.serialNum, - reason: current.reason || 'USER_APPLY_REFUND', - })) - showSuccess('已填入券码操作区') + setSelectedVoucher(row) + showSuccess(`已选择券码 ${row.voucherCode}`) } async function runCheckAvailable() { @@ -688,9 +693,17 @@ export default function AdminKuaishouIndustryPage() { } function buildVoucherToolPayload(): AdminKuaishouIndustryVoucherToolPayload { - const voucherCode = String(toolForm.voucherCode || '').trim() + const voucherCode = String(selectedVoucher?.voucherCode || toolForm.voucherCode || '').trim() + const oid = String(selectedVoucher?.oid || toolForm.oid || toolForm.orderId || '').trim() return { ...toolForm, + sellerId: selectedVoucher?.sellerId || toolForm.sellerId, + oid, + orderId: oid, + taskId: selectedVoucher?.taskId || toolForm.taskId, + voucherCode, + eticketType: selectedVoucher?.eticketType || toolForm.eticketType, + serialNum: toolForm.serialNum || selectedVoucher?.consumeSerialNum, etickets: voucherCode ? [{ id: voucherCode, code: voucherCode, num: 1 }] : undefined, } } @@ -878,6 +891,9 @@ export default function AdminKuaishouIndustryPage() { columns={columns} dataSource={vouchers} loading={voucherLoading} + rowClassName={(row) => + selectedVoucher?.id === row.id ? 'kuaishou-industry-row-selected' : '' + } // 列已压缩;仅在极窄容器时横向滚动 scroll={{ x: scrollX || 1064 }} pagination={buildAdminTablePagination({ @@ -900,6 +916,18 @@ export default function AdminKuaishouIndustryPage() { } function renderVoucherTab() { + const hasVoucherTarget = Boolean( + selectedVoucher || + String(toolForm.voucherCode || '').trim() || + String(toolForm.taskId || '').trim() || + String(toolForm.oid || toolForm.orderId || '').trim(), + ) + const selectedShopName = selectedVoucher + ? selectedVoucher.shopName || + shopNameBySellerId.get(String(selectedVoucher.sellerId || '').trim()) || + '未命名店铺' + : '' + return (
{renderVoucherFilters()} @@ -909,84 +937,200 @@ export default function AdminKuaishouIndustryPage() { {renderVoucherTable(1064)} - -
- updateToolForm({ sellerId: event.target.value })} - /> - - updateToolForm({ - oid: event.target.value, - orderId: event.target.value, - }) - } - /> - updateToolForm({ taskId: event.target.value })} - /> - updateToolForm({ voucherCode: event.target.value })} - /> - updateToolForm({ eticketType: event.target.value })} - /> - updateToolForm({ serialNum: event.target.value })} - /> - updateToolForm({ consumeType: event.target.value })} - /> - updateToolForm({ storeName: event.target.value })} - /> - updateToolForm({ storeAddress: event.target.value })} - /> + +
+
当前卡券
+ {selectedVoucher ? ( +
+
+ + {selectedVoucher.voucherCode} + + + + {getVoucherStatusLabel(selectedVoucher.status)} + + + +
+
+
+ 订单号 + + {selectedVoucher.oid || '-'} + +
+
+ 任务 + {selectedVoucher.taskNo || selectedVoucher.taskId || '-'} +
+
+ 店铺 + {selectedShopName} + {selectedVoucher.sellerId || '-'} +
+
+ 凭证类型 + + {selectedVoucher.eticketType || '-'} + +
+
+
+ ) : ( +
+ 尚未选择卡券 + 请从左侧列表选择,或在下方手动指定。 +
+ )}
- + +
+
操作参数
+
+ + + + +
+
+ + + + + + + +
+ ), + }, + ]} + /> + +
+ - - +
{renderInlineActionResult('vouchers')}
diff --git a/apps/frontend/src/styles/main.css b/apps/frontend/src/styles/main.css index 618d3780..9188859e 100644 --- a/apps/frontend/src/styles/main.css +++ b/apps/frontend/src/styles/main.css @@ -338,15 +338,144 @@ select { vertical-align: top; } +.kuaishou-industry-row-selected > td { + background: #eef6ff !important; +} + +.kuaishou-industry-row-selected:hover > td { + background: #e5f0ff !important; +} + +.kuaishou-industry-tool-card .ant-card-body { + padding: 16px; +} + +.kuaishou-industry-tool-section + .kuaishou-industry-tool-section { + margin-top: 16px; + padding-top: 16px; + border-top: 1px solid #edf0f5; +} + +.kuaishou-industry-tool-section-title { + margin-bottom: 10px; + color: #1f2937; + font-size: 14px; + font-weight: 700; +} + +.kuaishou-industry-selected-voucher { + min-width: 0; +} + +.kuaishou-industry-selected-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 8px; + min-width: 0; +} + +.kuaishou-industry-selected-code { + min-width: 0; + overflow-wrap: anywhere; + word-break: break-all; +} + +.kuaishou-industry-selected-meta { + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 10px 16px; + margin-top: 12px; +} + +.kuaishou-industry-selected-meta > div { + display: grid; + gap: 2px; + min-width: 0; +} + +.kuaishou-industry-selected-meta span, +.kuaishou-industry-selected-meta small { + color: #6b7280; + font-size: 12px; +} + +.kuaishou-industry-selected-meta strong, +.kuaishou-industry-selected-meta .ant-typography { + min-width: 0; + overflow-wrap: anywhere; + word-break: break-all; +} + +.kuaishou-industry-selected-empty { + display: grid; + gap: 4px; + padding: 4px 0; + color: #6b7280; + font-size: 13px; +} + +.kuaishou-industry-selected-empty strong { + color: #374151; +} + .kuaishou-industry-tool-grid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); - gap: 10px; - margin-bottom: 14px; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 12px; +} + +.kuaishou-industry-tool-field { + display: grid; + gap: 6px; + min-width: 0; +} + +.kuaishou-industry-tool-field > span { + color: #4b5563; + font-size: 12px; + line-height: 1.3; +} + +.kuaishou-industry-tool-field-wide { + grid-column: 1 / -1; +} + +.kuaishou-industry-tool-field .ant-select { + width: 100%; +} + +.kuaishou-industry-manual-target { + margin-top: 14px; + border-top: 1px solid #edf0f5; +} + +.kuaishou-industry-manual-target .ant-collapse-header { + padding: 12px 0 8px; + color: #6b7280; + font-size: 12px; +} + +.kuaishou-industry-manual-target .ant-collapse-content-box { + padding: 4px 0 0; } .kuaishou-industry-actions { - margin-top: 2px; + display: grid; + grid-template-columns: repeat(2, minmax(0, 1fr)); + gap: 8px; + margin-top: 16px; + padding-top: 16px; + border-top: 1px solid #edf0f5; +} + +.kuaishou-industry-actions .ant-btn { + width: 100%; + min-width: 0; +} + +.kuaishou-industry-actions > :last-child { + grid-column: 1 / -1; } .kuaishou-industry-action-result {