From dc9cc9eecfe3e5f5abef07e2c294b2a776706982 Mon Sep 17 00:00:00 2001 From: undefined Date: Tue, 25 Mar 2025 14:26:46 +0800 Subject: [PATCH] bug fixes --- framework/framework/server.ts | 1 - install/install.ts | 8 +++--- packages/hydrojudge/src/hosts/builtin.ts | 25 ++++++++++++------- packages/hydrooj/src/entry/common.ts | 1 - packages/hydrooj/src/handler/home.ts | 6 ++--- packages/hydrooj/src/lib/i18n.ts | 1 + packages/ui-default/build/config/webpack.ts | 1 + .../components/editor/cmeditor.styl | 7 ++++++ .../ui-default/components/editor/index.tsx | 10 +++++++- .../ui-default/components/editor/mdeditor.ts | 2 ++ .../ui-default/templates/problem_edit.html | 2 +- 11 files changed, 45 insertions(+), 19 deletions(-) diff --git a/framework/framework/server.ts b/framework/framework/server.ts index db436cf35..b9df6d4b7 100644 --- a/framework/framework/server.ts +++ b/framework/framework/server.ts @@ -670,7 +670,6 @@ ${c.response.status} ${endTime - startTime}ms ${c.response.length}`); } } catch (e) { // error during initialization (prepare, hooks) - logger.error(e); await clean(e); } } diff --git a/install/install.ts b/install/install.ts index e77fcaf78..b7ddfefe0 100644 --- a/install/install.ts +++ b/install/install.ts @@ -195,6 +195,7 @@ const Caddyfile = `\ # 仅需将 :80 改为你的域名(如 hydro.ac)后使用 caddy reload 重载配置即可自动签发 ssl 证书。 # 填写完整域名,注意区分有无 www (www.hydro.ac 和 hydro.ac 不同,请检查 DNS 设置) # 请注意在防火墙/安全组中放行端口,且部分运营商会拦截未经备案的域名。 +# 其他需求清参照 https://caddyserver.com/docs/ 说明进行设置。 # For more information, refer to caddy v2 documentation. :80 { encode zstd gzip @@ -242,6 +243,7 @@ hosts: uname: judge password: examplepassword detail: true + concurrency: 2 tmpfs_size: 512m stdio_size: 256m memoryMax: ${Math.min(1024, os.totalmem() / 4)}m @@ -253,7 +255,7 @@ parallelism: ${Math.max(1, Math.floor(cpus().length / 4))} singleTaskParallelism: 2 rate: 1.00 rerun: 2 -secret: ${String.random(32)} +secret: ${crypto.randomBytes(32).toString('hex')} env: | PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin HOME=/w @@ -409,8 +411,8 @@ ${nixConfBase}`); const docker = !exec('docker -v').code; if (!docker) return; const containers = exec('docker ps -a --format json').output?.split('\n') - .map((i) => i.trim()).filter((i) => i).map((i) => JSON.parse(i)); - const uoj = containers?.find((i) => i.Image.toLowerCase() === 'universaloj/uoj-system' && i.State === 'running'); + .map((i) => i.trim()).filter((i) => i).map((i) => JSON.parse(i)) || []; + const uoj = containers.find((i) => i.Image.toLowerCase() === 'universaloj/uoj-system' && i.State === 'running'); if (uoj) { log.info('migrate.uojFound'); const res = await rl.question('>'); diff --git a/packages/hydrojudge/src/hosts/builtin.ts b/packages/hydrojudge/src/hosts/builtin.ts index ff54fe0dc..fffa6d3d9 100644 --- a/packages/hydrojudge/src/hosts/builtin.ts +++ b/packages/hydrojudge/src/hosts/builtin.ts @@ -59,7 +59,7 @@ const session: Session = { }, }; -export async function* apply(ctx: HydroContext) { +export async function apply(ctx: HydroContext) { ctx.inject(['check'], (c) => { c.check.addChecker('Judge', async (_ctx, log, warn, error) => { await versionCheck(warn, error); @@ -75,9 +75,7 @@ export async function* apply(ctx: HydroContext) { } await (new JudgeTask(session, JSON.parse(JSON.stringify(Object.assign(rdoc, t))))).handle().catch(logger.error); }; - const parallelism = Math.max(getConfig('parallelism'), 2); - const taskConsumer = TaskModel.consume({ type: 'judge' }, handle, true, parallelism); - yield () => taskConsumer.destroy(); + const parallelism = getConfig('parallelism'); async function collectInfo() { const coll = db.collection('status'); const compilers = await compilerVersions(langs); @@ -93,11 +91,20 @@ export async function* apply(ctx: HydroContext) { { upsert: true }, ); } - yield ctx.on('system/setting', () => { - taskConsumer.setConcurrency(Math.max(getConfig('parallelism'), 2)); - collectInfo(); + ctx.effect(() => { + const taskConsumer = TaskModel.consume({ type: 'judge' }, handle, true, parallelism); + const dispose = ctx.on('system/setting', () => { + taskConsumer.setConcurrency(getConfig('parallelism')); + collectInfo(); + }); + return () => { + taskConsumer.destroy(); + dispose(); + }; + }); + ctx.effect(() => { + const generateConsumer = TaskModel.consume({ type: 'generate' }, handle); + return () => generateConsumer.destroy(); }); collectInfo(); - const generateConsumer = TaskModel.consume({ type: 'generate' }, handle); - yield () => generateConsumer.destroy(); } diff --git a/packages/hydrooj/src/entry/common.ts b/packages/hydrooj/src/entry/common.ts index a949ae73f..70af952bd 100644 --- a/packages/hydrooj/src/entry/common.ts +++ b/packages/hydrooj/src/entry/common.ts @@ -2,7 +2,6 @@ /* eslint-disable no-await-in-loop */ import '../lib/index'; -import os from 'os'; import path from 'path'; import fs from 'fs-extra'; import yaml from 'js-yaml'; diff --git a/packages/hydrooj/src/handler/home.ts b/packages/hydrooj/src/handler/home.ts index db4665ea3..a96e9714d 100644 --- a/packages/hydrooj/src/handler/home.ts +++ b/packages/hydrooj/src/handler/home.ts @@ -181,7 +181,6 @@ export class HomeHandler extends Handler { class HomeSecurityHandler extends Handler { @requireSudo async get() { - const geoip = this.ctx.get('geoip'); // TODO(iceboy): pagination? or limit session count for uid? const sessions = await token.getSessionListByUid(this.user._id); for (const session of sessions) { @@ -189,7 +188,7 @@ class HomeSecurityHandler extends Handler { session._id = md5(session._id); const ua = session.updateUa || session.createUa; if (ua) session.updateUaInfo = UAParser(ua); - session.updateGeoip = geoip?.lookup?.( + session.updateGeoip = this.ctx.geoip?.lookup?.( session.updateIp || session.createIp, this.translate('geoip_locale'), ); @@ -202,7 +201,7 @@ class HomeSecurityHandler extends Handler { 'credentialID', 'name', 'credentialType', 'credentialDeviceType', 'authenticatorAttachment', 'regat', 'fmt', ])), - geoipProvider: geoip?.provider, + geoipProvider: this.ctx.geoip?.provider, }; } @@ -610,6 +609,7 @@ class HomeMessagesConnectionHandler extends ConnectionHandler { } } +export const inject = { geoip: { required: false } }; export function apply(ctx: Context) { ctx.Route('homepage', '/', HomeHandler); ctx.Route('home_security', '/home/security', HomeSecurityHandler, PRIV.PRIV_USER_PROFILE); diff --git a/packages/hydrooj/src/lib/i18n.ts b/packages/hydrooj/src/lib/i18n.ts index 2965ceb89..1311abf52 100644 --- a/packages/hydrooj/src/lib/i18n.ts +++ b/packages/hydrooj/src/lib/i18n.ts @@ -16,6 +16,7 @@ declare module '../service/bus' { class I18nService extends Service { constructor(ctx: Context) { super(ctx, 'i18n'); + this.translate = this.translate.bind(this); this.load('ja', { __flag: '🇯🇵', __id: 'ja', __langname: '日本語' }); } diff --git a/packages/ui-default/build/config/webpack.ts b/packages/ui-default/build/config/webpack.ts index 9f59d917a..45bd6efa2 100644 --- a/packages/ui-default/build/config/webpack.ts +++ b/packages/ui-default/build/config/webpack.ts @@ -304,6 +304,7 @@ export default async function (env: { watch?: boolean, production?: boolean, mea }), new webpack.NormalModuleReplacementPlugin(/\/(vscode-)?nls\.js/, require.resolve('../../components/monaco/nls')), new webpack.NormalModuleReplacementPlugin(/^prettier[$/]/, root('../../modules/nop.ts')), + new webpack.NormalModuleReplacementPlugin(/^highlightjs[$/]/, root('../../modules/nop.ts')), new webpack.NormalModuleReplacementPlugin(/core-js\/stable/, root('__core-js.js')), new MonacoWebpackPlugin({ filename: '[name].[hash:6].worker.js', diff --git a/packages/ui-default/components/editor/cmeditor.styl b/packages/ui-default/components/editor/cmeditor.styl index f104bc1dc..d16930c21 100644 --- a/packages/ui-default/components/editor/cmeditor.styl +++ b/packages/ui-default/components/editor/cmeditor.styl @@ -1,3 +1,10 @@ .decoration-hide color: grey !important background-color: grey !important + +.md-editor-preview code + background-color: unset !important + color: unset !important + +.md-editor-scrn pre.syntax-hl code + padding-left: unset !important diff --git a/packages/ui-default/components/editor/index.tsx b/packages/ui-default/components/editor/index.tsx index dfd5915b7..ec81627bd 100644 --- a/packages/ui-default/components/editor/index.tsx +++ b/packages/ui-default/components/editor/index.tsx @@ -1,4 +1,5 @@ import $ from 'jquery'; +import { debounce } from 'lodash'; import { nanoid } from 'nanoid'; import React from 'react'; import ReactDOM from 'react-dom/client'; @@ -156,8 +157,12 @@ export default class Editor extends DOMAttachedObject { const { onChange } = this.options; const { MdEditor } = await import('./mdeditor'); + const debouncedTrigger = debounce(() => { + $(document.querySelector('.md-editor-preview')).trigger('vjContentNew'); + }, 500, { trailing: true }); const renderCallback = (ref) => { this.markdownEditor = ref; + setTimeout(debouncedTrigger, 200); }; function EditorComponent() { @@ -169,10 +174,12 @@ export default class Editor extends DOMAttachedObject { codeTheme='github' codeStyleReverse={false} ref={renderCallback} - modelValue={val} + value={val} theme={getTheme()} noMermaid noPrettier + noKatex + noHighlight autoDetectCode toolbarsExclude={[ // 'bold', @@ -214,6 +221,7 @@ export default class Editor extends DOMAttachedObject { $dom.val(v); $dom.text(v); onChange?.(v); + setTimeout(debouncedTrigger, 100); }} onUploadImg={async (files, callback) => { let ext: string; diff --git a/packages/ui-default/components/editor/mdeditor.ts b/packages/ui-default/components/editor/mdeditor.ts index 88f934d7d..6b96ecfbf 100644 --- a/packages/ui-default/components/editor/mdeditor.ts +++ b/packages/ui-default/components/editor/mdeditor.ts @@ -7,6 +7,7 @@ import MergeCells from 'markdown-it-merge-cells'; import TOC from 'markdown-it-table-of-contents'; import { config, MdEditor } from 'md-editor-rt'; import Imsize from '../../backendlib/markdown-it-imsize'; +import katex from '../../backendlib/markdown-it-katex'; import { Media } from '../../backendlib/markdown-it-media'; import { xssProtector } from '../../backendlib/markdown-it-xss'; @@ -28,6 +29,7 @@ config({ mdit.use(TOC); mdit.use(MergeCells); mdit.use(xssProtector); + mdit.use(katex); if (isProblemPage) { mdit.core.ruler.before('normalize', 'xss', (state) => { state.src = state.src.replace(/file:\/\//g, pagename === 'problem_create' ? `/file/${UserContext._id}/` : './file/'); diff --git a/packages/ui-default/templates/problem_edit.html b/packages/ui-default/templates/problem_edit.html index 0e06b7ff8..dce22d4ca 100644 --- a/packages/ui-default/templates/problem_edit.html +++ b/packages/ui-default/templates/problem_edit.html @@ -45,7 +45,7 @@ label:'Difficulty', help_text:'From 1-10', name:'difficulty', - value:pdoc['difficulty'] + value:pdoc['difficulty'] or '' }) }}