重构 UI 编辑器工作流校验逻辑
抽取工作流步骤的前置与后置校验逻辑至独立模块 `WorkflowChecks`,替换原有冗余实现并优化状态传递。
This commit is contained in:
+35
-21
@@ -142,29 +142,40 @@ export function validateLayoutReviewPrerequisites(
|
||||
return validateLayoutGenerationPrerequisites(state);
|
||||
}
|
||||
|
||||
function statusIssue(
|
||||
function layoutStatusIssue(
|
||||
status: StageStatus,
|
||||
stage: 'layout' | 'components',
|
||||
): UiEditorPrerequisiteIssue | null {
|
||||
if (status === 'Pending') {
|
||||
return {
|
||||
code: `${stage}-pending`,
|
||||
message:
|
||||
stage === 'layout'
|
||||
? '存在尚未识别的节点布局'
|
||||
: '存在尚未绑定的节点组件',
|
||||
};
|
||||
switch (status) {
|
||||
case 'Pending':
|
||||
return { code: 'layout-pending', message: '存在尚未识别的节点布局' };
|
||||
case 'Blocked':
|
||||
return { code: 'layout-blocked', message: '存在被阻塞的节点结果' };
|
||||
case 'Passed':
|
||||
return null;
|
||||
default:
|
||||
return {
|
||||
code: 'layout-needs-review',
|
||||
message: status.NeedReview || '存在需要人工审阅的节点结果',
|
||||
};
|
||||
}
|
||||
if (status === 'Blocked') {
|
||||
return { code: `${stage}-blocked`, message: '存在被阻塞的节点结果' };
|
||||
}
|
||||
|
||||
function componentStatusIssue(
|
||||
status: StageStatus,
|
||||
): UiEditorPrerequisiteIssue | null {
|
||||
switch (status) {
|
||||
case 'Pending':
|
||||
return { code: 'components-pending', message: '存在尚未绑定的节点组件' };
|
||||
case 'Blocked':
|
||||
return { code: 'components-blocked', message: '存在被阻塞的节点结果' };
|
||||
case 'Passed':
|
||||
return null;
|
||||
default:
|
||||
return {
|
||||
code: 'components-needs-review',
|
||||
message: status.NeedReview || '存在需要人工审阅的节点结果',
|
||||
};
|
||||
}
|
||||
if (typeof status === 'object' && 'NeedReview' in status) {
|
||||
return {
|
||||
code: `${stage}-needs-review`,
|
||||
message: status.NeedReview || '存在需要人工审阅的节点结果',
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function visitNodes(
|
||||
@@ -205,7 +216,7 @@ export function validateStructureRecognitionResult(
|
||||
const issues: UiEditorPrerequisiteIssue[] = [];
|
||||
for (const tree of state.ui_trees) {
|
||||
visitNodes([tree.root], (node) => {
|
||||
const issue = statusIssue(node.metadata.layout_status, 'layout');
|
||||
const issue = layoutStatusIssue(node.metadata.layout_status);
|
||||
if (issue) issues.push(issue);
|
||||
});
|
||||
}
|
||||
@@ -218,7 +229,10 @@ export function validateVisualBindingResult(
|
||||
const issues: UiEditorPrerequisiteIssue[] = [];
|
||||
for (const tree of state.ui_trees) {
|
||||
visitNodes([tree.root], (node) => {
|
||||
const issue = statusIssue(node.metadata.components_status, 'components');
|
||||
if (node.components.length == 0) {
|
||||
return;
|
||||
}
|
||||
const issue = componentStatusIssue(node.metadata.components_status);
|
||||
if (issue) issues.push(issue);
|
||||
});
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { UiEditorPrerequisiteIssue } from '../../../features/ui-editor/prerequisites';
|
||||
import type { UiEditorPrerequisiteIssue } from '../../../features/ui-editor/requisites';
|
||||
|
||||
export function PrerequisiteIssues({
|
||||
issues,
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
import {
|
||||
type UiEditorPrerequisiteIssue,
|
||||
validateAssetRecognitionPrerequisites,
|
||||
validateComponentRecognitionPrerequisites,
|
||||
validateLayoutReviewPrerequisites,
|
||||
validateReferenceAnalysisResult,
|
||||
validateStructureRecognitionResult,
|
||||
validateVisualBindingResult,
|
||||
} from '../../../features/ui-editor/requisites';
|
||||
import type { State } from '../../../features/ui-editor/types/State';
|
||||
import type { UiEditorStepId } from '../model';
|
||||
|
||||
export type { UiEditorPrerequisiteIssue };
|
||||
|
||||
export function prerequisiteIssuesForStep(
|
||||
state: State,
|
||||
step: UiEditorStepId,
|
||||
): UiEditorPrerequisiteIssue[] {
|
||||
switch (step) {
|
||||
case 'reference-analysis':
|
||||
return [];
|
||||
case 'structure-recognition':
|
||||
return validateComponentRecognitionPrerequisites(state);
|
||||
case 'visual-binding':
|
||||
return validateAssetRecognitionPrerequisites(state);
|
||||
}
|
||||
}
|
||||
|
||||
export function postCheckIssuesForStep(
|
||||
state: State,
|
||||
step: UiEditorStepId,
|
||||
): UiEditorPrerequisiteIssue[] {
|
||||
switch (step) {
|
||||
case 'reference-analysis':
|
||||
return validateReferenceAnalysisResult(state);
|
||||
case 'structure-recognition':
|
||||
return validateStructureRecognitionResult(state);
|
||||
case 'visual-binding':
|
||||
return validateVisualBindingResult(state);
|
||||
}
|
||||
}
|
||||
|
||||
export function postCheckIssuesForSave(
|
||||
state: State,
|
||||
): UiEditorPrerequisiteIssue[] {
|
||||
return [
|
||||
...validateReferenceAnalysisResult(state),
|
||||
...validateStructureRecognitionResult(state),
|
||||
...validateVisualBindingResult(state),
|
||||
];
|
||||
}
|
||||
|
||||
export function activeStepPrerequisiteIssues(
|
||||
state: State,
|
||||
step: UiEditorStepId,
|
||||
): UiEditorPrerequisiteIssue[] {
|
||||
switch (step) {
|
||||
case 'reference-analysis':
|
||||
return validateComponentRecognitionPrerequisites(state);
|
||||
case 'structure-recognition':
|
||||
return validateAssetRecognitionPrerequisites(state);
|
||||
case 'visual-binding':
|
||||
return validateLayoutReviewPrerequisites(state);
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,6 @@ import {
|
||||
prepareSpriteAssetBatch,
|
||||
} from '../../features/ui-editor/importAdapter';
|
||||
import { applyMergeResult } from '../../features/ui-editor/merge';
|
||||
import {
|
||||
type UiEditorPrerequisiteIssue,
|
||||
validateAssetRecognitionPrerequisites,
|
||||
validateComponentRecognitionPrerequisites,
|
||||
validateLayoutReviewPrerequisites,
|
||||
validateReferenceAnalysisResult,
|
||||
validateStructureRecognitionResult,
|
||||
validateVisualBindingResult,
|
||||
} from '../../features/ui-editor/prerequisites';
|
||||
import { applyRecognitionResult } from '../../features/ui-editor/recognition';
|
||||
import { collectUiNodeIds } from '../../features/ui-editor/treeUtils';
|
||||
import type { BindingDTO } from '../../features/ui-editor/types/BindingDTO';
|
||||
@@ -50,6 +41,13 @@ import {
|
||||
createProjectResourcePreviewRequestId,
|
||||
createProjectResourcePreviewScopeId,
|
||||
} from '../../services/projectResourcePreviewTransport';
|
||||
import {
|
||||
activeStepPrerequisiteIssues,
|
||||
postCheckIssuesForSave,
|
||||
postCheckIssuesForStep,
|
||||
prerequisiteIssuesForStep,
|
||||
type UiEditorPrerequisiteIssue,
|
||||
} from './components/WorkflowChecks';
|
||||
import {
|
||||
type PendingResourceRemoval,
|
||||
removalHasDownstreamReferences,
|
||||
@@ -562,24 +560,6 @@ export function useUiEditorPage(
|
||||
setPendingRemoval(null);
|
||||
}
|
||||
|
||||
function prerequisiteIssuesForStep(step: UiEditorStepId) {
|
||||
if (step === 'reference-analysis') return [];
|
||||
if (step === 'structure-recognition') {
|
||||
return validateComponentRecognitionPrerequisites(editor.state);
|
||||
}
|
||||
return validateAssetRecognitionPrerequisites(editor.state);
|
||||
}
|
||||
|
||||
function postCheckIssuesForStep(step: UiEditorStepId) {
|
||||
if (step === 'reference-analysis') {
|
||||
return validateReferenceAnalysisResult(editor.state);
|
||||
}
|
||||
if (step === 'structure-recognition') {
|
||||
return validateStructureRecognitionResult(editor.state);
|
||||
}
|
||||
return validateVisualBindingResult(editor.state);
|
||||
}
|
||||
|
||||
function enterStep(step: UiEditorStepId) {
|
||||
setActiveStep(step);
|
||||
const index =
|
||||
@@ -593,8 +573,8 @@ export function useUiEditorPage(
|
||||
|
||||
function requestStepChange(step: UiEditorStepId) {
|
||||
if (step === activeStep || isAiRunning) return;
|
||||
const leavingIssues = postCheckIssuesForStep(activeStep);
|
||||
const enteringIssues = prerequisiteIssuesForStep(step);
|
||||
const leavingIssues = postCheckIssuesForStep(editor.state, activeStep);
|
||||
const enteringIssues = prerequisiteIssuesForStep(editor.state, step);
|
||||
if (leavingIssues.length === 0 && enteringIssues.length === 0) {
|
||||
enterStep(step);
|
||||
return;
|
||||
@@ -613,21 +593,8 @@ export function useUiEditorPage(
|
||||
setPendingWorkflowStepChange(null);
|
||||
}
|
||||
|
||||
function postCheckIssuesForSave() {
|
||||
return [
|
||||
...validateReferenceAnalysisResult(editor.state),
|
||||
...validateStructureRecognitionResult(editor.state),
|
||||
...validateVisualBindingResult(editor.state),
|
||||
];
|
||||
}
|
||||
|
||||
function checkPrerequisites() {
|
||||
const issues =
|
||||
activeStep === 'reference-analysis'
|
||||
? validateComponentRecognitionPrerequisites(editor.state)
|
||||
: activeStep === 'structure-recognition'
|
||||
? validateAssetRecognitionPrerequisites(editor.state)
|
||||
: validateLayoutReviewPrerequisites(editor.state);
|
||||
const issues = activeStepPrerequisiteIssues(editor.state, activeStep);
|
||||
setStatus(
|
||||
issues.length === 0
|
||||
? '前置数据检查通过。'
|
||||
@@ -988,7 +955,7 @@ export function useUiEditorPage(
|
||||
},
|
||||
confirmStepChange,
|
||||
cancelStepChange: () => setPendingWorkflowStepChange(null),
|
||||
postCheckIssuesForSave,
|
||||
postCheckIssuesForSave: () => postCheckIssuesForSave(editor.state),
|
||||
checkPrerequisites,
|
||||
selectDesignImage,
|
||||
selectSprite,
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
import { validateComponentRecognitionPrerequisites } from '../src/features/ui-editor/prerequisites';
|
||||
import { validateComponentRecognitionPrerequisites } from '../src/features/ui-editor/requisites';
|
||||
import type { FontAsset } from '../src/features/ui-editor/types/FontAsset';
|
||||
import type { Node } from '../src/features/ui-editor/types/Node';
|
||||
import type { SpriteAsset } from '../src/features/ui-editor/types/SpriteAsset';
|
||||
|
||||
Reference in New Issue
Block a user