feat(edit): 采集插件、编辑页SKU 属性动态展示、颜色展示开发
This commit is contained in:
@@ -416,6 +416,7 @@ const ProductEditPage = () => {
|
||||
const [catalogRefresh, setCatalogRefresh] = useState(0);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [saving, setSaving] = useState(false);
|
||||
const [savingSourceDescription, setSavingSourceDescription] = useState(false);
|
||||
const [materializingTransferId, setMaterializingTransferId] = useState<string | null>(null);
|
||||
const [dirty, setDirty] = useState(false);
|
||||
const [moreFeaturesExpanded, setMoreFeaturesExpanded] = useState(false);
|
||||
@@ -849,6 +850,68 @@ const ProductEditPage = () => {
|
||||
});
|
||||
setDirty(true);
|
||||
};
|
||||
/** 独立持久化采集描述,避免要求页面上其他未完成字段一并通过整页校验。 */
|
||||
const saveSourceDescription = async (description: string) => {
|
||||
if (!productId || !currentPlatform || !snapshot) return;
|
||||
setSavingSourceDescription(true);
|
||||
try {
|
||||
const saved = await productEditorApi.saveSourceDescription(
|
||||
productId,
|
||||
currentPlatform.id,
|
||||
{ product: snapshot.product.revision, profile: snapshot.profile.revision },
|
||||
{
|
||||
description,
|
||||
source_snapshot_revision:
|
||||
(sourceDraft ?? snapshot.source_material).source_snapshot_revision,
|
||||
}
|
||||
);
|
||||
setSnapshot((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
product: {
|
||||
...current.product,
|
||||
revision: saved.product_revision,
|
||||
},
|
||||
profile: {
|
||||
...current.profile,
|
||||
revision: saved.profile_revision,
|
||||
},
|
||||
source_material: saved.source_material,
|
||||
source_material_state: saved.source_material_state,
|
||||
ai_input: {
|
||||
...current.ai_input,
|
||||
source_material: saved.source_material,
|
||||
},
|
||||
}
|
||||
: current
|
||||
);
|
||||
setSourceDraft((current) =>
|
||||
current
|
||||
? {
|
||||
...current,
|
||||
description: saved.source_material.description,
|
||||
source_snapshot_revision:
|
||||
saved.source_material.source_snapshot_revision,
|
||||
}
|
||||
: saved.source_material
|
||||
);
|
||||
setSourceOverriddenFields((current) => {
|
||||
const next = new Set(current);
|
||||
if (saved.source_material_state.overridden_fields.includes('description')) {
|
||||
next.add('description');
|
||||
} else {
|
||||
next.delete('description');
|
||||
}
|
||||
return [...next];
|
||||
});
|
||||
message.success('商品描述已保存');
|
||||
} catch (error) {
|
||||
message.error(`商品描述保存失败:${apiErrorMessage(error)}`);
|
||||
} finally {
|
||||
setSavingSourceDescription(false);
|
||||
}
|
||||
};
|
||||
const restoreSourceField = (field: Extract<ProductAiSourceField, 'title' | 'description'>) => {
|
||||
if (!snapshot) return;
|
||||
setSourceDraft({
|
||||
@@ -1130,6 +1193,8 @@ const ProductEditPage = () => {
|
||||
overriddenFields={sourceOverriddenFields}
|
||||
onRestore={restoreSourceField}
|
||||
onUpdate={updateSourceField}
|
||||
savingDescription={savingSourceDescription}
|
||||
onSaveDescription={(description) => void saveSourceDescription(description)}
|
||||
onShowDifferences={showSourceDifferences}
|
||||
onAcceptLatest={acceptLatestSource}
|
||||
/>
|
||||
|
||||
@@ -28,6 +28,8 @@ type Props = {
|
||||
field: Extract<ProductAiSourceField, 'title' | 'description'>,
|
||||
value: string
|
||||
) => void;
|
||||
savingDescription: boolean;
|
||||
onSaveDescription: (value: string) => void;
|
||||
onShowDifferences: () => void;
|
||||
onAcceptLatest: () => void;
|
||||
};
|
||||
@@ -48,6 +50,8 @@ export function CollectedProductInfoPanel({
|
||||
overriddenFields,
|
||||
onRestore,
|
||||
onUpdate,
|
||||
savingDescription,
|
||||
onSaveDescription,
|
||||
onShowDifferences,
|
||||
onAcceptLatest,
|
||||
}: Props) {
|
||||
@@ -137,14 +141,16 @@ export function CollectedProductInfoPanel({
|
||||
<Input.TextArea
|
||||
value={descriptionDraft}
|
||||
rows={12}
|
||||
disabled={savingDescription}
|
||||
placeholder="本次采集未取得商品描述。可补充后用于 AI 生成。"
|
||||
onChange={(event) => setDescriptionDraft(event.target.value)}
|
||||
/>
|
||||
<div className="collected-description-actions">
|
||||
<Button
|
||||
type="primary"
|
||||
loading={savingDescription}
|
||||
disabled={descriptionDraft === sourceDescription}
|
||||
onClick={() => onUpdate('description', descriptionDraft)}
|
||||
onClick={() => onSaveDescription(descriptionDraft)}
|
||||
>
|
||||
保存描述
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user