feat(版本详情): 接入计划时间与日期选择

This commit is contained in:
Script Generator
2026-06-29 14:18:58 +08:00
parent dde11c0899
commit 0f64a17d44
20 changed files with 601 additions and 12 deletions

View File

@@ -7,9 +7,11 @@ import { useRequirementStore } from '@/stores/useRequirementStore';
import { useMemberStore } from '@/stores/useMemberStore';
import { useTaskCategoryStore } from '@/stores/useTaskCategoryStore';
import { useAuthStore } from '@/stores/useAuthStore';
import { WorkDateTimePicker } from '@/components/WorkDateTimePicker';
import type { Priority } from '@/lib/derive';
import { getCategoriesByGroup, getDefaultCategoryByGroup } from '@/lib/task-category';
import { clampTestCaseEstimateHours, getDefaultTestCaseEstimateHours } from '@/lib/ai-estimation-policy';
import { isoToLocal, localToISO } from '@/lib/work-hours';
interface Props {
versionId: string;
@@ -18,6 +20,12 @@ interface Props {
onClose: () => void;
}
function defaultPlannedTestLocal(): string {
const d = new Date();
d.setHours(9, 0, 0, 0);
return isoToLocal(d.toISOString());
}
export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClose }: Props) {
const { createTestCase } = useTestCaseStore();
const { requirements } = useRequirementStore();
@@ -40,6 +48,7 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
[categories, categoryId, testCategories],
);
const [estimateHours, setEstimateHours] = useState(0.5);
const [plannedTestLocal, setPlannedTestLocal] = useState(defaultPlannedTestLocal);
const [assigneeId, setAssigneeId] = useState(user?.name || '');
const [description, setDescription] = useState('');
const [prototypeNotes, setPrototypeNotes] = useState('');
@@ -59,7 +68,8 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
};
const normalizedEstimateHours = clampTestCaseEstimateHours(selectedCategory?.code, estimateHours);
const canSubmit = title.trim() && categoryId && normalizedEstimateHours > 0;
const plannedTestAt = localToISO(plannedTestLocal);
const canSubmit = title.trim() && categoryId && normalizedEstimateHours > 0 && Boolean(plannedTestAt);
const handleSubmit = () => {
if (!canSubmit) return;
@@ -81,6 +91,7 @@ export function TestCaseCreateModal({ versionId, requirementIds, roundNo, onClos
categoryId,
priority,
estimateHours: normalizedEstimateHours,
plannedTestAt,
assigneeId: assigneeId || undefined,
references: references.length > 0 ? references : undefined,
createdBy: user?.name || '系统',
@@ -143,6 +154,15 @@ 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>
<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. 操作步骤...&#10;2. 预期结果..." />