feat(版本详情): 完善任务流程与风险预警
This commit is contained in:
@@ -26,6 +26,12 @@ function defaultPlannedTestLocal(): string {
|
||||
return isoToLocal(d.toISOString());
|
||||
}
|
||||
|
||||
function defaultPlannedEndLocal(): string {
|
||||
const d = new Date();
|
||||
d.setHours(10, 0, 0, 0);
|
||||
return isoToLocal(d.toISOString());
|
||||
}
|
||||
|
||||
export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClose }: Props) {
|
||||
const { createTestCase } = useTestCaseStore();
|
||||
const { requirements } = useRequirementStore();
|
||||
@@ -49,6 +55,7 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
|
||||
);
|
||||
const [estimateHours, setEstimateHours] = useState(0.5);
|
||||
const [plannedTestLocal, setPlannedTestLocal] = useState(defaultPlannedTestLocal);
|
||||
const [plannedEndLocal, setPlannedEndLocal] = useState(defaultPlannedEndLocal);
|
||||
const [assigneeId, setAssigneeId] = useState(user?.name || '');
|
||||
const [description, setDescription] = useState('');
|
||||
const [prototypeNotes, setPrototypeNotes] = useState('');
|
||||
@@ -69,7 +76,9 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
|
||||
|
||||
const normalizedEstimateHours = clampTestCaseEstimateHours(selectedCategory?.code, estimateHours);
|
||||
const plannedTestAt = localToISO(plannedTestLocal);
|
||||
const canSubmit = title.trim() && categoryId && normalizedEstimateHours > 0 && Boolean(plannedTestAt);
|
||||
const plannedEndAt = localToISO(plannedEndLocal);
|
||||
const hasValidPlan = Boolean(plannedTestAt && plannedEndAt && plannedEndAt > plannedTestAt);
|
||||
const canSubmit = title.trim() && categoryId && normalizedEstimateHours > 0 && hasValidPlan;
|
||||
|
||||
const handleSubmit = () => {
|
||||
if (!canSubmit) return;
|
||||
@@ -92,6 +101,7 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
|
||||
priority,
|
||||
estimateHours: normalizedEstimateHours,
|
||||
plannedTestAt,
|
||||
plannedEndAt,
|
||||
assigneeId: assigneeId || undefined,
|
||||
references: references.length > 0 ? references : undefined,
|
||||
createdBy: user?.name || '系统',
|
||||
@@ -154,15 +164,32 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[12px] text-[var(--ink-soft)] mb-1">计划测试时间 *</label>
|
||||
<WorkDateTimePicker
|
||||
value={plannedTestLocal}
|
||||
onChange={setPlannedTestLocal}
|
||||
placeholder="选择计划测试时间"
|
||||
defaultHour={9}
|
||||
/>
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<div>
|
||||
<label className="block text-[12px] text-[var(--ink-soft)] mb-1">计划开始 *</label>
|
||||
<WorkDateTimePicker
|
||||
value={plannedTestLocal}
|
||||
onChange={setPlannedTestLocal}
|
||||
placeholder="选择计划开始时间"
|
||||
defaultHour={9}
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<label className="block text-[12px] text-[var(--ink-soft)] mb-1">计划结束 *</label>
|
||||
<WorkDateTimePicker
|
||||
value={plannedEndLocal}
|
||||
onChange={setPlannedEndLocal}
|
||||
placeholder="选择计划结束时间"
|
||||
defaultHour={10}
|
||||
popoverAlign="right"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{!hasValidPlan && plannedTestLocal && plannedEndLocal && (
|
||||
<div className="rounded-lg border border-amber-200 bg-amber-50 p-2 text-[11px] text-amber-700">
|
||||
计划开始必须早于计划结束
|
||||
</div>
|
||||
)}
|
||||
<div>
|
||||
<label className="block text-[12px] text-[var(--ink-soft)] mb-1">测试步骤 & 预期结果</label>
|
||||
<textarea rows={4} value={description} onChange={(e) => setDescription(e.target.value)} className="w-full rounded-lg border border-[var(--line)] bg-[var(--bg)] px-3 py-2 text-[13px] focus:border-[var(--accent)] focus:outline-none resize-none" placeholder="1. 操作步骤... 2. 预期结果..." />
|
||||
|
||||
Reference in New Issue
Block a user