feat(distribution): 分站可下调收号比例且不超过主站上限

让分销站能按自身能力下调收号比例扩大利润,同时把主站回收比例作为硬边界,避免分站把比例加得比主站更高。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
yml2213
2026-09-15 20:35:30 +08:00
co-authored by Cursor
parent 1c86bef765
commit c9d9160ff4
27 changed files with 1159 additions and 106 deletions
+26 -2
View File
@@ -29,6 +29,7 @@ import {
} from '@ant-design/icons'
import {
formatMoney,
formatRatio,
listOrders,
listSites,
fetchReceivedListings,
@@ -527,6 +528,15 @@ export default function Orders({ kind }: { kind: 'all' | 'sold' | 'receive' }) {
)}
</div>
{kind === 'receive' && (
<Alert
type="info"
showIcon
message="本站收号比例以主站为上限"
description="可在「品牌装修」页下调本站收号比例以扩大利润,但不能高于主站。比例越低,号主底价越高,本站提价利润空间越大。"
/>
)}
{kind === 'receive' ? (
<Card>
<Tabs
@@ -584,7 +594,7 @@ export default function Orders({ kind }: { kind: 'all' | 'sold' | 'receive' }) {
rowKey="listing_id"
loading={recvLoading}
dataSource={receivedListings}
scroll={{ x: 1200 }}
scroll={{ x: 1400 }}
pagination={{
current: recvPage,
pageSize,
@@ -652,7 +662,21 @@ export default function Orders({ kind }: { kind: 'all' | 'sold' | 'receive' }) {
),
},
{
title: '价格 / 押金',
title: '收号比例 / 收号价',
width: 160,
render: (_: unknown, row: ReceivedListing) => (
<div>
<Typography.Text strong style={{ fontSize: 15, whiteSpace: 'nowrap', display: 'block' }}>
{formatRatio(row.seller_ratio)}
</Typography.Text>
<div style={{ fontSize: 12, color: '#888', whiteSpace: 'nowrap', marginTop: 2 }}>
收号价: {formatMoney(row.seller_total_price_cent)}
</div>
</div>
),
},
{
title: '挂牌价 / 押金',
width: 140,
render: (_: unknown, row: ReceivedListing) => (
<div>
@@ -8,6 +8,7 @@ import {
Button,
Form,
Input,
InputNumber,
Row,
Col,
Divider,
@@ -30,6 +31,7 @@ import {
import {
listSites,
updateSiteBranding,
updateSite,
getMe,
type Site,
type SiteBrandingPayload,
@@ -71,6 +73,8 @@ export default function SiteSettings() {
icp: '',
contact: '',
})
const [receiveRatioDelta, setReceiveRatioDelta] = useState(0)
const [savingRatio, setSavingRatio] = useState(false)
const loadSite = useCallback(async (id: number) => {
setLoading(true)
@@ -100,6 +104,7 @@ export default function SiteSettings() {
} catch {
setFooterInfo({})
}
setReceiveRatioDelta(Math.max(0, found.receive_ratio_delta || 0))
}
} catch {
message.error('加载站点设置失败')
@@ -181,6 +186,22 @@ export default function SiteSettings() {
setAnnouncements(announcements.filter((_, i) => i !== index))
}
async function handleSaveReceiveRatio() {
if (!siteID) return
setSavingRatio(true)
try {
const updated = await updateSite(siteID, { receive_ratio_delta: receiveRatioDelta })
setCurrentSite(updated)
setReceiveRatioDelta(Math.max(0, updated.receive_ratio_delta || 0))
message.success('收号比例已保存,本站上传账号将按新比例计价')
} catch (error: unknown) {
const respMessage = (error as { response?: { data?: { message?: string } } })?.response?.data?.message
message.error(respMessage || '保存收号比例失败')
} finally {
setSavingRatio(false)
}
}
async function handleSave() {
if (!siteID) return
setSaving(true)
@@ -249,6 +270,35 @@ export default function SiteSettings() {
</Space>
</div>
<Card loading={loading}>
<Space direction="vertical" style={{ width: '100%' }} size="middle">
<div>
<Typography.Title level={5} style={{ marginBottom: 4 }}>
本站收号比例
</Typography.Title>
<Typography.Text type="secondary">
主站回收比例是上限。下调点数越大,号主底价越高、本站利润空间越大,但不能高于主站比例。0 表示与主站一致。
</Typography.Text>
</div>
<Space wrap align="center">
<Typography.Text>相对主站下调</Typography.Text>
<InputNumber
min={0}
max={20}
step={0.1}
precision={1}
value={receiveRatioDelta}
onChange={(value) => setReceiveRatioDelta(Math.max(0, Number(value || 0)))}
addonAfter="点"
style={{ width: 160 }}
/>
<Button type="primary" icon={<SaveOutlined />} loading={savingRatio} onClick={() => void handleSaveReceiveRatio()}>
保存收号比例
</Button>
</Space>
</Space>
</Card>
<Row gutter={24}>
{/* Left Visual Form Customizer */}
<Col xs={24} lg={14}>
+10
View File
@@ -166,6 +166,16 @@ export default function Sites({ isSuperadmin = true }: { isSuperadmin?: boolean
render: (_: unknown, row: Site) =>
row.tax_enabled ? <Tag color="orange">{row.tax_rate_bps / 100}%</Tag> : <Tag>不征税</Tag>,
},
{
title: '收号下调',
width: 120,
render: (_: unknown, row: Site) =>
Number(row.receive_ratio_delta || 0) > 0 ? (
<Tag color="gold">-{Number(row.receive_ratio_delta).toFixed(1)} 点</Tag>
) : (
<Tag>与主站一致</Tag>
),
},
{
title: '创建时间',
dataIndex: 'created_at',