feat: 物品规则页左右布局,接单平台统计条精简
- 物品规则改为左右布局:左侧编辑/新建表单(加宽、一屏展示无滚动条),右侧可滚动规则列表 - 列表顶部新增搜索(规则标识/商品/SKU/店铺),点击行快速载入编辑,当前行高亮 - 接单平台顶部统计改为单行紧凑统计条,减少页面高度
This commit is contained in:
@@ -21,7 +21,6 @@ import {
|
|||||||
Modal,
|
Modal,
|
||||||
Select,
|
Select,
|
||||||
Space,
|
Space,
|
||||||
Statistic,
|
|
||||||
Switch,
|
Switch,
|
||||||
Table,
|
Table,
|
||||||
Tabs,
|
Tabs,
|
||||||
@@ -141,26 +140,23 @@ function SummaryCards() {
|
|||||||
})
|
})
|
||||||
const summary = summaryQuery.data?.data
|
const summary = summaryQuery.data?.data
|
||||||
|
|
||||||
|
const items = [
|
||||||
|
{ label: '待审核打手', value: summary?.pendingWorkerCount || 0 },
|
||||||
|
{ label: '待完善订单', value: summary?.pendingMaterialCount || 0 },
|
||||||
|
{ label: '大厅订单', value: summary?.openOrderCount || 0 },
|
||||||
|
{ label: '代练中', value: summary?.inProgressOrderCount || 0 },
|
||||||
|
]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="metric-grid four">
|
<Card size="small" bordered={false} className="platform-summary-strip-card">
|
||||||
<Card>
|
<Space size={32} wrap>
|
||||||
<Statistic
|
{items.map((item) => (
|
||||||
title="待审核打手"
|
<span key={item.label} className="platform-summary-strip-item">
|
||||||
value={summary?.pendingWorkerCount || 0}
|
{item.label}
|
||||||
/>
|
<strong>{item.value}</strong>
|
||||||
</Card>
|
</span>
|
||||||
<Card>
|
))}
|
||||||
<Statistic
|
</Space>
|
||||||
title="待完善订单"
|
</Card>
|
||||||
value={summary?.pendingMaterialCount || 0}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
<Card>
|
|
||||||
<Statistic title="大厅订单" value={summary?.openOrderCount || 0} />
|
|
||||||
</Card>
|
|
||||||
<Card>
|
|
||||||
<Statistic title="代练中" value={summary?.inProgressOrderCount || 0} />
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -201,6 +201,21 @@ export default function ProductRulesPanel() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const [keyword, setKeyword] = useState('')
|
||||||
|
|
||||||
|
const filteredRules = (rulesQuery.data?.data.items || []).filter((rule) => {
|
||||||
|
const keywordText = keyword.trim().toLowerCase()
|
||||||
|
if (!keywordText) return true
|
||||||
|
return [
|
||||||
|
rule.ruleKey,
|
||||||
|
rule.productName,
|
||||||
|
rule.skuCode,
|
||||||
|
rule.provider,
|
||||||
|
rule.shopId,
|
||||||
|
rule.categoryName,
|
||||||
|
].some((value) => String(value || '').toLowerCase().includes(keywordText))
|
||||||
|
})
|
||||||
|
|
||||||
function syncSharingRuleForm(next: {
|
function syncSharingRuleForm(next: {
|
||||||
sharingTotalQuantity?: number
|
sharingTotalQuantity?: number
|
||||||
sharingUnitReward?: number
|
sharingUnitReward?: number
|
||||||
@@ -304,7 +319,7 @@ export default function ProductRulesPanel() {
|
|||||||
width: 104,
|
width: 104,
|
||||||
fixed: 'right',
|
fixed: 'right',
|
||||||
render: (_, row) => (
|
render: (_, row) => (
|
||||||
<Space size={0}>
|
<Space size={0} onClick={(event) => event.stopPropagation()}>
|
||||||
<Button
|
<Button
|
||||||
type="text"
|
type="text"
|
||||||
icon={<EditOutlined />}
|
icon={<EditOutlined />}
|
||||||
@@ -335,294 +350,319 @@ export default function ProductRulesPanel() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="platform-panel-stack">
|
<section className="platform-panel-stack">
|
||||||
<Card
|
<div className="product-rules-layout">
|
||||||
title={editingRule ? `编辑物品规则 · ${editingRule.ruleKey}` : '新建物品规则'}
|
<Card
|
||||||
extra={
|
className="product-rules-form-card"
|
||||||
editingRule ? (
|
title={editingRule ? `编辑物品规则 · ${editingRule.ruleKey}` : '新建物品规则'}
|
||||||
<Button onClick={resetRuleForm}>取消编辑</Button>
|
extra={
|
||||||
) : null
|
<Space>
|
||||||
}
|
{editingRule ? (
|
||||||
bordered={false}
|
<Button type="link" onClick={resetRuleForm}>
|
||||||
>
|
取消编辑
|
||||||
<Form
|
</Button>
|
||||||
form={form}
|
) : null}
|
||||||
layout="vertical"
|
<Button
|
||||||
className="worker-rule-form"
|
type="primary"
|
||||||
initialValues={{
|
htmlType="submit"
|
||||||
platform: 'kuaishou',
|
form="product-rule-form"
|
||||||
matchType: 'contains',
|
>
|
||||||
pricingMode: 'fixed',
|
{editingRule ? '保存修改' : '创建规则'}
|
||||||
rewardAmount: 25,
|
</Button>
|
||||||
depositThresholdAmount: 200,
|
</Space>
|
||||||
enabled: true,
|
}
|
||||||
autoCreate: false,
|
bordered={false}
|
||||||
sharingEnabled: false,
|
|
||||||
sharingTotalQuantity: 10,
|
|
||||||
sharingUnitReward: 5,
|
|
||||||
sharingTotalAmount: 50,
|
|
||||||
fieldsText:
|
|
||||||
'gameId:游戏编号\ngameNickname:游戏昵称\nsystem:系统#安卓,苹果\nserverZone:区服#QQ区,微信区',
|
|
||||||
}}
|
|
||||||
onFinish={saveRule}
|
|
||||||
>
|
>
|
||||||
<div className="worker-rule-grid">
|
<Form
|
||||||
<Form.Item
|
id="product-rule-form"
|
||||||
label="规则标识"
|
form={form}
|
||||||
name="ruleKey"
|
layout="vertical"
|
||||||
rules={[
|
className="worker-rule-form"
|
||||||
{ required: true, message: '请输入规则标识' },
|
initialValues={{
|
||||||
{
|
platform: 'kuaishou',
|
||||||
validator: (_, value) => {
|
matchType: 'contains',
|
||||||
const key = String(value || '').trim()
|
pricingMode: 'fixed',
|
||||||
if (
|
rewardAmount: 25,
|
||||||
!editingRule &&
|
depositThresholdAmount: 200,
|
||||||
(rulesQuery.data?.data.items || []).some(
|
enabled: true,
|
||||||
(rule) => rule.ruleKey === key,
|
autoCreate: false,
|
||||||
)
|
sharingEnabled: false,
|
||||||
) {
|
sharingTotalQuantity: 10,
|
||||||
return Promise.reject(new Error('规则标识已存在,请更换'))
|
sharingUnitReward: 5,
|
||||||
}
|
sharingTotalAmount: 50,
|
||||||
return Promise.resolve()
|
fieldsText:
|
||||||
|
'gameId:游戏编号\ngameNickname:游戏昵称\nsystem:系统#安卓,苹果\nserverZone:区服#QQ区,微信区',
|
||||||
|
}}
|
||||||
|
onFinish={saveRule}
|
||||||
|
>
|
||||||
|
<div className="worker-rule-grid">
|
||||||
|
<Form.Item
|
||||||
|
label="规则标识"
|
||||||
|
name="ruleKey"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: '请输入规则标识' },
|
||||||
|
{
|
||||||
|
validator: (_, value) => {
|
||||||
|
const key = String(value || '').trim()
|
||||||
|
if (
|
||||||
|
!editingRule &&
|
||||||
|
(rulesQuery.data?.data.items || []).some(
|
||||||
|
(rule) => rule.ruleKey === key,
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
return Promise.reject(new Error('规则标识已存在,请更换'))
|
||||||
|
}
|
||||||
|
return Promise.resolve()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
|
||||||
]}
|
|
||||||
>
|
|
||||||
<Input placeholder="skin-training" disabled={Boolean(editingRule)} />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="来源" name="provider">
|
|
||||||
<Input placeholder="留空通配,如 91kaquan" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="平台" name="platform">
|
|
||||||
<Input placeholder="kuaishou" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="店铺" name="shopId">
|
|
||||||
<Input placeholder="留空通配" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="SKU" name="skuCode">
|
|
||||||
<Input placeholder="优先精确匹配" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="商品名" name="productName">
|
|
||||||
<Input placeholder="用于包含/精确匹配" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="匹配方式" name="matchType">
|
|
||||||
<Select
|
|
||||||
options={[
|
|
||||||
{ value: 'contains', label: '包含' },
|
|
||||||
{ value: 'exact', label: '精确' },
|
|
||||||
]}
|
]}
|
||||||
/>
|
>
|
||||||
</Form.Item>
|
<Input placeholder="skin-training" disabled={Boolean(editingRule)} />
|
||||||
<Form.Item label="分类" name="categoryId">
|
</Form.Item>
|
||||||
<Select
|
<Form.Item label="来源" name="provider">
|
||||||
allowClear
|
<Input placeholder="留空通配,如 91kaquan" />
|
||||||
loading={categoriesQuery.isLoading}
|
</Form.Item>
|
||||||
options={(categoriesQuery.data?.data.items || []).map(
|
<Form.Item label="平台" name="platform">
|
||||||
(item) => ({
|
<Input placeholder="kuaishou" />
|
||||||
value: item.categoryId,
|
</Form.Item>
|
||||||
label: item.name,
|
<Form.Item label="店铺" name="shopId">
|
||||||
}),
|
<Input placeholder="留空通配" />
|
||||||
)}
|
</Form.Item>
|
||||||
/>
|
<Form.Item label="SKU" name="skuCode">
|
||||||
</Form.Item>
|
<Input placeholder="优先精确匹配" />
|
||||||
<Form.Item
|
</Form.Item>
|
||||||
label="计价方式"
|
<Form.Item label="商品名" name="productName">
|
||||||
name="pricingMode"
|
<Input placeholder="用于包含/精确匹配" />
|
||||||
tooltip="按数量计价时,接单总价 = 单价 × 商品名称文字中的规格数量(如「指挥官秘钥15个」→ 15)"
|
</Form.Item>
|
||||||
>
|
<Form.Item label="匹配方式" name="matchType">
|
||||||
<Radio.Group
|
<Select
|
||||||
className="full-width"
|
options={[
|
||||||
options={[
|
{ value: 'contains', label: '包含' },
|
||||||
{ value: 'fixed', label: '固定金额' },
|
{ value: 'exact', label: '精确' },
|
||||||
{ value: 'unit', label: '按数量 × 单价' },
|
]}
|
||||||
]}
|
/>
|
||||||
/>
|
</Form.Item>
|
||||||
</Form.Item>
|
<Form.Item label="分类" name="categoryId">
|
||||||
|
<Select
|
||||||
|
allowClear
|
||||||
|
loading={categoriesQuery.isLoading}
|
||||||
|
options={(categoriesQuery.data?.data.items || []).map(
|
||||||
|
(item) => ({
|
||||||
|
value: item.categoryId,
|
||||||
|
label: item.name,
|
||||||
|
}),
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="计价方式"
|
||||||
|
name="pricingMode"
|
||||||
|
tooltip="按数量计价时,接单总价 = 单价 × 商品名称文字中的规格数量(如「指挥官秘钥15个」→ 15)"
|
||||||
|
>
|
||||||
|
<Radio.Group
|
||||||
|
className="full-width"
|
||||||
|
options={[
|
||||||
|
{ value: 'fixed', label: '固定金额' },
|
||||||
|
{ value: 'unit', label: '按数量 × 单价' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item noStyle shouldUpdate>
|
||||||
|
{({ getFieldValue }) =>
|
||||||
|
getFieldValue('pricingMode') === 'unit' ? (
|
||||||
|
<Form.Item
|
||||||
|
label="单价"
|
||||||
|
name="unitPrice"
|
||||||
|
rules={[{ required: true, message: '请填写单价' }]}
|
||||||
|
extra="接单总价 = 单价 × 商品名称文字中的数量"
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
min={0.01}
|
||||||
|
step={1}
|
||||||
|
addonAfter="元"
|
||||||
|
className="full-width"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
) : (
|
||||||
|
<Form.Item
|
||||||
|
label="接单金额"
|
||||||
|
name="rewardAmount"
|
||||||
|
extra="可填 0,但接单金额为 0 的工单不能发布到大厅"
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
min={0}
|
||||||
|
step={1}
|
||||||
|
addonAfter="元"
|
||||||
|
className="full-width"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="押金阈值" name="depositThresholdAmount">
|
||||||
|
<InputNumber
|
||||||
|
min={0}
|
||||||
|
step={10}
|
||||||
|
addonAfter="元"
|
||||||
|
className="full-width"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="固定押金" name="requiredDepositAmount">
|
||||||
|
<InputNumber
|
||||||
|
min={0}
|
||||||
|
step={10}
|
||||||
|
addonAfter="元"
|
||||||
|
className="full-width"
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="排序" name="sortOrder">
|
||||||
|
<InputNumber min={0} max={9999} className="full-width" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item label="启用" name="enabled" valuePropName="checked">
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="自动创建"
|
||||||
|
name="autoCreate"
|
||||||
|
valuePropName="checked"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="启用拼单"
|
||||||
|
name="sharingEnabled"
|
||||||
|
valuePropName="checked"
|
||||||
|
tooltip="开启后按下方总数量与单价生成拼单工单"
|
||||||
|
>
|
||||||
|
<Switch />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="默认任务时限"
|
||||||
|
name="timeoutMinutes"
|
||||||
|
tooltip="自动创建的工单继承该时限,打手抢单后开始计时;0 表示不限时"
|
||||||
|
>
|
||||||
|
<InputNumber min={0} step={5} addonAfter="分钟" />
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="默认超时策略"
|
||||||
|
name="timeoutPolicy"
|
||||||
|
tooltip="reopen:释放押金退回大厅;cancel_release:取消退押金;cancel_deduct:取消扣押金"
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{ value: 'reopen', label: '释放押金退回大厅' },
|
||||||
|
{ value: 'cancel_release', label: '取消订单并退还押金' },
|
||||||
|
{ value: 'cancel_deduct', label: '取消订单并扣除押金' },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</div>
|
||||||
<Form.Item noStyle shouldUpdate>
|
<Form.Item noStyle shouldUpdate>
|
||||||
{({ getFieldValue }) =>
|
{({ getFieldValue }) =>
|
||||||
getFieldValue('pricingMode') === 'unit' ? (
|
getFieldValue('sharingEnabled') ? (
|
||||||
<Form.Item
|
<Space size={16} wrap style={{ marginBottom: 16 }}>
|
||||||
label="单价"
|
<Form.Item
|
||||||
name="unitPrice"
|
label="拼单总数量"
|
||||||
rules={[{ required: true, message: '请填写单价' }]}
|
name="sharingTotalQuantity"
|
||||||
extra="接单总价 = 单价 × 商品名称文字中的数量"
|
rules={[{ required: true, message: '请填写总数量' }]}
|
||||||
>
|
>
|
||||||
<InputNumber
|
<InputNumber
|
||||||
min={0.01}
|
min={1}
|
||||||
step={1}
|
max={100000}
|
||||||
addonAfter="元"
|
addonAfter="份"
|
||||||
className="full-width"
|
onChange={(value) =>
|
||||||
/>
|
syncSharingRuleForm({
|
||||||
</Form.Item>
|
sharingTotalQuantity: Number(value) || 0,
|
||||||
) : (
|
})
|
||||||
<Form.Item
|
}
|
||||||
label="接单金额"
|
/>
|
||||||
name="rewardAmount"
|
</Form.Item>
|
||||||
extra="可填 0,但接单金额为 0 的工单不能发布到大厅"
|
<Form.Item
|
||||||
>
|
label="拼单单价"
|
||||||
<InputNumber
|
name="sharingUnitReward"
|
||||||
min={0}
|
rules={[{ required: true, message: '请填写单价' }]}
|
||||||
step={1}
|
tooltip="每个数量份对应的报酬,修改后总价自动重算"
|
||||||
addonAfter="元"
|
>
|
||||||
className="full-width"
|
<InputNumber
|
||||||
/>
|
min={0.01}
|
||||||
</Form.Item>
|
step={1}
|
||||||
)
|
addonAfter="元"
|
||||||
|
onChange={(value) =>
|
||||||
|
syncSharingRuleForm({
|
||||||
|
sharingUnitReward: Number(value) || 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="拼单总价"
|
||||||
|
name="sharingTotalAmount"
|
||||||
|
rules={[{ required: true, message: '请填写总价' }]}
|
||||||
|
tooltip="总价 = 单价 × 数量,修改总价会自动反推数量"
|
||||||
|
>
|
||||||
|
<InputNumber
|
||||||
|
min={0.01}
|
||||||
|
step={1}
|
||||||
|
addonAfter="元"
|
||||||
|
onChange={(value) =>
|
||||||
|
syncSharingRuleForm({
|
||||||
|
sharingTotalAmount: Number(value) || 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</Form.Item>
|
||||||
|
</Space>
|
||||||
|
) : null
|
||||||
}
|
}
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item label="押金阈值" name="depositThresholdAmount">
|
|
||||||
<InputNumber
|
|
||||||
min={0}
|
|
||||||
step={10}
|
|
||||||
addonAfter="元"
|
|
||||||
className="full-width"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="固定押金" name="requiredDepositAmount">
|
|
||||||
<InputNumber
|
|
||||||
min={0}
|
|
||||||
step={10}
|
|
||||||
addonAfter="元"
|
|
||||||
className="full-width"
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="排序" name="sortOrder">
|
|
||||||
<InputNumber min={0} max={9999} className="full-width" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item label="启用" name="enabled" valuePropName="checked">
|
|
||||||
<Switch />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
<Form.Item
|
||||||
label="自动创建"
|
label="资料字段"
|
||||||
name="autoCreate"
|
name="fieldsText"
|
||||||
valuePropName="checked"
|
extra="每行一个字段:key:名称,下拉项用 # 分隔(如 system:系统#安卓,苹果)"
|
||||||
>
|
>
|
||||||
<Switch />
|
<Input.TextArea rows={2} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
<Form.Item
|
</Form>
|
||||||
label="启用拼单"
|
</Card>
|
||||||
name="sharingEnabled"
|
<Card
|
||||||
valuePropName="checked"
|
className="product-rules-list-card"
|
||||||
tooltip="开启后按下方总数量与单价生成拼单工单"
|
title="物品规则"
|
||||||
>
|
extra={
|
||||||
<Switch />
|
<Space>
|
||||||
</Form.Item>
|
<Input.Search
|
||||||
</div>
|
allowClear
|
||||||
<Form.Item noStyle shouldUpdate>
|
placeholder="搜索规则标识/商品/SKU/店铺"
|
||||||
{({ getFieldValue }) =>
|
style={{ width: 240 }}
|
||||||
getFieldValue('sharingEnabled') ? (
|
value={keyword}
|
||||||
<Space size={16} wrap style={{ marginBottom: 16 }}>
|
onChange={(event) => setKeyword(event.target.value)}
|
||||||
<Form.Item
|
/>
|
||||||
label="拼单总数量"
|
<Button
|
||||||
name="sharingTotalQuantity"
|
icon={<ReloadOutlined />}
|
||||||
rules={[{ required: true, message: '请填写总数量' }]}
|
loading={rulesQuery.isFetching}
|
||||||
>
|
onClick={() => rulesQuery.refetch()}
|
||||||
<InputNumber
|
>
|
||||||
min={1}
|
刷新
|
||||||
max={100000}
|
</Button>
|
||||||
addonAfter="份"
|
</Space>
|
||||||
onChange={(value) =>
|
}
|
||||||
syncSharingRuleForm({
|
bordered={false}
|
||||||
sharingTotalQuantity: Number(value) || 0,
|
>
|
||||||
})
|
<Table<WorkProductRule>
|
||||||
}
|
rowKey="ruleId"
|
||||||
/>
|
loading={rulesQuery.isLoading}
|
||||||
</Form.Item>
|
dataSource={filteredRules}
|
||||||
<Form.Item
|
columns={columns}
|
||||||
label="拼单单价"
|
pagination={false}
|
||||||
name="sharingUnitReward"
|
scroll={{ x: 1000, y: 'calc(100vh - 300px)' }}
|
||||||
rules={[{ required: true, message: '请填写单价' }]}
|
rowClassName={(row) =>
|
||||||
tooltip="每个数量份对应的报酬,修改后总价自动重算"
|
editingRule?.ruleId === row.ruleId ? 'product-rule-row-active' : ''
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0.01}
|
|
||||||
step={1}
|
|
||||||
addonAfter="元"
|
|
||||||
onChange={(value) =>
|
|
||||||
syncSharingRuleForm({
|
|
||||||
sharingUnitReward: Number(value) || 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label="拼单总价"
|
|
||||||
name="sharingTotalAmount"
|
|
||||||
rules={[{ required: true, message: '请填写总价' }]}
|
|
||||||
tooltip="总价 = 单价 × 数量,修改总价会自动反推数量"
|
|
||||||
>
|
|
||||||
<InputNumber
|
|
||||||
min={0.01}
|
|
||||||
step={1}
|
|
||||||
addonAfter="元"
|
|
||||||
onChange={(value) =>
|
|
||||||
syncSharingRuleForm({
|
|
||||||
sharingTotalAmount: Number(value) || 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
</Space>
|
|
||||||
) : null
|
|
||||||
}
|
}
|
||||||
</Form.Item>
|
onRow={(row) => ({
|
||||||
<Form.Item
|
onClick: () => editRule(row),
|
||||||
label="资料字段"
|
title: '点击快速编辑',
|
||||||
name="fieldsText"
|
})}
|
||||||
extra="每行一个字段:key:名称,下拉项用 # 分隔(如 system:系统#安卓,苹果)"
|
/>
|
||||||
>
|
</Card>
|
||||||
<Input.TextArea rows={4} />
|
</div>
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label="默认任务时限"
|
|
||||||
name="timeoutMinutes"
|
|
||||||
tooltip="自动创建的工单继承该时限,打手抢单后开始计时;0 表示不限时"
|
|
||||||
>
|
|
||||||
<InputNumber min={0} step={5} addonAfter="分钟" />
|
|
||||||
</Form.Item>
|
|
||||||
<Form.Item
|
|
||||||
label="默认超时策略"
|
|
||||||
name="timeoutPolicy"
|
|
||||||
tooltip="reopen:释放押金退回大厅;cancel_release:取消退押金;cancel_deduct:取消扣押金"
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
style={{ width: 260 }}
|
|
||||||
options={[
|
|
||||||
{ value: 'reopen', label: '释放押金退回大厅' },
|
|
||||||
{ value: 'cancel_release', label: '取消订单并退还押金' },
|
|
||||||
{ value: 'cancel_deduct', label: '取消订单并扣除押金' },
|
|
||||||
]}
|
|
||||||
/>
|
|
||||||
</Form.Item>
|
|
||||||
<Space>
|
|
||||||
<Button type="primary" htmlType="submit">
|
|
||||||
{editingRule ? '保存修改' : '创建规则'}
|
|
||||||
</Button>
|
|
||||||
{!editingRule ? null : <Button onClick={resetRuleForm}>取消</Button>}
|
|
||||||
</Space>
|
|
||||||
</Form>
|
|
||||||
</Card>
|
|
||||||
<Card
|
|
||||||
title="物品规则"
|
|
||||||
extra={
|
|
||||||
<Button
|
|
||||||
icon={<ReloadOutlined />}
|
|
||||||
loading={rulesQuery.isFetching}
|
|
||||||
onClick={() => rulesQuery.refetch()}
|
|
||||||
>
|
|
||||||
刷新
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
bordered={false}
|
|
||||||
>
|
|
||||||
<Table<WorkProductRule>
|
|
||||||
rowKey="ruleId"
|
|
||||||
loading={rulesQuery.isLoading}
|
|
||||||
dataSource={rulesQuery.data?.data.items || []}
|
|
||||||
columns={columns}
|
|
||||||
pagination={false}
|
|
||||||
scroll={{ x: 1200 }}
|
|
||||||
/>
|
|
||||||
</Card>
|
|
||||||
</section>
|
</section>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1556,6 +1556,27 @@ select {
|
|||||||
gap: 5px;
|
gap: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 接单平台顶部紧凑统计条 */
|
||||||
|
.platform-summary-strip-card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-summary-strip-card .ant-card-body {
|
||||||
|
padding: 8px 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-summary-strip-item {
|
||||||
|
font-size: 13px;
|
||||||
|
color: rgba(0, 0, 0, 0.65);
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.platform-summary-strip-item strong {
|
||||||
|
font-size: 16px;
|
||||||
|
margin-left: 6px;
|
||||||
|
color: rgba(0, 0, 0, 0.88);
|
||||||
|
}
|
||||||
|
|
||||||
.metric-card span,
|
.metric-card span,
|
||||||
.metric-card small {
|
.metric-card small {
|
||||||
color: #6b7280;
|
color: #6b7280;
|
||||||
@@ -2373,9 +2394,66 @@ select {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 物品规则:左侧编辑表单 + 右侧可滚动列表 */
|
||||||
|
.product-rules-layout {
|
||||||
|
display: flex;
|
||||||
|
gap: 16px;
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-form-card {
|
||||||
|
width: 560px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 左侧表单一屏展示,不出现滚动条 */
|
||||||
|
.product-rules-form-card .ant-card-body {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-form-card .worker-rule-form .ant-form-item {
|
||||||
|
margin-bottom: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-form-card .worker-rule-form .ant-form-item-label {
|
||||||
|
padding-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-form-card .worker-rule-form .ant-input-textarea textarea {
|
||||||
|
min-height: 56px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-list-card {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-list-card .ant-card-body {
|
||||||
|
max-height: calc(100vh - 150px);
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-list-card .ant-table-wrapper {
|
||||||
|
max-height: calc(100vh - 230px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rule-row-active > td {
|
||||||
|
background: #e6f4ff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 1024px) {
|
||||||
|
.product-rules-layout {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.product-rules-form-card {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.worker-rule-grid {
|
.worker-rule-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||||
gap: 0 14px;
|
gap: 0 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user