题解点赞功能

pull/1/head
masnn 5 years ago
parent 41261f8c4b
commit 4c2edc3948

@ -25,6 +25,13 @@ class NotFoundError extends UserFacingError {
}
}
class AlreadyVotedError extends BadRequestError {
constructor(psid, uid) {
super('You\'ve already voted.');
this.params = [psid, uid];
}
}
class LoginError extends ForbiddenError {
constructor(uname) {
super('LoginError');
@ -122,7 +129,8 @@ module.exports = {
UserNotFoundError, VerifyPasswordError, ProblemDataNotFoundError,
OpcountExceededError, PermissionError, NoProblemError,
ValidationError, ProblemNotFoundError, TrainingNotFoundError,
ContestNotFoundError, RecordNotFoundError, SolutionNotFoundError
ContestNotFoundError, RecordNotFoundError, SolutionNotFoundError,
AlreadyVotedError
};
/*
@ -199,11 +207,6 @@ class InvalidOperationError(ForbiddenError):
pass
class AlreadyVotedError(ForbiddenError):
@property
def message(self):
return "You've already voted."
class InvalidTokenDigestError(ForbiddenError):
pass

@ -10,7 +10,8 @@ const
{ ROUTE } = require('../service/server'),
gridfs = require('../service/gridfs'),
queue = require('../service/queue'),
{ NoProblemError, ProblemDataNotFoundError, BadRequestError } = require('../error'),
{ NoProblemError, ProblemDataNotFoundError, BadRequestError,
SolutionNotFoundError } = require('../error'),
{ constants } = require('../options'),
{
PERM_VIEW_PROBLEM,
@ -242,13 +243,14 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
}
}
let udict = await user.getList(uids);
let pssdict = solution.getListStatus(docids, this.uid);
this.ctx.body.path = [
['problem_main', '/p'],
[this.pdoc.title, `/p/${this.pdoc.pid}`, true],
['problem_solution', null]
];
this.ctx.body = Object.assign(this.ctx.body, {
psdocs, page, pcount, pscount, udict
psdocs, page, pcount, pscount, udict, pssdict
});
}
async post({ psid }) {
@ -289,6 +291,16 @@ class ProblemSolutionHandler extends ProblemDetailHandler {
await solution.delReply(psid, psrid);
this.ctx.back();
}
async post_upvote() {
let [psdoc, pssdoc] = await solution.vote(this.psdoc._id, this.uid, 1);
this.ctx.body = { vote: psdoc.vote, user_vote: pssdoc.vote };
if (!this.ctx.preferJson) this.ctx.back();
}
async post_downvote() {
let [psdoc, pssdoc] = await solution.vote(this.psdoc._id, this.uid, -1);
this.ctx.body = { vote: psdoc.vote, user_vote: pssdoc.vote };
if (!this.ctx.preferJson) this.ctx.back();
}
}
class ProblemSolutionRawHandler extends ProblemDetailHandler {

@ -81,7 +81,6 @@ async function random(query) {
let pdoc = await pdocs.skip(Math.floor(Math.random() * pcount)).limit(1).toArray()[0];
return pdoc.pid;
} else return null;
}
module.exports = {

@ -1,9 +1,10 @@
const
{ ObjectID } = require('bson'),
{ SolutionNotFoundError } = require('../error'),
{ SolutionNotFoundError, AlreadyVotedError } = require('../error'),
validator = require('../lib/validator'),
db = require('../service/db.js'),
coll = db.collection('solution');
coll = db.collection('solution'),
coll_status = db.collection('solution.status');
/**
* @param {string} pid
@ -73,6 +74,22 @@ async function editReply(psid, psrid, content) {
async function delReply(psid, psrid) {
return await coll.findOneAndUpdate({ _id: psid }, { $pull: { reply: { _id: psrid } } });
}
async function vote(psid, uid, value) {
let pssdoc = await coll_status.findOne({ psid, uid });
if (pssdoc) await coll_status.deleteOne({ psid, uid });
await coll_status.insertOne({ psid, uid, vote: value });
if (pssdoc) value += -pssdoc.vote;
await coll.findOneAndUpdate({ _id: psid }, { $inc: { vote: value } });
pssdoc = await coll_status.findOne({ psid, uid });
let psdoc = await coll.findOne({ _id: psid });
return [psdoc, pssdoc];
}
async function getListStatus(list, uid) {
let result = {};
let res = await coll_status.find({ uid, psid: { $in: list } }).toArray();
for (let i of res) result[i.psid] = i;
return result;
}
module.exports = {
count,
add,
@ -84,5 +101,7 @@ module.exports = {
reply,
getReply,
editReply,
delReply
delReply,
vote,
getListStatus
};

@ -4,9 +4,7 @@ const res = [];
function checkResources() {
for (let i = res.length - 1; i >= 0; --i) {
if (res[i].detached || !document.body.contains(res[i].$dom[0])) {
if (!res[i].detached) {
res[i].detach();
}
if (!res[i].detached) res[i].detach();
res.splice(i, 1);
}
}
@ -36,15 +34,11 @@ export default class DOMAttachedObject {
const key = this.DOMAttachKey;
const Protoclass = this;
const instance = this.get($singleObj);
if (instance !== undefined) {
return instance;
}
if (instance !== undefined) return instance;
const newInstance = new Protoclass($singleObj, ...args);
// $dom may be updated in constructor so that we use $dom instead
// of $singleObj here.
if (!newInstance.$dom) {
return null;
}
if (!newInstance.$dom) return null;
newInstance.$dom.data(key, newInstance);
return newInstance;
}

Loading…
Cancel
Save