From 9d6a92e1d7e9a70317f4d3a4caa84ce49435b36c Mon Sep 17 00:00:00 2001 From: iven Date: Tue, 26 May 2026 10:30:22 +0800 Subject: [PATCH] =?UTF-8?q?fix(web):=20=E7=A7=AF=E5=88=86=E5=95=86?= =?UTF-8?q?=E5=93=81=E5=9B=BE=E7=89=87=E9=A2=84=E8=A7=88=20=E2=80=94=20?= =?UTF-8?q?=E6=94=B9=E7=94=A8=20React=20state=20=E9=A9=B1=E5=8A=A8?= =?UTF-8?q?=E6=9B=BF=E4=BB=A3=20antd=20Form=20shouldUpdate?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ant Form shouldUpdate + setFieldValue 在 DrawerForm 上下文中无法正确触发重渲染, 改用独立 imageUrl state 管理,Input/预览/MediaPicker/Upload 全部通过 state 同步 --- .../src/pages/health/PointsProductList.tsx | 110 ++++++++---------- 1 file changed, 51 insertions(+), 59 deletions(-) diff --git a/apps/web/src/pages/health/PointsProductList.tsx b/apps/web/src/pages/health/PointsProductList.tsx index b60a920..ce4e09f 100644 --- a/apps/web/src/pages/health/PointsProductList.tsx +++ b/apps/web/src/pages/health/PointsProductList.tsx @@ -66,7 +66,7 @@ export default function PointsProductList() { const [modalOpen, setModalOpen] = useState(false); const [editing, setEditing] = useState(null); const [mediaPickerOpen, setMediaPickerOpen] = useState(false); - const [form] = Form.useForm(); + const [imageUrl, setImageUrl] = useState(''); const isDark = useThemeMode(); const fetchProducts = useCallback( @@ -103,11 +103,13 @@ export default function PointsProductList() { // ---- 新建 / 编辑 ---- const openCreate = () => { setEditing(null); + setImageUrl(''); setModalOpen(true); }; const openEdit = (record: PointsProduct) => { setEditing(record); + setImageUrl(record.image_url || ''); setModalOpen(true); }; @@ -124,12 +126,12 @@ export default function PointsProductList() { points_cost: number; stock: number; description?: string; - image_url?: string; sort_order?: number; }; if (editing) { await pointsApi.updateProduct(editing.id, { ...typed, + image_url: imageUrl || undefined, version: editing.version, }); } else { @@ -139,7 +141,7 @@ export default function PointsProductList() { points_cost: typed.points_cost, stock: typed.stock, description: typed.description, - image_url: typed.image_url, + image_url: imageUrl || undefined, sort_order: typed.sort_order, }; await pointsApi.createProduct(req); @@ -318,59 +320,51 @@ export default function PointsProductList() { title: '展示设置', fields: ( <> - - prev.image_url !== cur.image_url}> - {({ getFieldValue, setFieldValue }) => { - const imageUrl: string | undefined = getFieldValue('image_url'); - return ( - <> - - setFieldValue('image_url', e.target.value || undefined)} - placeholder="输入 URL 或从媒体库选择" - style={{ flex: 1 }} - /> - - { - try { - const result = await uploadFile(file); - setFieldValue('image_url', result.url); - message.success('图片上传成功'); - } catch { - message.error('图片上传失败'); - } - return false; - }} - > - - - - {imageUrl && ( -
- 商品图片预览 { (e.target as HTMLImageElement).style.display = 'none'; }} - /> -
- )} - - ); - }} + + + setImageUrl(e.target.value)} + placeholder="输入 URL 或从媒体库选择" + style={{ flex: 1 }} + /> + + { + try { + const result = await uploadFile(file); + setImageUrl(result.url); + message.success('图片上传成功'); + } catch { + message.error('图片上传失败'); + } + return false; + }} + > + + + + {imageUrl && ( +
+ 商品图片预览 { (e.target as HTMLImageElement).style.display = 'none'; }} + /> +
+ )}
@@ -454,7 +448,6 @@ export default function PointsProductList() { points_cost: editing.points_cost, stock: editing.stock, description: editing.description, - image_url: editing.image_url, sort_order: editing.sort_order, } : { stock: -1, sort_order: 0 }} @@ -462,14 +455,13 @@ export default function PointsProductList() { width={600} columns={2} sections={formSections} - form={form} /> setMediaPickerOpen(false)} onSelect={(url) => { - form.setFieldValue('image_url', url); + setImageUrl(url); message.success('已选择图片'); }} />