优化打手端售后问题单页面展示问题类型处理结果与提交说明
This commit is contained in:
@@ -4,7 +4,6 @@ import {
|
|||||||
App,
|
App,
|
||||||
Alert,
|
Alert,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
|
||||||
Empty,
|
Empty,
|
||||||
Form,
|
Form,
|
||||||
Input,
|
Input,
|
||||||
@@ -20,6 +19,7 @@ import ImagePreviewList from '@/components/files/ImagePreviewList'
|
|||||||
import ImageUpload from '@/components/files/ImageUpload'
|
import ImageUpload from '@/components/files/ImageUpload'
|
||||||
import { fetchWorkerAfterSalesCases, submitWorkerAfterSalesCaseResponse } from '@/services/worker'
|
import { fetchWorkerAfterSalesCases, submitWorkerAfterSalesCaseResponse } from '@/services/worker'
|
||||||
import type { UploadedFile, WorkerAfterSalesCase } from '@/types/worker-platform'
|
import type { UploadedFile, WorkerAfterSalesCase } from '@/types/worker-platform'
|
||||||
|
import { formatDateTime } from '@/utils/date-time'
|
||||||
import { useIsMobile } from '@/utils/use-is-mobile'
|
import { useIsMobile } from '@/utils/use-is-mobile'
|
||||||
|
|
||||||
type AfterSalesResponseFormValues = {
|
type AfterSalesResponseFormValues = {
|
||||||
@@ -41,6 +41,13 @@ const STATUS_FILTERS: Array<{ value: StatusFilter; label: string }> = [
|
|||||||
{ value: 'closed', label: '已关闭' },
|
{ value: 'closed', label: '已关闭' },
|
||||||
]
|
]
|
||||||
|
|
||||||
|
/** 待办优先:待说明 > 处理中 > 追缴中 > 已关闭,同状态按发起时间倒序。 */
|
||||||
|
const STATUS_WEIGHT: Record<string, number> = {
|
||||||
|
awaiting_worker_response: 0,
|
||||||
|
under_review: 1,
|
||||||
|
recovery_pending: 2,
|
||||||
|
}
|
||||||
|
|
||||||
export function formatMoney(value: number | undefined) {
|
export function formatMoney(value: number | undefined) {
|
||||||
return `¥${((Number(value || 0) || 0) / 100).toFixed(2)}`
|
return `¥${((Number(value || 0) || 0) / 100).toFixed(2)}`
|
||||||
}
|
}
|
||||||
@@ -59,11 +66,40 @@ export function resolveWorkerAfterSalesStatusColor(status: string) {
|
|||||||
return 'green'
|
return 'green'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** 与后台售后面板保持相同的问题类型口径。 */
|
||||||
|
export function formatWorkerAfterSalesProblemType(value: string) {
|
||||||
|
if (value === 'fake_evidence') return '疑似P图 / 伪造验收'
|
||||||
|
if (value === 'result_not_met') return '实际结果未达标'
|
||||||
|
return '其他售后问题'
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveWorkerAfterSalesProblemTypeColor(value: string) {
|
||||||
|
if (value === 'fake_evidence') return 'red'
|
||||||
|
if (value === 'result_not_met') return 'volcano'
|
||||||
|
return 'default'
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatWorkerAfterSalesResolution(value: string) {
|
||||||
|
if (value === 'upheld') return '问题成立'
|
||||||
|
if (value === 'remedied') return '补救完成'
|
||||||
|
if (value === 'not_upheld') return '问题不成立'
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
function resolveWorkerAfterSalesResolutionColor(value: string) {
|
||||||
|
if (value === 'upheld') return 'red'
|
||||||
|
if (value === 'remedied') return 'gold'
|
||||||
|
if (value === 'not_upheld') return 'green'
|
||||||
|
return 'default'
|
||||||
|
}
|
||||||
|
|
||||||
|
function isAfterSalesClosed(status: string) {
|
||||||
|
return !['awaiting_worker_response', 'under_review', 'recovery_pending'].includes(status)
|
||||||
|
}
|
||||||
|
|
||||||
function matchesFilter(item: WorkerAfterSalesCase, filter: StatusFilter) {
|
function matchesFilter(item: WorkerAfterSalesCase, filter: StatusFilter) {
|
||||||
if (filter === 'all') return true
|
if (filter === 'all') return true
|
||||||
if (filter === 'closed') {
|
if (filter === 'closed') return isAfterSalesClosed(item.status)
|
||||||
return !['awaiting_worker_response', 'under_review', 'recovery_pending'].includes(item.status)
|
|
||||||
}
|
|
||||||
return item.status === filter
|
return item.status === filter
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,11 +113,26 @@ export default function WorkerAfterSalesPage() {
|
|||||||
retry: false,
|
retry: false,
|
||||||
})
|
})
|
||||||
const allCases = afterSalesCasesQuery.data?.data.items || []
|
const allCases = afterSalesCasesQuery.data?.data.items || []
|
||||||
|
const pendingCount = allCases.filter((item) => item.status === 'awaiting_worker_response').length
|
||||||
|
const countByFilter = useMemo(() => {
|
||||||
|
const counts: Record<string, number> = { all: allCases.length }
|
||||||
|
for (const filter of STATUS_FILTERS) {
|
||||||
|
if (filter.value === 'all') continue
|
||||||
|
counts[filter.value] = allCases.filter((item) => matchesFilter(item, filter.value)).length
|
||||||
|
}
|
||||||
|
return counts
|
||||||
|
}, [allCases])
|
||||||
const afterSalesCases = useMemo(
|
const afterSalesCases = useMemo(
|
||||||
() => allCases.filter((item) => matchesFilter(item, statusFilter)),
|
() =>
|
||||||
|
allCases
|
||||||
|
.filter((item) => matchesFilter(item, statusFilter))
|
||||||
|
.sort(
|
||||||
|
(a, b) =>
|
||||||
|
(STATUS_WEIGHT[a.status] ?? 3) - (STATUS_WEIGHT[b.status] ?? 3) ||
|
||||||
|
String(b.createdAt).localeCompare(String(a.createdAt)),
|
||||||
|
),
|
||||||
[allCases, statusFilter],
|
[allCases, statusFilter],
|
||||||
)
|
)
|
||||||
const pendingCount = allCases.filter((item) => item.status === 'awaiting_worker_response').length
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section
|
<section
|
||||||
@@ -89,46 +140,63 @@ export default function WorkerAfterSalesPage() {
|
|||||||
isMobile ? 'worker-after-sales-page worker-after-sales-mobile' : 'worker-after-sales-page'
|
isMobile ? 'worker-after-sales-page worker-after-sales-mobile' : 'worker-after-sales-page'
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<Card
|
{pendingCount > 0 ? (
|
||||||
className="worker-after-sales-card"
|
<Alert
|
||||||
title={
|
className="worker-after-sales-reminder"
|
||||||
<Space size={8}>
|
type="warning"
|
||||||
售后问题单
|
showIcon
|
||||||
{pendingCount > 0 ? <Tag color="orange">{pendingCount} 条待说明</Tag> : null}
|
message={`你有 ${pendingCount} 条售后单待提交说明,请尽快处理,逾期可能影响结算与等级`}
|
||||||
</Space>
|
/>
|
||||||
}
|
) : null}
|
||||||
extra={
|
<div className="worker-after-sales-toolbar">
|
||||||
<Button
|
<Segmented
|
||||||
size="small"
|
options={STATUS_FILTERS.map((filter) => ({
|
||||||
icon={<ReloadOutlined />}
|
value: filter.value,
|
||||||
loading={afterSalesCasesQuery.isFetching}
|
label: (
|
||||||
onClick={() => afterSalesCasesQuery.refetch()}
|
<Space size={4}>
|
||||||
>
|
{filter.label}
|
||||||
刷新
|
{countByFilter[filter.value] > 0 ? (
|
||||||
</Button>
|
<span className="worker-after-sales-filter-count">
|
||||||
}
|
{countByFilter[filter.value]}
|
||||||
>
|
</span>
|
||||||
<Space direction="vertical" size={12} style={{ width: '100%' }}>
|
) : null}
|
||||||
<Segmented
|
</Space>
|
||||||
options={STATUS_FILTERS}
|
),
|
||||||
value={statusFilter}
|
}))}
|
||||||
onChange={(value) => setStatusFilter(value as StatusFilter)}
|
value={statusFilter}
|
||||||
block={isMobile}
|
onChange={(value) => setStatusFilter(value as StatusFilter)}
|
||||||
/>
|
block={isMobile}
|
||||||
{afterSalesCasesQuery.isLoading ? (
|
/>
|
||||||
<Typography.Text type="secondary">加载中…</Typography.Text>
|
<Button
|
||||||
) : afterSalesCases.length === 0 ? (
|
icon={<ReloadOutlined />}
|
||||||
<Empty
|
loading={afterSalesCasesQuery.isFetching}
|
||||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
onClick={() => afterSalesCasesQuery.refetch()}
|
||||||
description="暂无售后问题单,请保持验收资料真实完整"
|
>
|
||||||
/>
|
刷新
|
||||||
) : (
|
</Button>
|
||||||
afterSalesCases.map((item) => (
|
</div>
|
||||||
<WorkerAfterSalesItem key={item.caseId} item={item} isMobile={isMobile} />
|
|
||||||
))
|
{afterSalesCasesQuery.isLoading ? (
|
||||||
)}
|
<Typography.Text type="secondary">加载中…</Typography.Text>
|
||||||
</Space>
|
) : afterSalesCasesQuery.isError ? (
|
||||||
</Card>
|
<Alert
|
||||||
|
type="error"
|
||||||
|
showIcon
|
||||||
|
message="售后问题单加载失败"
|
||||||
|
description="请刷新后重试;若问题持续存在,请联系客服。"
|
||||||
|
/>
|
||||||
|
) : afterSalesCases.length === 0 ? (
|
||||||
|
<Empty
|
||||||
|
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||||
|
description="暂无售后问题单,请保持验收资料真实完整"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div className="worker-after-sales-list">
|
||||||
|
{afterSalesCases.map((item) => (
|
||||||
|
<WorkerAfterSalesItem key={item.caseId} item={item} isMobile={isMobile} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -147,9 +215,14 @@ function WorkerAfterSalesItem({
|
|||||||
const [form] = Form.useForm<AfterSalesResponseFormValues>()
|
const [form] = Form.useForm<AfterSalesResponseFormValues>()
|
||||||
|
|
||||||
async function submit(values: AfterSalesResponseFormValues) {
|
async function submit(values: AfterSalesResponseFormValues) {
|
||||||
|
const response = String(values.response || '').trim()
|
||||||
|
if (!response && files.length === 0) {
|
||||||
|
message.error('请填写说明或至少上传一张补救材料图片')
|
||||||
|
return
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
await submitWorkerAfterSalesCaseResponse(item.caseId, {
|
await submitWorkerAfterSalesCaseResponse(item.caseId, {
|
||||||
response: String(values.response || '').trim(),
|
response,
|
||||||
files,
|
files,
|
||||||
})
|
})
|
||||||
message.success('售后说明已提交,等待客服处理')
|
message.success('售后说明已提交,等待客服处理')
|
||||||
@@ -162,31 +235,135 @@ function WorkerAfterSalesItem({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const resolutionLabel = formatWorkerAfterSalesResolution(item.resolutionAction)
|
||||||
|
const hasRecoveryDetail =
|
||||||
|
Number(item.recoveryAmount || 0) > 0 ||
|
||||||
|
Number(item.pendingDepositDeductionAmount || 0) > 0 ||
|
||||||
|
Number(item.availableDeductionAmount || 0) > 0 ||
|
||||||
|
Number(item.debtAmount || 0) > 0
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="worker-order-detail-value">
|
<article
|
||||||
<Space wrap size={[8, 6]}>
|
className={`worker-after-sales-item${item.status === 'awaiting_worker_response' ? ' is-awaiting' : ''}`}
|
||||||
<Tag color={resolveWorkerAfterSalesStatusColor(item.status)}>
|
>
|
||||||
{formatWorkerAfterSalesStatus(item.status)}
|
<div className="worker-after-sales-item-head">
|
||||||
</Tag>
|
<Space size={6} wrap>
|
||||||
<Typography.Text strong>
|
<Tag color={resolveWorkerAfterSalesStatusColor(item.status)}>
|
||||||
{item.productName || item.workOrderNo || item.caseNo}
|
{formatWorkerAfterSalesStatus(item.status)}
|
||||||
|
</Tag>
|
||||||
|
<Tag color={resolveWorkerAfterSalesProblemTypeColor(item.problemType)}>
|
||||||
|
{formatWorkerAfterSalesProblemType(item.problemType)}
|
||||||
|
</Tag>
|
||||||
|
</Space>
|
||||||
|
<Typography.Text strong ellipsis={{ tooltip: item.productName || item.caseNo }}>
|
||||||
|
{item.productName || item.caseNo}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
<Typography.Text type="secondary" copyable={{ text: item.caseNo }}>
|
<Typography.Text type="secondary" style={{ fontSize: 12 }}>
|
||||||
{item.caseNo}
|
发起 {formatDateTime(item.createdAt)}
|
||||||
</Typography.Text>
|
</Typography.Text>
|
||||||
|
</div>
|
||||||
|
<Space size={12} wrap className="worker-after-sales-item-meta">
|
||||||
|
<Typography.Text type="secondary" style={{ fontSize: 12 }} copyable>
|
||||||
|
{item.platformOrderId || 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>
|
||||||
|
) : null}
|
||||||
</Space>
|
</Space>
|
||||||
<Typography.Paragraph style={{ margin: '8px 0 4px' }}>
|
|
||||||
{item.complaintNote || '-'}
|
<div className="worker-after-sales-block">
|
||||||
</Typography.Paragraph>
|
<div className="worker-after-sales-block-label">投诉内容</div>
|
||||||
{item.complaintFiles.length > 0 ? (
|
<Typography.Paragraph style={{ marginBottom: item.complaintFiles.length ? 8 : 0 }}>
|
||||||
<ImagePreviewList files={item.complaintFiles} size={52} maxVisible={4} />
|
{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} />
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
) : null}
|
) : null}
|
||||||
<div style={{ marginTop: 8 }}>
|
|
||||||
{item.status === 'awaiting_worker_response' ? (
|
{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}
|
||||||
|
</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
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setFiles([])
|
setFiles([])
|
||||||
form.resetFields()
|
form.resetFields()
|
||||||
@@ -195,20 +372,12 @@ function WorkerAfterSalesItem({
|
|||||||
>
|
>
|
||||||
提交说明
|
提交说明
|
||||||
</Button>
|
</Button>
|
||||||
) : item.status === 'under_review' ? (
|
</div>
|
||||||
<Typography.Text type="secondary">已提交说明,等待客服处理</Typography.Text>
|
) : null}
|
||||||
) : item.status === 'recovery_pending' ? (
|
</article>
|
||||||
<Typography.Text type="danger">
|
|
||||||
待追缴 {formatMoney(item.debtAmount)},后续验收报酬将自动抵扣
|
|
||||||
</Typography.Text>
|
|
||||||
) : item.resolutionNote ? (
|
|
||||||
<Typography.Text type="secondary">处理结果:{item.resolutionNote}</Typography.Text>
|
|
||||||
) : null}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
title={`售后说明 · ${item.caseNo}`}
|
title={`售后说明 · ${item.productName || item.caseNo}`}
|
||||||
open={responseOpen}
|
open={responseOpen}
|
||||||
width={isMobile ? '92%' : 560}
|
width={isMobile ? '92%' : 560}
|
||||||
onCancel={() => setResponseOpen(false)}
|
onCancel={() => setResponseOpen(false)}
|
||||||
@@ -220,12 +389,39 @@ function WorkerAfterSalesItem({
|
|||||||
type="warning"
|
type="warning"
|
||||||
showIcon
|
showIcon
|
||||||
message="请针对售后问题说明情况或提交补救材料,原验收资料不可在此修改。"
|
message="请针对售后问题说明情况或提交补救材料,原验收资料不可在此修改。"
|
||||||
style={{ marginBottom: 16 }}
|
style={{ marginBottom: 12 }}
|
||||||
/>
|
/>
|
||||||
<Typography.Paragraph type="secondary">{item.complaintNote}</Typography.Paragraph>
|
<div className="worker-after-sales-block">
|
||||||
<Form form={form} layout="vertical" onFinish={submit}>
|
<div className="worker-after-sales-block-label">
|
||||||
<Form.Item label="说明" name="response">
|
投诉内容 · {formatWorkerAfterSalesProblemType(item.problemType)}
|
||||||
<Input.TextArea rows={4} maxLength={2000} showCount />
|
</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>
|
||||||
|
<Form form={form} layout="vertical" onFinish={submit} style={{ marginTop: 12 }}>
|
||||||
|
<Form.Item
|
||||||
|
label="说明"
|
||||||
|
name="response"
|
||||||
|
extra="说明与补救材料至少填写一项"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
validator: (_, value) =>
|
||||||
|
String(value || '').trim() || files.length > 0
|
||||||
|
? Promise.resolve()
|
||||||
|
: Promise.reject(new Error('请填写说明或至少上传一张图片')),
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input.TextArea
|
||||||
|
rows={4}
|
||||||
|
maxLength={2000}
|
||||||
|
showCount
|
||||||
|
placeholder="请说明当时的处理情况"
|
||||||
|
/>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="补救材料图片">
|
<Form.Item label="补救材料图片">
|
||||||
<ImageUpload
|
<ImageUpload
|
||||||
|
|||||||
@@ -2199,3 +2199,103 @@ body {
|
|||||||
.finance-summary-item strong {
|
.finance-summary-item strong {
|
||||||
color: #111827;
|
color: #111827;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ===== 售后问题单(打手端) ===== */
|
||||||
|
|
||||||
|
.worker-after-sales-page {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-reminder {
|
||||||
|
border-radius: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-toolbar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
gap: 12px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-filter-count {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
padding: 0 5px;
|
||||||
|
border-radius: 9px;
|
||||||
|
background: #e6f4ff;
|
||||||
|
color: #1677ff;
|
||||||
|
font-size: 11px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-list {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-item {
|
||||||
|
background: #ffffff;
|
||||||
|
border: 1px solid #e2e8f0;
|
||||||
|
border-left: 3px solid #cbd5e1;
|
||||||
|
border-radius: 14px;
|
||||||
|
padding: 14px 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 10px;
|
||||||
|
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.04);
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-item.is-awaiting {
|
||||||
|
border-left-color: #fa8c16;
|
||||||
|
background: #fffdf8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-item-head {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px 10px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-item-meta {
|
||||||
|
margin-top: -4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-block {
|
||||||
|
background: #f8fafc;
|
||||||
|
border: 1px solid #eef2f7;
|
||||||
|
border-radius: 10px;
|
||||||
|
padding: 10px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-block.is-mine {
|
||||||
|
background: #f6ffed;
|
||||||
|
border-color: #e6f4dc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-block.is-result {
|
||||||
|
background: #fff7e6;
|
||||||
|
border-color: #ffe7ba;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-block-label {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #64748b;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-item.is-awaiting .worker-after-sales-item-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worker-after-sales-mobile .worker-after-sales-toolbar .ant-segmented {
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user