From a8246eacd6af16c130f26e3d310ff7e0d13cfa00 Mon Sep 17 00:00:00 2001 From: undefined Date: Sun, 19 Oct 2025 20:13:27 +0800 Subject: [PATCH] bump beta.10 --- README.md | 14 +++++ framework/eslint-config/package.json | 16 ++--- framework/framework/api.ts | 15 ++++- framework/framework/package.json | 10 +-- framework/utils/package.json | 6 +- package.json | 22 +++---- packages/center/package.json | 2 +- packages/components/frontend/ConfigEditor.tsx | 2 +- packages/components/package.json | 6 +- packages/hydrojudge/package.json | 10 +-- packages/hydrojudge/src/sandbox.ts | 3 +- packages/hydrooj/package.json | 28 ++++----- packages/hydrooj/src/model/schedule.ts | 6 +- packages/hydrooj/src/model/storage.ts | 6 +- packages/hydrooj/src/service/bus.ts | 4 +- packages/hydrooj/src/service/layers/user.ts | 5 +- packages/hydrooj/src/service/migration.ts | 2 +- packages/migrate/package.json | 2 +- packages/onsite-toolkit/index.ts | 6 +- packages/onsite-toolkit/package.json | 4 +- packages/scoreboard-xcpcio/package.json | 4 +- .../ui-default/components/dialog/index.tsx | 2 +- .../components/notification/index.ts | 2 +- packages/ui-default/package.json | 62 +++++++++---------- .../templates/manage_user_import.html | 2 +- packages/ui-next/package.json | 8 +-- packages/vjudge/package.json | 6 +- 27 files changed, 143 insertions(+), 112 deletions(-) diff --git a/README.md b/README.md index f449cfb1f..947d9cf7f 100644 --- a/README.md +++ b/README.md @@ -111,6 +111,20 @@ Hydro 用户群:1085853538

更新日志(点击展开)

+## Hydro 5.0.0-beta.10 / UI 4.58.0-beta.10 + +- core&ui: 优化新设置页面 +- core: 修复乐多榜单尝试数为负 +- ui: 修复内置 qface 表情包链接 +- core: 修复编辑题号冲突提示 +- ui: 修复题目配置页语言选择 +- vjudge: 功能优化 +- judge: 稳定性修复 +- ui: 修复 css 动态加载 +- core: 支持比赛材料上传 +- core: 性能和内存占用优化 +- core: 重命名 PERM_VIEW_DISPLAYNAME 为 PERM_VIEW_USER_PRIVATE_INFO + ## Hydro 5.0.0-beta.9 / UI 4.58.0-beta.9 - core: 修复 OI/IOI 赛制一血计算 diff --git a/framework/eslint-config/package.json b/framework/eslint-config/package.json index 932b0b1ba..52a188e8c 100644 --- a/framework/eslint-config/package.json +++ b/framework/eslint-config/package.json @@ -1,18 +1,18 @@ { "name": "@hydrooj/eslint-config", - "version": "3.0.1", + "version": "3.0.2", "license": "MIT", "main": "base.mjs", "repository": "https://github.com/hydro-dev/Hydro", "dependencies": { - "@antfu/eslint-config": "^5.3.0", - "@eslint-react/eslint-plugin": "^1.53.1", - "@typescript-eslint/eslint-plugin": "^8.43.0", - "@typescript-eslint/parser": "^8.43.0", - "eslint-plugin-de-morgan": "^1.3.1", + "@antfu/eslint-config": "^6.0.0", + "@eslint-react/eslint-plugin": "^2.2.2", + "@typescript-eslint/eslint-plugin": "^8.46.1", + "@typescript-eslint/parser": "^8.46.1", + "eslint-plugin-de-morgan": "^2.0.0", "eslint-plugin-github": "^6.0.0", - "eslint-plugin-react-hooks": "^5.2.0", - "eslint-plugin-react-refresh": "^0.4.20", + "eslint-plugin-react-hooks": "^7.0.0", + "eslint-plugin-react-refresh": "^0.4.24", "eslint-plugin-simple-import-sort": "^12.1.1", "globals": "^16.4.0" }, diff --git a/framework/framework/api.ts b/framework/framework/api.ts index a88ca4e0e..a7086f8ed 100644 --- a/framework/framework/api.ts +++ b/framework/framework/api.ts @@ -130,6 +130,17 @@ export class ApiService extends Service { }); } + serialize() { + const result = {}; + for (const key in APIS) { + result[key] = { + type: APIS[key].type, + input: APIS[key].input.toJSON(), + }; + } + return result; + } + async execute( context: ApiExecutionContext, callOrName: ApiCall | string, rawArgs: any, emitHook?: any, project?: any, sendPayload?: (payload: any) => void, @@ -255,9 +266,9 @@ export class ApiConnectionHandler extends ConnectionHandler { + await ctx.inject(['server', 'api'], ({ Route, Connection }) => { Route(name, path, ApiHandler); Connection(`${name}_conn`, `${path}/conn`, ApiConnectionHandler); }); diff --git a/framework/framework/package.json b/framework/framework/package.json index 75f268146..78fb2e8df 100644 --- a/framework/framework/package.json +++ b/framework/framework/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/framework", - "version": "0.2.3", + "version": "0.2.4", "main": "index.ts", "license": "MIT", "repository": "https://github.com/hydro-dev/Hydro", @@ -10,15 +10,15 @@ "dependencies": { "@hydrooj/utils": "workspace:^", "@koa/router": "^14.0.0", - "emoji-regex": "^10.5.0", - "fs-extra": "^11.3.1", - "koa": "^3.0.1", + "emoji-regex": "^10.6.0", + "fs-extra": "^11.3.2", + "koa": "^3.0.3", "koa-body": "^6.0.1", "koa-compress": "^5.1.1", "path-to-regexp": "^8.3.0", "sanitize-filename": "^1.6.3", "saslprep": "^1.0.3", - "schemastery": "^3.17.0", + "schemastery": "^3.17.1", "shorty.js": "^1.0.1", "ws": "^8.18.3" }, diff --git a/framework/utils/package.json b/framework/utils/package.json index 4f917e3e8..0744780dc 100644 --- a/framework/utils/package.json +++ b/framework/utils/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/utils", - "version": "1.4.36", + "version": "1.4.37", "description": "hydrooj utils", "main": "lib/utils.ts", "repository": "https://github.com/hydro-dev/Hydro.git", @@ -14,11 +14,11 @@ "dependencies": { "@hydrooj/register": "workspace:^", "cac": "^6.7.14", - "fs-extra": "^11.3.1", + "fs-extra": "^11.3.2", "js-yaml": "^4.1.0", "reggol": "^2.1.0", "search-query-parser": "^1.6.0", - "systeminformation": "^5.27.8" + "systeminformation": "^5.27.11" }, "devDependencies": { "@types/fs-extra": "^11.0.4" diff --git a/package.json b/package.json index f0e7c5ae0..b19464936 100644 --- a/package.json +++ b/package.json @@ -35,32 +35,32 @@ "@types/autocannon": "^7.12.7", "@types/chai": "^5.2.2", "@types/cross-spawn": "^6.0.6", - "@types/node": "24.3.1", + "@types/node": "24.7.0", "@types/semver": "^7.7.1", "autocannon": "^8.0.0", "cac": "^6.7.14", - "chai": "^5.3.3", - "cross-env": "^10.0.0", + "chai": "^6.2.0", + "cross-env": "^10.1.0", "cross-spawn": "^7.0.6", "esbuild": "0.25.2", - "eslint": "^9.35.0", + "eslint": "^9.38.0", "eslint-import-resolver-typescript": "^4.4.4", "eslint-import-resolver-webpack": "^0.13.10", - "fs-extra": "^11.3.1", + "fs-extra": "^11.3.2", "globals": "^16.4.0", "globby": "~14.0.2", "inspectpack": "^4.7.1", - "mongodb-memory-server": "10.2.0", + "mongodb-memory-server": "10.2.3", "nyc": "^17.1.0", - "ora": "^8.2.0", - "oxlint": "^1.15.0", + "ora": "^9.0.0", + "oxlint": "^1.23.0", "package-json": "^10.0.1", - "semver": "^7.7.2", + "semver": "^7.7.3", "simple-git": "^3.28.0", "supertest": "^7.1.4", - "supports-hyperlinks": "^4.1.2", + "supports-hyperlinks": "^4.3.0", "typescript": "5.8.3", - "wtfnode": "^0.10.0" + "wtfnode": "^0.10.1" }, "packageManager": "yarn@4.10.3" } diff --git a/packages/center/package.json b/packages/center/package.json index 23e36e413..9f3055571 100644 --- a/packages/center/package.json +++ b/packages/center/package.json @@ -11,6 +11,6 @@ }, "dependencies": { "crypto-js": "^4.2.0", - "semver": "^7.7.2" + "semver": "^7.7.3" } } diff --git a/packages/components/frontend/ConfigEditor.tsx b/packages/components/frontend/ConfigEditor.tsx index 6bfa01e88..50a98305e 100644 --- a/packages/components/frontend/ConfigEditor.tsx +++ b/packages/components/frontend/ConfigEditor.tsx @@ -150,7 +150,7 @@ export default function ConfigEditor({ setTimeout(() => { updateFromMonaco(stringConfig === '{}' ? 'dummy: 1' : `${stringConfig}\n\ndummy: 1`); setTimeout(() => { - setStringConfig(stringConfig); + setStringConfig(stringConfig || '\n'); setValue(yaml.load(stringConfig)); }, 300); }, 300); diff --git a/packages/components/package.json b/packages/components/package.json index 4c825dc53..923e2c48a 100644 --- a/packages/components/package.json +++ b/packages/components/package.json @@ -1,6 +1,6 @@ { "name": "@hydrooj/components", - "version": "1.0.0-beta.6", + "version": "1.0.0-beta.7", "main": "./frontend/index.ts", "repository": "https://github.com/hydro-dev/Hydro", "sideEffects": [ @@ -15,13 +15,13 @@ "react-dnd": "^16.0.1", "react-dnd-html5-backend": "^16.0.1", "react-toastify": "^11.0.5", - "schemastery-react": "^0.1.4" + "schemastery-react": "^0.1.5" }, "devDependencies": { "@types/diff": "^8.0.0", "@types/js-yaml": "^4.0.9", "@types/lodash": "^4.17.20", - "sass": "^1.92.1" + "sass": "^1.93.2" }, "peerDependencies": { "react": "*", diff --git a/packages/hydrojudge/package.json b/packages/hydrojudge/package.json index fcd651455..ffb845025 100644 --- a/packages/hydrojudge/package.json +++ b/packages/hydrojudge/package.json @@ -1,18 +1,18 @@ { "name": "@hydrooj/hydrojudge", "bin": "bin/hydrojudge.js", - "version": "3.5.0-beta.8", + "version": "3.5.0-beta.9", "main": "./src/index.ts", "author": "undefined ", "repository": "https://github.com/hydro-dev/Hydro.git", "dependencies": { "@hydrooj/common": "workspace:^", "@hydrooj/utils": "workspace:^", - "@zip.js/zip.js": "^2.8.2", + "@zip.js/zip.js": "^2.8.8", "cac": "^6.7.14", - "p-queue": "^8.1.1", - "schemastery": "^3.17.0", - "semver": "^7.7.2", + "p-queue": "^9.0.0", + "schemastery": "^3.17.1", + "semver": "^7.7.3", "shell-quote": "^1.8.3", "superagent": "^10.2.3", "ws": "^8.18.3" diff --git a/packages/hydrojudge/src/sandbox.ts b/packages/hydrojudge/src/sandbox.ts index 91f5f253d..0466db632 100644 --- a/packages/hydrojudge/src/sandbox.ts +++ b/packages/hydrojudge/src/sandbox.ts @@ -196,7 +196,8 @@ export function runQueued( execute: Parameter[], pipeMapping: Pick[], params: Parameter, trace?: string, priority?: number, ): Promise; -export function runQueued(execute: string, params: Parameter, trace?: string, priority?: number +export function runQueued( + execute: string, params: Parameter, trace?: string, priority?: number, ): Promise; export function runQueued( arg0: string | Parameter[], arg1: Pick[] | Parameter, diff --git a/packages/hydrooj/package.json b/packages/hydrooj/package.json index a36849c01..ab2949b6a 100644 --- a/packages/hydrooj/package.json +++ b/packages/hydrooj/package.json @@ -1,6 +1,6 @@ { "name": "hydrooj", - "version": "5.0.0-beta.9", + "version": "5.0.0-beta.10", "bin": "bin/hydrooj.js", "main": "src/plugin-api", "module": "src/plugin-api", @@ -8,7 +8,7 @@ "author": "undefined ", "license": "AGPL-3.0-or-later OR Proprietary", "engines": { - "node": ">=18" + "node": ">=22" }, "preferUnplugged": true, "dependencies": { @@ -21,33 +21,33 @@ "@hydrooj/common": "workspace:^", "@hydrooj/framework": "workspace:^", "@hydrooj/utils": "workspace:^", - "@simplewebauthn/server": "13.1.2", + "@simplewebauthn/server": "13.2.2", "@undefined-moe/require-resolve-hook": "^1.1.0", - "@zip.js/zip.js": "^2.8.2", + "@zip.js/zip.js": "^2.8.8", "adm-zip": "0.5.16", "cac": "^6.7.14", "cordis": "4.0.0-beta.5", "csv-stringify": "^6.6.0", - "emoji-regex": "^10.5.0", + "emoji-regex": "^10.6.0", "emojis-list": "2.1.0", - "fs-extra": "^11.3.1", + "fs-extra": "^11.3.2", "js-yaml": "^4.1.0", "koa-proxies": "^0.12.4", "koa-static-cache": "^5.1.4", "lodash": "^4.17.21", - "lru-cache": "^11.2.1", + "lru-cache": "^11.2.2", "mime-types": "^3.0.1", "moment-timezone": "^0.6.0", - "mongodb": "^6.19.0", + "mongodb": "^6.20.0", "mongodb-uri": "^0.9.7", - "nanoid": "^5.1.5", - "nodemailer": "^7.0.6", + "nanoid": "^5.1.6", + "nodemailer": "^7.0.9", "notp": "^2.0.3", - "p-queue": "^8.1.1", + "p-queue": "^9.0.0", "sanitize-filename": "^1.6.3", "saslprep": "^1.0.3", - "schemastery": "^3.17.0", - "semver": "^7.7.2", + "schemastery": "^3.17.1", + "semver": "^7.7.3", "shorty.js": "^1.0.1", "superagent": "^10.2.3", "tar": "6.2.1", @@ -63,7 +63,7 @@ "@types/lodash": "^4.17.20", "@types/mime-types": "^3.0.1", "@types/mongodb-uri": "^0.9.4", - "@types/nodemailer": "^7.0.1", + "@types/nodemailer": "^7.0.2", "@types/notp": "^2.0.5", "@types/saslprep": "^1.0.3", "@types/semver": "^7.7.1", diff --git a/packages/hydrooj/src/model/schedule.ts b/packages/hydrooj/src/model/schedule.ts index 4add91061..944b285da 100644 --- a/packages/hydrooj/src/model/schedule.ts +++ b/packages/hydrooj/src/model/schedule.ts @@ -59,7 +59,9 @@ class ScheduleModel { } export async function apply(ctx: Context) { - ctx.inject(['worker'], (c) => { + ctx.on('domain/delete', (domainId) => coll.deleteMany({ domainId })); + + await ctx.inject(['worker'], (c) => { c.worker.addHandler('task.daily', async (task) => { const pref: Record = {}; let start = Date.now(); @@ -88,8 +90,6 @@ export async function apply(ctx: Context) { }); }); - ctx.on('domain/delete', (domainId) => coll.deleteMany({ domainId })); - if (process.env.NODE_APP_INSTANCE !== '0') return; if (!await ScheduleModel.count({ type: 'schedule', subType: 'task.daily' })) { await ScheduleModel.add({ diff --git a/packages/hydrooj/src/model/storage.ts b/packages/hydrooj/src/model/storage.ts index b0094d738..0455ab6a4 100644 --- a/packages/hydrooj/src/model/storage.ts +++ b/packages/hydrooj/src/model/storage.ts @@ -179,9 +179,6 @@ async function cleanFiles() { } export async function apply(ctx: Context) { - ctx.inject(['worker'], (c) => { - c.worker.addHandler('storage.prune', cleanFiles); - }); ctx.on('domain/delete', async (domainId) => { const [problemFiles, contestFiles, trainingFiles] = await Promise.all([ StorageModel.list(`problem/${domainId}`), @@ -190,6 +187,9 @@ export async function apply(ctx: Context) { ]); await StorageModel.del(problemFiles.concat(contestFiles).concat(trainingFiles).map((i) => i.path)); }); + await ctx.inject(['worker'], (c) => { + c.worker.addHandler('storage.prune', cleanFiles); + }); if (process.env.NODE_APP_INSTANCE !== '0') return; await db.ensureIndexes( StorageModel.coll, diff --git a/packages/hydrooj/src/service/bus.ts b/packages/hydrooj/src/service/bus.ts index f7dadce44..14aacd7ba 100644 --- a/packages/hydrooj/src/service/bus.ts +++ b/packages/hydrooj/src/service/bus.ts @@ -25,7 +25,7 @@ export interface EventMap { 'subscription/init': (h: ConnectionHandler, privileged: boolean) => VoidReturn; 'subscription/subscribe': (channel: string, user: User, metadata: Record) => VoidReturn; 'subscription/enable': ( - channel: string, h: ConnectionHandler, privileged: boolean, onDispose: (disposable: () => void) => void + channel: string, h: ConnectionHandler, privileged: boolean, onDispose: (disposable: () => void) => void, ) => VoidReturn; 'app/watch/change': (path: string) => VoidReturn; @@ -61,7 +61,7 @@ export interface EventMap { 'document/add': (doc: any) => VoidReturn; 'document/set': ( domainId: string, docType: T, docId: DocType[T], - $set: any, $unset: OnlyFieldsOfType + $set: any, $unset: OnlyFieldsOfType, ) => VoidReturn; 'discussion/before-add': (payload: Partial) => VoidReturn; diff --git a/packages/hydrooj/src/service/layers/user.ts b/packages/hydrooj/src/service/layers/user.ts index c9df9cb76..37e97e75f 100644 --- a/packages/hydrooj/src/service/layers/user.ts +++ b/packages/hydrooj/src/service/layers/user.ts @@ -1,5 +1,5 @@ import type { KoaContext } from '@hydrooj/framework'; -import { PERM } from '../../model/builtin'; +import { PERM, PRIV } from '../../model/builtin'; import UserModel from '../../model/user'; export default async (ctx: KoaContext, next) => { @@ -13,6 +13,9 @@ export default async (ctx: KoaContext, next) => { user = await UserModel.getById(domainId, ctx.session.uid, ctx.session.scope); } if (user._id === 0) delete user.viewLang; + else if (!user._udoc.ip.includes(ctx.request.ip) && user.hasPriv(PRIV.PRIV_USER_PROFILE)) { + await UserModel.setById(user._id, { loginip: ctx.request.ip }); + } ctx.HydroContext.user = await user.private(); await next(); }; diff --git a/packages/hydrooj/src/service/migration.ts b/packages/hydrooj/src/service/migration.ts index 96410e794..b923323bf 100644 --- a/packages/hydrooj/src/service/migration.ts +++ b/packages/hydrooj/src/service/migration.ts @@ -24,7 +24,7 @@ export default class MigrationService extends Service { } async registerChannel(name: string, s: MigrationScript[]) { - if (this.called) logger.warn('MigrationService.registerChannel: called after doUpgrade'); + if (this.called) logger.warn('MigrationService.registerChannel: called after doUpgrade with name: %s', name); this.channels[name] = s; } diff --git a/packages/migrate/package.json b/packages/migrate/package.json index c78193b1d..efd5a9212 100644 --- a/packages/migrate/package.json +++ b/packages/migrate/package.json @@ -7,7 +7,7 @@ "license": "AGPL-3.0-or-later", "dependencies": { "mariadb": "^3.4.5", - "mongodb": "^6.19.0", + "mongodb": "^6.20.0", "turndown": "^7.2.1", "xml2js": "^0.6.2" }, diff --git a/packages/onsite-toolkit/index.ts b/packages/onsite-toolkit/index.ts index 7322c892f..74d31681a 100644 --- a/packages/onsite-toolkit/index.ts +++ b/packages/onsite-toolkit/index.ts @@ -199,7 +199,7 @@ export function apply(ctx: Context) { ordinal: idx, color: (typeof (tdoc.balloon?.[idx]) === 'object' ? tdoc.balloon[idx].name : tdoc.balloon?.[idx]) || 'white', rgb: (typeof (tdoc.balloon?.[idx]) === 'object' ? tdoc.balloon[idx].color : null) || '#ffffff', - time_limit: (parseTimeMS((pdict[i].config as ProblemConfig).timeMax) / 1000).toFixed(1), + time_limit: Math.floor(parseTimeMS((pdict[i].config as ProblemConfig).timeMax) / 100) / 10, test_data_count: 20, })), ]; @@ -260,8 +260,10 @@ export function apply(ctx: Context) { await zip.add(`teams/${i.team_id}/photo.download.txt`, new Zip.TextReader(i.avatar)); })); await Promise.all(organizations.map(async (i) => { + const avatarSrc = teams.find((j) => j.organization === i)?.avatar; + if (!avatarSrc) return; await zip.add(`organizations/${orgId[i]}/`, null, { directory: true }); - await zip.add(`organizations/${orgId[i]}/photo.download.txt`, new Zip.TextReader(avatar(teams.find((j) => j.organization === i)?.avatar || 'no photo, find and download it yourself'))); + await zip.add(`organizations/${orgId[i]}/photo.download.txt`, new Zip.TextReader(avatar(avatarSrc))); })); this.binary(await zip.close(), `contest-${tdoc._id}-cdp.zip`); }, diff --git a/packages/onsite-toolkit/package.json b/packages/onsite-toolkit/package.json index bd2fc643f..a08298ccb 100644 --- a/packages/onsite-toolkit/package.json +++ b/packages/onsite-toolkit/package.json @@ -1,8 +1,8 @@ { "name": "@hydrooj/onsite-toolkit", - "version": "0.1.0-beta.2", + "version": "0.1.0-beta.3", "dependencies": { - "@react-spring/web": "^10.0.2", + "@react-spring/web": "^10.0.3", "react-use": "^17.6.0" } } diff --git a/packages/scoreboard-xcpcio/package.json b/packages/scoreboard-xcpcio/package.json index 3b3e70e1d..60d594e38 100644 --- a/packages/scoreboard-xcpcio/package.json +++ b/packages/scoreboard-xcpcio/package.json @@ -1,13 +1,13 @@ { "name": "@hydrooj/scoreboard-xcpcio", "license": "AGPL-3.0-or-later", - "version": "0.0.5-beta.3", + "version": "0.0.5-beta.4", "main": "index.ts", "repository": "https://github.com/hydro-dev/Hydro.git", "scripts": { "postinstall": "node -r @hydrooj/register install.ts" }, "dependencies": { - "@xcpcio/board-app": "^0.58.3" + "@xcpcio/board-app": "^0.64.5" } } diff --git a/packages/ui-default/components/dialog/index.tsx b/packages/ui-default/components/dialog/index.tsx index 8cf11aeb8..1cd700533 100644 --- a/packages/ui-default/components/dialog/index.tsx +++ b/packages/ui-default/components/dialog/index.tsx @@ -169,7 +169,7 @@ export async function prompt>(title

{title}

{layout.map((i) =>
- {i.map(([name, field]: [string, Field]) =>
+ {i.map(([name, field]: [string, Field]) =>
{['text', 'user', 'userId', 'username', 'domain'].includes(field.type) &&