import React, { useEffect, useMemo, useRef, useState } from 'react'; import { Button, Card, Drawer, Form, Image, Input, InputNumber, message, Select, Space, Table, Tag, Tree, TreeSelect, Typography, } from 'antd'; import { TableOutlined } from '@ant-design/icons'; import type { FormInstance, TableProps } from 'antd'; import XinTable from '@/components/XinTable'; import type { XinTableColumn, XinTableInstance, XinTableProps } from '@/components/XinTable/typings.ts'; import type IProduct from '@/domain/iProduct.ts'; import type { IBatchPriceUpdate, IPriceMatrixRow, IProductPrice } from '@/domain/iProduct.ts'; import { PRODUCT_STATUS_MAP } from '@/domain/iProduct.ts'; import type ICustomerLevel from '@/domain/iCustomerLevel.ts'; import type {IProductCategoryTree} from '@/domain/iProductCategory.ts'; import { getLevelOptions } from '@/api/customer/level.ts'; import { getSupplierOptions } from '@/api/customer/supplier.ts'; import type ISupplier from '@/domain/iSupplier.ts'; import { getCategoryTree } from '@/api/product/category.ts'; import { batchPrice, getPriceMatrix } from '@/api/product/goods.ts'; const { Title, Text } = Typography; /** 计价类型:0 固定价 / 1 成本百分比(与后端 ProductPriceModel::PRICE_TYPE_* 一致) */ const PRICE_TYPE_FIXED = 0; const PRICE_TYPE_PERCENT = 1; const PRICE_TYPE_OPTIONS = [ { value: PRICE_TYPE_FIXED, label: '固定价' }, { value: PRICE_TYPE_PERCENT, label: '成本百分比' }, ]; /** 四舍五入保留两位 */ const round2 = (v: number) => Math.round(v * 100) / 100; /** 商品表单用分类树:有子分类的节点禁选(商品只能挂在末级分类上) */ const markParentDisabled = (nodes: IProductCategoryTree[]): IProductCategoryTree[] => nodes.map((node) => ({ ...node, disabled: !!node.children?.length, children: node.children?.length ? markParentDisabled(node.children) : node.children, })); /** 侧栏用分类树:有子分类的节点不可选中(仅供展开,筛选按末级分类) */ const markParentUnselectable = (nodes: IProductCategoryTree[]): IProductCategoryTree[] => nodes.map((node) => ({ ...node, selectable: !node.children?.length, children: node.children?.length ? markParentUnselectable(node.children) : node.children, })); /** * 等级价格表单:每个等级 = 计价类型(固定价/成本百分比)+ 对应输入框; * 切换计价类型时按成本价自动换算(固定→百分比:percent=(price/cost-1)*100;百分比→固定:price=cost*(1+percent/100)) */ const LevelPriceFields: React.FC<{ form: FormInstance; levels: ICustomerLevel[]; }> = ({ form, levels }) => { const prices = Form.useWatch('prices', form) ?? []; const costPrice = Number(Form.useWatch('cost_price', form) ?? 0); if (levels.length === 0) { return ( 暂无可配置的客户等级,请先到「客户等级」中新增 ); } const updateRow = (levelId: number, patch: Partial) => { const next = prices.filter((p) => p.level_id !== levelId); next.push({ ...patch, level_id: levelId }); form.setFieldValue('prices', next); }; const removeRow = (levelId: number) => { form.setFieldValue('prices', prices.filter((p) => p.level_id !== levelId)); }; /** 切换计价类型:按成本价自动换算(成本未设置时百分比计价不可用) */ const onTypeChange = (levelId: number, row: IProductPrice | undefined, type: number) => { if (type === PRICE_TYPE_PERCENT) { if (!(costPrice > 0)) { message.warning('请先在商品信息中设置成本价,才能按成本百分比计价'); return; // Select 为受控组件,未更新表单值即回弹 } const price = Number(row?.price ?? 0); updateRow(levelId, { price_type: type, percent: price > 0 ? round2((price / costPrice - 1) * 100) : null, }); } else { const percent = Number(row?.percent ?? 0); updateRow(levelId, { price_type: type, price: costPrice > 0 && percent > 0 ? round2(costPrice * (1 + percent / 100)) : (row?.price ?? null), }); } }; return ( {levels.map((level) => { if (level.id == null) return null; const row = prices.find((p) => p.level_id === level.id); const type = row?.price_type ?? PRICE_TYPE_FIXED; return ( {level.name}