fix(ai): 拆解原型无需求ID任务

This commit is contained in:
Script Generator
2026-07-01 13:33:04 +08:00
parent 24e8635a94
commit 756621d366
23 changed files with 371 additions and 45 deletions

View File

@@ -10,6 +10,7 @@ import { useTaskCategoryStore } from '@/stores/useTaskCategoryStore';
import { useAuthStore } from '@/stores/useAuthStore';
import { findCategoryByCode, resolveCategoryIdFromCode } from '@/lib/task-category';
import { clampDevAiEstimateHours, clampTestCaseAiEstimateHours } from '@/lib/ai-estimation-policy';
import { resolveDecomposeDraftRequirementFields } from '@/lib/ai-decompose-adoption';
import { formatReportRequirementLabel } from '@/lib/ai-decompose-report';
import { resolveRecommendedAssignee } from '@/lib/ai-assignee-recommendation';
import type {
@@ -52,6 +53,7 @@ export function DecomposeReportModal({
const showTestDrafts = target !== 'dev_tasks';
const filteredDuplicateCount =
(dedupeSummary?.removedDevTaskCount ?? 0) + (dedupeSummary?.removedTestCaseCount ?? 0);
const prototypeOnlyGroups = data.report.prototypeOnly ?? [];
const [selectedDevIdx, setSelectedDevIdx] = useState<Set<number>>(
new Set(showDevDrafts ? data.devTaskDrafts.map((_, i) => i) : []),
@@ -108,14 +110,15 @@ export function DecomposeReportModal({
if (!selectedDevIdx.has(i)) continue;
const draft = data.devTaskDrafts[i];
const refs = normalizeRefs(draft.references);
const reqRef = refs.find((r) => r.type === 'requirement');
const requirementId = reqRef?.id ?? requirements[0]?.id ?? '';
const requirementFields = resolveDecomposeDraftRequirementFields({ ...draft, references: refs }, requirements);
const categoryId = resolveCategoryIdFromCode(categories, draft.categoryCode, 'development');
const aiEstimateHours = clampDevAiEstimateHours(draft.categoryCode, draft.aiEstimateHours);
const recommendedAssignee = resolveRecommendedAssignee(draft, version.members ?? []);
createTask({
requirementId,
versionId: version.id,
requirementId: requirementFields.requirementId,
requirementName: requirementFields.requirementName,
title: draft.title,
description: draft.description,
categoryId,
@@ -148,14 +151,15 @@ export function DecomposeReportModal({
if (!selectedTcIdx.has(i)) continue;
const draft = data.testCaseDrafts[i];
const refs = normalizeRefs(draft.references);
const reqRef = refs.find((r) => r.type === 'requirement');
const requirementFields = resolveDecomposeDraftRequirementFields({ ...draft, references: refs }, requirements);
const categoryId = resolveCategoryIdFromCode(categories, draft.categoryCode, 'testing');
const aiEstimateHours = clampTestCaseAiEstimateHours(draft.categoryCode, draft.aiEstimateHours);
const recommendedAssignee = resolveRecommendedAssignee(draft, version.members ?? []);
createTestCase({
versionId: version.id,
requirementId: reqRef?.id,
requirementId: requirementFields.requirementId || undefined,
requirementName: requirementFields.requirementName,
title: draft.title,
description: draft.description,
categoryId,
@@ -269,17 +273,22 @@ export function DecomposeReportModal({
</div>
)}
{data.report.noteOnly.length > 0 && (
{prototypeOnlyGroups.length > 0 && (
<div className="rounded-lg border border-blue-200 bg-blue-50 p-3 mb-2">
<div className="flex items-center gap-1.5 mb-1.5">
<AlertTriangle className="h-3.5 w-3.5 text-blue-600" />
<span className="text-[12px] font-medium text-blue-700"></span>
<span className="text-[12px] font-medium text-blue-700">ID分组</span>
</div>
<p className="text-[11px] text-blue-700 mb-1">
/
</p>
<ul className="text-[12px] text-blue-800 ml-5 list-disc">
{data.report.noteOnly.map((id, i) => <li key={i}>{id}</li>)}
<ul className="text-[12px] text-blue-800 ml-5 list-disc space-y-0.5">
{prototypeOnlyGroups.map((item, i) => (
<li key={i}>
<span className="font-medium">ID · {item.requirementName}</span>
<span>{item.noteIds.join(', ') || '无批注编号'} {item.taskCount} </span>
</li>
))}
</ul>
</div>
)}
@@ -336,6 +345,11 @@ export function DecomposeReportModal({
<span className="text-[10px] text-[var(--ink-muted)]">
AI预估 {clampDevAiEstimateHours(d.categoryCode, d.aiEstimateHours)}h
</span>
{d.requirementName && (
<span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-50 text-blue-700 border border-blue-200">
ID · {d.requirementName}
</span>
)}
{recommendation && (
<span
className="text-[10px] px-1.5 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-200"
@@ -402,6 +416,11 @@ export function DecomposeReportModal({
<span className="text-[10px] text-[var(--ink-muted)]">
AI预估 {clampTestCaseAiEstimateHours(d.categoryCode, d.aiEstimateHours)}h
</span>
{d.requirementName && (
<span className="text-[10px] px-1.5 py-0.5 rounded bg-blue-50 text-blue-700 border border-blue-200">
ID · {d.requirementName}
</span>
)}
{recommendation && (
<span
className="text-[10px] px-1.5 py-0.5 rounded bg-emerald-50 text-emerald-700 border border-emerald-200"