chore: 加 oxlint,现存 19 条 warning 清零
Deploy / deploy (push) Canceled after 0s

原来只有 Prettier,没有任何 lint。根目录加 `bun run lint`(oxlint,覆盖后端、前端、
契约,--deny-warnings:有一条就算失败),CLAUDE.md 常用检查里加上。

现存 19 条顺手清掉:
- 11 处未使用的 import / catch 参数 / 回调参数
- oj/store/problem.ts:`...problem.value?.languages` 展开可能是 undefined
  (外层 if 已经保证非空,去掉 ?.)
- admin/problem/detail.vue:`contestId = contestId` 自赋值,删掉
- judge/sql/engine.ts:注释里的 `/*x*/` 示例原来靠零宽空格防止提前闭合注释,
  改成 `*\/`
- 其余:多余的 !!、new Array(n)、展开里多余的 `|| {}`

两边类型检查、前端构建、后端单二进制编译都过。

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xuyueandClaude Opus 5.5 committed 2026-09-27 15:25:27 +08:00
1 parent 83b9d23c68
commit f8b04af4ea
20 files changed
+61 -23

No files matched your search

+1 -1
View File
@@ -755,7 +755,7 @@ export const problemTag = pgTable(
id: serial().primaryKey().notNull(),
name: text().notNull(),
},
(table) => [
() => [
uniqueIndex("problem_tag_name_ci_unique").using("btree", sql`lower(name)`),
],
)
+1 -1
View File
@@ -159,7 +159,7 @@ function iterate(db: Database, script: string): Iterable<PreparedStatement> {
/**
* 取语句的首关键字。优先用 sqlite3_normalized_sql —— 归一化由 SQLite 自己做,
* 注释、大小写、空白都已抹平(`/*x*​/ pragma Query_Only = 0` → `PRAGMA query_only=?`),
* 注释、大小写、空白都已抹平(`/*x*\/ pragma Query_Only = 0` → `PRAGMA query_only=?`),
* 比在原文上自己做词法猜测可靠得多。
*/
function leadingKeyword(statement: PreparedStatement) {
-1
View File
@@ -2,7 +2,6 @@ import { randomBytes } from "node:crypto"
import { resolve } from "node:path"
import {
rankProfileSchema,
registerRequestSchema,
STUDENT_ROLES,
updateProfileRequestSchema,
+1 -1
View File
@@ -14,7 +14,7 @@ import type { AuthUser } from "../../auth/session"
import { db, schema } from "../../db"
import { failure, parseBody, success } from "../../http"
import { contestStatus } from "../../services/contest"
import { objectValue, queryInteger, sampleUser } from "../helpers"
import { queryInteger, sampleUser } from "../helpers"
export const adminContestRoutes = new Hono<AppEnv>()
-1
View File
@@ -1,6 +1,5 @@
import {
createMessageRequestSchema,
embeddedSubmissionSchema,
exerciseAttemptRequestSchema,
reactionKeySchema,
setReactionRequestSchema,
+2 -2
View File
@@ -147,7 +147,7 @@ flowchartRoutes.post("/flowcharts", requireAuth, async (c) => {
})
try {
await flowchartQueue.add("evaluate", { submissionId: id }, { jobId: id })
} catch (error) {
} catch {
await db
.update(schema.flowchartSubmission)
.set({ status: 3 })
@@ -642,7 +642,7 @@ flowchartRoutes.post("/flowcharts/:id/retry", requireAuth, async (c) => {
{ submissionId: row.flowchart.id },
{ jobId: `${row.flowchart.id}:retry:${Date.now()}` },
)
} catch (error) {
} catch {
// 入队失败就落 FAILED,别把提交丢在 PENDING 上 —— 和 POST /flowcharts 同一处理
await db
.update(schema.flowchartSubmission)
@@ -26,7 +26,6 @@ import {
import { Hono } from "hono"
import { optionalAuth, requireTeacher } from "../auth/middleware"
import type { AuthUser } from "../auth/session"
import { db, schema } from "../db"
import { failure, success } from "../http"
import {
@@ -162,7 +162,7 @@ function getRulesForLang(lang: string): AstRule[] {
}
function updateRules(lang: string, rules: AstRule[]) {
const current = { ...(props.modelValue || {}) }
const current = { ...props.modelValue }
if (rules.length === 0) {
delete current[lang]
} else {
-3
View File
@@ -266,9 +266,6 @@ async function getProblemDetail() {
code: "",
}))
}
if (problem.value.contestId) {
problem.value.contestId = problem.value.contestId
}
// 下面是用来显示的:
// 代码模板 和 模板开关
+1 -1
View File
@@ -30,7 +30,7 @@ function generateUsers() {
)
return false
}
let className = !!prefix.value ? `ks${prefix.value}` : ""
let className = prefix.value ? `ks${prefix.value}` : ""
// 占位邮箱必须全站唯一:注册、编辑用户、导入三条路都查重,而且库里同一个邮箱
// 出现两次的话,那两个账号在「编辑用户」里保存一次就撞 409,从此改不动。
// 原来只按「班级 + 批内序号」拼,同一个班分两批导入必然重号 —— 加一段每批随机的
+2 -2
View File
@@ -55,7 +55,7 @@ router.beforeEach(async (to, _from, next) => {
if (!userStore.user) {
try {
await userStore.getMyProfile()
} catch (error) {
} catch {
next("/")
return
}
@@ -85,7 +85,7 @@ router.beforeEach(async (to, _from, next) => {
app.mount("#app")
if (!!import.meta.env.PUBLIC_ICONIFY_URL) {
if (import.meta.env.PUBLIC_ICONIFY_URL) {
addAPIProvider("", {
resources: [import.meta.env.PUBLIC_ICONIFY_URL],
})
@@ -113,7 +113,7 @@ const chartData = computed(() => {
if (b.solved !== a.solved) return b.solved - a.solved
return a.penalty - b.penalty
})
const ranks = new Array(topUsers.length).fill(0)
const ranks = Array.from({ length: topUsers.length }, () => 0)
indexed.forEach((item, pos) => {
ranks[item.i] = pos + 1
})
@@ -12,7 +12,7 @@ import { copyToClipboard } from "utils/functions"
const message = useMessage()
const route = useRoute()
const contestID = !!route.params.contestID ? route.params.contestID : null
const contestID = route.params.contestID ? route.params.contestID : null
const codeStore = useCodeStore()
const problemStore = useProblemStore()
+1 -1
View File
@@ -106,7 +106,7 @@ export const useContestStore = defineStore("contest", () => {
async function _getProblems(contestID: string) {
try {
problems.value = await getContestProblems(contestID)
} catch (err) {
} catch {
problems.value = []
toggleAccess(false)
}
+1 -1
View File
@@ -29,7 +29,7 @@ export const useProblemStore = defineStore("problem", () => {
const languages = computed<LANGUAGE[]>(() => {
if (route.name === "problem" && problem.value?.allowFlowchart) {
return ["Flowchart", ...problem.value?.languages]
return ["Flowchart", ...problem.value.languages]
}
return problem.value?.languages ?? []
})
+1 -1
View File
@@ -34,7 +34,7 @@ export const useLoginSummaryStore = defineStore("loginSummary", () => {
summary.value = res.summary
analysis.value = res.analysis || ""
analysisError.value = res.analysisError || ""
} catch (err) {
} catch {
analysisError.value = "获取登录统计失败,请稍后再试"
} finally {
loading.value = false
+1 -1
View File
@@ -47,7 +47,7 @@ export async function consumeJSONEventStream<T = any>(
let parsed: T
try {
parsed = JSON.parse(payloadStr)
} catch (error) {
} catch {
throw new Error(`无法解析服务端事件数据: ${payloadStr}`)
}