对账标记
This commit is contained in:
@@ -17,9 +17,10 @@ import {
|
|||||||
Table,
|
Table,
|
||||||
Tabs,
|
Tabs,
|
||||||
Tag,
|
Tag,
|
||||||
|
Tooltip,
|
||||||
Typography,
|
Typography,
|
||||||
} from 'antd';
|
} from 'antd';
|
||||||
import {AccountBookOutlined, DeleteOutlined, DownloadOutlined, EditOutlined, PlusOutlined, UnorderedListOutlined} from '@ant-design/icons';
|
import {AccountBookOutlined, CheckOutlined, DeleteOutlined, DownloadOutlined, EditOutlined, PlusOutlined, UnorderedListOutlined} from '@ant-design/icons';
|
||||||
import type { TableProps } from 'antd';
|
import type { TableProps } from 'antd';
|
||||||
import XinTable from '@/components/XinTable';
|
import XinTable from '@/components/XinTable';
|
||||||
import type {
|
import type {
|
||||||
@@ -98,6 +99,9 @@ const PurchaseOrderPage: React.FC = () => {
|
|||||||
const [detailLoading, setDetailLoading] = useState(false);
|
const [detailLoading, setDetailLoading] = useState(false);
|
||||||
const [completing, setCompleting] = useState(false);
|
const [completing, setCompleting] = useState(false);
|
||||||
|
|
||||||
|
// 商品明细:单品「已对账」勾选标记(前端本地控制不入库,按采购单持久化到 localStorage)
|
||||||
|
const [checkedItems, setCheckedItems] = useState<Set<number>>(new Set());
|
||||||
|
|
||||||
// 行内编辑:供应商选项(品名/供应商/包规/单位/成本与各门店订货量直接在表格中编辑)
|
// 行内编辑:供应商选项(品名/供应商/包规/单位/成本与各门店订货量直接在表格中编辑)
|
||||||
const [suppliers, setSuppliers] = useState<ISupplier[]>([]);
|
const [suppliers, setSuppliers] = useState<ISupplier[]>([]);
|
||||||
|
|
||||||
@@ -246,6 +250,37 @@ const PurchaseOrderPage: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [detailOpen, detailTab, storeId, detail?.purchase.id]);
|
}, [detailOpen, detailTab, storeId, detail?.purchase.id]);
|
||||||
|
|
||||||
|
// 切换采购单时从 localStorage 恢复单品「已对账」标记
|
||||||
|
useEffect(() => {
|
||||||
|
if (!detail) {
|
||||||
|
setCheckedItems(new Set());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const raw = localStorage.getItem(`purchase-checked-items:${detail.purchase.id}`);
|
||||||
|
setCheckedItems(new Set(raw ? (JSON.parse(raw) as number[]) : []));
|
||||||
|
} catch {
|
||||||
|
setCheckedItems(new Set());
|
||||||
|
}
|
||||||
|
}, [detail]);
|
||||||
|
|
||||||
|
/** 切换单品「已对账」标记(前端本地控制,不入库) */
|
||||||
|
const toggleItemChecked = (productId: number) => {
|
||||||
|
if (!detail) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCheckedItems((prev) => {
|
||||||
|
const next = new Set(prev);
|
||||||
|
if (next.has(productId)) {
|
||||||
|
next.delete(productId);
|
||||||
|
} else {
|
||||||
|
next.add(productId);
|
||||||
|
}
|
||||||
|
localStorage.setItem(`purchase-checked-items:${detail.purchase.id}`, JSON.stringify([...next]));
|
||||||
|
return next;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const loadDetail = async (id: number) => {
|
const loadDetail = async (id: number) => {
|
||||||
setDetailLoading(true);
|
setDetailLoading(true);
|
||||||
try {
|
try {
|
||||||
@@ -566,17 +601,36 @@ const PurchaseOrderPage: React.FC = () => {
|
|||||||
title: '市场',
|
title: '市场',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
dataIndex: 'market',
|
dataIndex: 'market',
|
||||||
width: 110,
|
width: 90,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
filters: itemMarketOptions.map((m) => ({ text: m, value: m })),
|
filters: itemMarketOptions.map((m) => ({ text: m, value: m })),
|
||||||
filteredValue: itemColumnFilters.market ?? null,
|
filteredValue: itemColumnFilters.market ?? null,
|
||||||
onFilter: (value, row) => (row.market ?? '') === value,
|
onFilter: (value, row) => (row.market ?? '') === value,
|
||||||
render: (v) => v || '-',
|
render: (v, row) => {
|
||||||
|
// ✔ 按钮标记本单品已对账(前端本地标记,不入库)
|
||||||
|
const checked = checkedItems.has(row.product_id);
|
||||||
|
return (
|
||||||
|
<Space size={4}>
|
||||||
|
<span>{v || '-'}</span>
|
||||||
|
<Tooltip title={checked ? '取消对账标记' : '标记本单品已对账'}>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
shape="circle"
|
||||||
|
style={{ minWidth: 16, height: 16, width: 16 }}
|
||||||
|
icon={<CheckOutlined />}
|
||||||
|
color={checked ? 'green' : 'default'}
|
||||||
|
variant={checked ? 'solid' : 'outlined'}
|
||||||
|
onClick={() => toggleItemChecked(row.product_id)}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
);
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '单价',
|
title: '单价',
|
||||||
key: 'retail_price',
|
key: 'retail_price',
|
||||||
width: 110,
|
width: 90,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render: (_, row) => {
|
render: (_, row) => {
|
||||||
// 加权平均售价 ÷ 包规数值(无订货数量时无参考价)
|
// 加权平均售价 ÷ 包规数值(无订货数量时无参考价)
|
||||||
@@ -590,20 +644,20 @@ const PurchaseOrderPage: React.FC = () => {
|
|||||||
title: '包规',
|
title: '包规',
|
||||||
dataIndex: 'product_spec',
|
dataIndex: 'product_spec',
|
||||||
align: 'center',
|
align: 'center',
|
||||||
width: 110,
|
width: 90,
|
||||||
render: (v, row) => renderEditableCell(row, 'product_spec', v || '-'),
|
render: (v, row) => renderEditableCell(row, 'product_spec', v || '-'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '单位',
|
title: '单位',
|
||||||
dataIndex: 'unit',
|
dataIndex: 'unit',
|
||||||
width: 110,
|
width: 90,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render: (v, row) => renderEditableCell(row, 'unit', v || '-'),
|
render: (v, row) => renderEditableCell(row, 'unit', v || '-'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: '成本',
|
title: '成本',
|
||||||
dataIndex: 'cost_price',
|
dataIndex: 'cost_price',
|
||||||
width: 110,
|
width: 120,
|
||||||
align: 'center',
|
align: 'center',
|
||||||
render: (v, row) => renderEditableCell(row, 'cost_price', `¥${Number(v).toFixed(2)}`),
|
render: (v, row) => renderEditableCell(row, 'cost_price', `¥${Number(v).toFixed(2)}`),
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user