diff --git a/furniture-3d-system/src/app/installation-demo-workbench/InstallationDemoWorkbenchClient.tsx b/furniture-3d-system/src/app/installation-demo-workbench/InstallationDemoWorkbenchClient.tsx index cc4cf8a0..1f6cee20 100644 --- a/furniture-3d-system/src/app/installation-demo-workbench/InstallationDemoWorkbenchClient.tsx +++ b/furniture-3d-system/src/app/installation-demo-workbench/InstallationDemoWorkbenchClient.tsx @@ -109,6 +109,7 @@ import { useInstallationStepCameraPlayback } from "./hooks/useInstallationStepCa import { useInstallationStepEditor } from "./hooks/useInstallationStepEditor"; import { useInstallationStepMaterialThumbnails } from "./hooks/useInstallationStepMaterialThumbnails"; import { InstallationInspector } from "./components/InstallationInspector"; +import { computeInstallationStageReadiness } from "./lib/installationWorkflowReadiness"; import { InstallationPreviewStage } from "./components/InstallationPreviewStage"; import { InstallationFinishedMiniPreview } from "./components/InstallationFinishedMiniPreview"; import { InstallationPartTexturePanel } from "./components/InstallationPartTexturePanel"; @@ -2005,6 +2006,19 @@ export default function InstallationDemoWorkbenchClient({ buildShareInput: buildCurrentShareInput, }); + // 制作流程完成度(工作台体验移植自 V2) + const stageReadiness = useMemo( + () => + computeInstallationStageReadiness({ + modelLoaded: Boolean(modelUrl), + parts: partCatalog.parts, + numberingParts: numberingCatalog.parts, + steps: stepEditor.steps, + materialCount: Object.keys(nodeMaterials.nodeMaterialConfigs ?? {}).length, + }), + [modelUrl, partCatalog.parts, numberingCatalog.parts, stepEditor.steps, nodeMaterials.nodeMaterialConfigs], + ); + const handleConfirmedQrShare = useCallback( (share: InstallationDemoQrShareDTO) => { setQrShareUrl(share.url); @@ -2877,6 +2891,7 @@ export default function InstallationDemoWorkbenchClient({ hardwareHingeContext={{ engine: previewEngine, modelNodeNames, parts: numberingCatalog.parts, steps: stepEditor.steps, templates: drawingTools.tools }} activeTab={activeTab} + stages={stageReadiness} onTabChange={(nextTab) => { setActiveTab(nextTab); if (nextTab === "share") { diff --git a/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationDetailsPanel.tsx b/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationDetailsPanel.tsx index c1e0e47f..60d5e911 100644 --- a/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationDetailsPanel.tsx +++ b/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationDetailsPanel.tsx @@ -14,14 +14,17 @@ import type { import { ExplosionEditorPanel } from './ExplosionEditorPanel' import { InstallationDrawingToolSelection } from './InstallationDrawingToolSelection' import { InstallationToolsInventoryBoard } from './InstallationToolsInventoryBoard' +import { InstallationWorkflowFooterNav, InstallationWorkflowNavigator } from './InstallationWorkflowNavigator' import { PartCatalogSection } from './PartCatalogSection' import { StepEditingPanel } from './StepEditingPanel' +import type { InstallationStageReadiness } from '../lib/installationWorkflowReadiness' import type { InstallationHardwareHingeEditorContext } from './InstallationHardwareHingeEditor' interface InstallationDetailsPanelProps { hardwareHingeContext?: InstallationHardwareHingeEditorContext detailView: InstallationDetailView onDetailViewChange: (view: InstallationDetailView) => void + stages: InstallationStageReadiness[] canEdit: boolean modelNodeNames: string[] parts: InstallationPartItem[] @@ -88,18 +91,6 @@ interface InstallationDetailsPanelProps { partTextureEditor?: ReactNode } -const DETAIL_STAGE_ITEMS: Array<{ - value: InstallationDetailView - title: string - description: string -}> = [ - { value: 'finished', title: '第一步:成品展示', description: '固定展示产品安装完成后的样子。' }, - { value: 'exploded', title: '第二步:爆炸图', description: '固定展示产品拆开的状态。' }, - { value: 'numbering', title: '第三步:部件编号', description: '按编号顺序逐组展示,并支持折角引线标注。' }, - { value: 'materials', title: '第四步:部件贴图', description: '按板件编号绑定颜色、纹理和方向。' }, - { value: 'steps', title: '第五步:安装步骤', description: '进入后续安装步骤与动画设置。' }, -] - const NUMBERING_CATEGORY_TABS: Array<{ value: InstallationNumberingDisplayCategory label: string @@ -204,6 +195,7 @@ export function InstallationDetailsPanel({ hardwareHingeContext, detailView, onDetailViewChange, + stages, canEdit, modelNodeNames, parts, @@ -272,36 +264,9 @@ export function InstallationDetailsPanel({ -
-
-
-

详情阶段

-
-
- {DETAIL_STAGE_ITEMS.map((item) => { - const active = item.value === detailView - return ( - - ) - })} -
-
+ +
{detailView === 'numbering' || detailView === 'materials' ? (
{finishedPreview}
) : null} @@ -436,9 +401,9 @@ export function InstallationDetailsPanel({
-

安装图纸

+

出图与分享

- 先打开固定模板,再手动截取成品、爆炸图和每个动作画面。 + 先打开固定模板,再手动截取成品、爆炸图和每个动作画面;分享入口在顶部「分享」标签。

+ +
) } diff --git a/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationInspector.tsx b/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationInspector.tsx index 02e49d6c..b1584c5b 100644 --- a/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationInspector.tsx +++ b/furniture-3d-system/src/app/installation-demo-workbench/components/InstallationInspector.tsx @@ -1,8 +1,9 @@ 'use client' +import { useState } from 'react' import Link from 'next/link' import type { ReactNode } from 'react' -import { Share2, Wrench } from 'lucide-react' +import { ArrowLeft, Share2, Wrench } from 'lucide-react' import type { InstallationDetailView, InstallationDrawingNode, @@ -17,14 +18,17 @@ import type { InstallationInspectorTab, } from '../types' import { InstallationDetailsPanel } from './InstallationDetailsPanel' +import { InstallationDrawingToolSelection } from './InstallationDrawingToolSelection' import { InstallationSharePanel } from './InstallationSharePanel' import { ProductStructurePanel } from './ProductStructurePanel' +import type { InstallationStageReadiness } from '../lib/installationWorkflowReadiness' import type { InstallationHardwareHingeEditorContext } from './InstallationHardwareHingeEditor' interface InstallationInspectorProps { hardwareHingeContext?: InstallationHardwareHingeEditorContext activeTab: InstallationInspectorTab onTabChange: (tab: InstallationInspectorTab) => void + stages: InstallationStageReadiness[] spus: InstallationSpuNode[] selectedSpu: InstallationSpuNode | null selectedModel: InstallationModelNode | null @@ -119,9 +123,10 @@ interface InstallationInspectorProps { partTextureEditor?: ReactNode } +// 标签名与内容对齐:目录=SPU/型号/图纸树,制作=五阶段流程;工具改为面板内抽屉入口 const TABS: Array<{ value: InstallationInspectorTab; label: string }> = [ - { value: 'structure', label: '模型' }, - { value: 'steps', label: '详情' }, + { value: 'structure', label: '目录' }, + { value: 'steps', label: '制作' }, { value: 'share', label: '分享' }, ] @@ -216,9 +221,11 @@ export function InstallationInspector({ stepActionEditor, finishedPreview, partTextureEditor, + stages, }: InstallationInspectorProps) { + const [toolsDrawerOpen, setToolsDrawerOpen] = useState(false) return ( -