仓库自动配送开关
CI / verify (pull_request) Has been cancelled

This commit is contained in:
2026-07-17 08:50:18 +08:00
parent c643b0b979
commit c204fb0a92
3 changed files with 85 additions and 74 deletions
+80 -69
View File
@@ -11,6 +11,7 @@ import {
Popconfirm,
Select,
Space,
Switch,
Table,
Tag,
Typography,
@@ -59,29 +60,54 @@ type PartnerOption = { id: string; companyName: string };
const MANAGER_OPTIONS = Object.entries(WAREHOUSE_MANAGER_LABELS).map(([value, label]) => ({ value, label }));
const STATUS_OPTIONS = Object.entries(WAREHOUSE_STATUS_LABELS).map(([value, label]) => ({ value, label }));
const FULFILLMENT_MODE_OPTIONS = Object.entries(WAREHOUSE_FULFILLMENT_MODE_LABELS).map(([value, label]) => ({
value,
label,
}));
function FulfillmentFields({
mode,
providerOptions,
onModeChange,
}: {
mode: WarehouseFulfillmentMode;
providerOptions: FulfillmentProviderDto[];
onModeChange: (mode: WarehouseFulfillmentMode) => void;
}) {
const autoShip = mode === WarehouseFulfillmentMode.API_AUTO;
return (
<>
{mode === WarehouseFulfillmentMode.API_AUTO && (
<Form.Item name="fulfillmentProviderId" label="仓配承运商" rules={[{ required: true }]}>
<Form.Item
name="fulfillmentMode"
label="支付后自动发货"
extra={
autoShip
? '同城订单支付成功后,自动推送仓配承运商(如小飞侠)并进入配送中'
: '支付后仅分配仓库,保持待发货,由仓管或总部手工填运单'
}
getValueProps={(v) => ({ checked: v === WarehouseFulfillmentMode.API_AUTO })}
getValueFromEvent={(checked: boolean) =>
checked ? WarehouseFulfillmentMode.API_AUTO : WarehouseFulfillmentMode.MANUAL
}
>
<Switch
checkedChildren="开"
unCheckedChildren="关"
onChange={(checked) => {
onModeChange(
checked ? WarehouseFulfillmentMode.API_AUTO : WarehouseFulfillmentMode.MANUAL,
);
}}
/>
</Form.Item>
{autoShip && (
<Form.Item
name="fulfillmentProviderId"
label="仓配承运商"
rules={[{ required: true, message: '自动发货须选择承运商' }]}
>
<Select
placeholder={providerOptions.length ? '选择已注册承运商' : '请先在仓配管理注册'}
options={providerOptions.map((p) => ({ value: p.id, label: `${p.name} (${p.code})` }))}
/>
</Form.Item>
)}
{mode === WarehouseFulfillmentMode.MANUAL && (
{!autoShip && (
<>
<Form.Item name="manualCarrierLabel" label="默认承运商名称">
<Input placeholder="如 顺丰速运" />
@@ -183,18 +209,17 @@ export default function CityWarehousesPage() {
}
function onManagerTypeChange(
type: WarehouseManagerType,
form: typeof createForm | typeof editForm,
setType: (v: WarehouseManagerType) => void,
v: WarehouseManagerType,
form: typeof createForm,
setType: (t: WarehouseManagerType) => void,
) {
setType(type);
if (type !== WarehouseManagerType.PARTNER) {
setType(v);
if (v !== WarehouseManagerType.PARTNER) {
form.setFieldValue('partnerAccountId', undefined);
}
}
const columns: ColumnsType<Row> = [
{ title: '仓库名', dataIndex: 'name', ellipsis: true, width: 140 },
{
title: '城市',
width: 100,
@@ -204,17 +229,17 @@ export default function CityWarehousesPage() {
</span>
),
},
{ title: '地址', dataIndex: 'address', ellipsis: true },
{ title: '仓库', dataIndex: 'name', width: 140, ellipsis: true },
{ title: '地址', dataIndex: 'address', width: 180, ellipsis: true },
{ title: '联系人', dataIndex: 'contactName', width: 90 },
{ title: '电话', dataIndex: 'contactPhone', width: 120 },
{
title: '管仓类型',
dataIndex: 'managerType',
width: 100,
render: (v) => WAREHOUSE_MANAGER_LABELS[v as WarehouseManagerType] || v,
title: '管仓',
width: 90,
render: (_, row) => WAREHOUSE_MANAGER_LABELS[row.managerType] || row.managerType,
},
{
title: '管仓合伙人',
title: '合伙人',
dataIndex: 'partnerCompanyName',
width: 120,
ellipsis: true,
@@ -226,12 +251,14 @@ export default function CityWarehousesPage() {
),
},
{
title: '履约',
width: 120,
title: '自动发货',
width: 130,
render: (_, row) =>
row.fulfillmentMode === 'API_AUTO'
? row.fulfillmentProviderName || 'API'
: WAREHOUSE_FULFILLMENT_MODE_LABELS[WarehouseFulfillmentMode.MANUAL],
row.fulfillmentMode === 'API_AUTO' ? (
<Tag color="blue">{row.fulfillmentProviderName || '自动'}</Tag>
) : (
<Tag>{WAREHOUSE_FULFILLMENT_MODE_LABELS[WarehouseFulfillmentMode.MANUAL]}</Tag>
),
},
{
title: '状态',
@@ -274,21 +301,23 @@ export default function CityWarehousesPage() {
return (
<div>
<Space style={{ marginBottom: 16, width: '100%', justifyContent: 'space-between' }}>
<Typography.Title level={4} style={{ margin: 0 }}>
</Typography.Title>
<Typography.Title level={4} style={{ margin: 0 }}></Typography.Title>
<Button
type="primary"
onClick={() => {
createForm.resetFields();
createForm.setFieldsValue({ managerType: WarehouseManagerType.HQ, status: WarehouseStatus.ACTIVE });
setCreateManagerType(WarehouseManagerType.HQ);
setCreateCityId(undefined);
setPartners([]);
setCreateFulfillmentMode(WarehouseFulfillmentMode.MANUAL);
createForm.setFieldsValue({
managerType: WarehouseManagerType.HQ,
status: WarehouseStatus.ACTIVE,
fulfillmentMode: WarehouseFulfillmentMode.MANUAL,
});
setCreateOpen(true);
}}
>
</Button>
</Space>
@@ -296,7 +325,7 @@ export default function CityWarehousesPage() {
type="info"
showIcon
style={{ marginBottom: 16 }}
message="管仓合伙人仅可在此页面分配;城市合伙人详情中的管仓仓库为只读展示。"
message="同城有仓订单:支付后按「自动发货」开关决定是否推仓配 API;关闭则待人工填单。跨城/无仓仍走总部快递填单。"
/>
<Form
@@ -309,7 +338,7 @@ export default function CityWarehousesPage() {
}}
>
<Form.Item name="name" label="仓库名">
<Input allowClear placeholder="仓库名" />
<Input allowClear />
</Form.Item>
<Form.Item name="cityId" label="城市">
<Select
@@ -317,47 +346,33 @@ export default function CityWarehousesPage() {
showSearch
optionFilterProp="label"
style={{ width: 140 }}
placeholder="全部城市"
options={cities.map((c) => ({ value: c.id, label: c.name }))}
/>
</Form.Item>
<Form.Item name="managerType" label="管仓类型">
<Select allowClear style={{ width: 120 }} placeholder="全部" options={MANAGER_OPTIONS} />
<Form.Item name="managerType" label="管仓">
<Select allowClear style={{ width: 120 }} options={MANAGER_OPTIONS} />
</Form.Item>
<Form.Item name="status" label="状态">
<Select allowClear style={{ width: 100 }} placeholder="全部" options={STATUS_OPTIONS} />
<Select allowClear style={{ width: 100 }} options={STATUS_OPTIONS} />
</Form.Item>
<Form.Item>
<Space>
<Button type="primary" htmlType="submit">
</Button>
<Button
onClick={() => {
filterForm.resetFields();
setFilters({});
setPage(1);
}}
>
</Button>
</Space>
<Button type="primary" htmlType="submit">
</Button>
</Form.Item>
</Form>
<Table
rowKey="id"
className="admin-table-nowrap"
loading={loading}
columns={columns}
dataSource={data?.items ?? []}
scroll={{ x: 1100 }}
scroll={{ x: 1400 }}
pagination={{
current: page,
pageSize,
total: data?.total ?? 0,
showSizeChanger: true,
showTotal: (t) => `${t}`,
onChange: (p, ps) => {
setPage(p);
setPageSize(ps);
@@ -366,7 +381,7 @@ export default function CityWarehousesPage() {
/>
<Modal
title="新仓库"
title="新仓库"
open={createOpen}
width={520}
onCancel={() => setCreateOpen(false)}
@@ -425,13 +440,11 @@ export default function CityWarehousesPage() {
<Form.Item name="status" label="状态" initialValue={WarehouseStatus.ACTIVE}>
<Select options={STATUS_OPTIONS} />
</Form.Item>
<Form.Item name="fulfillmentMode" label="履约方式" initialValue={WarehouseFulfillmentMode.MANUAL}>
<Select
options={FULFILLMENT_MODE_OPTIONS}
onChange={(v) => setCreateFulfillmentMode(v)}
/>
</Form.Item>
<FulfillmentFields mode={createFulfillmentMode} providerOptions={providerOptions} />
<FulfillmentFields
mode={createFulfillmentMode}
providerOptions={providerOptions}
onModeChange={setCreateFulfillmentMode}
/>
</Form>
</Modal>
@@ -490,13 +503,11 @@ export default function CityWarehousesPage() {
<Form.Item name="status" label="状态">
<Select options={STATUS_OPTIONS} />
</Form.Item>
<Form.Item name="fulfillmentMode" label="履约方式">
<Select
options={FULFILLMENT_MODE_OPTIONS}
onChange={(v) => setEditFulfillmentMode(v)}
/>
</Form.Item>
<FulfillmentFields mode={editFulfillmentMode} providerOptions={providerOptions} />
<FulfillmentFields
mode={editFulfillmentMode}
providerOptions={providerOptions}
onModeChange={setEditFulfillmentMode}
/>
</Form>
</Modal>
</div>
+2 -2
View File
@@ -194,8 +194,8 @@ export const FULFILLMENT_PROVIDER_STATUS_LABELS: Record<FulfillmentProviderStatu
};
export const WAREHOUSE_FULFILLMENT_MODE_LABELS: Record<WarehouseFulfillmentMode, string> = {
[WarehouseFulfillmentMode.API_AUTO]: 'API 自动推单',
[WarehouseFulfillmentMode.MANUAL]: '自管手工填单',
[WarehouseFulfillmentMode.API_AUTO]: '自动发货',
[WarehouseFulfillmentMode.MANUAL]: '关闭(手工填单',
};
export enum AccountStatus {
+3 -3
View File
@@ -177,7 +177,7 @@ async function main() {
const xfxProvider = await prisma.fulfillmentProvider.create({
await prisma.fulfillmentProvider.create({
data: {
code: 'XFX',
name: '小飞侠',
@@ -218,9 +218,9 @@ async function main() {
status: 'ACTIVE',
fulfillmentMode: 'API_AUTO',
fulfillmentMode: 'MANUAL',
fulfillmentProviderId: xfxProvider.id,
fulfillmentProviderId: null,
lng: 113.665,