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

@@ -9,14 +9,22 @@ import { useRequirementStore } from '@/stores/useRequirementStore';
import { useMemberStore } from '@/stores/useMemberStore';
import { useAuthStore } from '@/stores/useAuthStore';
import { resolveMemberDisplayName } from '@/lib/member-system';
import { WorkDateTimePicker } from '@/components/WorkDateTimePicker';
import type { Priority } from '@/lib/derive';
import type { BugSeverity } from '@/lib/bug';
import { isoToLocal, localToISO } from '@/lib/work-hours';
interface Props {
testCaseId: string;
onClose: () => void;
}
function defaultPlannedFixLocal(): string {
const d = new Date();
d.setHours(18, 0, 0, 0);
return isoToLocal(d.toISOString());
}
export function BugCreateModal({ testCaseId, onClose }: Props) {
const { createBug } = useBugStore();
const { testCases } = useTestCaseStore();
@@ -42,10 +50,12 @@ export function BugCreateModal({ testCaseId, onClose }: Props) {
const [severity, setSeverity] = useState<BugSeverity>('major');
const [priority, setPriority] = useState<Priority>(tc?.priority || 'P1');
const [assigneeId, setAssigneeId] = useState(defaultAssignee);
const [plannedFixLocal, setPlannedFixLocal] = useState(defaultPlannedFixLocal);
const [images, setImages] = useState<string[]>([]);
const fileRef = useRef<HTMLInputElement>(null);
const canSubmit = title.trim() && description.trim() && assigneeId;
const plannedFixAt = localToISO(plannedFixLocal);
const canSubmit = title.trim() && description.trim() && assigneeId && Boolean(plannedFixAt);
const handleFiles = (files: FileList | null) => {
if (!files) return;
@@ -72,6 +82,7 @@ export function BugCreateModal({ testCaseId, onClose }: Props) {
priority,
reportedBy: operator,
assigneeId,
plannedFixAt,
images: images.length > 0 ? images : undefined,
}, operator);
onClose();
@@ -154,6 +165,15 @@ export function BugCreateModal({ testCaseId, onClose }: Props) {
</select>
</div>
</div>
<div>
<label className="block text-[12px] text-[var(--ink-soft)] mb-1"> *</label>
<WorkDateTimePicker
value={plannedFixLocal}
onChange={setPlannedFixLocal}
placeholder="选择计划修复时间"
defaultHour={18}
/>
</div>
</div>
<div className="flex justify-end gap-2 pt-4 border-t border-[var(--line)] mt-4">
<button onClick={onClose} className="h-8 px-3 rounded-lg text-[12px] font-medium border border-[var(--line)] text-[var(--ink-soft)] hover:bg-[var(--bg-subtle)]"></button>

View File

@@ -166,6 +166,7 @@ export function BugDetailDrawer({ bugId, onClose, contextLabel }: Props) {
<div className="rounded-xl border border-[var(--line)] bg-[var(--bg-card)] p-4">
<div className="text-[10px] text-[var(--ink-muted)] uppercase tracking-wide mb-3"></div>
<div className="grid grid-cols-2 gap-y-3 gap-x-4 text-[12px]">
<div><span className="text-[var(--ink-muted)]"></span><span className="text-[var(--ink)] font-medium">{bug.plannedFixAt ? formatDateTime(bug.plannedFixAt) : '待排期'}</span></div>
<div><span className="text-[var(--ink-muted)]"></span><span className="text-[var(--ink)]">{reporterName}</span></div>
<div><span className="text-[var(--ink-muted)]"></span><span className="text-[var(--ink)] font-medium">{assigneeName}</span></div>
<div><span className="text-[var(--ink-muted)]"></span><span className="text-[var(--ink)]">{formatDateTime(bug.createdAt)}</span></div>

View File

@@ -4,6 +4,7 @@ import { memo } from 'react';
import { BugStatusBadge } from './BugStatusBadge';
import { BUG_SEVERITY_LABEL, BUG_SEVERITY_COLOR, getBugActualHours } from '@/lib/bug';
import { formatWorkHours } from '@/lib/work-hours';
import { formatDateTimeShort } from '@/lib/format';
import { resolveMemberDisplayName } from '@/lib/member-system';
import { useMemberStore } from '@/stores/useMemberStore';
import type { Bug } from '@/lib/bug';
@@ -32,6 +33,9 @@ function BugRowImpl({ bug, testCaseNo, onClick }: Props) {
<span className="text-[13px] text-[var(--ink)] flex-1 truncate">{bug.title}</span>
<span className={`text-[10px] px-1.5 py-0.5 rounded shrink-0 ${BUG_SEVERITY_COLOR[bug.severity]}`}>{BUG_SEVERITY_LABEL[bug.severity]}</span>
<BugStatusBadge status={bug.status} />
<span className="text-[11px] text-[var(--ink-muted)] tabular-nums w-24 text-right shrink-0 whitespace-nowrap" title="计划修复时间">
{bug.plannedFixAt ? formatDateTimeShort(bug.plannedFixAt) : '待排期'}
</span>
{actualHours > 0 && (
<span className="text-[11px] text-[var(--ink-muted)] tabular-nums w-28 text-right shrink-0 whitespace-nowrap">{formatWorkHours(actualHours)}</span>
)}