feat(版本详情): 接入计划时间与日期选择
This commit is contained in:
@@ -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. 操作步骤... 2. 预期结果..." />
|
||||
|
||||
Reference in New Issue
Block a user