mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-17 09:36:08 +08:00
bug fixes
This commit is contained in:
20 files changed
+43
-35
No files matched your search
@@ -137,11 +137,12 @@ Hydro 用户群:1085853538
|
||||
- serializer: 移除 showDisplayName 参数
|
||||
- 移除了 loader.addScript, loader.addon 函数
|
||||
- 移除了 Hydro.module.render (请使用 ctx.server.registerRenderer)
|
||||
- 移除了 lib/paginate 和 lib/rank (请使用 db.paginate 和 db.ranked)
|
||||
|
||||
### Hydro 4.12.3 / UI 4.50.2
|
||||
- core: 将 API 模块移入 service
|
||||
- core: 比赛时提交被 hack 不触发整体重测
|
||||
- core: 将添加 pid match 的逻辑移入搜索中
|
||||
- core: 将添加 pid match 的逻辑移入搜索中
|
||||
- ui: 修正 cssFilter
|
||||
- judge: builtin: 维护 callback 顺序
|
||||
- core: 优化邮件地址处理
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "@hydrooj/hydrojudge",
|
||||
"bin": "bin/hydrojudge.js",
|
||||
"version": "3.3.14",
|
||||
"version": "3.3.15",
|
||||
"main": "./src/index.ts",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"repository": "https://github.com/hydro-dev/Hydro.git",
|
||||
|
||||
@@ -99,7 +99,7 @@ export async function postInit(ctx) {
|
||||
function collectCompilerInfo() {
|
||||
const coll = db.collection('status');
|
||||
compilerVersions(langs).then((compilers) => coll.updateOne(
|
||||
{ mid: info.mid, type: 'judge' },
|
||||
{ mid: info.mid, type: 'server' },
|
||||
{ $set: { compilers } },
|
||||
{ upsert: true },
|
||||
)).catch((e) => logger.error(e));
|
||||
|
||||
@@ -175,6 +175,7 @@ export default class Hydro implements Session {
|
||||
? JSON.stringify({ key: 'config', ...config })
|
||||
: '{"key":"ping"}';
|
||||
let compilers = {};
|
||||
let compilerVersionCallback = () => { };
|
||||
this.ws.on('message', (data) => {
|
||||
if (data.toString() === 'ping') {
|
||||
this.ws.send('pong');
|
||||
@@ -185,6 +186,7 @@ export default class Hydro implements Session {
|
||||
this.language = request.language;
|
||||
compilerVersions(this.language).then((res) => {
|
||||
compilers = res;
|
||||
compilerVersionCallback();
|
||||
});
|
||||
}
|
||||
if (request.task) queue.add(() => new JudgeTask(this, request.task).handle().catch((e) => log.error(e)));
|
||||
@@ -203,7 +205,10 @@ export default class Hydro implements Session {
|
||||
this.ws.send('{"key":"start"}');
|
||||
if (!this.config.noStatus) {
|
||||
const info = await sysinfo.get();
|
||||
this.ws.send(JSON.stringify({ key: 'status', info: { ...info, compilers } }));
|
||||
this.ws.send(JSON.stringify({ key: 'status', info: { ...info } }));
|
||||
compilerVersionCallback = () => {
|
||||
this.ws.send(JSON.stringify({ key: 'status', info: { ...info, compilers } }));
|
||||
};
|
||||
setInterval(async () => {
|
||||
const [mid, inf] = await sysinfo.update();
|
||||
this.ws.send(JSON.stringify({ key: 'status', info: { mid, ...inf, compilers } }));
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "hydrooj",
|
||||
"version": "4.13.0",
|
||||
"version": "4.13.1",
|
||||
"bin": "bin/hydrooj.js",
|
||||
"main": "src/plugin-api",
|
||||
"module": "src/plugin-api",
|
||||
|
||||
@@ -274,6 +274,7 @@ SystemSetting(
|
||||
Setting('setting_basic', 'pagination.contest', 20, 'number', 'pagination.contest', 'Contests per page'),
|
||||
Setting('setting_basic', 'pagination.discussion', 50, 'number', 'pagination.discussion', 'Discussions per page'),
|
||||
Setting('setting_basic', 'pagination.record', 100, 'number', 'pagination.record', 'Records per page'),
|
||||
Setting('setting_basic', 'pagination.ranking', 100, 'number', 'pagination.ranking', 'Users per page'),
|
||||
Setting('setting_basic', 'pagination.solution', 20, 'number', 'pagination.solution', 'Solutions per page'),
|
||||
Setting('setting_basic', 'pagination.training', 10, 'number', 'pagination.training', 'Trainings per page'),
|
||||
Setting('setting_basic', 'pagination.reply', 50, 'number', 'pagination.reply', 'Replies per page'),
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { KoaContext } from '@hydrooj/framework';
|
||||
import { KoaContext, NotFoundError } from '@hydrooj/framework';
|
||||
import BlackListModel from '../../model/blacklist';
|
||||
import DomainModel from '../../model/domain';
|
||||
import * as system from '../../model/system';
|
||||
@@ -24,5 +24,12 @@ export default async (ctx: KoaContext, next) => {
|
||||
ctx.domainId = inferDomain?._id || domainId;
|
||||
ctx.domainInfo = inferDomain || absoluteDomain;
|
||||
if (ctx.domainInfo && ctx.domainId !== ctx.domainInfo._id) ctx.redirect(ctx.originalPath.replace(/^\/d\/[^/]+\//, `/d/${ctx.domainInfo._id}/`));
|
||||
else await next();
|
||||
else {
|
||||
if (!ctx.domainInfo) {
|
||||
ctx.pendingError = new NotFoundError(ctx.domainId);
|
||||
ctx.domainId = 'system';
|
||||
ctx.domainInfo = await DomainModel.get('system');
|
||||
}
|
||||
await next();
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { KoaContext } from '@hydrooj/framework';
|
||||
import { NotFoundError } from '../../error';
|
||||
import { PERM } from '../../model/builtin';
|
||||
import UserModel from '../../model/user';
|
||||
|
||||
@@ -15,9 +14,5 @@ export default async (ctx: KoaContext, next) => {
|
||||
}
|
||||
if (user._id === 0) delete user.viewLang;
|
||||
ctx.HydroContext.user = await user.private();
|
||||
if (!domain) {
|
||||
ctx.pendingError = new NotFoundError(args.domainId);
|
||||
args.domainId = 'system';
|
||||
}
|
||||
await next();
|
||||
};
|
||||
@@ -276,6 +276,7 @@ export async function apply(ctx: Context) {
|
||||
text: global.Hydro.module.oauth[key].text,
|
||||
}));
|
||||
if (!h.noCheckPermView && !h.user.hasPriv(PRIV.PRIV_VIEW_ALL_DOMAIN)) h.checkPerm(PERM.PERM_VIEW);
|
||||
if (h.context.pendingError) throw h.context.pendingError;
|
||||
});
|
||||
|
||||
on('app/listen', () => {
|
||||
|
||||
@@ -89,6 +89,7 @@ export default function (env: { watch?: boolean, production?: boolean, measure?:
|
||||
output: {
|
||||
path: root('public'),
|
||||
publicPath: '/', // overwrite in entry.js
|
||||
workerPublicPath: '/',
|
||||
hashFunction: 'sha1',
|
||||
hashDigest: 'hex',
|
||||
hashDigestLength: 10,
|
||||
|
||||
@@ -49,7 +49,10 @@ async function runWebpack({
|
||||
return;
|
||||
}
|
||||
if (argv.options.detail) console.log(stats.toString());
|
||||
if (!watch && (!stats || stats.hasErrors())) process.exitCode = 1;
|
||||
if (!watch && (!stats || stats.hasErrors())) {
|
||||
if (!argv.options.detail) console.log(stats.toString());
|
||||
process.exitCode = 1;
|
||||
}
|
||||
resolve(stats);
|
||||
}
|
||||
if (watch) compiler.watch({}, compilerCallback);
|
||||
|
||||
@@ -24,9 +24,8 @@ const Component = React.forwardRef<any, any>((props, ref) => {
|
||||
);
|
||||
});
|
||||
|
||||
export default class CustomSelectAutoComplete<Multi extends boolean> extends AutoComplete {
|
||||
export default class CustomSelectAutoComplete<Multi extends boolean> extends AutoComplete<CustomSelectOptions> {
|
||||
static DOMAttachKey = 'ucwCustomSelectAutoCompleteInstance';
|
||||
options: CustomSelectOptions & AutoCompleteOptions;
|
||||
|
||||
constructor($dom, options: CustomSelectOptions & AutoCompleteOptions<Multi>) {
|
||||
super($dom, {
|
||||
|
||||
@@ -27,9 +27,8 @@ const Component = React.forwardRef<any, any>((props, ref) => {
|
||||
);
|
||||
});
|
||||
|
||||
export default class FileSelectAutoComplete<Multi extends boolean> extends AutoComplete {
|
||||
export default class FileSelectAutoComplete<Multi extends boolean> extends AutoComplete<FileSelectOptions> {
|
||||
static DOMAttachKey = 'ucwFileSelectAutoCompleteInstance';
|
||||
options: FileSelectOptions & AutoCompleteOptions;
|
||||
|
||||
constructor($dom, options: FileSelectOptions & AutoCompleteOptions<Multi>) {
|
||||
super($dom, {
|
||||
|
||||
@@ -8,6 +8,7 @@ export interface AutoCompleteOptions<Multi extends boolean = boolean> {
|
||||
defaultItems?: string;
|
||||
width?: string;
|
||||
height?: string;
|
||||
classes?: string;
|
||||
listStyle?: any;
|
||||
allowEmptyQuery?: boolean;
|
||||
freeSolo?: boolean;
|
||||
@@ -18,17 +19,17 @@ export interface AutoCompleteOptions<Multi extends boolean = boolean> {
|
||||
text?: () => string;
|
||||
}
|
||||
|
||||
export default class AutoComplete extends DOMAttachedObject {
|
||||
export default class AutoComplete<Options extends Record<string, any> = {}> extends DOMAttachedObject {
|
||||
static DOMAttachKey = 'ucwAutoCompleteInstance';
|
||||
ref = null;
|
||||
container = document.createElement('div');
|
||||
options: AutoCompleteOptions;
|
||||
options: AutoCompleteOptions & Options;
|
||||
component = ReactDOM.createRoot(this.container);
|
||||
changeListener = [
|
||||
(val) => this.$dom.val(val),
|
||||
];
|
||||
|
||||
constructor($dom, options = {}) {
|
||||
constructor($dom, options = {} as Options) {
|
||||
super($dom);
|
||||
this.options = {
|
||||
items: async () => [],
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { nanoid } from 'nanoid';
|
||||
import ReconnectingWebsocket from 'reconnecting-websocket';
|
||||
import { InfoDialog } from 'vj/components/dialog';
|
||||
import VjNotification from 'vj/components/notification/index';
|
||||
import {
|
||||
@@ -7,6 +6,7 @@ import {
|
||||
} from 'vj/constant/message';
|
||||
import { AutoloadPage } from 'vj/misc/Page';
|
||||
import { i18n, tpl } from 'vj/utils';
|
||||
import Sock from '../socket';
|
||||
|
||||
let previous: VjNotification;
|
||||
const onmessage = (msg) => {
|
||||
@@ -128,12 +128,8 @@ const messagePage = new AutoloadPage('messagePage', (pagename) => {
|
||||
isMaster = true;
|
||||
localStorage.setItem('page.master', selfId);
|
||||
const masterChannel = new BroadcastChannel('hydro-messages');
|
||||
const sock = new ReconnectingWebsocket(endpoint);
|
||||
sock.onopen = () => console.log('Connected');
|
||||
sock.onerror = console.error;
|
||||
sock.onclose = (...args) => console.log('Closed', ...args);
|
||||
const sock = new Sock(endpoint);
|
||||
sock.onmessage = async (message) => {
|
||||
if (process.env.NODE_ENV !== 'production') console.log('onmessage: ', message);
|
||||
const payload = JSON.parse(message.data);
|
||||
masterChannel.postMessage({ type: 'message', payload });
|
||||
};
|
||||
|
||||
@@ -31,7 +31,7 @@ window.UserContext = JSON.parse(window.UserContext);
|
||||
if (process.env.NODE_ENV === 'production' && !UiContext.sentry_disable) {
|
||||
window.captureException = (e) => Sentry.captureException(e);
|
||||
Sentry.init({
|
||||
dsn: UiContext.sentry_dsn || 'https://04d1d77b095231d55e1202bdc912ff16@sentry.hydro.ac/3',
|
||||
dsn: UiContext.sentry_dsn || 'https://2f95d53751e08c74c1af1c4b93ccaff7@sentry.hydro.ac/2',
|
||||
release: process.env.VERSION,
|
||||
integrations: [
|
||||
Sentry.browserTracingIntegration(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@hydrooj/ui-default",
|
||||
"version": "4.51.0",
|
||||
"version": "4.51.1",
|
||||
"author": "undefined <i@undefined.moe>",
|
||||
"license": "AGPL-3.0",
|
||||
"main": "index.ts",
|
||||
@@ -51,6 +51,7 @@
|
||||
"clean-webpack-plugin": "^4.0.0",
|
||||
"clipboard": "^2.0.11",
|
||||
"copy-webpack-plugin": "^12.0.2",
|
||||
"core-js": "^3.37.1",
|
||||
"css-loader": "^6.11.0",
|
||||
"diff": "^5.2.0",
|
||||
"diff-dom": "^5.1.3",
|
||||
@@ -90,7 +91,6 @@
|
||||
"prop-types": "^15.8.1",
|
||||
"qface": "^1.4.1",
|
||||
"qrcode": "^1.5.3",
|
||||
"queue-microtask": "^1.2.3",
|
||||
"react": "^18.3.1",
|
||||
"react-colorful": "^5.6.1",
|
||||
"react-dnd": "^16.0.1",
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import 'matchmedia-polyfill';
|
||||
import 'core-js/stable';
|
||||
|
||||
import browserUpdate from 'browser-update';
|
||||
import queueMicrotask from 'queue-microtask';
|
||||
|
||||
window.queueMicrotask = queueMicrotask;
|
||||
browserUpdate({
|
||||
required: {
|
||||
e: -10, f: -10, o: -3, s: -1, c: -10,
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
var _htmlNode = document.documentElement;
|
||||
_htmlNode.className = _htmlNode.className.replace(' nojs', ' hasjs');
|
||||
try {
|
||||
import('data:text/javascript,');Object.fromEntries([]);window.matchMedia('all').addEventListener('change',()=>{});
|
||||
import('data:text/javascript,');Object.fromEntries([]);window.matchMedia('all').addEventListener('change',()=>{});Array.prototype.at(0);
|
||||
} catch(e) {
|
||||
const s = document.createElement('script');
|
||||
s.async = false;
|
||||
|
||||
@@ -34,8 +34,8 @@ export function secureRandomString(digit = 32, dict = defaultDict) {
|
||||
|
||||
type Substitution = string | number | { templateRaw: true, html: string };
|
||||
|
||||
export function tpl(node: React.ReactNode, reactive?: boolean);
|
||||
export function tpl(pieces: TemplateStringsArray, ...substitutions: Substitution[]);
|
||||
export function tpl<T extends boolean>(node: React.ReactNode, reactive?: T): T extends true ? React.ReactElement : string;
|
||||
export function tpl(pieces: TemplateStringsArray, ...substitutions: Substitution[]): string;
|
||||
export function tpl(pieces: TemplateStringsArray | React.ReactNode, ...substitutions: Substitution[] | boolean[]) {
|
||||
if (React.isValidElement(pieces)) {
|
||||
if (substitutions[0]) {
|
||||
@@ -49,7 +49,7 @@ export function tpl(pieces: TemplateStringsArray | React.ReactNode, ...substitut
|
||||
for (let i = 0; i < substitutions.length; ++i) {
|
||||
const subst = substitutions[i];
|
||||
let substHtml: string;
|
||||
if (typeof subst === 'object' && subst.templateRaw) {
|
||||
if (subst && typeof subst === 'object' && subst.templateRaw) {
|
||||
substHtml = subst.html;
|
||||
} else substHtml = _.escape(String(subst));
|
||||
result += substHtml + pieces[i + 1];
|
||||
|
||||
Reference in new issue
Block a user