diff --git a/src/components/warehouse/ProductForm.tsx b/src/components/warehouse/ProductForm.tsx
index 40153f5..766c9fa 100644
--- a/src/components/warehouse/ProductForm.tsx
+++ b/src/components/warehouse/ProductForm.tsx
@@ -18,6 +18,7 @@ interface ProductFormData {
production_price: string;
yarn_ratios: { yarn_name: string; ratio: number; yarn_type: 'warp' | 'weft' | 'all' }[];
image_url?: string;
+ product_type?: string;
}
interface ProductFormProps {
@@ -63,7 +64,8 @@ const defaultInitialForm: ProductFormData = {
color_code: '01',
production_price: '',
yarn_ratios: [{ yarn_name: '', ratio: 100, yarn_type: 'all' }],
- image_url: undefined
+ image_url: undefined,
+ product_type: 'raw_fabric'
};
export function ProductForm({
@@ -104,7 +106,8 @@ export function ProductForm({
yarn_ratios: ratios.length > 0
? ratios.map(r => ({ yarn_name: r.yarn_name, ratio: r.ratio, yarn_type: (r.yarn_type as 'warp' | 'weft' | 'all') || 'all' }))
: [{ yarn_name: '', ratio: 100, yarn_type: 'all' }],
- image_url: editingProduct.image_url || undefined
+ image_url: editingProduct.image_url || undefined,
+ product_type: (editingProduct as any).product_type || 'raw_fabric'
});
setPreviewUrl(editingProduct.image_url || null);
} else if (initialFormData) {
@@ -525,6 +528,23 @@ export function ProductForm({
)}
+ {/* 产品类型选择 */}
+
+
+
+
+
{/* 三级结构:成品名称-颜色 */}
{/* 成品名称 - 带搜索建议 */}
diff --git a/src/components/warehouse/ProductList.tsx b/src/components/warehouse/ProductList.tsx
index 195d473..f2b7cf0 100644
--- a/src/components/warehouse/ProductList.tsx
+++ b/src/components/warehouse/ProductList.tsx
@@ -15,6 +15,12 @@ interface ProductListProps {
onDelete: (id: string) => void;
}
+const productTypeLabels: Record
= {
+ raw_fabric: { label: '原坯布', color: 'bg-gray-100 text-gray-600' },
+ textile: { label: '纺织成品', color: 'bg-blue-100 text-blue-600' },
+ washed: { label: '水洗成品', color: 'bg-green-100 text-green-600' },
+};
+
export function ProductList({
products,
productRatios,
@@ -402,7 +408,14 @@ function ProductRow({ product, ratios, onViewRecords, onViewPriceHistory, onView
)}
{product.color}
-
色号: {product.color_code}
+
+
色号: {product.color_code}
+ {(() => {
+ const pt = (product as any).product_type || 'raw_fabric';
+ const info = productTypeLabels[pt] || productTypeLabels.raw_fabric;
+ return
{info.label};
+ })()}
+
@@ -469,9 +482,16 @@ function ProductCardMobile({ product, ratios, onViewRecords, onViewPriceHistory,
)}
{product.color}
-
- {product.fabric_code}
-
+
+
+ {product.fabric_code}
+
+ {(() => {
+ const pt = (product as any).product_type || 'raw_fabric';
+ const info = productTypeLabels[pt] || productTypeLabels.raw_fabric;
+ return {info.label};
+ })()}
+
diff --git a/src/pages/purchaser/NewPlan.tsx b/src/pages/purchaser/NewPlan.tsx
index 5bfbde5..cc848a0 100644
--- a/src/pages/purchaser/NewPlan.tsx
+++ b/src/pages/purchaser/NewPlan.tsx
@@ -28,6 +28,7 @@ interface Product {
production_price: number;
image_url: string | null;
yarn_usage_per_meter: number;
+ product_type?: string;
}
// 纱线配比类型
@@ -125,16 +126,19 @@ export function NewPlan() {
setFactories(textileFactories);
};
- // 根据搜索词筛选产品
+ // 根据搜索词筛选产品(仅原坯布类型)
const filteredProducts = useMemo(() => {
- if (!searchQuery.trim()) return [];
- const query = searchQuery.toLowerCase();
- return products.filter(product =>
- product.product_name?.toLowerCase().includes(query) ||
- product.fabric_code?.toLowerCase().includes(query) ||
- product.color?.toLowerCase().includes(query) ||
- product.color_code?.toLowerCase().includes(query)
- ).slice(0, 10); // 最多显示10条
+ let list = products.filter(p => !p.product_type || p.product_type === 'raw_fabric');
+ if (searchQuery.trim()) {
+ const query = searchQuery.toLowerCase();
+ list = list.filter(product =>
+ product.product_name?.toLowerCase().includes(query) ||
+ product.fabric_code?.toLowerCase().includes(query) ||
+ product.color?.toLowerCase().includes(query) ||
+ product.color_code?.toLowerCase().includes(query)
+ );
+ }
+ return list.slice(0, 20);
}, [searchQuery, products]);
// 选择产品后自动填充表单
diff --git a/src/pages/purchaser/NewWashingPlan.tsx b/src/pages/purchaser/NewWashingPlan.tsx
index 7bd0a0f..bb95e01 100644
--- a/src/pages/purchaser/NewWashingPlan.tsx
+++ b/src/pages/purchaser/NewWashingPlan.tsx
@@ -43,16 +43,18 @@ export function NewWashingPlan() {
const res = await purchaserApi.listProducts();
const productsData = res.data || [];
- const productsWithInventory: ProductWithInventory[] = productsData.map(product => ({
- ...product,
- raw_fabric_meters: product.raw_fabric_meters || 0,
- raw_fabric_rolls: product.raw_fabric_rolls || 0,
- total_stock: product.total_stock || 0,
- total_in_meters: 0,
- total_in_rolls: 0,
- total_out_meters: 0,
- total_out_rolls: 0
- }));
+ const productsWithInventory: ProductWithInventory[] = productsData
+ .filter((p: any) => p.product_type === 'textile')
+ .map(product => ({
+ ...product,
+ raw_fabric_meters: product.raw_fabric_meters || 0,
+ raw_fabric_rolls: product.raw_fabric_rolls || 0,
+ total_stock: product.total_stock || 0,
+ total_in_meters: 0,
+ total_in_rolls: 0,
+ total_out_meters: 0,
+ total_out_rolls: 0
+ }));
setProducts(productsWithInventory);
}, [auth.company]);
diff --git a/src/pages/purchaser/WarehouseManage.tsx b/src/pages/purchaser/WarehouseManage.tsx
index d8361ef..14da957 100644
--- a/src/pages/purchaser/WarehouseManage.tsx
+++ b/src/pages/purchaser/WarehouseManage.tsx
@@ -38,6 +38,7 @@ interface ProductFormData {
production_price: string;
yarn_ratios: { yarn_name: string; ratio: number; yarn_type: 'warp' | 'weft' | 'all' }[];
image_url?: string;
+ product_type?: string;
}
interface InboundFormData {
@@ -103,6 +104,7 @@ export function WarehouseManage() {
// 搜索
const [searchQuery, setSearchQuery] = useState('');
+ const [productTypeFilter, setProductTypeFilter] = useState('all');
// 展开状态
const [expandedGroups, setExpandedGroups] = useState>({});
@@ -145,13 +147,19 @@ export function WarehouseManage() {
// 筛选产品
const filteredProducts = useMemo(() => {
- if (!searchQuery) return products;
- return products.filter(p =>
- p.product_name.includes(searchQuery) ||
- p.fabric_code.includes(searchQuery) ||
- p.color.includes(searchQuery)
- );
- }, [products, searchQuery]);
+ let filtered = products;
+ if (productTypeFilter !== 'all') {
+ filtered = filtered.filter(p => (p as any).product_type === productTypeFilter || (!((p as any).product_type) && productTypeFilter === 'raw_fabric'));
+ }
+ if (searchQuery) {
+ filtered = filtered.filter(p =>
+ p.product_name.includes(searchQuery) ||
+ p.fabric_code.includes(searchQuery) ||
+ p.color.includes(searchQuery)
+ );
+ }
+ return filtered;
+ }, [products, searchQuery, productTypeFilter]);
// 保存产品
const handleSaveProduct = useCallback(async (formData: ProductFormData) => {
@@ -167,7 +175,8 @@ export function WarehouseManage() {
fabric_code: formData.fabric_code.toUpperCase(),
color_code: formData.color_code,
production_price: parseFloat(formData.production_price) || 0,
- image_url: formData.image_url || null
+ image_url: formData.image_url || null,
+ product_type: formData.product_type || 'raw_fabric'
};
const yarnRatios = formData.yarn_ratios.filter(r => r.yarn_name && r.ratio > 0);
@@ -393,6 +402,28 @@ export function WarehouseManage() {
+ {/* 产品类型筛选 */}
+
+ {[
+ { key: 'all', label: '全部' },
+ { key: 'raw_fabric', label: '原坯布' },
+ { key: 'textile', label: '纺织成品' },
+ { key: 'washed', label: '水洗成品' },
+ ].map(tab => (
+
+ ))}
+
+
{/* 产品列表 */}
{filteredProducts.length === 0 ? (
diff --git a/src/supabase/types.ts b/src/supabase/types.ts
index 15064e9..3aefb04 100644
--- a/src/supabase/types.ts
+++ b/src/supabase/types.ts
@@ -1221,6 +1221,7 @@ export type Database = {
id: string
image_url: string | null
product_name: string
+ product_type: string
production_price: number | null
raw_fabric_meters: number
raw_fabric_rolls: number
@@ -1243,6 +1244,7 @@ export type Database = {
id?: string
image_url?: string | null
product_name: string
+ product_type?: string
production_price?: number | null
raw_fabric_meters?: number
raw_fabric_rolls?: number
@@ -1265,6 +1267,7 @@ export type Database = {
id?: string
image_url?: string | null
product_name?: string
+ product_type?: string
production_price?: number | null
raw_fabric_meters?: number
raw_fabric_rolls?: number