Browse Source

Merge branch 'master' of zhaojunzhe/fair-web into master

pull/31/head
richie 5 years ago committed by Gogs
parent
commit
718611d3ba
  1. 3
      libs/submissions_process.js
  2. 5
      models-built/judge_state.js
  3. 2
      models-built/judge_state.js.map
  4. 71
      models-built/reply.js
  5. 1
      models-built/reply.js.map
  6. 4
      models-built/user.js
  7. 2
      models-built/user.js.map
  8. 4
      models/judge_state.ts
  9. 35
      models/reply.ts
  10. 3
      models/user.ts
  11. 9
      modules/api.js
  12. 89
      modules/discussion.js
  13. 12
      modules/index.js
  14. 8
      modules/problem.js
  15. 10
      modules/submission.js
  16. 15
      modules/user.js
  17. 96
      views/article.ejs
  18. 18
      views/problem.ejs
  19. 6
      views/submissions_item.ejs
  20. 4
      views/user_edit.ejs

3
libs/submissions_process.js

@ -14,7 +14,8 @@ const getSubmissionInfo = (s, displayConfig) => {
submitTime: syzoj.utils.formatDate(s.submit_time),
isPractice: s.is_practice,
c_id: s.c_id,
is_share: s.is_share || false
is_share: s.is_share || false,
is_anonymous: s.is_anonymous
}
};

5
models-built/judge_state.js

@ -372,6 +372,11 @@ var JudgeState = /** @class */ (function (_super) {
TypeORM.Column({ nullable: true, type: "boolean" }),
__metadata("design:type", Boolean)
], JudgeState.prototype, "is_share");
__decorate([
TypeORM.Index(),
TypeORM.Column({ nullable: true, type: "boolean", "default": 0 }),
__metadata("design:type", Boolean)
], JudgeState.prototype, "is_anonymous");
JudgeState = __decorate([
TypeORM.Entity(),
TypeORM.Index(['type', 'type_info']),

2
models-built/judge_state.js.map

File diff suppressed because one or more lines are too long

71
models-built/reply.js

@ -0,0 +1,71 @@
"use strict";
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
exports.__esModule = true;
var TypeORM = require("typeorm");
var common_1 = require("./common");
var Reply = /** @class */ (function (_super) {
__extends(Reply, _super);
function Reply() {
return _super !== null && _super.apply(this, arguments) || this;
}
Reply.cache = false;
__decorate([
TypeORM.PrimaryGeneratedColumn(),
__metadata("design:type", Number)
], Reply.prototype, "id");
__decorate([
TypeORM.Column({ nullable: true, type: "mediumtext" }),
__metadata("design:type", String)
], Reply.prototype, "content");
__decorate([
TypeORM.Index(),
TypeORM.Column({ nullable: true, type: "integer" }),
__metadata("design:type", Number)
], Reply.prototype, "user_id");
__decorate([
TypeORM.Index(),
TypeORM.Column({ nullable: true, type: "integer" }),
__metadata("design:type", Number)
], Reply.prototype, "comment_id");
__decorate([
TypeORM.Index(),
TypeORM.Column({ nullable: true, type: "integer" }),
__metadata("design:type", Number)
], Reply.prototype, "article_id");
__decorate([
TypeORM.Column({ nullable: true, type: "integer" }),
__metadata("design:type", Number)
], Reply.prototype, "public_time");
__decorate([
TypeORM.Column({ nullable: true, type: "integer" }),
__metadata("design:type", Number)
], Reply.prototype, "update_time");
Reply = __decorate([
TypeORM.Entity()
], Reply);
return Reply;
}(common_1["default"]));
exports["default"] = Reply;
;
//# sourceMappingURL=reply.js.map

1
models-built/reply.js.map

@ -0,0 +1 @@
{"version":3,"file":"reply.js","sourceRoot":"","sources":["../models/reply.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,iCAAmC;AACnC,mCAA6B;AAO7B;IAAmC,yBAAK;IAAxC;;IA0BA,CAAC;IAzBU,WAAK,GAAG,KAAK,CAAC;IAGrB;QADC,OAAO,CAAC,sBAAsB,EAAE;;6BACtB;IAGX;QADC,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,YAAY,EAAE,CAAC;;kCACvC;IAIhB;QAFC,OAAO,CAAC,KAAK,EAAE;QACf,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;kCACpC;IAIhB;QAFC,OAAO,CAAC,KAAK,EAAE;QACf,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;qCACjC;IAInB;QAFC,OAAO,CAAC,KAAK,EAAE;QACf,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;qCACjC;IAGnB;QADC,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;sCAChC;IAGpB;QADC,OAAO,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;;sCAChC;IAzBH,KAAK;QADzB,OAAO,CAAC,MAAM,EAAE;OACI,KAAK,CA0BzB;IAAD,YAAC;CAAA,AA1BD,CAAmC,mBAAK,GA0BvC;qBA1BoB,KAAK;AA0BzB,CAAC"}

4
models-built/user.js

@ -360,6 +360,10 @@ var User = /** @class */ (function (_super) {
TypeORM.Column({ nullable: true, type: "varchar", length: 80 }),
__metadata("design:type", String)
], User.prototype, "username");
__decorate([
TypeORM.Column({ nullable: true, type: "varchar", length: 60, "default": '' }),
__metadata("design:type", String)
], User.prototype, "anonymous_name");
__decorate([
TypeORM.Column({ nullable: true, type: "varchar", length: 120 }),
__metadata("design:type", String)

2
models-built/user.js.map

File diff suppressed because one or more lines are too long

4
models/judge_state.ts

@ -106,6 +106,10 @@ export default class JudgeState extends Model {
@TypeORM.Column({ nullable: true, type: "boolean" })
is_share:boolean;
@TypeORM.Index()
@TypeORM.Column({ nullable: true, type: "boolean", default: 0 })
is_anonymous:boolean;
user?: User;
problem?: Problem;

35
models/reply.ts

@ -0,0 +1,35 @@
import * as TypeORM from "typeorm";
import Model from "./common";
import User from "./user";
import Article from "./article";
declare var syzoj: any;
@TypeORM.Entity()
export default class Reply extends Model {
static cache = false;
@TypeORM.PrimaryGeneratedColumn()
id: number;
@TypeORM.Column({ nullable: true, type: "mediumtext" })
content: string;
@TypeORM.Index()
@TypeORM.Column({ nullable: true, type: "integer" })
user_id: number;
@TypeORM.Index()
@TypeORM.Column({ nullable: true, type: "integer" })
comment_id: number;
@TypeORM.Index()
@TypeORM.Column({ nullable: true, type: "integer" })
article_id: number;
@TypeORM.Column({ nullable: true, type: "integer" })
public_time: number;
@TypeORM.Column({ nullable: true, type: "integer" })
update_time: number;
};

3
models/user.ts

@ -18,6 +18,9 @@ export default class User extends Model {
@TypeORM.Column({ nullable: true, type: "varchar", length: 80 })
username: string;
@TypeORM.Column({ nullable: true, type: "varchar", length: 60 , default: ''})
anonymous_name: string;
@TypeORM.Column({ nullable: true, type: "varchar", length: 120 })
email: string;

9
modules/api.js

@ -20,6 +20,12 @@ app.post('/api/login', async (req, res) => {
else {
req.session.user_id = user.id;
setLoginCookie(user.username, user.password, res);
const userQuery = await User.createQueryBuilder();
const userId = user.id;
const userInfo = await userQuery.where("id = :id", { id:userId }).getOne();
if (!userInfo.anonymous_name || userInfo.anonymous_name.length === 0){
await userQuery.update(User).set({anonymous_name: require('randomstring').generate(6)}).where("id = :id", { id:userId }).execute();
}
res.send({ error_code: 1 });
}
} catch (e) {
@ -129,7 +135,8 @@ app.post('/api/sign_up', async (req, res) => {
email: req.body.email,
is_show: syzoj.config.default.user.show,
rating: syzoj.config.default.user.rating,
register_time: parseInt((new Date()).getTime() / 1000)
register_time: parseInt((new Date()).getTime() / 1000),
anonymous_name: require('randomstring').generate(6)
});
await user.save();

89
modules/discussion.js

@ -2,6 +2,7 @@ let Problem = syzoj.model('problem');
let Article = syzoj.model('article');
let ArticleComment = syzoj.model('article-comment');
let User = syzoj.model('user');
let Reply = syzoj.model('reply');
app.get('/discussion/:type?', async (req, res) => {
try {
@ -76,6 +77,7 @@ app.get('/discussion/problem/:pid', async (req, res) => {
app.get('/article/:id', async (req, res) => {
try {
let id = parseInt(req.params.id);
let replyQuery = await Reply.createQueryBuilder();
let article = await Article.findById(id);
if (!article) throw new ErrorMessage('无此帖子。');
@ -93,6 +95,17 @@ app.get('/article/:id', async (req, res) => {
});
for (let comment of comments) {
const commentId = comment.id;
const reply = await replyQuery.where("comment_id = :commentId", { commentId }).getMany();
if (reply.length === 0) {
comment.reply = [];
} else {
comment.reply = await reply.mapAsync(async (item) => {
const replyUserId = item.user_id;
item.reply_user = await User.findById(replyUserId);
return item
});
}
comment.content = await syzoj.utils.markdown(comment.content);
comment.allowedEdit = await comment.isAllowedEditBy(res.locals.user);
await comment.loadRelationships();
@ -105,8 +118,8 @@ app.get('/article/:id', async (req, res) => {
throw new ErrorMessage('您没有权限进行此操作。');
}
}
res.render('article', {
user: res.locals.user,
article: article,
comments: comments,
paginate: paginate,
@ -203,7 +216,11 @@ app.post('/article/:id/delete', async (req, res) => {
await Promise.all((await ArticleComment.find({
article_id: article.id
})).map(comment => comment.destroy()))
})).map(comment => comment.destroy()));
await Promise.all((await Reply.find({
article_id: article.id
})).map(reply => reply.destroy()));
await article.destroy();
@ -249,13 +266,55 @@ app.post('/article/:id/comment', async (req, res) => {
}
});
app.post('/article/:id/comment/:commentId', async (req, res) => {
try {
if (!res.locals.user) throw new ErrorMessage('请登录后继续。', { '登录': syzoj.utils.makeUrl(['login'], { 'url': req.originalUrl }) });
let id = parseInt(req.params.id);
let commentId = parseInt(req.params.commentId);
let userId = parseInt(res.locals.user.id);
let article = await Article.findById(id);
let articleComment = await ArticleComment.findById(commentId);
if (!articleComment) {
throw new ErrorMessage('无此回复。');
}
if (!article) {
throw new ErrorMessage('无此帖子。');
} else {
if (!await article.isAllowedCommentBy(res.locals.user)) throw new ErrorMessage('您没有权限进行此操作。');
}
let newReply = await Reply.create({
content: req.body.comment,
article_id: id,
user_id: userId,
comment_id: commentId,
public_time: syzoj.utils.getCurrentDate(),
update_time: syzoj.utils.getCurrentDate()
});
const reply = await newReply.save();
await article.resetReplyCountAndTime();
//
res.redirect(syzoj.utils.makeUrl(['article', article.id]));
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
});
app.post('/article/:article_id/comment/:id/delete', async (req, res) => {
try {
if (!res.locals.user) throw new ErrorMessage('请登录后继续。', { '登录': syzoj.utils.makeUrl(['login'], { 'url': req.originalUrl }) });
let id = parseInt(req.params.id);
let comment = await ArticleComment.findById(id);
let replyQuery = await Reply.createQueryBuilder();
if (!comment) {
throw new ErrorMessage('无此评论。');
} else {
@ -265,6 +324,7 @@ app.post('/article/:article_id/comment/:id/delete', async (req, res) => {
const article = await Article.findById(comment.article_id);
await comment.destroy();
await replyQuery.delete().from(Reply).where("comment_id = :id", { id }).execute();
await article.resetReplyCountAndTime();
@ -276,3 +336,26 @@ app.post('/article/:article_id/comment/:id/delete', async (req, res) => {
});
}
});
app.post('/article/:articleId/reply/:id/delete', async (req, res) => {
try {
if (!res.locals.user) throw new ErrorMessage('请登录后继续。', { '登录': syzoj.utils.makeUrl(['login'], { 'url': req.originalUrl }) });
let id = parseInt(req.params.id);
let reply = await Reply.findById(id);
let articleId = parseInt(req.params.articleId);
let replyQuery = await Reply.createQueryBuilder();
if (!reply) {
throw new ErrorMessage('无此回复。');
}
await reply.destroy();
res.redirect(`/article/${articleId}`);
} catch (e) {
syzoj.log(e);
res.render('error', {
err: e
});
}
});

12
modules/index.js

@ -16,7 +16,7 @@ app.get('/', async (req, res) => {
await ranklist.forEachAsync(async x => x.renderInformation());
let notices = (await Article.find({
where: { is_notice: true },
where: { is_notice: true },
order: { public_time: 'DESC' }
})).map(article => ({
title: article.title,
@ -40,7 +40,15 @@ app.get('/', async (req, res) => {
title: problem.title,
time: timeAgo.format(new Date(problem.publicize_time)),
}));
// 增加匿名用户名后用户的第一次登陆
if (res.locals.user){
const userQuery = await User.createQueryBuilder();
const userId = res.locals.user.id;
const userInfo = await userQuery.where("id = :id", { id:userId }).getOne();
if (!userInfo.anonymous_name || userInfo.anonymous_name.length === 0){
await userQuery.update(User).set({anonymous_name: require('randomstring').generate(6)}).where("id = :id", { id:userId }).execute();
}
}
res.render('index', {
ranklist: ranklist,
notices: notices,

8
modules/problem.js

@ -669,7 +669,7 @@ app.post('/problem/:id/submit', app.multer.fields([{ name: 'answer', maxCount: 1
let id = parseInt(req.params.id);
let problem = await Problem.findById(id);
const curUser = res.locals.user;
const is_anonymous = req.body.is_anonymous ? 1 : 0;
if (!problem) throw new ErrorMessage('无此题目。');
if (problem.type !== 'submit-answer' && !syzoj.config.enabled_languages.includes(req.body.language)) throw new ErrorMessage('不支持该语言。');
if (!curUser) throw new ErrorMessage('请登录后继续。', { '登录': syzoj.utils.makeUrl(['login'], { 'url': syzoj.utils.makeUrl(['problem', id]) }) });
@ -704,7 +704,8 @@ app.post('/problem/:id/submit', app.multer.fields([{ name: 'answer', maxCount: 1
language: null,
user_id: curUser.id,
problem_id: id,
is_public: problem.is_public
is_public: problem.is_public,
is_anonymous
});
} else {
let code;
@ -725,7 +726,8 @@ app.post('/problem/:id/submit', app.multer.fields([{ name: 'answer', maxCount: 1
language: req.body.language,
user_id: curUser.id,
problem_id: id,
is_public: problem.is_public
is_public: problem.is_public,
is_anonymous
});
}

10
modules/submission.js

@ -140,6 +140,9 @@ app.get('/submissions', async (req, res) => {
info.isPractice = true;
info.c_id = practiceInfo.c_id;
}
let userQuery = await User.createQueryBuilder();
const userInfo = await userQuery.where("id = :id", { id:x.user_id }).getOne();
info.anonymous_name = userInfo.anonymous_name
return {
info,
token: (x.pending && x.task_id != null) ? jwt.sign({
@ -286,8 +289,13 @@ app.get('/submission/:id', async (req, res) => {
} else {
judge.code = "作者没有开放此题代码,请联系作者分享。";
}
let info = getSubmissionInfo(judge, currentConfig);
let userQuery = await User.createQueryBuilder();
const userInfo = await userQuery.where("id = :id", { id:judge.user_id }).getOne();
console.log(userInfo);
info.anonymous_name = userInfo.anonymous_name
res.render('submission', {
info: getSubmissionInfo(judge, currentConfig),
info,
roughResult: getRoughResult(judge, currentConfig, false),
code: judge.code,
formattedCode: judge.formattedCode ? judge.formattedCode.toString("utf8") : null,

15
modules/user.js

@ -125,20 +125,22 @@ app.get('/user/:id', async (req, res) => {
app.get('/user/:id/edit', async (req, res) => {
try {
let id = parseInt(req.params.id);
let user = await User.findById(id);
if (!user) throw new ErrorMessage('无此用户。');
let userQuery = await User.createQueryBuilder();
const userInfo = await userQuery.where("id = :id", { id }).getOne();
if (!userInfo) throw new ErrorMessage('无此用户。');
let allowedEdit = await user.isAllowedEditBy(res.locals.user);
let allowedEdit = await userInfo.isAllowedEditBy(res.locals.user);
if (!allowedEdit) {
throw new ErrorMessage('您没有权限进行此操作。');
}
user.privileges = await user.getPrivileges();
userInfo.privileges = await userInfo.getPrivileges();
console.log(userInfo);
res.locals.user.allowedManage = await res.locals.user.hasPrivilege('manage_user');
res.render('user_edit', {
edited_user: user,
edited_user: userInfo,
error_info: null
});
} catch (e) {
@ -190,6 +192,7 @@ app.post('/user/:id/edit', async (req, res) => {
}
user.information = req.body.information;
user.anonymous_name = req.body.anonymous_name || '';
user.sex = req.body.sex;
user.public_email = (req.body.public_email === 'on');
user.prefer_formatted_code = (req.body.prefer_formatted_code === 'on');

96
views/article.ejs

@ -4,6 +4,18 @@
.small{
font-size: 0.7em;
}
.reply{
margin-left: 45px !important;
}
.article-comment{
cursor: pointer;
display: inline-block;
margin: 0 .75em 0 0;
color: rgba(0,0,0,.4);
}
.article-comment:hover{
color: rgba(0,0,0,.8);
}
</style>
<div class="padding">
<div class="ui breadcrumb">
@ -17,11 +29,15 @@
<a href="<%= syzoj.utils.makeUrl(['discussion', 'global']) %>" class="section">全局板块</a>
<% } %>
</div>
<span id="user-info" style="display: none"><%= user %></span>
<h1><%= article.title %></h1>
<p style="margin-bottom: -5px; ">
<img style="vertical-align: middle; margin-bottom: 2px; margin-right: 2px; " src="<%= syzoj.utils.gravatar(article.user.email, 34) %>" width="17" height="17">
<b style="margin-right: 30px; "><a class="black-link" href="<%= syzoj.utils.makeUrl(['user', article.user_id]) %>"><%= article.user.username %></a><% if (article.user.nameplate) { %><%- article.user.nameplate %><% } %></b>
<b style="margin-right: 30px; "><i class="calendar icon"></i> <%= syzoj.utils.formatDate(article.public_time) %></b>
<% if(user) {%>
<span class="article-comment" onclick="reply('comment')">回复</span>
<%}%>
<% if (article.public_time !== article.update_time) { %><b style="margin-right: 30px; "><i class="edit icon"></i> <%= syzoj.utils.formatDate(article.update_time) %></b><% } %>
<% if (article.allowedEdit) { %>
<a style="margin-top: -4px; " class="ui mini right floated labeled icon button" href="<%= syzoj.utils.makeUrl(['article', article.id, 'edit']) %>"><i class="ui edit icon"></i>编辑</a>
@ -65,14 +81,14 @@
</div>
<div class="text font-content" style="min-height: 19.5px; "><%- comment.content %></div>
<% if (comment.allowedEdit) { %>
<div class="actions"><a onclick="$('#modal-delete-<%= comment.id %>').modal('show')">删除</a></div>
<div class="actions"><a onclick="$('#modal-delete-<%= comment.id %>').modal('show')">删除</a><a onclick="reply('reply', <%= comment.id %>)">回复</a></div>
<div class="ui basic modal" id="modal-delete-<%= comment.id %>">
<div class="ui icon header">
<i class="trash icon"></i>
<p style="margin-top: 15px; ">删除评论</p>
</div>
<div class="content" style="text-align: center; ">
<p>确认删除这条评论吗?</p>
<p>确认删除这条评论吗?评论下所有回复也会被删除</p>
</div>
<div class="actions">
<div class="ui red basic cancel inverted button">
@ -85,10 +101,52 @@
</a>
</div>
</div>
<% } %>
<% } else { %>
<div class="actions">
<% if(user){%>
<a onclick="reply('reply', <%= comment.id %>)">回复</a>
<%}%>
</div>
<%}%>
</div>
</div>
<% } %>
<% for (let reply of comment.reply) { %>
<div class="comment reply">
<a class="avatar">
<img src="<%= syzoj.utils.gravatar(reply.reply_user.email, 120) %>" alt="">
</a>
<div class="content">
<a class="author" href="<%= syzoj.utils.makeUrl(['user', reply.user_id]) %>"><%= reply.reply_user.username %></a><% if (reply.reply_user.nameplate) { %><%- reply.reply_user.nameplate %><% } %>
<div class="metadata">
<span class="date"><%= syzoj.utils.formatDate(reply.public_time) %></span>
</div>
<div class="text font-content" style="min-height: 19.5px; "><%- reply.content %></div>
<% if (comment.allowedEdit) { %>
<div class="actions"><a onclick="$('#modal-delete-reply-<%= reply.id %>').modal('show')">删除</a></div>
<div class="ui basic modal" id="modal-delete-reply-<%= reply.id %>">
<div class="ui icon header">
<i class="trash icon"></i>
<p style="margin-top: 15px; ">删除回复</p>
</div>
<div class="content" style="text-align: center; ">
<p>确认删除这条回复吗?</p>
</div>
<div class="actions">
<div class="ui red basic cancel inverted button">
<i class="remove icon"></i>
</div>
<a class="ui green ok inverted button" href-post="<%= syzoj.utils.makeUrl(['article', article.id, 'reply', reply.id, 'delete']) %>">
<i class="checkmark icon"></i>
</a>
</div>
</div>
<% } %>
</div>
</div>
<% } %>
<% } %>
</div>
<div style="margin-bottom: 50px; ">
<% include page %>
@ -96,14 +154,14 @@
<% } %>
<% if (article.allowedComment) { %>
<% include monaco-editor %>
<form class="ui reply form" method="post" action="<%= syzoj.utils.makeUrl(['article', article.id, 'comment']) %>">
<form id="comment-box" class="ui reply form" method="post" action="" style="visibility:hidden">
<div id="comment" class="editor editor-with-border" style="height: 200px; width: 100%; margin-bottom: 1em; ">
<%- this.showLoadingEditor(); %>
</div>
<input type="hidden" name="comment">
<div style="text-align: center; ">
<button id="submit_button" type="submit" class="ui disabled labeled submit icon button">
<i class="icon edit"></i> 回复
<i class="icon edit"></i> <span id="reply-text">回复</span>
</button>
</div>
</form>
@ -111,7 +169,7 @@
var editors = {
comment: { defaultValue: '' }
};
window.onEditorLoaded(function () {
for (var name in editors) {
var editor = editors[name];
@ -122,7 +180,29 @@
$('#submit_button').removeClass('disabled');
});
</script>
</script>
<% } %>
</div>
<% include footer %>
<script>
function reply(type, replyId){
const id = document.getElementById('user-info').innerHTML;
if (id) {
const editorDom = document.getElementById('comment-box');
const editorBtn = document.getElementById('reply-text');
const articleId = <%= article.id %>;
let actionUrl = null;
let btnText = null;
if (type === 'comment') {
actionUrl = `/article/${articleId}/comment`;
btnText='回复帖子';
} else if (type === 'reply' && replyId) {
actionUrl = `/article/${articleId}/comment/${replyId}`;
btnText='回复评论';
}
editorDom.setAttribute('action', actionUrl);
editorBtn.innerText=btnText;
editorDom.style.visibility='initial';
}
}
</script>

18
views/problem.ejs

@ -293,7 +293,15 @@ if (contest) {
</div>
</div>
</div>
<div class="ui center aligned vertical segment" style="padding-bottom: 0; "><button type="submit" class="ui labeled icon button"><i class="ui edit icon"></i>提交</button></div>
<div class="ui center aligned vertical segment" style="padding-bottom: 0; ">
<button type="submit" class="ui labeled icon button"><i class="ui edit icon"></i>提交</button>
<% if (!contest) {%>
<div class="ui toggle chekbox">
<input type="checkbox" name="is_anonymous">
<label>是否匿名提交</label>
</div>
<% } %>
</div>
<% } else { %>
<input name="language" type="hidden" id="form">
<input name="code" type="hidden">
@ -329,7 +337,13 @@ if (contest) {
</div>
</div>
<div class="ui center aligned vertical segment" style="padding-bottom: 0; ">
<button type="submit" class="ui labeled icon button"><i class="ui edit icon"></i>提交</button>
<button type="submit" class="ui labeled icon button"><i class="ui edit icon"></i>提交</button>
<% if (!contest) {%>
<div class="ui toggle chekbox">
<input type="checkbox" name="is_anonymous">
<label>是否匿名提交</label>
</div>
<% } %>
</div>
<% } %>
</form>

6
views/submissions_item.ejs

@ -120,7 +120,11 @@
<% } %>
{{ formatSize(data.info.codeSize, 1) }}
</td>
<td><a :href="userLink">{{ data.info.user }}</a></td>
<td v-if="data.info.is_anonymous">{{ data.info.anonymous_name }}</td>
<td v-else>
<a :href="userLink">{{ data.info.user }}</a>
</td>
<td>{{ data.info.submitTime }}</td>
<td v-if="showRejudge">
<a id="rejudge-button"

4
views/user_edit.ejs

@ -22,6 +22,10 @@
<% } %>
>
</div>
<div class="field">
<label for="username">匿名名称</label>
<input type="text" id="anonymous_name" name="anonymous_name" value="<%= edited_user.anonymous_name %>">
</div>
<div class="field">
<label for="sex">性别</label>
<select class="ui dropdown" name="sex">

Loading…
Cancel
Save