import { useCallback, useEffect, useState } from 'react'; import { Link } from 'react-router-dom'; import { Alert, Button, Descriptions, Form, Input, InputNumber, Modal, Popconfirm, Select, Space, Switch, Table, Tag, Typography, message, } from 'antd'; import type { ColumnsType } from 'antd/es/table'; import { WAREHOUSE_FULFILLMENT_MODE_LABELS, WAREHOUSE_MANAGER_LABELS, WAREHOUSE_STATUS_LABELS, WarehouseFulfillmentMode, WarehouseManagerType, WarehouseStatus, type FulfillmentProviderDto, } from '@dukang/shared-types'; import { request, type Paginated } from '../lib/api'; import { ADMIN_OPTIONS_PAGE_SIZE, fmtTime } from '../lib/constants'; import { useAdminList } from '../lib/useAdminList'; type Row = { id: string; cityId: string; cityName: string; cityCode: string; name: string; address: string; contactName: string; contactPhone: string; managerType: WarehouseManagerType; partnerAccountId: string | null; partnerCompanyName?: string | null; status: string; fulfillmentMode?: string; fulfillmentProviderId?: string | null; fulfillmentProviderName?: string | null; manualCarrierLabel?: string | null; manualQueryUrlTemplate?: string | null; lng?: number | null; lat?: number | null; createdAt: string; }; type CityOption = { id: string; name: string; code: string }; 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 })); function FulfillmentFields({ mode, providerOptions, onModeChange, }: { mode: WarehouseFulfillmentMode; providerOptions: FulfillmentProviderDto[]; onModeChange: (mode: WarehouseFulfillmentMode) => void; }) { const autoShip = mode === WarehouseFulfillmentMode.API_AUTO; return ( <> ({ checked: v === WarehouseFulfillmentMode.API_AUTO })} getValueFromEvent={(checked: boolean) => checked ? WarehouseFulfillmentMode.API_AUTO : WarehouseFulfillmentMode.MANUAL } > { onModeChange( checked ? WarehouseFulfillmentMode.API_AUTO : WarehouseFulfillmentMode.MANUAL, ); }} /> {autoShip && ( )} ); } export default function CityWarehousesPage() { const [filterForm] = Form.useForm(); const [createForm] = Form.useForm(); const [editForm] = Form.useForm(); const [filters, setFilters] = useState>({}); const { data, loading, page, pageSize, setPage, setPageSize, reload } = useAdminList( '/admin/city-warehouses', () => { const qs = new URLSearchParams(); if (filters.name) qs.set('name', filters.name); if (filters.cityId) qs.set('cityId', filters.cityId); if (filters.managerType) qs.set('managerType', filters.managerType); if (filters.status) qs.set('status', filters.status); return qs; }, [filters], ); const [cities, setCities] = useState([]); const [partners, setPartners] = useState([]); const [createOpen, setCreateOpen] = useState(false); const [editOpen, setEditOpen] = useState(false); const [editRow, setEditRow] = useState(null); const [createManagerType, setCreateManagerType] = useState(WarehouseManagerType.HQ); const [editManagerType, setEditManagerType] = useState(WarehouseManagerType.HQ); const [createCityId, setCreateCityId] = useState(); const [createFulfillmentMode, setCreateFulfillmentMode] = useState( WarehouseFulfillmentMode.MANUAL, ); const [editFulfillmentMode, setEditFulfillmentMode] = useState( WarehouseFulfillmentMode.MANUAL, ); const [providerOptions, setProviderOptions] = useState([]); const loadCities = useCallback(async () => { const res = await request>(`/admin/cities?pageSize=${ADMIN_OPTIONS_PAGE_SIZE}`); setCities(res.items); }, []); const loadPartners = useCallback(async (cityId: string) => { const res = await request>( `/admin/partners?pageSize=${ADMIN_OPTIONS_PAGE_SIZE}&cityId=${cityId}`, ); setPartners(res.items); }, []); useEffect(() => { void loadCities(); void request('/admin/fulfillment-providers/active-api') .then(setProviderOptions) .catch(() => {}); }, [loadCities]); async function openEdit(row: Row) { setEditRow(row); setEditManagerType(row.managerType); await loadPartners(row.cityId); editForm.setFieldsValue({ name: row.name, address: row.address, contactName: row.contactName, contactPhone: row.contactPhone, managerType: row.managerType, partnerAccountId: row.partnerAccountId, status: row.status, fulfillmentMode: row.fulfillmentMode ?? WarehouseFulfillmentMode.MANUAL, fulfillmentProviderId: row.fulfillmentProviderId ?? undefined, manualCarrierLabel: row.manualCarrierLabel ?? undefined, manualQueryUrlTemplate: row.manualQueryUrlTemplate ?? undefined, lng: row.lng ?? undefined, lat: row.lat ?? undefined, }); setEditFulfillmentMode((row.fulfillmentMode as WarehouseFulfillmentMode) ?? WarehouseFulfillmentMode.MANUAL); setEditOpen(true); } function onManagerTypeChange( v: WarehouseManagerType, form: typeof createForm, setType: (t: WarehouseManagerType) => void, ) { setType(v); if (v !== WarehouseManagerType.PARTNER) { form.setFieldValue('partnerAccountId', undefined); } } const columns: ColumnsType = [ { title: '城市', width: 100, render: (_, row) => ( {row.cityName} ), }, { 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: '管仓', width: 90, render: (_, row) => WAREHOUSE_MANAGER_LABELS[row.managerType] || row.managerType, }, { title: '合伙人', dataIndex: 'partnerCompanyName', width: 120, ellipsis: true, render: (v, row) => v && row.partnerAccountId ? ( {v} ) : ( '—' ), }, { title: '自动发货', width: 130, render: (_, row) => row.fulfillmentMode === 'API_AUTO' ? ( {row.fulfillmentProviderName || '自动'} ) : ( {WAREHOUSE_FULFILLMENT_MODE_LABELS[WarehouseFulfillmentMode.MANUAL]} ), }, { title: '状态', dataIndex: 'status', width: 80, render: (s) => ( {WAREHOUSE_STATUS_LABELS[s as WarehouseStatus] || s} ), }, { title: '创建', dataIndex: 'createdAt', width: 150, render: fmtTime }, { title: '操作', width: 120, fixed: 'right', render: (_, row) => ( { await request(`/admin/city-warehouses/${row.id}`, { method: 'DELETE' }); message.success('已删除'); void reload(); }} > ), }, ]; return (
仓库
{ setFilters(v); setPage(1); }} > ({ value: c.id, label: `${c.name} (${c.code})` }))} onChange={(id) => { setCreateCityId(id); createForm.setFieldValue('partnerAccountId', undefined); void loadPartners(id); }} /> ({ value: p.id, label: p.companyName }))} /> )} ({ value: p.id, label: p.companyName }))} /> )}