diff --git a/packages/hydrooj/src/handler/problem.ts b/packages/hydrooj/src/handler/problem.ts index 9ab72c2475..5713f06fbd 100644 --- a/packages/hydrooj/src/handler/problem.ts +++ b/packages/hydrooj/src/handler/problem.ts @@ -753,6 +753,7 @@ export class ProblemEditHandler extends ProblemManageHandler { @post('hidden', Types.Boolean) @post('tag', Types.Content, true, null, parseCategory) @post('difficulty', Types.PositiveInt, (i) => +i <= 10, true) + @param('index', Types.PositiveInt, true) async post( domainId: string, pid: string | number, @@ -762,6 +763,7 @@ export class ProblemEditHandler extends ProblemManageHandler { hidden = false, tag: string[] = [], difficulty = 0, + index = 0, ) { if (typeof newPid !== 'string') newPid = `P${newPid}`; if (newPid !== this.pdoc.pid && (await problem.get(domainId, newPid))) throw new ProblemAlreadyExistError(pid); @@ -773,6 +775,7 @@ export class ProblemEditHandler extends ProblemManageHandler { tag: tag ?? [], difficulty, html: false, + index, }; const pdoc = await problem.edit(domainId, this.pdoc.docId, $update); this.response.redirect = this.url('problem_detail', { pid: newPid || pdoc.docId }); @@ -1121,10 +1124,20 @@ export class ProblemCreateHandler extends Handler { @post('hidden', Types.Boolean) @post('difficulty', Types.PositiveInt, (i) => +i <= 10, true) @post('tag', Types.Content, true, null, parseCategory) - async post(domainId: string, title: string, content: string, pid: string | number = '', hidden = false, difficulty = 0, tag: string[] = []) { + @post('index', Types.PositiveInt, true) + async post( + domainId: string, + title: string, + content: string, + pid: string | number = '', + hidden = false, + difficulty = 0, + tag: string[] = [], + index = 0, + ) { if (typeof pid !== 'string') pid = `P${pid}`; if (pid && (await problem.get(domainId, pid))) throw new ProblemAlreadyExistError(pid); - const docId = await problem.add(domainId, pid, title, content, this.user._id, tag ?? [], { hidden, difficulty }); + const docId = await problem.add(domainId, pid, title, content, this.user._id, tag ?? [], { hidden, difficulty, index }); const files = new Set(Array.from(content.matchAll(/file:\/\/([a-zA-Z0-9_-]+\.[a-zA-Z0-9]+)/g)).map((i) => i[1])); const tasks = []; for (const file of files) { diff --git a/packages/hydrooj/src/interface.ts b/packages/hydrooj/src/interface.ts index 7d1f5725b7..c89f880312 100644 --- a/packages/hydrooj/src/interface.ts +++ b/packages/hydrooj/src/interface.ts @@ -296,6 +296,8 @@ declare module './model/problem' { /** string (errormsg) */ config: string | ProblemConfig; + + index?: number; } } export type { ProblemDoc } from './model/problem'; diff --git a/packages/hydrooj/src/model/problem.ts b/packages/hydrooj/src/model/problem.ts index ec5826ff62..cf715ab0b9 100644 --- a/packages/hydrooj/src/model/problem.ts +++ b/packages/hydrooj/src/model/problem.ts @@ -25,6 +25,12 @@ export interface ProblemDoc extends Document {} export type Field = keyof ProblemDoc; +export type ProblemMeta = { + difficulty?: number; + hidden?: boolean; + index?: number; +}; + const logger = new Logger('problem'); function sortable(source: string) { @@ -117,18 +123,9 @@ export class ProblemModel { difficulty: 0, }; - static async add( - domainId: string, - pid: string = '', - title: string, - content: string, - owner: number, - tag: string[] = [], - meta: { difficulty?: number; hidden?: boolean } = {}, - ) { + static async add(domainId: string, pid: string = '', title: string, content: string, owner: number, tag: string[] = [], meta: ProblemMeta = {}) { const [doc] = await ProblemModel.getMulti(domainId, {}).sort({ docId: -1 }).limit(1).project({ docId: 1 }).toArray(); - const result = await ProblemModel.addWithId(domainId, (doc?.docId || 0) + 1, pid, title, content, owner, tag, meta); - return result; + return await ProblemModel.addWithId(domainId, (doc?.docId || 0) + 1, pid, title, content, owner, tag, meta); } static async addWithId( @@ -139,7 +136,7 @@ export class ProblemModel { content: string, owner: number, tag: string[] = [], - meta: { difficulty?: number; hidden?: boolean } = {}, + meta: ProblemMeta = {}, ) { const args: Partial = { title, @@ -151,6 +148,7 @@ export class ProblemModel { }; if (pid) args.pid = pid; if (meta.difficulty) args.difficulty = meta.difficulty; + if (meta.index) args.index = meta.index; await bus.parallel('problem/before-add', domainId, content, owner, docId, args); const result = await document.add(domainId, content, owner, document.TYPE_PROBLEM, docId, null, null, args); args.content = content; @@ -182,7 +180,7 @@ export class ProblemModel { } static getMulti(domainId: string, query: Filter, projection = ProblemModel.PROJECTION_LIST) { - return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection).sort({ sort: 1 }); + return document.getMulti(domainId, document.TYPE_PROBLEM, query, projection).sort({ index: -1, sort: 1 }); } static async list( @@ -206,7 +204,14 @@ export class ProblemModel { } if (filter) { // 当filter存在时做全文查询 - let docs = await document.getMulti(id, document.TYPE_PROBLEM, query, projection).sort({ sort: 1, docId: 1 }).toArray(); + let docs = await document + .getMulti(id, document.TYPE_PROBLEM, query, projection) + .sort({ + index: -1, + sort: 1, + docId: 1, + }) + .toArray(); docs = docs.filter(filter); count += docs.length; // 查询到所有文档的数量 if (pdocs.length >= pageSize) continue; @@ -221,7 +226,7 @@ export class ProblemModel { pdocs.push( ...(await document .getMulti(id, document.TYPE_PROBLEM, query, projection) - .sort({ sort: 1, docId: 1 }) + .sort({ index: -1, sort: 1, docId: 1 }) .skip(Math.max((page - 1) * pageSize - count, 0)) .limit(pageSize - pdocs.length) .toArray()),