Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
"devDependencies": {
"@types/bcryptjs": "^2.4.6",
"@types/lodash": "^4.17.24",
"@types/node": "^22.0.0",
"@types/node": "^24.0.0",
"@types/nodemailer": "^8.0.0",
"@types/react": "19.2.2",
"@types/react-dom": "19.2.3",
"@types/uuid": "^10.0.0",
"tsx": "^4.19.0",
"typescript": "^5.7.0",
"typescript": "^7.0.0",
"vite": "catalog:",
"vite-plus": "catalog:"
}
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/lib/db.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import { boolEq, boolValue } from "./db-compat";
import { deleteReplyWithStore, type ReplyDeletionStore } from "./reply-deletion";
import { createReplyWithStore, type ReplyCreationStore } from "./reply-creation";

let dbInstance: DB | null = null;
let dbInstance: DB = null;
const INTERNAL_TABS = ["dev", "test"];

function getDb(): DB {
Expand Down
3 changes: 2 additions & 1 deletion apps/api/src/lib/moderation-scan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,9 @@ export function scanDefaults() {
function decodeJsonArray(value: unknown): number[] | null {
if (!value) return null;
if (Array.isArray(value)) return value.map(Number).filter((v) => v > 0);
if (typeof value !== "string") return null;
try {
const parsed = JSON.parse(String(value));
const parsed = JSON.parse(value);
return Array.isArray(parsed) ? parsed.map(Number).filter((v) => v > 0) : null;
} catch {
return null;
Expand Down
2 changes: 1 addition & 1 deletion apps/api/src/middleware/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { roleQueries, userQueries } from "../lib/db";
import { resolveUserAccess } from "../lib/user-access";

export interface AuthVars {
user: Awaited<ReturnType<typeof userQueries.getById>> | null;
user: Awaited<ReturnType<typeof userQueries.getById>>;
isLogin: boolean;
isAdmin: boolean;
isMod: boolean;
Expand Down
8 changes: 4 additions & 4 deletions apps/api/src/routes/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -572,7 +572,7 @@ auth.openapi(githubCreateRoute, async (c) => {
if (!profile)
return c.json({ success: false as const, error_msg: "GitHub 登录状态已过期,请重新授权" }, 401);
const body = c.req.valid("json");
let user: Awaited<ReturnType<typeof userQueries.getById>> | null = null;
let user: Awaited<ReturnType<typeof userQueries.getById>> = null;
if (body.isnew) {
const loginname = profile.login.toLowerCase();
if (await userQueries.getByLoginName(loginname))
Expand Down Expand Up @@ -706,7 +706,7 @@ auth.openapi(githubUnbindRoute, async (c) => {
let result: Awaited<ReturnType<typeof executeGithubUnbind>>;
try {
result = await executeGithubUnbind(user, password, {
clearGithubInfo: userQueries.clearGithubInfo,
clearGithubInfo: (userId, githubId) => userQueries.clearGithubInfo(userId, githubId),
revokeToken: revokeGithubToken,
verifyPassword: bcryptjs.compare,
});
Expand Down Expand Up @@ -999,8 +999,8 @@ auth.post("/upload/image", async (c) => {
return c.json({ success: false, error_msg: "只支持 png/jpeg/gif/webp/svg 图片上传" }, 422);
const maxSize = Number(process.env.OSS_UPLOAD_MAX_BYTES || 5 * 1024 * 1024);
if (file.size > maxSize) return c.json({ success: false, error_msg: "图片不能超过 5MB" }, 413);
const purpose =
typeof formData?.get("purpose") === "string" ? String(formData.get("purpose")) : null;
const purposeValue = formData?.get("purpose");
const purpose = typeof purposeValue === "string" ? purposeValue : null;
const filename = `${uploadPrefix(purpose)}/${uuidv4()}${extensionForContentType(file.type)}`;
await createOssClient().put(filename, Buffer.from(await file.arrayBuffer()), {
headers: { "Content-Type": file.type },
Expand Down
1 change: 1 addition & 0 deletions apps/api/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"extends": "../../tsconfig.base.json",
"compilerOptions": {
"jsx": "react-jsx",
"rootDir": "../..",
"outDir": "./dist",
"types": ["node"],
"noImplicitAny": false,
Expand Down
4 changes: 2 additions & 2 deletions apps/web/app/components/CommandPalette.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,12 +72,12 @@ export function CommandPalette({
const value = query.trim();
if (!value) return;
onOpenChange(false);
navigate(`/search?q=${encodeURIComponent(value)}`);
void navigate(`/search?q=${encodeURIComponent(value)}`);
}

function go(to: string) {
onOpenChange(false);
navigate(to);
void navigate(to);
}

return (
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/components/ThemeToggle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export function ThemeToggle() {
const applyToDocument = useThemeStore((s) => s.applyToDocument);

useEffect(() => {
Promise.resolve(useThemeStore.persist.rehydrate()).then(() => {
void Promise.resolve(useThemeStore.persist.rehydrate()).then(() => {
useThemeStore.getState().applyToDocument();
});
}, [applyToDocument]);
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/lib/stores/auth-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const useAuthStore = create<AuthState>()((set, get) => ({
if (get().hydrated) return;
set({ user, hydrated: true });
if (user) {
get().fetchUnread();
void get().fetchUnread();
}
},
fetchUnread: async () => {
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/routes/_index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ export default function Index({ loaderData }: Route.ComponentProps) {
onValueChange={(value) => {
const params = new URLSearchParams();
if (value !== "all") params.set("tab", value);
navigate(params.size ? `/?${params.toString()}` : "/");
void navigate(params.size ? `/?${params.toString()}` : "/");
}}
>
<Card>
Expand Down
14 changes: 7 additions & 7 deletions apps/web/app/routes/admin/bans.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ export default function AdminBans({ loaderData }: any) {
currentItemCount: bannedUsers.length,
removedCount: 1,
});
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(result.error_msg || `${userActionLabel}失败`);
}
Expand Down Expand Up @@ -195,8 +195,8 @@ export default function AdminBans({ loaderData }: any) {
currentItemCount: bannedUsers.length,
removedCount: result.processed || 0,
});
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(result.error_msg || `批量${userActionLabel}失败`);
}
Expand All @@ -218,7 +218,7 @@ export default function AdminBans({ loaderData }: any) {
setIp("");
setReason("");
setAddIpConfirmOpen(false);
revalidate();
void revalidate();
} else {
toast.error(result.error_msg || "添加 IP 规则失败");
}
Expand All @@ -243,8 +243,8 @@ export default function AdminBans({ loaderData }: any) {
currentItemCount: bannedIps.length,
removedCount: 1,
});
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(res.error_msg || "移除失败");
}
Expand Down
8 changes: 4 additions & 4 deletions apps/web/app/routes/admin/keywords.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ export default function AdminKeywords({ loaderData }: any) {
if (res.success) {
toast.success("已添加");
setNewWord("");
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "添加失败");
}
Expand Down Expand Up @@ -93,8 +93,8 @@ export default function AdminKeywords({ loaderData }: any) {
currentItemCount: keywords.length,
removedCount: 1,
});
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(res.error_msg || "删除失败");
}
Expand All @@ -120,7 +120,7 @@ export default function AdminKeywords({ loaderData }: any) {
toast.success(`已导入 ${result.count} 条`);
setBulkText("");
setShowBulk(false);
revalidate();
void revalidate();
} else {
toast.error(result.error_msg || "导入失败");
}
Expand Down
10 changes: 5 additions & 5 deletions apps/web/app/routes/admin/mod.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ export default function AdminMod({ loaderData }: any) {
if (res.success) {
toast.success("操作成功");
setDeleteTarget(null);
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "操作失败");
}
Expand All @@ -135,7 +135,7 @@ export default function AdminMod({ loaderData }: any) {
toast.success(`已处理 ${res.handled || selected.length} 条`);
setSelected([]);
setDeleteTarget(null);
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "批量操作失败");
}
Expand All @@ -158,7 +158,7 @@ export default function AdminMod({ loaderData }: any) {
toast.success(`已确认删除 ${res.handled || 0} 条命中内容`);
setConfirmJobId(null);
setSelected([]);
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "任务批量确认删除失败");
}
Expand All @@ -181,7 +181,7 @@ export default function AdminMod({ loaderData }: any) {
onSuccess: (res) => {
if (res.success) {
toast.success("扫描任务已创建");
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "创建任务失败");
}
Expand All @@ -208,7 +208,7 @@ export default function AdminMod({ loaderData }: any) {
: "任务已更新",
);
if (result.action === "cancel") setCancelJobId(null);
revalidate();
void revalidate();
} else {
toast.error(result.error_msg || "更新任务失败");
}
Expand Down
20 changes: 17 additions & 3 deletions apps/web/app/routes/admin/reports.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ import {
ItemTitle,
} from "~/components/ui/item";

type ReportRow = {
id: number;
type: string;
description: string | null;
status: string;
reporter_count: number;
target_type: string;
target_id: string;
topic_id: number | null;
topic_title: string;
target_summary: string;
create_at: string;
};

export function meta() {
return [{ title: "举报队列 · CNode Admin" }];
}
Expand All @@ -46,7 +60,7 @@ export default function AdminReports({ loaderData }: any) {
const { revalidate } = useRevalidator();
const location = useLocation();
const navigate = useNavigate();
const [confirmTarget, setConfirmTarget] = useState<any | null>(null);
const [confirmTarget, setConfirmTarget] = useState<ReportRow | null>(null);
const confirmTriggerRef = useRef<HTMLElement | null>(null);

const { run: handleAction, pending: handling } = useAsyncAction(
Expand All @@ -69,8 +83,8 @@ export default function AdminReports({ loaderData }: any) {
currentItemCount: reports.length,
removedCount: 1,
});
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(result.error_msg || "操作失败");
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/routes/admin/tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export default function AdminTabs({ loaderData }: { loaderData: any }) {
);
if (res.success) {
toast.success("已保存");
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "保存失败");
}
Expand Down
8 changes: 4 additions & 4 deletions apps/web/app/routes/admin/topics.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ export default function AdminTopics({ loaderData }: any) {
removedCount: res.ids.length,
})
: null;
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(res.error_msg || "操作失败");
}
Expand All @@ -186,8 +186,8 @@ export default function AdminTopics({ loaderData }: any) {
currentItemCount: topics.length,
removedCount: res.deleted || permanentDeleteIds.length,
});
if (fallback) navigate(fallback, { replace: true });
else revalidate();
if (fallback) void navigate(fallback, { replace: true });
else void revalidate();
} else {
toast.error(res.error_msg || "永久删除失败");
}
Expand Down
6 changes: 3 additions & 3 deletions apps/web/app/routes/admin/users.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export default function AdminUsers({ loaderData }: any) {
if (res.success) {
toast.success("用户治理状态已更新");
setGovernanceTarget(null);
revalidate();
void revalidate();
} else toast.error(res.error_msg || "操作失败");
},
},
Expand All @@ -131,7 +131,7 @@ export default function AdminUsers({ loaderData }: any) {
if (res.success) {
toast.success("用户角色已更新");
setRoleTarget(null);
revalidate();
void revalidate();
} else toast.error(res.error_msg || "角色操作失败");
},
},
Expand All @@ -148,7 +148,7 @@ export default function AdminUsers({ loaderData }: any) {
if (res.success) {
toast.success("已删除该用户所有发言");
setDeleteAllTarget(null);
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "删除失败");
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/routes/admin/zones.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export default function AdminZones({ loaderData }: { loaderData: any }) {
);
if (res.success) {
toast.success("已保存");
revalidate();
void revalidate();
} else {
toast.error(res.error_msg || "保存失败");
}
Expand Down
2 changes: 1 addition & 1 deletion apps/web/app/routes/auth.github.new.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ export default function GithubNew({ loaderData }: Route.ComponentProps) {
onSuccess: (res) => {
if (res.success) {
toast.success("GitHub 登录成功");
navigate("/");
void navigate("/");
} else {
toast.error(res.error_msg || "GitHub 登录失败");
}
Expand Down
10 changes: 5 additions & 5 deletions apps/web/app/routes/my.messages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export default function Messages({ loaderData }: Route.ComponentProps) {
useEffect(() => {
setReadMsgs(initialRead || []);
setUnreadMsgs(initialUnread || []);
fetchUnread();
void fetchUnread();
}, [initialRead, initialUnread, fetchUnread]);

const { run: markOneRead, pending: markingOne } = useAsyncAction(
Expand All @@ -74,8 +74,8 @@ export default function Messages({ loaderData }: Route.ComponentProps) {
if (msg) setReadMsgs((items) => [{ ...msg, has_read: true }, ...items]);
setUnreadCount(Math.max(0, unreadMsgs.length - 1));
toast.success("已标记已读");
fetchUnread();
revalidate();
void fetchUnread();
void revalidate();
},
},
);
Expand All @@ -97,8 +97,8 @@ export default function Messages({ loaderData }: Route.ComponentProps) {
setUnreadMsgs([]);
setUnreadCount(0);
toast.success("已全部标记已读");
fetchUnread();
revalidate();
void fetchUnread();
void revalidate();
},
},
);
Expand Down
Loading