mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 01:38:19 +08:00
比赛举办者可给用户推送通知
This commit is contained in:
1 parent
0f1f5f26e1
commit
bfc2e95ef5
5 files changed
+48
-11
No files matched your search
@@ -2,7 +2,6 @@
|
|||||||
discussion前端权限节点显示异常?
|
discussion前端权限节点显示异常?
|
||||||
web端运行脚本异常?
|
web端运行脚本异常?
|
||||||
讨论回复通知
|
讨论回复通知
|
||||||
比赛举办者发布通知
|
|
||||||
举报功能
|
举报功能
|
||||||
SETTINGS_PRIVACY.allowRegisteredUsers
|
SETTINGS_PRIVACY.allowRegisteredUsers
|
||||||
model.setting.ui.name
|
model.setting.ui.name
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import AdmZip from 'adm-zip';
|
|||||||
import { isSafeInteger } from 'lodash';
|
import { isSafeInteger } from 'lodash';
|
||||||
import {
|
import {
|
||||||
ContestNotLiveError, ValidationError, ProblemNotFoundError,
|
ContestNotLiveError, ValidationError, ProblemNotFoundError,
|
||||||
ContestNotAttendedError,
|
ContestNotAttendedError, PermissionError,
|
||||||
} from '../error';
|
} from '../error';
|
||||||
import { isContent, isTitle } from '../lib/validator';
|
import { isContent, isTitle } from '../lib/validator';
|
||||||
import paginate from '../lib/paginate';
|
import paginate from '../lib/paginate';
|
||||||
@@ -14,6 +14,7 @@ import * as document from '../model/document';
|
|||||||
import * as problem from '../model/problem';
|
import * as problem from '../model/problem';
|
||||||
import * as record from '../model/record';
|
import * as record from '../model/record';
|
||||||
import * as user from '../model/user';
|
import * as user from '../model/user';
|
||||||
|
import * as message from '../model/message';
|
||||||
import * as system from '../model/system';
|
import * as system from '../model/system';
|
||||||
import {
|
import {
|
||||||
Route, Handler, Types, param,
|
Route, Handler, Types, param,
|
||||||
@@ -65,7 +66,7 @@ class ContestDetailHandler extends ContestHandler {
|
|||||||
]);
|
]);
|
||||||
const psdict = {};
|
const psdict = {};
|
||||||
let rdict = {};
|
let rdict = {};
|
||||||
let attended;
|
let attended: boolean;
|
||||||
if (tsdoc) {
|
if (tsdoc) {
|
||||||
attended = tsdoc.attend === 1;
|
attended = tsdoc.attend === 1;
|
||||||
for (const pdetail of tsdoc.journal || []) psdict[pdetail.pid] = pdetail;
|
for (const pdetail of tsdoc.journal || []) psdict[pdetail.pid] = pdetail;
|
||||||
@@ -97,6 +98,35 @@ class ContestDetailHandler extends ContestHandler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ContestBoardcastHandler extends ContestHandler {
|
||||||
|
@param('tid', Types.ObjectID)
|
||||||
|
async get(domainId: string, tid: ObjectID) {
|
||||||
|
const tdoc = await contest.get(domainId, tid);
|
||||||
|
if (tdoc.owner !== this.user._id) throw new PermissionError('Boardcast Message');
|
||||||
|
const path = [
|
||||||
|
['Hydro', 'homepage'],
|
||||||
|
['contest_main', 'contest_main'],
|
||||||
|
[tdoc.title, 'contest_detail', { tid }, true],
|
||||||
|
['contest_boardcast'],
|
||||||
|
];
|
||||||
|
this.response.template = 'contest_boardcast.html';
|
||||||
|
this.response.body = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
@param('tid', Types.ObjectID)
|
||||||
|
@param('content', Types.String, isContent)
|
||||||
|
async post(domainId: string, tid: ObjectID, content: string) {
|
||||||
|
const tdoc = await contest.get(domainId, tid);
|
||||||
|
if (tdoc.owner !== this.user._id) throw new PermissionError('Boardcast Message');
|
||||||
|
const tsdocs = await contest.getMultiStatus(domainId, { docId: tid }).toArray();
|
||||||
|
const uids = Array.from(new Set(tsdocs.map((tsdoc) => tsdoc.uid)));
|
||||||
|
await Promise.all(
|
||||||
|
uids.map((uid) => message.send(this.user._id, uid, content, message.FLAG_ALERT)),
|
||||||
|
);
|
||||||
|
this.response.redirect = this.url('contest_detail', { tid });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ContestScoreboardHandler extends ContestHandler {
|
class ContestScoreboardHandler extends ContestHandler {
|
||||||
@param('tid', Types.ObjectID)
|
@param('tid', Types.ObjectID)
|
||||||
async get(domainId: string, tid: ObjectID) {
|
async get(domainId: string, tid: ObjectID) {
|
||||||
@@ -383,6 +413,7 @@ export async function apply() {
|
|||||||
Route('contest_create', '/contest/create', ContestCreateHandler, PERM.PERM_CREATE_CONTEST);
|
Route('contest_create', '/contest/create', ContestCreateHandler, PERM.PERM_CREATE_CONTEST);
|
||||||
Route('contest_main', '/contest', ContestListHandler, PERM.PERM_VIEW_CONTEST);
|
Route('contest_main', '/contest', ContestListHandler, PERM.PERM_VIEW_CONTEST);
|
||||||
Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM.PERM_VIEW_CONTEST);
|
Route('contest_detail', '/contest/:tid', ContestDetailHandler, PERM.PERM_VIEW_CONTEST);
|
||||||
|
Route('contest_boardcast', '/contest/:tid/boardcast', ContestBoardcastHandler);
|
||||||
Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM.PERM_VIEW_CONTEST);
|
Route('contest_edit', '/contest/:tid/edit', ContestEditHandler, PERM.PERM_VIEW_CONTEST);
|
||||||
Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST);
|
Route('contest_scoreboard', '/contest/:tid/scoreboard', ContestScoreboardHandler, PERM.PERM_VIEW_CONTEST);
|
||||||
Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardDownloadHandler, PERM.PERM_VIEW_CONTEST);
|
Route('contest_scoreboard_download', '/contest/:tid/export/:ext', ContestScoreboardDownloadHandler, PERM.PERM_VIEW_CONTEST);
|
||||||
|
|||||||
@@ -321,10 +321,7 @@ class HomeMessagesHandler extends Handler {
|
|||||||
if (!udoc) throw new UserNotFoundError(uid);
|
if (!udoc) throw new UserNotFoundError(uid);
|
||||||
if (udoc.gravatar) udoc.gravatar = misc.gravatar(udoc.gravatar);
|
if (udoc.gravatar) udoc.gravatar = misc.gravatar(udoc.gravatar);
|
||||||
const mdoc = await message.send(this.user._id, uid, content, message.FLAG_UNREAD);
|
const mdoc = await message.send(this.user._id, uid, content, message.FLAG_UNREAD);
|
||||||
// TODO(twd2): improve here: projection
|
// TODO(twd2): improve here: projection\
|
||||||
if (this.user._id !== uid) {
|
|
||||||
bus.publish(`user_message-${uid}`, { mdoc, udoc });
|
|
||||||
}
|
|
||||||
this.back({ mdoc, udoc });
|
this.back({ mdoc, udoc });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
import { ObjectID } from 'mongodb';
|
import { ObjectID } from 'mongodb';
|
||||||
|
import * as user from './user';
|
||||||
import { Mdoc } from '../interface';
|
import { Mdoc } from '../interface';
|
||||||
import * as db from '../service/db';
|
import * as db from '../service/db';
|
||||||
|
import * as bus from '../service/bus';
|
||||||
|
|
||||||
const coll = db.collection('message');
|
const coll = db.collection('message');
|
||||||
|
|
||||||
@@ -14,9 +16,15 @@ export async function send(
|
|||||||
const res = await coll.insertOne({
|
const res = await coll.insertOne({
|
||||||
from, to, content, flag,
|
from, to, content, flag,
|
||||||
});
|
});
|
||||||
return {
|
const mdoc = {
|
||||||
from, to, content, _id: res.insertedId, flag,
|
from, to, content, _id: res.insertedId, flag,
|
||||||
};
|
};
|
||||||
|
if (from !== to) {
|
||||||
|
// ENHANCE domainId?
|
||||||
|
const udoc = await user.getById('system', to);
|
||||||
|
bus.publish(`user_message-${to}`, { mdoc, udoc });
|
||||||
|
}
|
||||||
|
return mdoc;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get(_id: ObjectID): Promise<Mdoc> {
|
export async function get(_id: ObjectID): Promise<Mdoc> {
|
||||||
|
|||||||
@@ -59,7 +59,8 @@ const Tools: Array<[Converter, Validator, boolean?]> = [
|
|||||||
[(v) => parseInt(v, 10), (v) => parseInt(v, 10) > 0],
|
[(v) => parseInt(v, 10), (v) => parseInt(v, 10) > 0],
|
||||||
[(v) => parseFloat(v), (v) => {
|
[(v) => parseFloat(v), (v) => {
|
||||||
const t = parseFloat(v);
|
const t = parseFloat(v);
|
||||||
return t && !Number.isNaN(t) && !Number.isFinite(t);
|
console.log(t);
|
||||||
|
return t && !Number.isNaN(t) && Number.isFinite(t);
|
||||||
}],
|
}],
|
||||||
[(v) => new ObjectID(v), ObjectID.isValid],
|
[(v) => new ObjectID(v), ObjectID.isValid],
|
||||||
[(v) => !!v, null, true],
|
[(v) => !!v, null, true],
|
||||||
@@ -72,7 +73,8 @@ const Tools: Array<[Converter, Validator, boolean?]> = [
|
|||||||
(v) => {
|
(v) => {
|
||||||
const d = v.split('-');
|
const d = v.split('-');
|
||||||
assert(d.length === 3);
|
assert(d.length === 3);
|
||||||
return moment(`${d[0]}-${d[1].length === 1 ? '0' : ''}${d[1]}-${d[2].length === 1 ? '0' : ''}${d[2]}`).isValid();
|
const st = `${d[0]}-${d[1].length === 1 ? '0' : ''}${d[1]}-${d[2].length === 1 ? '0' : ''}${d[2]}`;
|
||||||
|
return moment(st).isValid();
|
||||||
}],
|
}],
|
||||||
[
|
[
|
||||||
(v) => {
|
(v) => {
|
||||||
@@ -83,7 +85,7 @@ const Tools: Array<[Converter, Validator, boolean?]> = [
|
|||||||
(v) => {
|
(v) => {
|
||||||
const t = v.split(':');
|
const t = v.split(':');
|
||||||
assert(t.length === 2);
|
assert(t.length === 2);
|
||||||
return moment(`${(t[0].length === 1 ? '0' : '') + t[0]}:${t[1].length === 1 ? '0' : ''}${t[1]}`).isValid();
|
return moment(`2020-01-01 ${(t[0].length === 1 ? '0' : '') + t[0]}:${t[1].length === 1 ? '0' : ''}${t[1]}`).isValid();
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in new issue
Block a user