R31-1 R31-4: 收口详情页工作台化与 E2E 契约
这个提交包含在:
@@ -15,6 +15,7 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from ".
|
||||
import { toast } from "sonner";
|
||||
import { isApiError } from "../api/types";
|
||||
import { mapApiErrorMessage } from "../api/errorMessages";
|
||||
import { TEST_IDS } from "../lib/testIds";
|
||||
|
||||
function errorMessage(error: unknown, fallback: string) {
|
||||
if (isApiError(error)) {
|
||||
@@ -135,7 +136,13 @@ export function WeeklyReportsPage() {
|
||||
<div className="text-sm font-medium text-zinc-900">按周归档</div>
|
||||
<div className="text-sm text-zinc-500">默认按周一归档;提交后会同步更新 Portal 与项目摘要。</div>
|
||||
</div>
|
||||
<input className="input-std w-[220px]" type="date" value={weekStart} onChange={(event) => setWeekStart(event.target.value)} />
|
||||
<input
|
||||
aria-label="周报归档周"
|
||||
className="input-std w-[220px]"
|
||||
type="date"
|
||||
value={weekStart}
|
||||
onChange={(event) => setWeekStart(event.target.value)}
|
||||
/>
|
||||
</FilterBar>
|
||||
|
||||
<section className="grid gap-4 md:grid-cols-2 xl:grid-cols-4">
|
||||
@@ -151,16 +158,16 @@ export function WeeklyReportsPage() {
|
||||
{reportQuery.isError ? <div className="text-sm text-red-600">{errorMessage(reportQuery.error, "加载周报失败")}</div> : null}
|
||||
<div className="grid gap-4">
|
||||
<div className="grid gap-2">
|
||||
<label className="text-sm text-zinc-500">本周完成</label>
|
||||
<Textarea value={draft.highlightsText} onChange={(event) => setDraft((prev) => ({ ...prev, highlightsText: event.target.value }))} />
|
||||
<label className="text-sm text-zinc-500" htmlFor="weekly-report-highlights">本周完成</label>
|
||||
<Textarea id="weekly-report-highlights" value={draft.highlightsText} onChange={(event) => setDraft((prev) => ({ ...prev, highlightsText: event.target.value }))} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-sm text-zinc-500">当前阻塞</label>
|
||||
<Textarea value={draft.blockersText} onChange={(event) => setDraft((prev) => ({ ...prev, blockersText: event.target.value }))} />
|
||||
<label className="text-sm text-zinc-500" htmlFor="weekly-report-blockers">当前阻塞</label>
|
||||
<Textarea id="weekly-report-blockers" value={draft.blockersText} onChange={(event) => setDraft((prev) => ({ ...prev, blockersText: event.target.value }))} />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<label className="text-sm text-zinc-500">下周计划</label>
|
||||
<Textarea value={draft.nextWeekText} onChange={(event) => setDraft((prev) => ({ ...prev, nextWeekText: event.target.value }))} />
|
||||
<label className="text-sm text-zinc-500" htmlFor="weekly-report-next-week">下周计划</label>
|
||||
<Textarea id="weekly-report-next-week" value={draft.nextWeekText} onChange={(event) => setDraft((prev) => ({ ...prev, nextWeekText: event.target.value }))} />
|
||||
</div>
|
||||
<label className="flex items-center gap-2 text-sm text-zinc-700">
|
||||
<input type="checkbox" checked={draft.needsHelp} onChange={(event) => setDraft((prev) => ({ ...prev, needsHelp: event.target.checked }))} />
|
||||
@@ -193,9 +200,9 @@ export function WeeklyReportsPage() {
|
||||
</div>
|
||||
))}
|
||||
<div className="flex flex-wrap justify-end gap-2">
|
||||
<Button type="button" variant="secondary" onClick={() => createTodoMutation.mutate()} disabled={createTodoMutation.isPending}>转成待办</Button>
|
||||
<Button type="button" variant="secondary" onClick={() => saveMutation.mutate()} disabled={saveMutation.isPending}>保存草稿</Button>
|
||||
<Button type="button" onClick={() => submitMutation.mutate()} disabled={submitMutation.isPending}>提交周报</Button>
|
||||
<Button data-testid={TEST_IDS.weeklyReport.createTodo} type="button" variant="secondary" onClick={() => createTodoMutation.mutate()} disabled={createTodoMutation.isPending}>转成待办</Button>
|
||||
<Button data-testid={TEST_IDS.weeklyReport.save} type="button" variant="secondary" onClick={() => saveMutation.mutate()} disabled={saveMutation.isPending}>保存草稿</Button>
|
||||
<Button data-testid={TEST_IDS.weeklyReport.submit} type="button" onClick={() => submitMutation.mutate()} disabled={submitMutation.isPending}>提交周报</Button>
|
||||
</div>
|
||||
</div>
|
||||
</SectionPanel>
|
||||
|
||||
在新工单中引用
屏蔽一个用户