Both list pages had 查看 links with no onClick. Added detail pages showing header info and line items, with action buttons (确认开始盘点 / 审核通过+驳回). Also: extended StockCheck/StockAdjust types to include details and extra fields; added /inventory/checks/:id and /inventory/adjusts/:id routes; moved columns definitions inside components (module-level columns with history.push were silently ignored by the browser due to MFSU caching); switched to Link component for SPA navigation.
192 lines
6.9 KiB
TypeScript
192 lines
6.9 KiB
TypeScript
import { DeleteOutlined, PlusOutlined } from '@ant-design/icons';
|
|
import { ActionType, ProColumns, ProTable } from '@ant-design/pro-components';
|
|
import { Button, Col, Form, Input, Modal, Row, Select, Table, Tag, message } from 'antd';
|
|
import { useEffect, useRef, useState } from 'react';
|
|
import { Link } from '@umijs/max';
|
|
import { createStockAdjust, listProducts, listStockAdjusts } from '@/services/api';
|
|
import type { Product, StockAdjust } from '@/types/api';
|
|
|
|
const STATUS_MAP: Record<number, { text: string; color: string }> = {
|
|
0: { text: '待审核', color: 'warning' },
|
|
1: { text: '已审核', color: 'success' },
|
|
2: { text: '已驳回', color: 'error' },
|
|
};
|
|
|
|
interface DetailRow { key: number; productId?: string; adjustQuantity?: string }
|
|
let rowKey = 0;
|
|
|
|
const AdjustsPage: React.FC = () => {
|
|
const columns: ProColumns<StockAdjust>[] = [
|
|
{ title: '调整单号', dataIndex: 'adjustNo' },
|
|
{ title: '调整日期', dataIndex: 'adjustDate', valueType: 'date', search: false },
|
|
{ title: '调整原因', dataIndex: 'adjustReason', search: false },
|
|
{ title: '操作人', dataIndex: 'operator', search: false },
|
|
{
|
|
title: '状态',
|
|
dataIndex: 'status',
|
|
search: false,
|
|
render: (_, record) => {
|
|
const s = STATUS_MAP[record.status] ?? STATUS_MAP[0];
|
|
return <Tag color={s.color}>{s.text}</Tag>;
|
|
},
|
|
},
|
|
{ title: '创建时间', dataIndex: 'createdAt', valueType: 'dateTime', search: false },
|
|
{ title: '操作', valueType: 'option', render: (_, record) => [<Link key="view" to={`/inventory/adjusts/${record.adjustId}`}>查看</Link>] },
|
|
];
|
|
const actionRef = useRef<ActionType>();
|
|
const [form] = Form.useForm();
|
|
const [open, setOpen] = useState(false);
|
|
const [submitting, setSubmitting] = useState(false);
|
|
const [products, setProducts] = useState<Product[]>([]);
|
|
const [details, setDetails] = useState<DetailRow[]>([{ key: rowKey++ }]);
|
|
|
|
useEffect(() => {
|
|
listProducts({ page: 1, pageSize: 500 }).then((res) => {
|
|
if (res?.code === 0) setProducts(res.data?.list || []);
|
|
});
|
|
}, []);
|
|
|
|
const handleOpen = () => {
|
|
setDetails([{ key: rowKey++ }]);
|
|
setOpen(true);
|
|
};
|
|
|
|
const handleSubmit = async () => {
|
|
let values: { adjustDate: string; adjustReason?: string; remark?: string };
|
|
try {
|
|
values = await form.validateFields();
|
|
} catch {
|
|
return;
|
|
}
|
|
const validDetails = details.filter((r) => r.productId && r.adjustQuantity);
|
|
if (validDetails.length === 0) {
|
|
message.error('请至少添加一条调整明细');
|
|
return;
|
|
}
|
|
setSubmitting(true);
|
|
try {
|
|
const res = await createStockAdjust({
|
|
...values,
|
|
details: validDetails.map((r) => ({ productId: r.productId!, adjustQuantity: r.adjustQuantity! })),
|
|
});
|
|
if (res?.code !== 0) { message.error(res?.msg || '创建失败'); return; }
|
|
setOpen(false);
|
|
actionRef.current?.reload();
|
|
message.success('调整单已创建');
|
|
} catch {
|
|
message.error('创建失败');
|
|
} finally {
|
|
setSubmitting(false);
|
|
}
|
|
};
|
|
|
|
const addRow = () => setDetails((prev) => [...prev, { key: rowKey++ }]);
|
|
const removeRow = (idx: number) => setDetails((prev) => prev.filter((_, i) => i !== idx));
|
|
const updateRow = (idx: number, field: keyof DetailRow, value: string) =>
|
|
setDetails((prev) => prev.map((r, i) => (i === idx ? { ...r, [field]: value } : r)));
|
|
|
|
const today = new Date().toISOString().slice(0, 10);
|
|
|
|
return (
|
|
<>
|
|
<ProTable<StockAdjust>
|
|
actionRef={actionRef}
|
|
headerTitle="库存调整"
|
|
rowKey="adjustId"
|
|
columns={columns}
|
|
search={false}
|
|
request={async (params) => {
|
|
const res = await listStockAdjusts({ page: params.current, pageSize: params.pageSize });
|
|
return { data: res?.data?.list || [], total: res?.data?.total || 0, success: res?.code === 0 };
|
|
}}
|
|
toolBarRender={() => [
|
|
<Button key="add" type="primary" icon={<PlusOutlined />} onClick={handleOpen}>创建调整单</Button>,
|
|
]}
|
|
/>
|
|
|
|
<Modal
|
|
title="创建调整单"
|
|
open={open}
|
|
onOk={handleSubmit}
|
|
onCancel={() => setOpen(false)}
|
|
confirmLoading={submitting}
|
|
width={680}
|
|
afterOpenChange={(o) => { if (!o) form.resetFields(); }}
|
|
>
|
|
<Form form={form} layout="vertical" initialValues={{ adjustDate: today, adjustReason: '', remark: '' }}>
|
|
<Row gutter={16}>
|
|
<Col span={12}>
|
|
<Form.Item name="adjustDate" label="调整日期" rules={[{ required: true, message: '请选择日期' }]}>
|
|
<Input type="date" />
|
|
</Form.Item>
|
|
</Col>
|
|
<Col span={12}>
|
|
<Form.Item name="adjustReason" label="调整原因">
|
|
<Input placeholder="如:盘亏、损耗、退货入库" />
|
|
</Form.Item>
|
|
</Col>
|
|
</Row>
|
|
<Form.Item name="remark" label="备注">
|
|
<Input.TextArea rows={2} />
|
|
</Form.Item>
|
|
</Form>
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 8 }}>
|
|
<span style={{ fontWeight: 500 }}>调整明细</span>
|
|
<Button size="small" icon={<PlusOutlined />} onClick={addRow}>添加行</Button>
|
|
</div>
|
|
<Table
|
|
size="small"
|
|
rowKey="key"
|
|
dataSource={details}
|
|
pagination={false}
|
|
columns={[
|
|
{
|
|
title: '产品',
|
|
render: (_, __, idx) => (
|
|
<Select
|
|
style={{ width: '100%' }}
|
|
showSearch
|
|
placeholder="选择产品"
|
|
value={details[idx].productId}
|
|
optionFilterProp="label"
|
|
options={products.map((p) => ({ value: p.productId, label: `${p.productName}${p.spec ? ' ' + p.spec : ''}${p.color ? ' ' + p.color : ''}` }))}
|
|
onChange={(v) => updateRow(idx, 'productId', v)}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
title: '调整数量(米)',
|
|
width: 150,
|
|
render: (_, __, idx) => (
|
|
<Input
|
|
type="number"
|
|
step="0.01"
|
|
placeholder="正数增加,负数减少"
|
|
value={details[idx].adjustQuantity}
|
|
onChange={(e) => updateRow(idx, 'adjustQuantity', e.target.value)}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
title: '',
|
|
width: 40,
|
|
render: (_, __, idx) => (
|
|
<Button
|
|
type="text"
|
|
danger
|
|
icon={<DeleteOutlined />}
|
|
disabled={details.length === 1}
|
|
onClick={() => removeRow(idx)}
|
|
/>
|
|
),
|
|
},
|
|
]}
|
|
/>
|
|
</Modal>
|
|
</>
|
|
);
|
|
};
|
|
|
|
export default AdjustsPage;
|