import { productcontrollerGetproductlist } from '@/servers/api/product'; import { siteapicontrollerGetproducts, siteapicontrollerUpsertproduct, } from '@/servers/api/siteApi'; import { templatecontrollerRendertemplate } from '@/servers/api/template'; import { SyncOutlined } from '@ant-design/icons'; import { ModalForm, ProFormText } from '@ant-design/pro-components'; import { Button, message, Spin, Tag } from 'antd'; import React, { useEffect, useState } from 'react'; // 定义站点接口 interface Site { id: number; name: string; skuPrefix?: string; isDisabled?: boolean; } // 定义本地产品接口(与后端 Product 实体匹配) interface SiteProduct { id: number; sku: string; name: string; nameCn: string; shortDescription?: string; description?: string; price: number; promotionPrice: number; type: string; categoryId?: number; category?: any; attributes?: any[]; components?: any[]; siteSkus: string[]; source: number; createdAt: Date; updatedAt: Date; } // 定义本地产品完整接口 interface LocalProduct { id: number; sku: string; name: string; nameCn: string; shortDescription?: string; description?: string; price: number; promotionPrice: number; type: string; categoryId?: number; category?: any; attributes?: any[]; components?: any[]; siteSkus: string[]; source: number; images?: string[]; weight?: number; dimensions?: any; } // 定义站点产品数据接口 interface SiteProductData { sku: string; regular_price?: number; price?: number; sale_price?: number; stock_quantity?: number; stockQuantity?: number; status?: string; externalProductId?: string; name?: string; description?: string; images?: string[]; } interface SiteProductCellProps { // 产品行数据 product: SiteProduct; // 站点列数据 site: Site; // 同步成功后的回调 onSyncSuccess?: () => void; } const SiteProductCell: React.FC = ({ product, site, onSyncSuccess, }) => { // 存储该站点对应的产品数据 const [siteProduct, setSiteProduct] = useState(null); // 存储本地产品完整数据 const [localProduct, setLocalProduct] = useState(null); // 加载状态 const [loading, setLoading] = useState(false); // 是否已加载过数据 const [loaded, setLoaded] = useState(false); // 同步中状态 const [syncing, setSyncing] = useState(false); // 组件挂载时加载数据 useEffect(() => { loadSiteProduct(); }, [product.id, site.id]); // 加载站点产品数据 const loadSiteProduct = async () => { // 如果已经加载过,则不再重复加载 if (loaded) { return; } setLoading(true); try { // 首先查找该产品在该站点的实际SKU // 注意:siteSkus 现在是字符串数组,无法直接匹配站点 // 这里使用模板生成的 SKU 作为默认值 let siteProductSku = ''; // 如果需要更精确的站点 SKU 匹配,需要后端提供额外的接口 // 如果没有找到实际的siteSku,则根据模板或默认规则生成期望的SKU const expectedSku = siteProductSku || `${site.skuPrefix || ''}-${product.sku}`; // 使用 siteapicontrollerGetproducts 获取该站点的所有产品 const productsRes = await siteapicontrollerGetproducts({ siteId: site.id, current: 1, pageSize: 10000, } as any); if (productsRes.data?.items) { // 在该站点的产品数据中查找匹配的产品 let foundProduct = productsRes.data.items.find( (item: any) => item.sku === expectedSku, ); // 如果根据实际SKU没找到,再尝试用模板生成的SKU查找 if (!foundProduct && siteProductSku) { foundProduct = productsRes.data.items.find( (item: any) => item.sku === siteProductSku, ); } if (foundProduct) { setSiteProduct(foundProduct as SiteProductData); } } // 标记为已加载 setLoaded(true); } catch (error) { console.error(`加载站点 ${site.name} 的产品数据失败:`, error); } finally { setLoading(false); } }; // 获取本地产品完整信息 const getLocalProduct = async (): Promise => { try { // 如果已经有本地产品数据,直接返回 if (localProduct) { return localProduct; } // 使用 productcontrollerGetproductlist 获取本地产品完整信息 const res = await productcontrollerGetproductlist({ where: { id: product.id, }, } as any); if (res.success && res.data) { const productData = res.data as LocalProduct; setLocalProduct(productData); return productData; } return null; } catch (error) { console.error('获取本地产品信息失败:', error); return null; } }; // 渲染站点SKU const renderSiteSku = async (data: any): Promise => { try { // 使用 templatecontrollerRendertemplate API 渲染模板 const res = await templatecontrollerRendertemplate( { name: 'siteproduct-sku' } as any, data, ); return res?.template || res?.result || ''; } catch (error) { console.error('渲染SKU模板失败:', error); return ''; } }; // 同步产品到站点 const syncProductToSite = async (values: any) => { try { setSyncing(true); const hide = message.loading('正在同步...', 0); // 获取本地产品完整信息 const productDetail = await getLocalProduct(); if (!productDetail) { hide(); message.error('获取本地产品信息失败'); return false; } // 构造要同步的产品数据 const productData: any = { sku: values.sku, name: productDetail.name, description: productDetail.description || '', regular_price: productDetail.price, price: productDetail.price, stock_quantity: productDetail.stock, status: 'publish', }; // 如果有图片,添加图片信息 if (productDetail.images && productDetail.images.length > 0) { productData.images = productDetail.images; } // 如果有重量,添加重量信息 if (productDetail.weight) { productData.weight = productDetail.weight; } // 如果有尺寸,添加尺寸信息 if (productDetail.dimensions) { productData.dimensions = productDetail.dimensions; } // 使用 siteapicontrollerUpsertproduct API 同步产品到站点 const res = await siteapicontrollerUpsertproduct( { siteId: site.id } as any, productData as any, ); if (!res.success) { hide(); throw new Error(res.message || '同步失败'); } // 更新本地状态 if (res.data && typeof res.data === 'object') { setSiteProduct(res.data as SiteProductData); } hide(); message.success('同步成功'); // 触发回调 if (onSyncSuccess) { onSyncSuccess(); } return true; } catch (error: any) { message.error('同步失败: ' + (error.message || error.toString())); return false; } finally { setSyncing(false); } }; // 更新同步产品到站点 const updateSyncProduct = async (values: any) => { try { setSyncing(true); const hide = message.loading('正在更新...', 0); // 获取本地产品完整信息 const productDetail = await getLocalProduct(); if (!productDetail) { hide(); message.error('获取本地产品信息失败'); return false; } // 构造要更新的产品数据 const productData: any = { ...siteProduct, sku: values.sku, name: productDetail.name, description: productDetail.description || '', regular_price: productDetail.price, price: productDetail.price, stock_quantity: productDetail.stock, status: 'publish', }; // 如果有图片,添加图片信息 if (productDetail.images && productDetail.images.length > 0) { productData.images = productDetail.images; } // 如果有重量,添加重量信息 if (productDetail.weight) { productData.weight = productDetail.weight; } // 如果有尺寸,添加尺寸信息 if (productDetail.dimensions) { productData.dimensions = productDetail.dimensions; } // 使用 siteapicontrollerUpsertproduct API 更新产品到站点 const res = await siteapicontrollerUpsertproduct( { siteId: site.id } as any, productData as any, ); if (!res.success) { hide(); throw new Error(res.message || '更新失败'); } // 更新本地状态 if (res.data && typeof res.data === 'object') { setSiteProduct(res.data as SiteProductData); } hide(); message.success('更新成功'); // 触发回调 if (onSyncSuccess) { onSyncSuccess(); } return true; } catch (error: any) { message.error('更新失败: ' + (error.message || error.toString())); return false; } finally { setSyncing(false); } }; // 如果正在加载,显示加载状态 if (loading) { return (
); } // 如果没有找到站点产品,显示同步按钮 if (!siteProduct) { // 首先查找该产品在该站点的实际SKU // 注意:siteSkus 现在是字符串数组,无法直接匹配站点 // 这里使用模板生成的 SKU 作为默认值 let siteProductSku = ''; // 如果需要更精确的站点 SKU 匹配,需要后端提供额外的接口 const defaultSku = siteProductSku || `${site.skuPrefix || ''}-${product.sku}`; return ( }> 同步到站点 } width={400} onFinish={async (values) => { return await syncProductToSite(values); }} initialValues={{ sku: defaultSku, }} > ); } // 显示站点产品信息 return (
{siteProduct.sku}
} > 更新 } width={400} onFinish={async (values) => { return await updateSyncProduct(values); }} initialValues={{ sku: siteProduct.sku, }} >
确定要将本地产品数据更新到站点吗?
Price: {siteProduct.regular_price ?? siteProduct.price}
{siteProduct.sale_price && (
Sale: {siteProduct.sale_price}
)}
Stock: {siteProduct.stock_quantity ?? siteProduct.stockQuantity}
Status:{' '} {siteProduct.status === 'publish' ? ( Published ) : ( {siteProduct.status} )}
); }; export default SiteProductCell;