feat(consignment): 寄卖规格与价格动态配置重构

This commit is contained in:
2026-11-05 17:09:05 +08:00
parent 2ef16ddcc7
commit d41ec44679
22 changed files with 3761 additions and 621 deletions
File diff suppressed because it is too large Load Diff
@@ -14,6 +14,7 @@ import {
Card,
Col,
Descriptions,
Divider,
Form,
Input,
InputNumber,
@@ -270,6 +271,10 @@ export default function ConsignmentInventoryPanel() {
values.salePrice !== undefined
? Math.max(0, Math.round(Number(values.salePrice) * 100))
: undefined,
specValues:
values.specValues && Object.keys(values.specValues).length
? values.specValues
: undefined,
buyerName: values.buyerName,
shopName: values.shopName,
inboundBatch: values.inboundBatch,
@@ -349,6 +354,11 @@ export default function ConsignmentInventoryPanel() {
render: (_, record) => (
<div>
<div style={{ fontWeight: 600, fontSize: 14 }}>{record.itemName}</div>
{record.specText ? (
<Text type="secondary" style={{ fontSize: 12 }}>
{record.specText}
</Text>
) : null}
<Space size={4} align="center">
<Text type="secondary" style={{ fontSize: 12 }}>
寄卖单号
@@ -666,6 +676,10 @@ export default function ConsignmentInventoryPanel() {
setEditingItem(record)
editForm.setFieldsValue({
...record,
specValues:
record.specValues && Object.keys(record.specValues).length
? record.specValues
: undefined,
costPrice: record.costPriceFen / 100,
salePrice: (record.salePriceFen ?? record.costPriceFen) / 100,
workerId: record.workerId || undefined,
@@ -961,6 +975,46 @@ export default function ConsignmentInventoryPanel() {
</Col>
</Row>
{editingItem?.specs?.length ? (
<>
<Divider plain>动态规格</Divider>
<Row gutter={16}>
{editingItem.specs.map((field) => (
<Col span={8} key={field.key}>
<Form.Item name={['specValues', field.key]} label={field.label}>
{field.type === 'select' || field.type === 'radio' ? (
field.type === 'radio' ? (
<Radio.Group
options={field.options
.filter((option) => option.enabled !== false)
.map((option) => ({ label: option.label, value: option.value }))}
/>
) : (
<Select
options={field.options
.filter((option) => option.enabled !== false)
.map((option) => ({ label: option.label, value: option.value }))}
/>
)
) : field.type === 'number' ? (
<InputNumber style={{ width: '100%' }} />
) : field.type === 'date' ? (
<Input type="date" />
) : field.type === 'textarea' ? (
<Input.TextArea
placeholder={field.placeholder || undefined}
autoSize={{ minRows: 2, maxRows: 4 }}
/>
) : (
<Input placeholder={field.placeholder || undefined} />
)}
</Form.Item>
</Col>
))}
</Row>
</>
) : null}
<Row gutter={16}>
<Col span={8}>
<Form.Item name="buyerName" label="收购人">
@@ -166,6 +166,10 @@ export default function ConsignmentSubmissionsPanel() {
series: values.series,
diamondLevel: Number(values.diamondLevel || 1),
brillianceCount: Number(values.brillianceCount || 0),
specValues:
values.specValues && Object.keys(values.specValues).length
? values.specValues
: undefined,
sellerContact: values.sellerContact,
sellerGameId: values.sellerGameId,
sellerPaymentInfo: values.sellerPaymentInfo,
@@ -375,6 +379,10 @@ export default function ConsignmentSubmissionsPanel() {
setApproveModalItem(record)
approveForm.setFieldsValue({
...record,
specValues:
record.specValues && Object.keys(record.specValues).length
? record.specValues
: undefined,
costPrice: record.askingPriceFen / 100,
sellerContact: record.contactInfo,
buyerName: '客服',
@@ -667,6 +675,47 @@ export default function ConsignmentSubmissionsPanel() {
</Col>
</Row>
{approveModalItem?.specs?.length ? (
<Row gutter={12}>
{approveModalItem.specs.map((field) => (
<Col span={8} key={field.key}>
<Form.Item
name={['specValues', field.key]}
label={field.label}
style={{ marginBottom: 16 }}
>
{field.type === 'select' || field.type === 'radio' ? (
field.type === 'radio' ? (
<Radio.Group
options={field.options
.filter((option) => option.enabled !== false)
.map((option) => ({ label: option.label, value: option.value }))}
/>
) : (
<Select
options={field.options
.filter((option) => option.enabled !== false)
.map((option) => ({ label: option.label, value: option.value }))}
/>
)
) : field.type === 'number' ? (
<InputNumber style={{ width: '100%' }} />
) : field.type === 'date' ? (
<Input type="date" />
) : field.type === 'textarea' ? (
<Input.TextArea
placeholder={field.placeholder || undefined}
autoSize={{ minRows: 2, maxRows: 4 }}
/>
) : (
<Input placeholder={field.placeholder || undefined} />
)}
</Form.Item>
</Col>
))}
</Row>
) : null}
{/* 分组二:履约与打手 */}
<div
style={{
@@ -8,7 +8,6 @@ import {
InboxOutlined,
SearchOutlined,
PictureOutlined,
PlusOutlined,
ReloadOutlined,
SafetyCertificateOutlined,
UserOutlined,
@@ -21,6 +20,7 @@ import {
Button,
Card,
Col,
DatePicker,
Divider,
Empty,
Form,
@@ -38,14 +38,14 @@ import {
Typography,
Spin,
} from 'antd'
import { useEffect, useMemo, useRef, useState } from 'react'
import { useEffect, useRef, useState } from 'react'
import ImageUpload from '@/components/files/ImageUpload'
import { WorkerContactModal } from '@/components/worker/WorkerContactModal'
import {
confirmWorkerConsignmentFriendAdded,
fetchWorkerConsignmentContacts,
fetchWorkerConsignmentPriceSuggestion,
fetchWorkerConsignmentPricePreview,
fetchWorkerConsignmentProfiles,
fetchWorkerConsignments,
fetchWorkerProfile,
@@ -54,35 +54,19 @@ import {
updateWorkerConsignmentPrice,
} from '@/services/worker'
import type { WorkerConsignmentRecord } from '@/services/worker'
import type { WorkerConsignmentProfile } from '@/types/consignment'
import type {
ConsignmentSpecField,
ConsignmentSpecValues,
WorkerConsignmentProfile,
} from '@/types/consignment'
import type { UploadedFile } from '@/types/worker-platform'
import {
SURNAN_DEFAULT_ZONE,
SURNAN_PUBLISH_SYSTEM_OPTIONS,
SURNAN_PUBLISH_ZONE_OPTIONS,
} from '@/utils/consignment-spec'
import { buildSpecItemName } from '@/utils/consignment-spec'
import { formatConsignmentContactSupporter } from '@/utils/consignment-contact'
import { formatGiftCooldownRemaining } from '@/utils/consignment-cooldown'
import { canWorkerPublishConsignment } from '@/utils/consignment-whitelist'
import { formatDateTime } from '@/utils/date-time'
import { useIsMobile } from '@/utils/use-is-mobile'
const SERIES_OPTIONS = [
{ label: '暗潮', value: '暗潮' },
{ label: '怒嚎', value: '怒嚎' },
{ label: '血宴', value: '血宴' },
]
const DIAMOND_OPTIONS = [1, 2, 3, 4, 5, 6, 7].map((v) => ({
label: `${v} 钻`,
value: v,
}))
const BRILLIANCE_OPTIONS = [
{ label: '无璀璨 (0)', value: 0 },
...[1, 2, 3, 4, 5, 6, 7].map((v) => ({ label: `${v} 璀璨`, value: v })),
]
type RecordFilter = 'all' | 'reviewing' | 'active' | 'finished'
const DEPOSIT_TIP_KEY = 'worker-consignment-deposit-tip-seen'
@@ -176,11 +160,11 @@ export default function WorkerConsignmentPage() {
const [cooldownNow, setCooldownNow] = useState(() => Date.now())
const [form] = Form.useForm()
const currentDiamondLevel = Form.useWatch('diamondLevel', form)
// 寄售价:完全由后台「接单模板」决定(规格选齐后自动带出),卖家只读不可改。
// 寄售价:按后台配置(模板折扣价 / 固定价)自动带出,打手只能往下调。
const [priceState, setPriceState] = useState<
| { status: 'idle' }
| { status: 'loading' }
| { status: 'matched'; fen: number }
| { status: 'matched'; fen: number; capFen: number }
| { status: 'empty' }
>({ status: 'idle' })
const priceFetchTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
@@ -218,6 +202,7 @@ export default function WorkerConsignmentPage() {
consignmentProfiles.find((profile) => profile.profileId === selectedProfileId) ||
consignmentProfiles[0] ||
null
const selectedSpecs: ConsignmentSpecField[] = selectedProfile?.config.specs ?? []
useEffect(() => {
if (selectedProfileId === null && consignmentProfiles.length > 0) {
setSelectedProfileId(consignmentProfiles[0]!.profileId)
@@ -262,9 +247,7 @@ export default function WorkerConsignmentPage() {
2000,
)
const publishDepositYuan = publishDepositFen / 100
const manualPriceAllowed =
selectedProfile?.config.pricing.allowWorkerPrice === true ||
(Boolean(selectedProfile) && !selectedProfile!.config.pricing.useTemplatePrice)
const manualPriceAllowed = selectedProfile?.config.pricing.allowWorkerPrice !== false
const availableAmount = Number(worker?.wallet?.availableAmount || 0)
const canPublish = availableAmount >= publishDepositFen
const canConsign = canWorkerPublishConsignment({
@@ -338,6 +321,24 @@ export default function WorkerConsignmentPage() {
})
}, [profileQuery.isLoading, modal, publishDepositYuan])
function collectSpecValues(): ConsignmentSpecValues {
const values: ConsignmentSpecValues = {}
for (const field of selectedSpecs) {
const raw = form.getFieldValue(field.key)
if (raw === undefined || raw === null || String(raw).trim() === '') continue
if (
field.type === 'date' &&
typeof raw === 'object' &&
typeof (raw as { format?: unknown }).format === 'function'
) {
values[field.key] = (raw as { format: (pattern: string) => string }).format('YYYY-MM-DD')
continue
}
values[field.key] = typeof raw === 'number' ? raw : String(raw)
}
return values
}
function handleFormValuesChange(changed: Record<string, unknown>) {
// 钻级改变时:璀璨数不能超过钻石等级(如 5钻调成 2钻,原 5璀自动收敛到 2璀)
if (changed && changed.diamondLevel !== undefined) {
@@ -347,28 +348,22 @@ export default function WorkerConsignmentPage() {
form.setFieldsValue({ brillianceCount: newDia })
}
}
const sys = form.getFieldValue('system')
const zone = form.getFieldValue('serverZone')
const ser = form.getFieldValue('series')
const dia = form.getFieldValue('diamondLevel')
const bri = form.getFieldValue('brillianceCount')
if (sys && zone && ser && dia != null && bri != null) {
const briNum = Number(bri)
const briStr = briNum > 0 ? `${briNum}璀璨` : ''
// 区服是通配值(互通/通用)时不拼进物品名:对买家无信息量,"安卓互通暗潮…"读着也别扭
const zoneLabel = zone === '互通' || zone === '通用' ? '' : zone
form.setFieldsValue({
itemName: `${sys}${zoneLabel}${ser}${dia}钻${briStr} 苏尔南`,
})
}
// 规格选齐(系统+系列+钻级+璀璨)后从「接单模板」带出寄售价:安卓+暗潮+1钻+0璀 → 模板价 ¥120。
// 价格只读、卖家不用填;只有规格真的变了才重新匹配(改联系方式等字段不会触发)。
const specKey =
sys && ser && dia != null && Number(dia) > 0 && bri != null
? `${sys}|${ser}|${dia}|${bri}`
: ''
if (!specKey) {
const specValues = collectSpecValues()
const itemName = buildSpecItemName(
selectedProfile?.config.nameTemplate || '',
selectedSpecs,
specValues,
selectedProfile?.categoryName || '',
)
if (itemName) form.setFieldsValue({ itemName })
const missing = selectedSpecs.some(
(field) =>
field.required &&
(specValues[field.key] === undefined || String(specValues[field.key]).trim() === ''),
)
if (missing) {
if (lastPriceQueryKeyRef.current !== '') {
lastPriceQueryKeyRef.current = ''
setPriceState({ status: 'idle' })
@@ -376,6 +371,8 @@ export default function WorkerConsignmentPage() {
}
return
}
const specKey = JSON.stringify(specValues)
if (specKey === lastPriceQueryKeyRef.current) return
lastPriceQueryKeyRef.current = specKey
setPriceState({ status: 'loading' })
@@ -385,17 +382,18 @@ export default function WorkerConsignmentPage() {
priceFetchTimer.current = setTimeout(() => {
void (async () => {
try {
const res = await fetchWorkerConsignmentPriceSuggestion({
system: String(sys),
series: String(ser),
diamondLevel: Number(dia),
brillianceCount: Number(bri),
const res = await fetchWorkerConsignmentPricePreview({
profileId: selectedProfile?.profileId,
specValues,
})
if (lastPriceQueryKeyRef.current !== specKey) return
const fen = Number(res.data?.suggestedPriceFen || 0)
const capFen = Number(res.data?.capFen || 0)
if (fen > 0) {
setPriceState({ status: 'matched', fen })
form.setFieldsValue({ askingPrice: fen / 100 })
setPriceState({ status: 'matched', fen, capFen: capFen > 0 ? capFen : fen })
if (manualPriceAllowed) {
form.setFieldsValue({ askingPrice: fen / 100 })
}
} else {
setPriceState({ status: 'empty' })
}
@@ -434,22 +432,34 @@ export default function WorkerConsignmentPage() {
return
}
// 寄售价:配置允许改价/不使用模板价时按打手填写;否则必须匹配到接单模板价。
// 寄售价:按后台配置带出系统建议价;允许改价时可下调,但不能高于建议价。
const minPriceFen = Math.max(0, selectedProfile?.config.pricing.minPriceFen || 0)
let askingPriceFen = priceState.status === 'matched' ? priceState.fen : 0
const suggestedPriceFen = priceState.status === 'matched' ? priceState.fen : 0
const capPriceFen = priceState.status === 'matched' ? priceState.capFen : 0
let askingPriceFen = suggestedPriceFen
if (manualPriceAllowed) {
askingPriceFen = Math.max(0, Math.round(Number(values.askingPrice || 0) * 100))
if (askingPriceFen < Math.max(100, minPriceFen)) {
message.error(`寄售价格不能少于 ¥${(Math.max(100, minPriceFen) / 100).toFixed(2)}`)
const submittedPriceFen = Math.max(0, Math.round(Number(values.askingPrice || 0) * 100))
if (submittedPriceFen > 0) {
if (capPriceFen > 0 && submittedPriceFen > capPriceFen) {
message.error(`寄售价格不能高于系统建议价 ¥${(capPriceFen / 100).toFixed(2)}`)
return
}
if (submittedPriceFen < Math.max(100, minPriceFen)) {
message.error(`寄售价格不能少于 ¥${(Math.max(100, minPriceFen) / 100).toFixed(2)}`)
return
}
askingPriceFen = submittedPriceFen
} else if (suggestedPriceFen <= 0) {
message.error('该规格暂无价格,请填写寄售价格')
return
}
} else {
if (priceState.status === 'loading') {
message.warning('正在匹配接单模板价,请稍候')
message.warning('正在计算系统建议价,请稍候')
return
}
if (priceState.status !== 'matched') {
message.error('该规格暂无接单模板价,请联系客服补充模板后再提报')
message.error('该规格暂无价格,请联系客服补充配置后再提报')
return
}
if (askingPriceFen < 100) {
@@ -458,11 +468,15 @@ export default function WorkerConsignmentPage() {
}
}
const briNum = Number(values.brillianceCount || 0)
const briStr = briNum > 0 ? `${briNum}璀璨` : ''
const specValues = collectSpecValues()
const itemName =
String(values.itemName || '').trim() ||
`${values.system}${values.serverZone}${values.series}${values.diamondLevel}钻${briStr} 苏尔南`
buildSpecItemName(
selectedProfile?.config.nameTemplate || '',
selectedSpecs,
specValues,
selectedProfile?.categoryName || '',
)
setSubmitting(true)
try {
@@ -470,11 +484,12 @@ export default function WorkerConsignmentPage() {
profileId: selectedProfile?.profileId,
quantity: Math.max(1, Number(values.quantity || 1)),
itemName,
system: values.system,
serverZone: values.serverZone,
series: values.series,
diamondLevel: Number(values.diamondLevel || 1),
brillianceCount: Number(values.brillianceCount || 0),
specValues,
system: String(specValues.system || ''),
serverZone: String(specValues.serverZone || ''),
series: String(specValues.series || ''),
diamondLevel: Number(specValues.diamondLevel || 1),
brillianceCount: Number(specValues.brillianceCount || 0),
askingPriceFen,
sellerContact: values.sellerContact,
sellerPhone: values.sellerPhone || worker?.phone || '',
@@ -653,94 +668,105 @@ export default function WorkerConsignmentPage() {
<div className="worker-consignment-specs">
<div className="worker-consignment-spec-grid">
<Form.Item
name="system"
label="操作系统"
rules={[{ required: true, message: '请选择系统' }]}
className="worker-consignment-spec-card"
>
<Radio.Group
className="worker-consignment-chips"
optionType="button"
buttonStyle="solid"
options={[...SURNAN_PUBLISH_SYSTEM_OPTIONS]}
/>
</Form.Item>
<Form.Item
name="serverZone"
label="游戏区服"
rules={[{ required: true, message: '请选择区服' }]}
// 苏尔南区服固定「通用」(QQ/微信互通),唯一选项默认选中
initialValue={SURNAN_DEFAULT_ZONE}
className="worker-consignment-spec-card"
>
<Radio.Group
className="worker-consignment-chips"
optionType="button"
buttonStyle="solid"
options={[...SURNAN_PUBLISH_ZONE_OPTIONS]}
/>
</Form.Item>
<Form.Item
name="series"
label="系列 / 枪系"
rules={[{ required: true, message: '请选择枪系' }]}
className="worker-consignment-spec-card"
>
<Radio.Group
className="worker-consignment-chips"
optionType="button"
buttonStyle="solid"
options={SERIES_OPTIONS}
/>
</Form.Item>
<Form.Item
name="diamondLevel"
label="钻石等级"
rules={[{ required: true, message: '请选择钻级' }]}
className="worker-consignment-spec-card is-count"
>
<Radio.Group
className="worker-consignment-chips is-count"
optionType="button"
buttonStyle="solid"
options={DIAMOND_OPTIONS.map((o) => ({
label: `${o.value}钻`,
value: o.value,
}))}
/>
</Form.Item>
<Form.Item
name="brillianceCount"
label="璀璨数"
rules={[
{ required: true, message: '请选择璀璨数' },
({ getFieldValue }) => ({
validator(_, value) {
const dia = getFieldValue('diamondLevel')
if (value != null && dia != null && Number(value) > Number(dia)) {
return Promise.reject(
new Error(`璀璨数不能超过钻石等级(当前${dia}钻最多选${dia}璀)`),
)
}
return Promise.resolve()
},
}),
]}
initialValue={0}
className="worker-consignment-spec-card is-count"
>
<Radio.Group
className="worker-consignment-chips is-count"
optionType="button"
buttonStyle="solid"
options={BRILLIANCE_OPTIONS.map((o) => ({
label: o.value === 0 ? '无' : `${o.value}璀`,
value: o.value,
disabled: currentDiamondLevel != null && o.value > Number(currentDiamondLevel),
}))}
/>
</Form.Item>
{selectedSpecs.map((field) => {
const isCountField = field.key === 'diamondLevel' || field.key === 'brillianceCount'
const options = field.options
.filter((option) => option.enabled !== false)
.map((option) => ({
label: option.label,
value: option.value,
disabled:
field.key === 'brillianceCount' &&
currentDiamondLevel != null &&
Number(option.value) > Number(currentDiamondLevel),
}))
const defaultValue =
field.key === 'serverZone'
? options.some((option) => option.value === '互通')
? '互通'
: options.length === 1
? options[0]?.value
: undefined
: field.key === 'brillianceCount'
? 0
: undefined
return (
<Form.Item
key={field.key}
name={field.key}
label={field.label}
initialValue={defaultValue}
extra={field.helpText || undefined}
className={`worker-consignment-spec-card${isCountField ? ' is-count' : ''}`}
rules={[
...(field.required
? [{ required: true, message: `请选择或填写${field.label}` }]
: []),
...(field.key === 'brillianceCount'
? [
({ getFieldValue }: { getFieldValue: (name: string) => unknown }) => ({
validator(_: unknown, value: unknown) {
const diamond = getFieldValue('diamondLevel')
if (
value != null &&
diamond != null &&
Number(value) > Number(diamond)
) {
return Promise.reject(
new Error(
`璀璨数不能超过钻石等级(当前${diamond}钻最多选${diamond}璀)`,
),
)
}
return Promise.resolve()
},
}),
]
: []),
]}
>
{field.type === 'select' ? (
<Select
className="worker-consignment-select"
options={options}
placeholder={field.placeholder || `请选择${field.label}`}
allowClear
showSearch
optionFilterProp="label"
/>
) : field.type === 'radio' ? (
<Radio.Group
className={`worker-consignment-chips${isCountField ? ' is-count' : ''}`}
optionType="button"
buttonStyle="solid"
options={options}
/>
) : field.type === 'number' ? (
<InputNumber
min={0}
precision={0}
placeholder={field.placeholder || undefined}
style={{ width: '100%' }}
/>
) : field.type === 'textarea' ? (
<Input.TextArea
placeholder={field.placeholder || undefined}
maxLength={2000}
autoSize={{ minRows: 2, maxRows: 5 }}
allowClear
/>
) : field.type === 'date' ? (
<DatePicker
format="YYYY-MM-DD"
placeholder={field.placeholder || '请选择日期'}
style={{ width: '100%' }}
/>
) : (
<Input placeholder={field.placeholder || undefined} maxLength={200} allowClear />
)}
</Form.Item>
)
})}
</div>
<div className="worker-consignment-price-grid">
@@ -748,8 +774,8 @@ export default function WorkerConsignmentPage() {
label="寄售价格"
tooltip={
manualPriceAllowed
? '当前寄卖配置允许自定义售价,价格不得低于配置的最低价。'
: '由后台「接单模板」按系统/系列/钻级/璀璨自动匹配,卖家无需填写;需要调整请联系客服。'
? `默认按后台配置带出(模板折扣价 / 固定价),可下调,不能高于系统建议价${selectedProfile?.config.pricing.minPriceFen ? `;最低 ¥${(selectedProfile.config.pricing.minPriceFen / 100).toFixed(2)}` : ''}。`
: '由后台寄卖配置自动带出,卖家不可修改;需要调整请联系客服。'
}
className="worker-consignment-spec-card is-price"
>
@@ -757,8 +783,14 @@ export default function WorkerConsignmentPage() {
<Form.Item name="askingPrice" noStyle>
<InputNumber
min={Math.max(1, Number(selectedProfile?.config.pricing.minPriceFen || 0) / 100)}
max={
priceState.status === 'matched' && priceState.capFen > 0
? priceState.capFen / 100
: undefined
}
precision={2}
addonBefore="¥"
placeholder="选完规格后自动带出"
style={{ width: '100%' }}
/>
</Form.Item>
@@ -766,12 +798,12 @@ export default function WorkerConsignmentPage() {
<div className="worker-consignment-price-readonly">
{priceState.status === 'loading' ? (
<span className="is-pending">
<Spin size="small" /> 匹配模板价…
<Spin size="small" /> 计算建议价…
</span>
) : priceState.status === 'matched' ? (
<span className="is-amount">¥{(priceState.fen / 100).toFixed(0)}</span>
) : priceState.status === 'empty' ? (
<span className="is-empty">该规格暂无模板价,请联系客服</span>
<span className="is-empty">该规格暂无价格,请联系客服</span>
) : (
<span className="is-empty">选完规格后自动带出</span>
)}
@@ -1032,6 +1064,17 @@ export default function WorkerConsignmentPage() {
}
const profileId = Number(String(key).replace('publish-', ''))
if (Number.isInteger(profileId) && profileId > 0) {
if (profileId !== selectedProfileId) {
const nextProfile = consignmentProfiles.find((item) => item.profileId === profileId)
const nextSpecs = nextProfile?.config.specs ?? []
const cleared: Record<string, undefined> = {}
for (const field of nextSpecs) cleared[field.key] = undefined
cleared.askingPrice = undefined
cleared.itemName = undefined
form.setFieldsValue(cleared)
setPriceState({ status: 'idle' })
lastPriceQueryKeyRef.current = ''
}
setSelectedProfileId(profileId)
}
setActiveTab('publish')
@@ -1474,13 +1517,19 @@ function ConsignmentRecordCard({
</Typography.Text>
<Tag color={record.color}>{record.label}</Tag>
</div>
<SpecTags
system={record.system}
serverZone={record.serverZone}
series={record.series}
diamondLevel={record.diamondLevel}
brillianceCount={record.brillianceCount}
/>
{record.specText ? (
<Typography.Text type="secondary" className="worker-consignment-record-spec-text">
{record.specText}
</Typography.Text>
) : (
<SpecTags
system={record.system}
serverZone={record.serverZone}
series={record.series}
diamondLevel={record.diamondLevel}
brillianceCount={record.brillianceCount}
/>
)}
<div className="worker-consignment-record-meta">
<span>
寄售价{' '}
@@ -1695,12 +1744,18 @@ function ConsignmentRecordCard({
>
<InputNumber
min={1}
max={record.priceCapFen && record.priceCapFen > 0 ? record.priceCapFen / 100 : undefined}
precision={2}
addonBefore="¥"
value={priceYuan}
onChange={(value) => setPriceYuan(Number(value || 0))}
style={{ width: '100%' }}
/>
{record.priceCapFen && record.priceCapFen > 0 ? (
<Typography.Text type="secondary" style={{ display: 'block', marginTop: 8 }}>
最高不能超过系统建议价 ¥{(record.priceCapFen / 100).toFixed(2)}
</Typography.Text>
) : null}
</Modal>
</article>
)