feat(worker): 彻底重构售后问题单与工单仲裁中心视觉与交互体验
This commit is contained in:
@@ -1,4 +1,16 @@
|
||||
import { ReloadOutlined } from '@ant-design/icons'
|
||||
import {
|
||||
AlertOutlined,
|
||||
AuditOutlined,
|
||||
CheckCircleFilled,
|
||||
CheckCircleOutlined,
|
||||
ClockCircleOutlined,
|
||||
CloseCircleOutlined,
|
||||
DollarCircleOutlined,
|
||||
FormOutlined,
|
||||
ReloadOutlined,
|
||||
SafetyCertificateOutlined,
|
||||
UserOutlined,
|
||||
} from '@ant-design/icons'
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query'
|
||||
import {
|
||||
App,
|
||||
@@ -122,6 +134,7 @@ export default function WorkerAfterSalesPage() {
|
||||
}
|
||||
return counts
|
||||
}, [allCases])
|
||||
|
||||
const afterSalesCases = useMemo(
|
||||
() =>
|
||||
allCases
|
||||
@@ -140,27 +153,109 @@ export default function WorkerAfterSalesPage() {
|
||||
isMobile ? 'worker-after-sales-page worker-after-sales-mobile' : 'worker-after-sales-page'
|
||||
}
|
||||
>
|
||||
{/* 待办紧急提醒横幅 */}
|
||||
{pendingCount > 0 ? (
|
||||
<Alert
|
||||
className="worker-after-sales-reminder"
|
||||
type="warning"
|
||||
showIcon
|
||||
message={`你有 ${pendingCount} 条售后单待提交说明,请尽快处理,逾期可能影响结算与等级`}
|
||||
/>
|
||||
<div className="worker-as-pending-alert">
|
||||
<div className="worker-as-alert-left">
|
||||
<span className="worker-as-alert-icon-wrap">
|
||||
<AlertOutlined />
|
||||
</span>
|
||||
<div className="worker-as-alert-text">
|
||||
<div className="worker-as-alert-title">
|
||||
您有 <strong>{pendingCount}</strong> 笔售后单待提交说明
|
||||
</div>
|
||||
<div className="worker-as-alert-desc">
|
||||
买家已发起售后投诉,请尽快提交完成凭据或情况答辩,逾期可能影响您的资金与接单等级。
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
className="worker-as-alert-btn"
|
||||
onClick={() => setStatusFilter('awaiting_worker_response')}
|
||||
>
|
||||
立即处理待办 ({pendingCount})
|
||||
</Button>
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{/* 4卡片争议处理概览网格 */}
|
||||
<div className="worker-as-kpi-grid">
|
||||
<div
|
||||
className={`worker-as-kpi-card is-awaiting ${statusFilter === 'awaiting_worker_response' ? 'is-active' : ''}`}
|
||||
onClick={() =>
|
||||
setStatusFilter(
|
||||
statusFilter === 'awaiting_worker_response' ? 'all' : 'awaiting_worker_response',
|
||||
)
|
||||
}
|
||||
>
|
||||
<div className="worker-as-kpi-icon-wrap amber">
|
||||
<AlertOutlined />
|
||||
</div>
|
||||
<div className="worker-as-kpi-info">
|
||||
<div className="worker-as-kpi-label">
|
||||
待我举证
|
||||
{pendingCount > 0 && <span className="worker-as-kpi-pulse-dot" />}
|
||||
</div>
|
||||
<div className="worker-as-kpi-value">{countByFilter.awaiting_worker_response || 0}</div>
|
||||
<div className="worker-as-kpi-sub">
|
||||
{pendingCount > 0 ? `${pendingCount} 笔需紧急说明` : '暂无待处理'}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`worker-as-kpi-card is-review ${statusFilter === 'under_review' ? 'is-active' : ''}`}
|
||||
onClick={() => setStatusFilter(statusFilter === 'under_review' ? 'all' : 'under_review')}
|
||||
>
|
||||
<div className="worker-as-kpi-icon-wrap blue">
|
||||
<AuditOutlined />
|
||||
</div>
|
||||
<div className="worker-as-kpi-info">
|
||||
<div className="worker-as-kpi-label">平台仲裁中</div>
|
||||
<div className="worker-as-kpi-value">{countByFilter.under_review || 0}</div>
|
||||
<div className="worker-as-kpi-sub">客服公正审核中</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`worker-as-kpi-card is-recovery ${statusFilter === 'recovery_pending' ? 'is-active' : ''}`}
|
||||
onClick={() =>
|
||||
setStatusFilter(statusFilter === 'recovery_pending' ? 'all' : 'recovery_pending')
|
||||
}
|
||||
>
|
||||
<div className="worker-as-kpi-icon-wrap rose">
|
||||
<DollarCircleOutlined />
|
||||
</div>
|
||||
<div className="worker-as-kpi-info">
|
||||
<div className="worker-as-kpi-label">待追缴/扣款</div>
|
||||
<div className="worker-as-kpi-value">{countByFilter.recovery_pending || 0}</div>
|
||||
<div className="worker-as-kpi-sub">存在待追缴或抵扣款</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={`worker-as-kpi-card is-closed ${statusFilter === 'closed' ? 'is-active' : ''}`}
|
||||
onClick={() => setStatusFilter(statusFilter === 'closed' ? 'all' : 'closed')}
|
||||
>
|
||||
<div className="worker-as-kpi-icon-wrap emerald">
|
||||
<CheckCircleFilled />
|
||||
</div>
|
||||
<div className="worker-as-kpi-info">
|
||||
<div className="worker-as-kpi-label">已结案归档</div>
|
||||
<div className="worker-as-kpi-value">{countByFilter.closed || 0}</div>
|
||||
<div className="worker-as-kpi-sub">历史完结记录</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 桌面端与移动端顶部筛选与控制栏 */}
|
||||
<div className="worker-after-sales-desktop-header">
|
||||
<div className="worker-after-sales-header-left">
|
||||
<Typography.Title level={3} className="worker-after-sales-heading">
|
||||
售后问题单
|
||||
售后维权与工单仲裁
|
||||
</Typography.Title>
|
||||
{pendingCount > 0 ? (
|
||||
<span className="worker-after-sales-alert-pill">
|
||||
<span className="worker-after-sales-pulse-dot" />
|
||||
{pendingCount} 条待提交说明
|
||||
</span>
|
||||
) : (
|
||||
<span className="worker-after-sales-normal-pill">无待办售后单</span>
|
||||
)}
|
||||
<span className="worker-as-total-badge">共 {allCases.length} 笔工单记录</span>
|
||||
</div>
|
||||
|
||||
<div className="worker-after-sales-header-center">
|
||||
@@ -197,7 +292,9 @@ export default function WorkerAfterSalesPage() {
|
||||
</div>
|
||||
|
||||
{afterSalesCasesQuery.isLoading ? (
|
||||
<Typography.Text type="secondary">加载中…</Typography.Text>
|
||||
<div className="worker-as-loading-state">
|
||||
<Typography.Text type="secondary">正在加载售后问题单…</Typography.Text>
|
||||
</div>
|
||||
) : afterSalesCasesQuery.isError ? (
|
||||
<Alert
|
||||
type="error"
|
||||
@@ -206,10 +303,12 @@ export default function WorkerAfterSalesPage() {
|
||||
description="请刷新后重试;若问题持续存在,请联系客服。"
|
||||
/>
|
||||
) : afterSalesCases.length === 0 ? (
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description="暂无售后问题单,请保持验收资料真实完整"
|
||||
/>
|
||||
<div className="worker-as-empty-card">
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description="暂无匹配的售后问题单,请保持验收资料真实完整"
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<div className="worker-after-sales-list">
|
||||
{afterSalesCases.map((item) => (
|
||||
@@ -260,180 +359,294 @@ function WorkerAfterSalesItem({
|
||||
Number(item.recoveryAmount || 0) > 0 ||
|
||||
Number(item.pendingDepositDeductionAmount || 0) > 0 ||
|
||||
Number(item.availableDeductionAmount || 0) > 0 ||
|
||||
Number(item.debtAmount || 0) > 0
|
||||
Number(item.debtAmount || 0) > 0 ||
|
||||
Number(item.refundedAmount || 0) > 0
|
||||
|
||||
return (
|
||||
<>
|
||||
<article
|
||||
className={`worker-after-sales-item${item.status === 'awaiting_worker_response' ? ' is-awaiting' : ''}`}
|
||||
>
|
||||
<div className="worker-after-sales-item-head">
|
||||
<Space size={6} wrap>
|
||||
<Tag color={resolveWorkerAfterSalesStatusColor(item.status)}>
|
||||
<article className={`worker-as-case-card is-status-${item.status}`}>
|
||||
{/* 卡片头部:状态、问题类型、工单标题、订单单号 */}
|
||||
<div className="worker-as-card-header">
|
||||
<div className="worker-as-card-header-left">
|
||||
<span className={`worker-as-status-badge is-${item.status}`}>
|
||||
<span className="worker-as-status-dot" />
|
||||
{formatWorkerAfterSalesStatus(item.status)}
|
||||
</Tag>
|
||||
<Tag color={resolveWorkerAfterSalesProblemTypeColor(item.problemType)}>
|
||||
</span>
|
||||
<Tag
|
||||
color={resolveWorkerAfterSalesProblemTypeColor(item.problemType)}
|
||||
className="worker-as-problem-tag"
|
||||
>
|
||||
{formatWorkerAfterSalesProblemType(item.problemType)}
|
||||
</Tag>
|
||||
</Space>
|
||||
<Typography.Text strong ellipsis={{ tooltip: item.productName || item.caseNo }}>
|
||||
{item.productName || item.caseNo}
|
||||
</Typography.Text>
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
发起 {formatDateTime(item.createdAt)}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Space size={12} wrap className="worker-after-sales-item-meta">
|
||||
<Typography.Text
|
||||
type="secondary"
|
||||
style={{ fontSize: 12 }}
|
||||
copyable={{ text: item.workOrderNo || item.caseNo }}
|
||||
>
|
||||
工单号 {item.workOrderNo || item.caseNo}
|
||||
</Typography.Text>
|
||||
<Typography.Text
|
||||
type="secondary"
|
||||
style={{ fontSize: 12 }}
|
||||
copyable={{ text: item.caseNo }}
|
||||
>
|
||||
售后单号 {item.caseNo}
|
||||
</Typography.Text>
|
||||
{item.shareQuantity ? (
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
拼单 {item.shareQuantity} 份
|
||||
<Typography.Text
|
||||
strong
|
||||
className="worker-as-product-title"
|
||||
ellipsis={{ tooltip: item.productName || item.caseNo }}
|
||||
>
|
||||
{item.productName || item.caseNo}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</Space>
|
||||
|
||||
<div className="worker-after-sales-block">
|
||||
<div className="worker-after-sales-block-label">投诉内容</div>
|
||||
<Typography.Paragraph style={{ marginBottom: item.complaintFiles.length ? 8 : 0 }}>
|
||||
{item.complaintNote || '-'}
|
||||
</Typography.Paragraph>
|
||||
{item.complaintFiles.length > 0 ? (
|
||||
<ImagePreviewList files={item.complaintFiles} size={48} maxVisible={5} />
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
{item.workerResponse || item.workerResponseFiles.length > 0 ? (
|
||||
<div className="worker-after-sales-block is-mine">
|
||||
<div className="worker-after-sales-block-label">
|
||||
我提交的说明{item.respondedAt ? ` · ${formatDateTime(item.respondedAt)}` : ''}
|
||||
</div>
|
||||
{item.workerResponse ? (
|
||||
<Typography.Paragraph
|
||||
style={{ marginBottom: item.workerResponseFiles.length ? 8 : 0 }}
|
||||
>
|
||||
{item.workerResponse}
|
||||
</Typography.Paragraph>
|
||||
) : null}
|
||||
{item.workerResponseFiles.length > 0 ? (
|
||||
<ImagePreviewList files={item.workerResponseFiles} size={48} maxVisible={5} />
|
||||
{item.shareQuantity ? (
|
||||
<Tag className="worker-as-share-tag">拼单 {item.shareQuantity} 份</Tag>
|
||||
) : null}
|
||||
</div>
|
||||
) : null}
|
||||
|
||||
{resolutionLabel || item.resolutionNote || hasRecoveryDetail ? (
|
||||
<div className="worker-after-sales-block is-result">
|
||||
<div className="worker-after-sales-block-label">处理结果</div>
|
||||
<Space direction="vertical" size={6} style={{ width: '100%' }}>
|
||||
{resolutionLabel ? (
|
||||
<Space size={8} wrap>
|
||||
<Tag color={resolveWorkerAfterSalesResolutionColor(item.resolutionAction)}>
|
||||
{resolutionLabel}
|
||||
</Tag>
|
||||
{item.resolvedAt ? (
|
||||
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||
{formatDateTime(item.resolvedAt)}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</Space>
|
||||
) : null}
|
||||
{item.resolutionNote ? (
|
||||
<Typography.Paragraph style={{ marginBottom: 0 }}>
|
||||
{item.resolutionNote}
|
||||
</Typography.Paragraph>
|
||||
) : null}
|
||||
{hasRecoveryDetail ? (
|
||||
<Space size={12} wrap>
|
||||
{Number(item.recoveryAmount || 0) > 0 ? (
|
||||
<Typography.Text type="danger" strong>
|
||||
追缴 {formatMoney(item.recoveryAmount)}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
{Number(item.pendingDepositDeductionAmount || 0) > 0 ? (
|
||||
<Typography.Text type="secondary">
|
||||
待解冻资金抵扣 {formatMoney(item.pendingDepositDeductionAmount)}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
{Number(item.availableDeductionAmount || 0) > 0 ? (
|
||||
<Typography.Text type="secondary">
|
||||
余额抵扣 {formatMoney(item.availableDeductionAmount)}
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
{Number(item.debtAmount || 0) > 0 ? (
|
||||
<Typography.Text type="danger" strong>
|
||||
待追缴 {formatMoney(item.debtAmount)},后续验收报酬将自动抵扣
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
{Number(item.refundedAmount || 0) > 0 ? (
|
||||
<Typography.Text type="success" strong>
|
||||
已退还追缴 {formatMoney(item.refundedAmount)} 至可用余额
|
||||
</Typography.Text>
|
||||
) : null}
|
||||
</Space>
|
||||
) : null}
|
||||
</Space>
|
||||
</div>
|
||||
) : item.status === 'under_review' ? (
|
||||
<Typography.Text type="secondary">已提交说明,等待客服处理</Typography.Text>
|
||||
) : null}
|
||||
|
||||
{item.status === 'awaiting_worker_response' ? (
|
||||
<div className="worker-after-sales-item-actions">
|
||||
<Button
|
||||
type="primary"
|
||||
onClick={() => {
|
||||
setFiles([])
|
||||
form.resetFields()
|
||||
setResponseOpen(true)
|
||||
<div className="worker-as-card-header-right">
|
||||
<span className="worker-as-meta-time">
|
||||
<ClockCircleOutlined style={{ marginRight: 4 }} />
|
||||
发起 {formatDateTime(item.createdAt)}
|
||||
</span>
|
||||
<Typography.Text
|
||||
className="worker-as-meta-code"
|
||||
type="secondary"
|
||||
copyable={{
|
||||
text: item.workOrderNo || item.caseNo,
|
||||
tooltips: ['复制工单号', '已复制'],
|
||||
}}
|
||||
>
|
||||
提交说明
|
||||
</Button>
|
||||
工单 {item.workOrderNo || item.caseNo}
|
||||
</Typography.Text>
|
||||
<Typography.Text
|
||||
className="worker-as-meta-code"
|
||||
type="secondary"
|
||||
copyable={{ text: item.caseNo, tooltips: ['复制售后单号', '已复制'] }}
|
||||
>
|
||||
售后单 {item.caseNo}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 主体对比区域:买家投诉诉求 vs 打手答辩举证 (并排双列) */}
|
||||
<div className="worker-as-card-body">
|
||||
{/* 左列:买家投诉诉求 */}
|
||||
<div className="worker-as-col worker-as-buyer-col">
|
||||
<div className="worker-as-col-header">
|
||||
<div className="worker-as-avatar-pill buyer">
|
||||
<UserOutlined />
|
||||
</div>
|
||||
<span className="worker-as-col-title">买家投诉诉求</span>
|
||||
</div>
|
||||
<div className="worker-as-box buyer-box">
|
||||
<div className="worker-as-box-text">
|
||||
{item.complaintNote ? (
|
||||
<p className="worker-as-complaint-text">{item.complaintNote}</p>
|
||||
) : (
|
||||
<p className="worker-as-empty-text">买家未填写文字描述</p>
|
||||
)}
|
||||
</div>
|
||||
{item.complaintFiles.length > 0 && (
|
||||
<div className="worker-as-box-files">
|
||||
<div className="worker-as-files-label">
|
||||
买家举证材料 ({item.complaintFiles.length}):
|
||||
</div>
|
||||
<ImagePreviewList files={item.complaintFiles} size={54} maxVisible={6} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 右列:打手答辩与举证 */}
|
||||
<div className="worker-as-col worker-as-worker-col">
|
||||
<div className="worker-as-col-header">
|
||||
<div className="worker-as-avatar-pill worker">
|
||||
<SafetyCertificateOutlined />
|
||||
</div>
|
||||
<span className="worker-as-col-title">我的答辩与说明</span>
|
||||
{item.respondedAt && (
|
||||
<span className="worker-as-col-subtitle">
|
||||
提交于 {formatDateTime(item.respondedAt)}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{item.workerResponse || item.workerResponseFiles.length > 0 ? (
|
||||
<div className="worker-as-box worker-box">
|
||||
<div className="worker-as-box-text">
|
||||
{item.workerResponse ? (
|
||||
<p className="worker-as-worker-text">{item.workerResponse}</p>
|
||||
) : null}
|
||||
</div>
|
||||
{item.workerResponseFiles.length > 0 && (
|
||||
<div className="worker-as-box-files">
|
||||
<div className="worker-as-files-label">
|
||||
补救举证材料 ({item.workerResponseFiles.length}):
|
||||
</div>
|
||||
<ImagePreviewList files={item.workerResponseFiles} size={54} maxVisible={6} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : item.status === 'awaiting_worker_response' ? (
|
||||
<div className="worker-as-box awaiting-cta-box">
|
||||
<div className="worker-as-cta-content">
|
||||
<div className="worker-as-cta-icon-wrap">
|
||||
<AlertOutlined className="worker-as-cta-icon" />
|
||||
</div>
|
||||
<div className="worker-as-cta-info">
|
||||
<h4 className="worker-as-cta-title">等待您提交说明材料</h4>
|
||||
<p className="worker-as-cta-desc">
|
||||
买家已发起售后申诉,请针对上述问题提交文字说明或补救凭据,以便平台客服公允判定。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<Button
|
||||
type="primary"
|
||||
className="worker-as-submit-btn"
|
||||
icon={<FormOutlined />}
|
||||
onClick={() => {
|
||||
setFiles([])
|
||||
form.resetFields()
|
||||
setResponseOpen(true)
|
||||
}}
|
||||
>
|
||||
立即提交说明与凭据
|
||||
</Button>
|
||||
</div>
|
||||
) : item.status === 'under_review' ? (
|
||||
<div className="worker-as-box neutral-state-box">
|
||||
<ClockCircleOutlined className="worker-as-neutral-icon" />
|
||||
<p className="worker-as-neutral-text">
|
||||
未补充文字材料,平台客服正在结合买家举证与订单原始验收凭据进行裁决审核。
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="worker-as-box neutral-state-box is-closed">
|
||||
<CheckCircleOutlined className="worker-as-neutral-icon" />
|
||||
<p className="worker-as-neutral-text">本工单已结案(未补充答辩记录)</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 底部横幅:平台仲裁裁决与资金明细 */}
|
||||
{resolutionLabel ||
|
||||
item.resolutionNote ||
|
||||
hasRecoveryDetail ||
|
||||
item.status === 'under_review' ? (
|
||||
<div
|
||||
className={`worker-as-resolution-banner ${item.status === 'under_review' && !resolutionLabel ? 'is-pending' : ''}`}
|
||||
>
|
||||
<div className="worker-as-resolution-head">
|
||||
<div className="worker-as-resolution-head-left">
|
||||
<span className="worker-as-gavel-icon">
|
||||
<AuditOutlined />
|
||||
</span>
|
||||
<span className="worker-as-resolution-title">平台仲裁判定</span>
|
||||
{resolutionLabel ? (
|
||||
<Tag
|
||||
color={resolveWorkerAfterSalesResolutionColor(item.resolutionAction)}
|
||||
className="worker-as-resolution-tag"
|
||||
>
|
||||
{item.resolutionAction === 'upheld' && (
|
||||
<CloseCircleOutlined style={{ marginRight: 4 }} />
|
||||
)}
|
||||
{item.resolutionAction === 'not_upheld' && (
|
||||
<CheckCircleOutlined style={{ marginRight: 4 }} />
|
||||
)}
|
||||
{resolutionLabel}
|
||||
</Tag>
|
||||
) : item.status === 'under_review' ? (
|
||||
<Tag color="blue" className="worker-as-resolution-tag">
|
||||
客服审核中
|
||||
</Tag>
|
||||
) : null}
|
||||
{item.resolvedAt ? (
|
||||
<span className="worker-as-resolution-time">
|
||||
裁决时间:{formatDateTime(item.resolvedAt)}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{item.resolutionNote && (
|
||||
<div className="worker-as-resolution-note">
|
||||
<span className="note-label">判定说明:</span>
|
||||
<span className="note-content">{item.resolutionNote}</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{hasRecoveryDetail && (
|
||||
<div className="worker-as-financial-breakdown">
|
||||
<span className="financial-label">资金处理明细:</span>
|
||||
<div className="financial-chips-wrap">
|
||||
{Number(item.recoveryAmount || 0) > 0 && (
|
||||
<span className="financial-chip is-recovery">
|
||||
<span className="chip-name">追缴金额</span>
|
||||
<span className="chip-amount">{formatMoney(item.recoveryAmount)}</span>
|
||||
</span>
|
||||
)}
|
||||
{Number(item.pendingDepositDeductionAmount || 0) > 0 && (
|
||||
<span className="financial-chip is-deposit">
|
||||
<span className="chip-name">待解冻资金抵扣</span>
|
||||
<span className="chip-amount">
|
||||
{formatMoney(item.pendingDepositDeductionAmount)}
|
||||
</span>
|
||||
</span>
|
||||
)}
|
||||
{Number(item.availableDeductionAmount || 0) > 0 && (
|
||||
<span className="financial-chip is-available">
|
||||
<span className="chip-name">余额抵扣</span>
|
||||
<span className="chip-amount">
|
||||
{formatMoney(item.availableDeductionAmount)}
|
||||
</span>
|
||||
</span>
|
||||
)}
|
||||
{Number(item.debtAmount || 0) > 0 && (
|
||||
<span className="financial-chip is-debt">
|
||||
<span className="chip-name">待追缴欠款</span>
|
||||
<span className="chip-amount">{formatMoney(item.debtAmount)}</span>
|
||||
<span className="chip-hint">(后续报酬自动抵扣)</span>
|
||||
</span>
|
||||
)}
|
||||
{Number(item.refundedAmount || 0) > 0 && (
|
||||
<span className="financial-chip is-refunded">
|
||||
<span className="chip-name">退还追缴</span>
|
||||
<span className="chip-amount">{formatMoney(item.refundedAmount)}</span>
|
||||
<span className="chip-hint">(已入可用余额)</span>
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
) : null}
|
||||
</article>
|
||||
|
||||
{/* 提交说明材料弹窗 */}
|
||||
<Modal
|
||||
title={`售后说明 · ${item.productName || item.caseNo}`}
|
||||
title={`提交售后说明 · ${item.productName || item.caseNo}`}
|
||||
open={responseOpen}
|
||||
width={isMobile ? '92%' : 560}
|
||||
width={isMobile ? '94%' : 580}
|
||||
onCancel={() => setResponseOpen(false)}
|
||||
onOk={() => form.submit()}
|
||||
okText="提交说明"
|
||||
okText="确认提交说明"
|
||||
destroyOnHidden
|
||||
className="worker-as-submit-modal"
|
||||
>
|
||||
<Alert
|
||||
type="warning"
|
||||
showIcon
|
||||
message="请针对售后问题说明情况或提交补救材料,原验收资料不可在此修改。"
|
||||
style={{ marginBottom: 12 }}
|
||||
message="请针对售后问题如实说明情况或提交补救凭证。原订单验收资料不可在此修改。"
|
||||
style={{ marginBottom: 14 }}
|
||||
/>
|
||||
<div className="worker-after-sales-block">
|
||||
<div className="worker-after-sales-block-label">
|
||||
投诉内容 · {formatWorkerAfterSalesProblemType(item.problemType)}
|
||||
|
||||
{/* 弹窗内展示买家投诉内容供参考 */}
|
||||
<div className="worker-as-modal-buyer-summary">
|
||||
<div className="modal-summary-title">
|
||||
<UserOutlined style={{ marginRight: 6, color: '#ef4444' }} />
|
||||
买家投诉内容 · {formatWorkerAfterSalesProblemType(item.problemType)}
|
||||
</div>
|
||||
<Typography.Paragraph style={{ marginBottom: item.complaintFiles.length ? 8 : 0 }}>
|
||||
{item.complaintNote || '-'}
|
||||
</Typography.Paragraph>
|
||||
{item.complaintFiles.length > 0 ? (
|
||||
<ImagePreviewList files={item.complaintFiles} size={44} maxVisible={4} />
|
||||
) : null}
|
||||
<div className="modal-summary-content">
|
||||
{item.complaintNote || '(买家未填写文字描述)'}
|
||||
</div>
|
||||
{item.complaintFiles.length > 0 && (
|
||||
<div className="modal-summary-files">
|
||||
<ImagePreviewList files={item.complaintFiles} size={46} maxVisible={4} />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<Form form={form} layout="vertical" onFinish={submit} style={{ marginTop: 12 }}>
|
||||
|
||||
<Form form={form} layout="vertical" onFinish={submit} style={{ marginTop: 14 }}>
|
||||
<Form.Item
|
||||
label="说明"
|
||||
label="我的说明与答辩"
|
||||
name="response"
|
||||
extra="说明与补救材料至少填写一项"
|
||||
rules={[
|
||||
@@ -441,7 +654,7 @@ function WorkerAfterSalesItem({
|
||||
validator: (_, value) =>
|
||||
String(value || '').trim() || files.length > 0
|
||||
? Promise.resolve()
|
||||
: Promise.reject(new Error('请填写说明或至少上传一张图片')),
|
||||
: Promise.reject(new Error('请填写说明或至少上传一张补救材料图片')),
|
||||
},
|
||||
]}
|
||||
>
|
||||
@@ -449,10 +662,10 @@ function WorkerAfterSalesItem({
|
||||
rows={4}
|
||||
maxLength={2000}
|
||||
showCount
|
||||
placeholder="请说明当时的处理情况"
|
||||
placeholder="请详细客观说明当时订单处理情况、与买家沟通情况或补救事实…"
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item label="补救材料图片">
|
||||
<Form.Item label="补救举证材料图片 (支持粘贴直接上传)">
|
||||
<ImageUpload
|
||||
scene="worker-acceptance"
|
||||
scope="worker"
|
||||
|
||||
Reference in New Issue
Block a user