mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-19 17:38:19 +08:00
Merge branch 'master' into events
This commit is contained in:
20 files changed
+150
-39
No files matched your search
@@ -434,7 +434,7 @@ export const DomainApi = {
|
||||
}),
|
||||
async (ctx, args) => {
|
||||
if (!ctx.user.hasPerm(PERM.PERM_EDIT_DOMAIN)) throw new PermissionError(PERM.PERM_EDIT_DOMAIN);
|
||||
if (args.uids) {
|
||||
if (args.uids?.length) {
|
||||
const res = await user.updateGroup(ctx.domain._id, args.name, args.uids);
|
||||
return res.upsertedCount > 0;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
const versionNum = +process.version.replace(/v/gim, '').split('.')[0];
|
||||
if (versionNum < 18) throw new Error('NodeJS >=18 required');
|
||||
if (versionNum < 22) throw new Error('NodeJS >=22 required');
|
||||
|
||||
console.log('Process', process.pid, 'running as', process.env.NODE_APP_INSTANCE === '0' ? 'master' : 'worker');
|
||||
if (!global.Hydro) {
|
||||
|
||||
@@ -104,9 +104,9 @@ export async function set<K extends keyof DocType>(
|
||||
): Promise<DocType[K]> {
|
||||
await bus.parallel('document/set', domainId, docType, docId, $set, $unset);
|
||||
const update: UpdateFilter<DocType[K]> = {};
|
||||
if ($set) update.$set = $set;
|
||||
if ($unset) update.$unset = $unset;
|
||||
if ($push) update.$push = $push;
|
||||
if ($set && Object.keys($set).length) update.$set = $set;
|
||||
if ($unset && Object.keys($unset).length) update.$unset = $unset;
|
||||
if ($push && Object.keys($push).length) update.$push = $push;
|
||||
return await coll.findOneAndUpdate(
|
||||
{ domainId, docType, docId },
|
||||
update,
|
||||
@@ -317,14 +317,14 @@ export async function setMultiStatus<K extends keyof DocStatusType>(
|
||||
);
|
||||
}
|
||||
|
||||
export async function setStatusIfNotCondition<T extends keyof DocStatusType>(
|
||||
export async function setStatusIfCondition<T extends keyof DocStatusType>(
|
||||
domainId: string, docType: T, docId: DocStatusType[T]['docId'], uid: number,
|
||||
filter: Filter<DocStatusType[T]>, args: Partial<DocStatusType[T]> = {},
|
||||
returnDocument: 'before' | 'after' = 'after',
|
||||
): Promise<DocStatusType[T]> {
|
||||
try {
|
||||
return await collStatus.findOneAndUpdate(
|
||||
{ domainId, docType, docId, uid, $nor: [filter] },
|
||||
{ domainId, docType, docId, uid, ...filter },
|
||||
{ $set: args },
|
||||
{ upsert: true, returnDocument },
|
||||
);
|
||||
@@ -338,8 +338,8 @@ export async function setIfNotStatus<T extends keyof DocStatusType, K extends ke
|
||||
key: K, value: DocStatusType[T][K], ifNot: DocStatusType[T][K], args: Partial<DocStatusType[T]>,
|
||||
returnDocument: 'before' | 'after' = 'after',
|
||||
): Promise<DocStatusType[T]> {
|
||||
return await setStatusIfNotCondition(
|
||||
domainId, docType, docId, uid, { [key]: ifNot } as any,
|
||||
return await setStatusIfCondition(
|
||||
domainId, docType, docId, uid, { [key]: { $ne: ifNot } } as any,
|
||||
{ [key]: value, ...args }, returnDocument,
|
||||
);
|
||||
}
|
||||
@@ -474,7 +474,7 @@ global.Hydro.model.document = {
|
||||
revSetStatus,
|
||||
set,
|
||||
setIfNotStatus,
|
||||
setStatusIfNotCondition,
|
||||
setStatusIfCondition,
|
||||
setStatus,
|
||||
setMultiStatus,
|
||||
setSub,
|
||||
|
||||
@@ -231,14 +231,15 @@ export class ProblemModel {
|
||||
static async edit(domainId: string, _id: number, $set: Partial<ProblemDoc>): Promise<ProblemDoc> {
|
||||
const delpid = $set.pid === '';
|
||||
const ddoc = await DomainModel.get(domainId);
|
||||
const $unset = delpid ? { pid: '' } : {};
|
||||
if (delpid) {
|
||||
delete $set.pid;
|
||||
$set.sort = sortable(`P${_id}`, ddoc.namespaces);
|
||||
} else if ($set.pid) {
|
||||
$set.sort = sortable($set.pid, ddoc.namespaces);
|
||||
}
|
||||
await bus.parallel('problem/before-edit', $set);
|
||||
const result = await document.set(domainId, document.TYPE_PROBLEM, _id, $set, delpid ? { pid: '' } : undefined);
|
||||
await bus.parallel('problem/before-edit', $set, $unset);
|
||||
const result = await document.set(domainId, document.TYPE_PROBLEM, _id, $set, $unset);
|
||||
await bus.emit('problem/edit', result);
|
||||
return result;
|
||||
}
|
||||
@@ -419,10 +420,10 @@ export class ProblemModel {
|
||||
domainId: string, pid: number, uid: number,
|
||||
rid: ObjectId, status: number, score: number,
|
||||
) {
|
||||
const filter: Filter<ProblemStatusDoc> = { rid: { $ne: rid }, status: STATUS.STATUS_ACCEPTED };
|
||||
const res = await document.setStatusIfNotCondition(
|
||||
const condition = status === STATUS.STATUS_ACCEPTED ? {} : { status: { $ne: STATUS.STATUS_ACCEPTED } };
|
||||
const res = await document.setStatusIfCondition(
|
||||
domainId, document.TYPE_PROBLEM, pid, uid,
|
||||
filter, { rid, status, score },
|
||||
condition, { rid, status, score },
|
||||
);
|
||||
return !!res;
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { ArgMethod, buildProjection, Time } from '../utils';
|
||||
import { STATUS } from './builtin';
|
||||
import DomainModel from './domain';
|
||||
import problem from './problem';
|
||||
import * as SystemModel from './system';
|
||||
import task from './task';
|
||||
|
||||
export default class RecordModel {
|
||||
@@ -291,6 +292,14 @@ export async function apply(ctx: Context) {
|
||||
ctx.on('domain/delete', (domainId) => RecordModel.coll.deleteMany({ domainId }));
|
||||
ctx.on('record/judge', async (rdoc, updated) => {
|
||||
if (rdoc.status === STATUS.STATUS_ACCEPTED && updated) {
|
||||
if (SystemModel.get('record.statMode') === 'unique') {
|
||||
await RecordModel.collStat.deleteMany({
|
||||
_id: { $ne: rdoc._id },
|
||||
uid: rdoc.uid,
|
||||
pid: rdoc.pid,
|
||||
domainId: rdoc.domainId,
|
||||
});
|
||||
}
|
||||
await RecordModel.collStat.updateOne({
|
||||
_id: rdoc._id,
|
||||
}, {
|
||||
|
||||
@@ -334,6 +334,7 @@ SystemSetting(
|
||||
Setting('setting_basic', 'discussion.nodes', builtin.DEFAULT_NODES, 'yaml', 'discussion.nodes', 'Discussion Nodes'),
|
||||
Setting('setting_basic', 'problem.categories', builtin.CATEGORIES, 'yaml', 'problem.categories', 'Problem Categories'),
|
||||
Setting('setting_basic', 'training.enrolled-users', true, 'boolean', 'training.enrolled-users', 'Show enrolled users for training'),
|
||||
Setting('setting_basic', 'record.statMode', 'unique', 'text', 'record.statMode', 'Record stat mode'),
|
||||
Setting('setting_basic', 'pagination.problem', 100, 'number', 'pagination.problem', 'Problems per page'),
|
||||
Setting('setting_basic', 'pagination.contest', 20, 'number', 'pagination.contest', 'Contests per page'),
|
||||
Setting('setting_basic', 'pagination.discussion', 50, 'number', 'pagination.discussion', 'Discussions per page'),
|
||||
|
||||
@@ -66,7 +66,7 @@ export interface EventMap {
|
||||
|
||||
'problem/before-add': (domainId: string, content: string, owner: number, docId: number, doc: Partial<ProblemDoc>) => VoidReturn
|
||||
'problem/add': (doc: Partial<ProblemDoc>, docId: number) => VoidReturn
|
||||
'problem/before-edit': (doc: Partial<ProblemDoc>) => VoidReturn
|
||||
'problem/before-edit': (doc: Partial<ProblemDoc>, $unset: OnlyFieldsOfType<ProblemDoc, any, true | '' | 1>) => VoidReturn
|
||||
'problem/edit': (doc: ProblemDoc) => VoidReturn
|
||||
'problem/before-del': (domainId: string, docId: number) => VoidReturn
|
||||
'problem/del': (domainId: string, docId: number) => VoidReturn
|
||||
|
||||
Reference in new issue
Block a user