diff --git a/PROJECT_AUDIT_2026-03-03.md b/PROJECT_AUDIT_2026-03-03.md index d6a6e9d..0754534 100644 --- a/PROJECT_AUDIT_2026-03-03.md +++ b/PROJECT_AUDIT_2026-03-03.md @@ -153,9 +153,10 @@ - 修复内容: - 修复 `GlobalUserBadge`、`RestaurantCard`、`SwipeableCard`、`PageTransition`、`useGeolocation` 的 hooks 规则 error; - 修复页面文案中的未转义引号(`react/no-unescaped-entities`); - - `npm run lint` 已恢复为 0 error(仍有 warning,后续可持续清理)。 + - 第二轮清理补齐所有剩余 warning(未使用变量、无效 eslint-disable、hooks 依赖、`no-img-element` 策略化处理); + - `npm run lint` 已恢复为 0 error / 0 warning。 - 证据: - - 修复后执行 `npm run lint`:`0 errors / 29 warnings`。 + - 修复后执行 `npm run lint`:`0 errors / 0 warnings`。 - 代表性问题: - `src/components/SwipeableCard.tsx:81`(render 阶段注册副作用) - `src/components/GlobalUserBadge.tsx:23`(effect 内同步 setState) @@ -241,6 +242,12 @@ --- +## 第二轮执行进展(2026-03-03) +- 任务 2(清理 lint warning):✅ 已完成 + - 结果:`npm run lint` => `0 errors / 0 warnings`。 + +--- + ## 基线执行结果(本次审查) - `npm run lint`:失败,`10 errors / 32 warnings`。 - `npm test`:通过,`53 files / 329 tests`,但有 `act(...)` 警告。 @@ -257,5 +264,5 @@ 4. 最后推进 R 类重构(N+1、增量更新、API client 统一)。 ## 交付说明 -- 本文档为静态审查结论,未改动业务代码。 -- 建议下一步按“P0/P1 修复 PR + 回归测试补齐”方式分批落地。 +- 本文档已从“静态审查结论”演进为“修复跟踪文档”,会随每轮修复持续更新状态。 +- 现阶段建议继续按“问题分组 + 回归测试同步补齐”的节奏推进。 diff --git a/scripts/generate-pwa-icons.mjs b/scripts/generate-pwa-icons.mjs index 07a1676..4f2a64f 100644 --- a/scripts/generate-pwa-icons.mjs +++ b/scripts/generate-pwa-icons.mjs @@ -1,5 +1,4 @@ import sharp from "sharp"; -import { mkdirSync } from "fs"; import { join, dirname } from "path"; import { fileURLToPath } from "url"; diff --git a/src/__tests__/helpers/prisma-mock.ts b/src/__tests__/helpers/prisma-mock.ts index adf3902..c4dc35e 100644 --- a/src/__tests__/helpers/prisma-mock.ts +++ b/src/__tests__/helpers/prisma-mock.ts @@ -1,5 +1,5 @@ import { vi } from "vitest"; -import { mockDeep, mockReset, type DeepMockProxy } from "vitest-mock-extended"; +import { mockDeep, mockReset } from "vitest-mock-extended"; import type { PrismaClient } from "@prisma/client"; export const prismaMock = mockDeep(); diff --git a/src/app/api/blindbox/room/[code]/route.test.ts b/src/app/api/blindbox/room/[code]/route.test.ts index 70a65fe..3b1adcd 100644 --- a/src/app/api/blindbox/room/[code]/route.test.ts +++ b/src/app/api/blindbox/room/[code]/route.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { prismaMock, resetPrismaMock } from "@/__tests__/helpers/prisma-mock"; import { createRequest, createRouteContext, parseJsonResponse } from "@/__tests__/helpers/api-test-utils"; -import { TEST_BLINDBOX_ROOM, TEST_USER } from "@/__tests__/helpers/fixtures"; +import { TEST_BLINDBOX_ROOM } from "@/__tests__/helpers/fixtures"; vi.mock("@/lib/auth", () => ({ getAuthUserId: vi.fn().mockResolvedValue("user-1"), diff --git a/src/app/api/room/[id]/manage/route.test.ts b/src/app/api/room/[id]/manage/route.test.ts index ba48141..ab0d78f 100644 --- a/src/app/api/room/[id]/manage/route.test.ts +++ b/src/app/api/room/[id]/manage/route.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { createRequest, createRouteContext, parseJsonResponse } from "@/__tests__/helpers/api-test-utils"; -import { TEST_ROOM_DATA, TEST_RESTAURANT } from "@/__tests__/helpers/fixtures"; +import { createRequest, createRouteContext } from "@/__tests__/helpers/api-test-utils"; +import { TEST_ROOM_DATA } from "@/__tests__/helpers/fixtures"; vi.mock("@/lib/prisma", () => ({ prisma: {} })); diff --git a/src/app/api/room/[id]/reset/route.test.ts b/src/app/api/room/[id]/reset/route.test.ts index cfd6b78..7681ca6 100644 --- a/src/app/api/room/[id]/reset/route.test.ts +++ b/src/app/api/room/[id]/reset/route.test.ts @@ -1,6 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; import { createRequest, createRouteContext, parseJsonResponse } from "@/__tests__/helpers/api-test-utils"; -import { TEST_ROOM_DATA, TEST_RESTAURANT, TEST_RESTAURANT_2 } from "@/__tests__/helpers/fixtures"; +import { TEST_ROOM_DATA, TEST_RESTAURANT } from "@/__tests__/helpers/fixtures"; vi.mock("@/lib/prisma", () => ({ prisma: {} })); diff --git a/src/app/blindbox/[code]/page.test.tsx b/src/app/blindbox/[code]/page.test.tsx index ef41368..9e14ac1 100644 --- a/src/app/blindbox/[code]/page.test.tsx +++ b/src/app/blindbox/[code]/page.test.tsx @@ -1,5 +1,5 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { render, screen, waitFor } from "@testing-library/react"; +import { render, waitFor } from "@testing-library/react"; import React from "react"; import { ToastContext, type ToastContextValue } from "@/hooks/useToast"; diff --git a/src/app/blindbox/page.tsx b/src/app/blindbox/page.tsx index 9d68412..58d23a7 100644 --- a/src/app/blindbox/page.tsx +++ b/src/app/blindbox/page.tsx @@ -121,7 +121,11 @@ function RoomCard({ tabIndex={0} onClick={(e) => { e.stopPropagation(); - confirmDelete ? onCancelDelete() : onRequestDelete(); + if (confirmDelete) { + onCancelDelete(); + } else { + onRequestDelete(); + } }} className="flex h-7 w-7 shrink-0 items-center justify-center rounded-full text-muted/40 transition-colors hover:bg-elevated hover:text-muted active:text-foreground" > @@ -276,7 +280,7 @@ export default function BlindboxLobbyPage() { } finally { setDeletingId(null); } - }, [deletingId, profile, toast]); + }, [deletingId, profile, toast, mutateRooms]); return (
diff --git a/src/app/global-error.tsx b/src/app/global-error.tsx index 0030977..b48be90 100644 --- a/src/app/global-error.tsx +++ b/src/app/global-error.tsx @@ -1,6 +1,7 @@ "use client"; import { useEffect } from "react"; +import Image from "next/image"; export default function GlobalError({ error, @@ -17,7 +18,7 @@ export default function GlobalError({
- 错误 + 错误

应用崩溃了

发生了严重错误,请尝试刷新页面 diff --git a/src/app/room/[id]/page.tsx b/src/app/room/[id]/page.tsx index 0b36f9e..63985bb 100644 --- a/src/app/room/[id]/page.tsx +++ b/src/app/room/[id]/page.tsx @@ -10,7 +10,6 @@ import Button from "@/components/Button"; import { useRoomPolling } from "@/hooks/useRoomPolling"; import { getUserId } from "@/lib/userId"; import { joinRoom } from "@/lib/room"; -import { getSceneConfig } from "@/lib/sceneConfig"; import { useToast } from "@/hooks/useToast"; export default function RoomPage() { @@ -126,8 +125,6 @@ export default function RoomPage() { const initialIndex = swipeCounts[userId] ?? 0; const ready = joined && userId && restaurants.length > 0; - const sceneConfig = getSceneConfig(scene); - if (!ready) { return ; } diff --git a/src/components/Input.test.tsx b/src/components/Input.test.tsx index 11ba6f5..d31b646 100644 --- a/src/components/Input.test.tsx +++ b/src/components/Input.test.tsx @@ -1,4 +1,4 @@ -import { describe, it, expect, vi } from "vitest"; +import { describe, it, expect } from "vitest"; import { render, screen } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; import Input from "./Input"; diff --git a/src/components/MatchResult.test.tsx b/src/components/MatchResult.test.tsx index acd13c4..e3f20c3 100644 --- a/src/components/MatchResult.test.tsx +++ b/src/components/MatchResult.test.tsx @@ -23,7 +23,7 @@ vi.mock("./ShareCardModal", () => ({ })); vi.mock("./RestaurantImage", () => ({ - default: ({ alt }: { alt: string }) => {alt}, + default: ({ alt }: { alt: string }) =>

, })); vi.mock("./AuthModal", () => ({ diff --git a/src/components/RestaurantImage.tsx b/src/components/RestaurantImage.tsx index 35cdd63..f3b5dc2 100644 --- a/src/components/RestaurantImage.tsx +++ b/src/components/RestaurantImage.tsx @@ -1,4 +1,5 @@ "use client"; +/* eslint-disable @next/next/no-img-element -- Uses raw img for unrestricted external sources and card capture fidelity. */ import { useState, useCallback } from "react"; diff --git a/src/components/RestaurantShareCard.tsx b/src/components/RestaurantShareCard.tsx index 2a6070f..bea3ebe 100644 --- a/src/components/RestaurantShareCard.tsx +++ b/src/components/RestaurantShareCard.tsx @@ -1,3 +1,4 @@ +/* eslint-disable @next/next/no-img-element -- Share card rendering requires direct img tags for html-to-image output. */ import { Star, MapPin, Zap } from "lucide-react"; import type { Restaurant, MatchType, SceneType } from "@/types"; import { getSceneConfig } from "@/lib/sceneConfig"; diff --git a/src/components/RoomManageModal.tsx b/src/components/RoomManageModal.tsx index 4ac5de6..73f8489 100644 --- a/src/components/RoomManageModal.tsx +++ b/src/components/RoomManageModal.tsx @@ -83,8 +83,6 @@ export default function RoomManageModal({ [roomId, userId, toast, onClose], ); - const otherUsers = users.filter((u) => u !== userId); - return (