feat(orders): 优化我的订单列表与订单详情界面
This commit is contained in:
@@ -13,7 +13,7 @@ import {
|
||||
Tag,
|
||||
Typography,
|
||||
} from 'antd'
|
||||
import { ArrowLeftOutlined, MessageOutlined } from '@ant-design/icons'
|
||||
import { ArrowLeftOutlined, CopyOutlined, MessageOutlined } from '@ant-design/icons'
|
||||
import { useQueryClient } from '@tanstack/react-query'
|
||||
import { Link, useNavigate, useParams } from 'react-router-dom'
|
||||
|
||||
@@ -37,6 +37,18 @@ const handoffRecordTypeMap: Record<string, string> = {
|
||||
renter_return: '归还记录',
|
||||
}
|
||||
|
||||
const TAG_COLORS: Record<string, string> = {
|
||||
default: 'default',
|
||||
primary: 'blue',
|
||||
success: 'green',
|
||||
warning: 'orange',
|
||||
danger: 'red',
|
||||
}
|
||||
|
||||
function toneColor(tone: string) {
|
||||
return TAG_COLORS[tone] ?? 'default'
|
||||
}
|
||||
|
||||
export function OrderDetailPage() {
|
||||
const { id } = useParams()
|
||||
const navigate = useNavigate()
|
||||
@@ -50,6 +62,16 @@ export function OrderDetailPage() {
|
||||
const records = handoffQuery.data ?? []
|
||||
const [openingChat, setOpeningChat] = useState(false)
|
||||
|
||||
const copyOrderNo = async () => {
|
||||
if (!order) return
|
||||
try {
|
||||
await navigator.clipboard.writeText(order.order_no)
|
||||
message.success('订单号已复制')
|
||||
} catch {
|
||||
message.error('复制失败,请手动选择订单号')
|
||||
}
|
||||
}
|
||||
|
||||
const openOrderChat = async () => {
|
||||
if (!order || openingChat) return
|
||||
setOpeningChat(true)
|
||||
@@ -135,28 +157,78 @@ export function OrderDetailPage() {
|
||||
</div>
|
||||
|
||||
<section className="pc-order-detail-hero">
|
||||
<div>
|
||||
<span className="pc-order-detail-hero__no">{order.order_no}</span>
|
||||
<div className="pc-order-detail-hero__main">
|
||||
<div className="pc-order-detail-hero__no">
|
||||
<span>{order.order_no}</span>
|
||||
<Button
|
||||
type="text"
|
||||
size="small"
|
||||
icon={<CopyOutlined />}
|
||||
className="pc-order-detail-hero__copy"
|
||||
onClick={() => void copyOrderNo()}
|
||||
>
|
||||
复制
|
||||
</Button>
|
||||
</div>
|
||||
<Typography.Title level={2} className="brand-title">
|
||||
{order.title}
|
||||
</Typography.Title>
|
||||
<Space size={6} wrap>
|
||||
<Tag color={status.tone}>{status.label}</Tag>
|
||||
<Tag color={handoff.tone} bordered={false}>
|
||||
<Tag color={toneColor(status.tone)}>{status.label}</Tag>
|
||||
<Tag color={toneColor(handoff.tone)} bordered={false}>
|
||||
交接:{handoff.label}
|
||||
</Tag>
|
||||
<Tag color={settlement.tone} bordered={false}>
|
||||
<Tag color={toneColor(settlement.tone)} bordered={false}>
|
||||
结算:{settlement.label}
|
||||
</Tag>
|
||||
{order.active_dispute ? <Tag color="red">申诉处理中</Tag> : null}
|
||||
</Space>
|
||||
{order.status === 'pending_payment' ? (
|
||||
<p className="pc-order-detail-hero__hint">
|
||||
请在 {formatDateTime(order.payment_deadline_at)} 前完成支付,超时订单会自动关闭。
|
||||
</p>
|
||||
) : null}
|
||||
</div>
|
||||
<div className="pc-order-detail-hero__amount">
|
||||
<span>订单金额</span>
|
||||
<strong>{formatMoney(order.display_amount_cent)}</strong>
|
||||
<small>押金 {formatMoney(order.deposit_amount_cent)}</small>
|
||||
<small>含押金 {formatMoney(order.deposit_amount_cent)}</small>
|
||||
{order.deposit_waived_amount_cent > 0 ? (
|
||||
<small>已免押 {formatMoney(order.deposit_waived_amount_cent)}</small>
|
||||
) : null}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div className="pc-order-metrics">
|
||||
<div className="pc-order-metric">
|
||||
<span>租金</span>
|
||||
<strong>
|
||||
{formatMoney(
|
||||
order.rent_amount_cent ??
|
||||
Math.max(0, order.display_amount_cent - order.deposit_amount_cent)
|
||||
)}
|
||||
</strong>
|
||||
</div>
|
||||
<div className="pc-order-metric">
|
||||
<span>实收押金</span>
|
||||
<strong>{formatMoney(order.deposit_amount_cent)}</strong>
|
||||
</div>
|
||||
<div className="pc-order-metric">
|
||||
<span>押金减免</span>
|
||||
<strong className={order.deposit_waived_amount_cent > 0 ? 'is-waived' : ''}>
|
||||
{order.deposit_waived_amount_cent > 0
|
||||
? `-${formatMoney(order.deposit_waived_amount_cent)}`
|
||||
: '—'}
|
||||
</strong>
|
||||
</div>
|
||||
<div className="pc-order-metric">
|
||||
<span>预计租期</span>
|
||||
<strong>
|
||||
{order.estimated_duration_hours ? `${order.estimated_duration_hours} 小时` : '—'}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Row gutter={[20, 20]} className="pc-order-detail-page__body">
|
||||
<Col xs={24} lg={16}>
|
||||
<Card title="商品信息" className="pc-order-detail-card">
|
||||
@@ -222,7 +294,7 @@ export function OrderDetailPage() {
|
||||
<Card title="结账单" className="pc-order-detail-card">
|
||||
<Descriptions column={2} size="small" colon={false}>
|
||||
<Descriptions.Item label="结账状态">
|
||||
<Tag color={checkoutStatusMeta(checkout.status).tone}>
|
||||
<Tag color={toneColor(checkoutStatusMeta(checkout.status).tone)}>
|
||||
{checkoutStatusMeta(checkout.status).label}
|
||||
</Tag>
|
||||
</Descriptions.Item>
|
||||
@@ -285,7 +357,10 @@ export function OrderDetailPage() {
|
||||
|
||||
<Card title="交接与结账记录" className="pc-order-detail-card">
|
||||
{records.length === 0 ? (
|
||||
<Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description="暂无交接或结账记录" />
|
||||
<Empty
|
||||
image={Empty.PRESENTED_IMAGE_SIMPLE}
|
||||
description="暂无记录,支付完成并开始交接后,这里会保留每一次交接与结账内容。"
|
||||
/>
|
||||
) : (
|
||||
<div className="pc-order-records">
|
||||
{records.map(record => (
|
||||
|
||||
@@ -4,12 +4,13 @@ import {
|
||||
Alert,
|
||||
Button,
|
||||
Card,
|
||||
Empty,
|
||||
Pagination,
|
||||
Select,
|
||||
Skeleton,
|
||||
Space,
|
||||
Table,
|
||||
Tag,
|
||||
Typography,
|
||||
type TableColumnsType,
|
||||
} from 'antd'
|
||||
import { ReloadOutlined, RightOutlined } from '@ant-design/icons'
|
||||
import { Link, useNavigate } from 'react-router-dom'
|
||||
@@ -23,6 +24,14 @@ import { formatDateTime, formatMoney, formatText } from '@/shared/utils/format'
|
||||
|
||||
const PAGE_SIZE = 20
|
||||
|
||||
const TAG_COLORS: Record<string, string> = {
|
||||
default: 'default',
|
||||
primary: 'blue',
|
||||
success: 'green',
|
||||
warning: 'orange',
|
||||
danger: 'red',
|
||||
}
|
||||
|
||||
const statusOptions = [
|
||||
'pending_payment',
|
||||
'pending_handoff',
|
||||
@@ -38,91 +47,79 @@ const statusOptions = [
|
||||
'abnormal',
|
||||
].map(value => ({ value, label: orderStatusMeta(value).label }))
|
||||
|
||||
function buildColumns(navigate: (id: number) => void): TableColumnsType<UserOrderListItem> {
|
||||
return [
|
||||
{
|
||||
title: '订单',
|
||||
dataIndex: 'order_no',
|
||||
width: 300,
|
||||
fixed: 'left',
|
||||
render: (_, row) => (
|
||||
<div className="pc-order-cell">
|
||||
<button type="button" className="pc-order-link" onClick={() => navigate(row.id)}>
|
||||
{row.order_no}
|
||||
</button>
|
||||
<strong>{row.title}</strong>
|
||||
<span>
|
||||
<Tag bordered={false}>{roleLabel(row.role)}</Tag>
|
||||
<span className="pc-order-muted">{row.listing_no}</span>
|
||||
</span>
|
||||
function toneColor(tone: string) {
|
||||
return TAG_COLORS[tone] ?? 'default'
|
||||
}
|
||||
|
||||
function OrderCard({
|
||||
order,
|
||||
onOpen,
|
||||
}: {
|
||||
order: UserOrderListItem
|
||||
onOpen: () => void
|
||||
}) {
|
||||
const status = orderStatusMeta(order.status)
|
||||
const handoff = handoffStatusMeta(order.handoff_status)
|
||||
|
||||
return (
|
||||
<article
|
||||
className="pc-order-card"
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
onClick={onOpen}
|
||||
onKeyDown={event => {
|
||||
if (event.key === 'Enter' || event.key === ' ') {
|
||||
event.preventDefault()
|
||||
onOpen()
|
||||
}
|
||||
}}
|
||||
>
|
||||
<div className="pc-order-card__head">
|
||||
<div className="pc-order-card__no">
|
||||
<span>{order.order_no}</span>
|
||||
<Tag bordered={false}>{roleLabel(order.role)}</Tag>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '商品',
|
||||
key: 'listing',
|
||||
width: 220,
|
||||
render: (_, row) => (
|
||||
<div className="pc-order-cell">
|
||||
<span>{formatText(row.server_region)}</span>
|
||||
<span className="pc-order-muted">{formatText(row.login_platform)}</span>
|
||||
<span className="pc-order-muted">
|
||||
{row.rental_days ? `${row.rental_days} 天` : '按账号规则'}
|
||||
</span>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '金额',
|
||||
key: 'amount',
|
||||
width: 180,
|
||||
align: 'right',
|
||||
render: (_, row) => (
|
||||
<div className="pc-order-amount">
|
||||
<strong>{formatMoney(row.display_amount_cent)}</strong>
|
||||
<span>押金 {formatMoney(row.deposit_amount_cent)}</span>
|
||||
{row.deposit_waived_amount_cent > 0 ? (
|
||||
<span>减免 {formatMoney(row.deposit_waived_amount_cent)}</span>
|
||||
) : null}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
key: 'status',
|
||||
width: 190,
|
||||
render: (_, row) => (
|
||||
<Space size={4} wrap>
|
||||
<Tag color={orderStatusMeta(row.status).tone}>{orderStatusMeta(row.status).label}</Tag>
|
||||
<Tag color={handoffStatusMeta(row.handoff_status).tone} bordered={false}>
|
||||
{handoffStatusMeta(row.handoff_status).label}
|
||||
<Space size={6} wrap>
|
||||
<Tag color={toneColor(status.tone)}>{status.label}</Tag>
|
||||
<Tag color={toneColor(handoff.tone)} bordered={false}>
|
||||
{handoff.label}
|
||||
</Tag>
|
||||
</Space>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
key: 'time',
|
||||
width: 190,
|
||||
render: (_, row) => (
|
||||
<div className="pc-order-cell">
|
||||
<span>下单 {formatDateTime(row.created_at)}</span>
|
||||
<span className="pc-order-muted">支付截止 {formatDateTime(row.payment_deadline_at)}</span>
|
||||
</div>
|
||||
|
||||
<div className="pc-order-card__body">
|
||||
<div className="pc-order-card__main">
|
||||
<h3>{order.title || '未命名订单'}</h3>
|
||||
<div className="pc-order-card__meta">
|
||||
<span>商品编号 {formatText(order.listing_no)}</span>
|
||||
<span>{formatText(order.server_region)}</span>
|
||||
<span>{formatText(order.login_platform)}</span>
|
||||
<span>{order.rental_days ? `${order.rental_days} 天` : '按账号规则'}</span>
|
||||
{order.daily_loss_m ? <span>日耗 {order.daily_loss_m}M</span> : null}
|
||||
</div>
|
||||
<div className="pc-order-card__times">
|
||||
<span>下单 {formatDateTime(order.created_at)}</span>
|
||||
<span>支付截止 {formatDateTime(order.payment_deadline_at)}</span>
|
||||
</div>
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '',
|
||||
key: 'actions',
|
||||
width: 90,
|
||||
fixed: 'right',
|
||||
render: (_, row) => (
|
||||
<Button type="link" onClick={() => navigate(row.id)}>
|
||||
详情 <RightOutlined />
|
||||
</Button>
|
||||
),
|
||||
},
|
||||
]
|
||||
|
||||
<div className="pc-order-card__side">
|
||||
<div className="pc-order-card__amount">
|
||||
<strong>{formatMoney(order.display_amount_cent)}</strong>
|
||||
<span>押金 {formatMoney(order.deposit_amount_cent)}</span>
|
||||
{order.deposit_waived_amount_cent > 0 ? (
|
||||
<span className="is-waived">
|
||||
押金减免 -{formatMoney(order.deposit_waived_amount_cent)}
|
||||
</span>
|
||||
) : null}
|
||||
</div>
|
||||
<span className="pc-order-card__detail">
|
||||
查看详情 <RightOutlined />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
export function OrderListPage() {
|
||||
@@ -139,8 +136,9 @@ export function OrderListPage() {
|
||||
enabled: Boolean(token),
|
||||
})
|
||||
|
||||
const columns = buildColumns(id => navigate(`/orders/${id}`))
|
||||
const errorText = error instanceof Error ? error.message : '请稍后重试或重新登录。'
|
||||
const items = data?.items ?? []
|
||||
const total = data?.total ?? 0
|
||||
|
||||
if (!hydrated) {
|
||||
return (
|
||||
@@ -183,7 +181,7 @@ export function OrderListPage() {
|
||||
查看租用进度、支付、交接、结账与申诉记录。
|
||||
</Typography.Text>
|
||||
</div>
|
||||
<Space>
|
||||
<Space wrap>
|
||||
<Select
|
||||
allowClear
|
||||
style={{ width: 190 }}
|
||||
@@ -217,29 +215,52 @@ export function OrderListPage() {
|
||||
) : null}
|
||||
|
||||
<Card className="pc-orders-card">
|
||||
<Table<UserOrderListItem>
|
||||
rowKey="id"
|
||||
columns={columns}
|
||||
dataSource={data?.items ?? []}
|
||||
loading={isPending || isFetching}
|
||||
scroll={{ x: 'max-content' }}
|
||||
pagination={{
|
||||
current: data?.page ?? page,
|
||||
pageSize: data?.page_size ?? PAGE_SIZE,
|
||||
total: data?.total ?? 0,
|
||||
showSizeChanger: false,
|
||||
showTotal: (count, range) => `第 ${range[0]}-${range[1]} 条 / 共 ${count} 条`,
|
||||
onChange: next => setPage(next),
|
||||
}}
|
||||
locale={{
|
||||
emptyText: (
|
||||
<div className="pc-orders-empty">
|
||||
<p>还没有订单</p>
|
||||
<Link to="/#listings">去看看柜选</Link>
|
||||
<div className="pc-orders-toolbar">
|
||||
<Typography.Text type="secondary">
|
||||
{isFetching ? '正在刷新订单…' : `共 ${total} 条订单`}
|
||||
</Typography.Text>
|
||||
</div>
|
||||
|
||||
{isPending ? (
|
||||
<div className="pc-orders-skeleton">
|
||||
{[0, 1, 2].map(index => (
|
||||
<div key={index} className="pc-order-card pc-order-card--skeleton">
|
||||
<Skeleton active paragraph={{ rows: 2 }} title={false} />
|
||||
</div>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
) : items.length === 0 ? (
|
||||
<Empty className="pc-orders-empty" description="还没有订单">
|
||||
<Link to="/#listings">
|
||||
<Button type="primary">去看看柜选</Button>
|
||||
</Link>
|
||||
</Empty>
|
||||
) : (
|
||||
<div className="pc-orders-list">
|
||||
{items.map(order => (
|
||||
<OrderCard
|
||||
key={order.id}
|
||||
order={order}
|
||||
onOpen={() => navigate(`/orders/${order.id}`)}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{total > PAGE_SIZE ? (
|
||||
<div className="pc-orders-pagination">
|
||||
<Typography.Text type="secondary">
|
||||
第 {page} 页 · 每页 {PAGE_SIZE} 条
|
||||
</Typography.Text>
|
||||
<Pagination
|
||||
current={data?.page ?? page}
|
||||
pageSize={data?.page_size ?? PAGE_SIZE}
|
||||
total={total}
|
||||
showSizeChanger={false}
|
||||
onChange={next => setPage(next)}
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -152,6 +152,156 @@
|
||||
background: var(--paper-warm);
|
||||
}
|
||||
|
||||
.pc-orders-toolbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
.pc-orders-list,
|
||||
.pc-orders-skeleton {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.pc-order-card {
|
||||
padding: 16px 18px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
background: #fff;
|
||||
cursor: pointer;
|
||||
transition:
|
||||
border-color 0.16s ease,
|
||||
box-shadow 0.16s ease,
|
||||
transform 0.16s ease;
|
||||
}
|
||||
|
||||
.pc-order-card:hover,
|
||||
.pc-order-card:focus-visible {
|
||||
border-color: var(--brand-ink);
|
||||
box-shadow: 0 10px 26px rgba(30, 77, 66, 0.08);
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.pc-order-card--skeleton {
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.pc-order-card__head {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 8px 12px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.pc-order-card__no {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
color: var(--ink-muted);
|
||||
font-family: 'Inter', monospace;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pc-order-card__body {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 220px;
|
||||
gap: 20px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.pc-order-card__main h3 {
|
||||
margin: 0 0 8px;
|
||||
color: var(--brand-ink);
|
||||
font-family: 'Noto Serif SC', 'Songti SC', serif;
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.pc-order-card__meta,
|
||||
.pc-order-card__times {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px 16px;
|
||||
color: var(--ink-secondary);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pc-order-card__times {
|
||||
margin-top: 10px;
|
||||
color: var(--ink-muted);
|
||||
}
|
||||
|
||||
.pc-order-card__side {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-end;
|
||||
gap: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.pc-order-card__amount strong {
|
||||
display: block;
|
||||
color: var(--brand-seal);
|
||||
font-family: 'Inter', 'DIN Alternate', sans-serif;
|
||||
font-size: 24px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.pc-order-card__amount span {
|
||||
display: block;
|
||||
color: var(--ink-muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pc-order-card__amount .is-waived {
|
||||
color: var(--brand-seal);
|
||||
}
|
||||
|
||||
.pc-order-card__detail {
|
||||
color: var(--brand-ink);
|
||||
font-size: 12px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.pc-orders-pagination {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
margin-top: 18px;
|
||||
}
|
||||
|
||||
.pc-orders-empty {
|
||||
padding: 36px 0;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.pc-order-card__body {
|
||||
grid-template-columns: 1fr;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.pc-order-card__side {
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
justify-content: space-between;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.pc-order-card__amount strong {
|
||||
font-size: 21px;
|
||||
}
|
||||
}
|
||||
|
||||
.pc-orders-login {
|
||||
max-width: 520px;
|
||||
margin: 60px auto;
|
||||
@@ -249,12 +399,26 @@
|
||||
}
|
||||
|
||||
.pc-order-detail-hero__no {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
color: #b9cbc3;
|
||||
font-family: 'Inter', monospace;
|
||||
font-size: 11px;
|
||||
letter-spacing: 0.06em;
|
||||
}
|
||||
|
||||
.pc-order-detail-hero__copy {
|
||||
color: #d8e4de !important;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.pc-order-detail-hero__hint {
|
||||
margin: 12px 0 0;
|
||||
color: #f0d7b8;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pc-order-detail-hero h2 {
|
||||
margin: 8px 0 12px !important;
|
||||
color: #f6f2e8 !important;
|
||||
@@ -286,6 +450,39 @@
|
||||
background: var(--paper-warm);
|
||||
}
|
||||
|
||||
.pc-order-metrics {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, minmax(0, 1fr));
|
||||
gap: 12px;
|
||||
margin-bottom: 18px;
|
||||
}
|
||||
|
||||
.pc-order-metric {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 5px;
|
||||
padding: 13px 16px;
|
||||
border: 1px solid var(--line);
|
||||
border-radius: 10px;
|
||||
background: var(--paper-warm);
|
||||
}
|
||||
|
||||
.pc-order-metric span {
|
||||
color: var(--ink-muted);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.pc-order-metric strong {
|
||||
color: var(--brand-ink);
|
||||
font-family: 'Inter', 'DIN Alternate', sans-serif;
|
||||
font-size: 18px;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.pc-order-metric strong.is-waived {
|
||||
color: var(--brand-seal);
|
||||
}
|
||||
|
||||
.pc-order-detail-side {
|
||||
position: sticky;
|
||||
top: 84px;
|
||||
@@ -300,6 +497,12 @@
|
||||
background: var(--paper-warm);
|
||||
}
|
||||
|
||||
.pc-order-action-card .ant-btn-primary {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.pc-order-action-card .ant-card-head-title {
|
||||
color: var(--brand-ink);
|
||||
}
|
||||
@@ -323,12 +526,26 @@
|
||||
}
|
||||
|
||||
.pc-order-record {
|
||||
padding: 14px 0;
|
||||
border-bottom: 1px dashed var(--line);
|
||||
position: relative;
|
||||
margin-left: 6px;
|
||||
padding: 0 0 18px 20px;
|
||||
border-left: 1px solid var(--line);
|
||||
}
|
||||
|
||||
.pc-order-record::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: -4px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
border-radius: 50%;
|
||||
background: var(--brand-ink);
|
||||
}
|
||||
|
||||
.pc-order-record:last-child {
|
||||
border-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
border-left-color: transparent;
|
||||
}
|
||||
|
||||
.pc-order-record__head {
|
||||
@@ -354,6 +571,10 @@
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.pc-order-metrics {
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.pc-orders-page__head,
|
||||
.pc-order-detail-hero {
|
||||
flex-direction: column;
|
||||
|
||||
Reference in New Issue
Block a user