+
+
diff --git a/app/controllers/problem_statement_md.php b/app/controllers/problem_statement_md.php
new file mode 100644
index 0000000..843a99b
--- /dev/null
+++ b/app/controllers/problem_statement_md.php
@@ -0,0 +1,68 @@
+= $problem_content['statement_md'] ?>
diff --git a/app/controllers/submissions_list.php b/app/controllers/submissions_list.php
index cc4f565..224d8c6 100644
--- a/app/controllers/submissions_list.php
+++ b/app/controllers/submissions_list.php
@@ -5,10 +5,6 @@
requirePHPLib('form');
- function validateTime($time) {
- return is_string($time) && (preg_match('/^(19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])( (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?$/', $time));
- }
-
$search_form = new SOJForm();
$common = 'class="form-control input-sm" ';
$q_problem_id = $search_form->addText('problem_id', UOJLocale::get('problems::problem id').':', $common . 'maxlength="4" style="width:4em"', 'validateUInt');
diff --git a/app/locale/basic/en.php b/app/locale/basic/en.php
index 0ef6edf..4ee35b0 100644
--- a/app/locale/basic/en.php
+++ b/app/locale/basic/en.php
@@ -173,4 +173,8 @@
'manageable' => 'Manageable',
'log out all' => 'Log out on all devices',
'cut off time' => 'Cut-off time',
+ 'problem collection' => 'Collection',
+ 'manage' => 'Manage',
+ 'propose' => 'Propose',
+ 'note' => 'Note',
];
diff --git a/app/locale/basic/zh-cn.php b/app/locale/basic/zh-cn.php
index 32137b6..32a2829 100644
--- a/app/locale/basic/zh-cn.php
+++ b/app/locale/basic/zh-cn.php
@@ -173,4 +173,8 @@
'manageable' => '有权限',
'log out all' => '在所有设备登出',
'cut off time' => '截止时间',
+ 'problem collection' => '题单',
+ 'manage' => '管理',
+ 'propose' => '提议',
+ 'note' => '备注',
];
diff --git a/app/models/UOJBlogEditor.php b/app/models/UOJBlogEditor.php
index c032032..bb3d8c5 100644
--- a/app/models/UOJBlogEditor.php
+++ b/app/models/UOJBlogEditor.php
@@ -41,6 +41,11 @@ function __construct() {
if (strlen($content_md) > 1000000) {
return '内容过长';
}
+ foreach (UOJConfig::$data['profile']['oj-address'] as $address) {
+ if (strpos($content_md, $address) !== false) {
+ return 'Warning: 使用相对链接';
+ }
+ }
return '';
},
'tags' => function(&$tags) {
@@ -78,10 +83,15 @@ public function validate($name) {
}
private function receivePostData() {
$errors = array();
+ $warnings = array();
foreach (array('title', 'content_md', 'tags') as $name) {
$cur_err = $this->validate($name);
if ($cur_err) {
- $errors[$name] = $cur_err;
+ if (substr($cur_err, 0, 7) == 'Warning') {
+ $warnings[$name] = $cur_err;
+ } else {
+ $errors[$name] = $cur_err;
+ }
}
}
if ($errors) {
@@ -188,11 +198,12 @@ private function receivePostData() {
}
$this->post_data['content'] = json_encode($config) . "\n" . $this->post_data['content'];
}
+ return $warnings;
}
public function handleSave() {
$save = $this->save;
- $this->receivePostData();
+ $warnings = $this->receivePostData();
$ret = $save($this->post_data);
if (!$ret) {
$ret = array();
@@ -218,6 +229,8 @@ public function handleSave() {
$ret['html'] = ob_get_contents();
ob_end_clean();
}
+
+ $ret['warnings'] = $warnings;
die(json_encode($ret));
}
diff --git a/app/route.php b/app/route.php
index 9d0d949..102508a 100644
--- a/app/route.php
+++ b/app/route.php
@@ -17,11 +17,16 @@
Route::any('/problems/template', '/problem_set.php?tab=template');
Route::any('/problems/contested', '/problem_set.php?tab=contested');
Route::any('/problem/{id}', '/problem.php');
+ Route::any('/problem/{id}/statement.md', '/problem_statement_md.php');
Route::any('/problem/{id}/statistics', '/problem_statistics.php');
Route::any('/problem/{id}/manage/statement', '/problem_statement_manage.php');
Route::any('/problem/{id}/manage/managers', '/problem_managers_manage.php');
Route::any('/problem/{id}/manage/data', '/problem_data_manage.php');
+ Route::any('/collection', '/collection.php');
+ Route::any('/collection/propose', '/collection_propose.php');
+ Route::any('/collection/manage', '/collection_manage.php');
+
Route::any('/contests', '/contests.php');
Route::any('/contest/new', '/add_contest.php');
Route::any('/contest/{id}', '/contest_inside.php');
diff --git a/app/uoj-form-lib.php b/app/uoj-form-lib.php
index 7aaa827..0a43404 100644
--- a/app/uoj-form-lib.php
+++ b/app/uoj-form-lib.php
@@ -998,3 +998,7 @@ public function printHTML($url) {
function validateLength($len) {
return function($x) use ($len) {return mb_strlen($x) <= $len;};
}
+
+ function validateTime($time) {
+ return is_string($time) && (preg_match('/^(19|20)\d{2}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01])( (0[0-9]|1[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9]))?$/', $time));
+ }
diff --git a/app/uoj-html-lib.php b/app/uoj-html-lib.php
index c1c28c4..67236df 100644
--- a/app/uoj-html-lib.php
+++ b/app/uoj-html-lib.php
@@ -321,7 +321,7 @@ function echoSubmission($submission, $config, $user) {
$limitLevel = querySubmissionDetailPermission($user, $submission);
$problem = queryProblemBrief($submission['problem_id']);
$status = explode(', ', $submission['status'])[0];
- $show_status_details = isOurSubmission($user, $submission) && $status !== 'Judged';
+ $show_status_details = (isOurSubmission($user, $submission) || isSuperUser(Auth::user())) && $status !== 'Judged';
$submission_uri = getSubmissionUri($submission['id']);
$submission_id_str = getSubmissionLink($submission['id']);
diff --git a/app/uoj-query-lib.php b/app/uoj-query-lib.php
index 47eb374..fd982de 100644
--- a/app/uoj-query-lib.php
+++ b/app/uoj-query-lib.php
@@ -94,6 +94,12 @@ function queryProblemTags($id) {
return $tags;
}
+function queryCollectionTags($id) {
+ $result = DB::select("select tag from collection_tags where collection_id = '$id' order by id");
+ for ($tags = array(); $row = DB::fetch($result, MYSQLI_NUM); $tags[] = $row[0]);
+ return $tags;
+}
+
function queryContestProblemRank($contest, $problem) {
if (!DB::selectFirst("select * from contests_problems where contest_id = {$contest['id']} and problem_id = {$problem['id']}")) {
return null;
@@ -405,12 +411,14 @@ function getHacksAuditLog($config = array()) {
'actor' => $his['hacker'],
'details' => $his
);
- $audit_log[] = array(
- 'time' => $his['judge_time'],
- 'type' => 'hack judgement, auto',
- 'hack_id' => $his['hack_id'],
- 'details' => $his
- );
+ if($his['success'] != null) {
+ $audit_log[] = array(
+ 'time' => $his['judge_time'],
+ 'type' => 'hack judgement, auto',
+ 'hack_id' => $his['hack_id'],
+ 'details' => $his
+ );
+ }
}
sortAuditLogByTime($audit_log);
return $audit_log;
diff --git a/app/views/blog-preview.php b/app/views/blog-preview.php
index fc426e7..bc15b0c 100644
--- a/app/views/blog-preview.php
+++ b/app/views/blog-preview.php
@@ -23,6 +23,16 @@
= $content ?>
+
diff --git a/css/soj-theme.css b/css/soj-theme.css
index 0ff2a2a..6c9ad3f 100644
--- a/css/soj-theme.css
+++ b/css/soj-theme.css
@@ -401,6 +401,10 @@ pre {
margin-left: 5px;
margin-right: 5px;
}
+.uoj-collection-tag {
+ margin-left: 5px;
+ margin-right: 5px;
+}
.uoj-blog-tag {
margin-left: 5px;
margin-right: 5px;
diff --git a/js/blog-editor/blog-editor.js b/js/blog-editor/blog-editor.js
index 747fa52..310d0ed 100644
--- a/js/blog-editor/blog-editor.js
+++ b/js/blog-editor/blog-editor.js
@@ -184,6 +184,9 @@ function blog_editor_init(name, editor_config) {
$(['title', 'content_md', 'tags']).each(function() {
ok &= showErrorHelp(name + '_' + this, data[this]);
});
+ $(['title', 'content_md', 'tags']).each(function() {
+ showWarningHelp(name + '_' + this, data['warnings'][this]);
+ });
if (data.extra !== undefined) {
alert(data.extra);
ok = false;
diff --git a/js/marked.js b/js/marked.js
index f2c231e..a5a0595 100644
--- a/js/marked.js
+++ b/js/marked.js
@@ -1,5 +1,5 @@
/**
- * marked - a markdown parser
+ * Modified from marked - a markdown parser
* Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
* https://github.com/chjj/marked
*/
@@ -363,7 +363,8 @@ Lexer.prototype.token = function(src, top) {
src = src.substring(cap[0].length);
this.tokens.links[cap[1].toLowerCase()] = {
href: cap[2],
- title: cap[3]
+ title: cap[3],
+ rest: ''
};
continue;
}
@@ -452,11 +453,14 @@ var inline = {
math: /^\$((?:[^\\]|\\\\|\\[^\\]+?)+?)\$|^\$\$((?:[^\\]|\\\\|\\[^\\]+?)+?)\$\$|^\\begin{[^}]+}((?:[^\\]|\\\\|\\[^\\]+?)+?)\\end{[^}]+}/,
br: /^ {2,}\n(?!\s*$)/,
del: noop,
- text: /^[\s\S]+?(?=[\\?(?:\s+['"]([\s\S]*?)['"])?\s*/;
+inline._href = /\s*([^\s)]*?)>?(?:\s+['"]([^)]*?)['"])?(\s*(?:\s\.[\w=]+\s*)*)/;
inline.link = replace(inline.link)
('inside', inline._inside)
@@ -618,7 +622,8 @@ InlineLexer.prototype.output = function(src) {
src = src.substring(cap[0].length);
out += this.outputLink(cap, {
href: cap[2],
- title: cap[3]
+ title: cap[3],
+ rest: cap[4]
});
continue;
}
@@ -703,6 +708,31 @@ InlineLexer.prototype.output = function(src) {
InlineLexer.prototype.outputLink = function(cap, link) {
if (cap[0][0] !== '!') {
+
+ if (link.href[0] == '%') {
+ link.href = link.href.substring(1);
+ return '
'
+ + this.output(cap[1])
+ + '';
+ }
+
+ if (link.href[0] == ':') {
+ var ret = this.extractProperties(link.rest);
+ if (link.href == ':user' && ret[1].rating !== undefined) {
+ return '
' + escape(cap[1]) + '';
+ } else {
+ return '
{errors occur in processing ' + escape(link.href) + '}';
+ }
+ }
+
return '
';
} else {
+ var ret = this.extractProperties(link.rest)
+ , style = ''
+ , cls;
+
+ if (ret[1].h !== undefined) {
+ style += "height:" + ret[1].h + "px;";
+ }
+ if (ret[1].w !== undefined) {
+ style += "width:" + ret[1].w + "px;";
+ }
+ if (ret[1].left) {
+ cls = 'img-responsive';
+ } else if (ret[1].right) {
+ cls = 'img-responsive';
+ style += "margin-left: auto;";
+ } else if (ret[1].inline) {
+ cls = '';
+ } else {
+ cls = 'img-responsive center-block';
+ }
+
return '
';
}
};
+/**
+ * Extract Properties
+ */
+
+InlineLexer.prototype.extractProperties = function(src) {
+ var props = {}
+ , cap;
+
+ if (!src) {
+ return ['', props];
+ }
+ while (src) {
+ // width, height, rating
+ if (cap = this.rules.property_num.exec(src)) {
+ src = src.substring(0, src.length - cap[0].length);
+ if (!(cap[1] in props)) {
+ props[cap[1]] = cap[2];
+ }
+ continue;
+ }
+
+ // keep, left, right, center
+ if (cap = this.rules.property_bool.exec(src)) {
+ src = src.substring(0, src.length - cap[0].length);
+ props[cap[1]] = true;
+ continue;
+ }
+
+ break;
+ }
+
+ return [src, props];
+};
+
/**
* Mangle Links
*/
@@ -820,8 +903,8 @@ Parser.prototype.parseText = function() {
*/
Parser.prototype.tok = function() {
- var tok_class = this.options.getElementClass == null ? null : this.options.getElementClass(this.token);
- tok_class = tok_class == null ? '' : ' class="' + tok_class + '"';
+ var inner_tok_class = this.options.getElementClass == null ? null : this.options.getElementClass(this.token);
+ tok_class = inner_tok_class == null ? '' : ' class="' + inner_tok_class + '"';
switch (this.token.type) {
case 'space': {
return '';
@@ -851,16 +934,18 @@ Parser.prototype.tok = function() {
if (!this.token.escaped) {
this.token.text = escape(this.token.text, true);
}
-
- return '' + this.token.text + '
';
+ } else if (this.options.getLangClass && this.token.lang != undefined) {
+ return ''
+ + '">'
+ this.token.text
+ '
\n';
+ } else {
+ return '' + this.token.text + '
';
+ }
}
case 'table': {
var body = ''
@@ -868,15 +953,32 @@ Parser.prototype.tok = function() {
, i
, row
, cell
+ , attr
, j;
+ var rowspan = false;
+
// header
body += '\n\n';
for (i = 0; i < this.token.header.length; i++) {
- heading = this.inline.output(this.token.header[i]);
- body += this.token.align[i]
- ? '| ' + heading + ' | \n'
- : '' + heading + ' | \n';
+ if (!this.token.header[i]) {
+ continue;
+ }
+
+ heading = this.inline.extractProperties(this.token.header[i]);
+ heading[0] = this.inline.output(heading[0]);
+ attr = '';
+ if (this.token.align[i]) {
+ attr += ' style="text-align:' + this.token.align[i] + '"';
+ }
+ if (heading[1].w !== undefined) {
+ attr += ' colspan="' + cell[1].w + '"';
+ }
+ if (heading[1].h !== undefined) {
+ attr += ' rowspan="' + cell[1].h + '"';
+ rowspan = true;
+ }
+ body += '' + heading[0] + ' | \n';
}
body += '
\n\n';
@@ -886,18 +988,39 @@ Parser.prototype.tok = function() {
row = this.token.cells[i];
body += '\n';
for (j = 0; j < row.length; j++) {
- cell = this.inline.output(row[j]);
- body += this.token.align[j]
- ? '| ' + cell + ' | \n'
- : '' + cell + ' | \n';
+ if (!row[j]) {
+ continue;
+ }
+
+ cell = this.inline.extractProperties(row[j]);
+ cell[0] = this.inline.output(cell[0]);
+ attr = '';
+ if (this.token.align[j]) {
+ attr += ' style="text-align:' + this.token.align[j] + '"';
+ }
+ if (cell[1].w !== undefined) {
+ attr += ' colspan="' + cell[1].w + '"';
+ }
+ if (cell[1].h !== undefined) {
+ attr += ' rowspan="' + cell[1].h + '"';
+ rowspan = true;
+ }
+ body += '' + cell[0] + ' | \n';
}
body += '
\n';
}
body += '\n';
- return '\n'
+ if (!rowspan) {
+ if (inner_tok_class != null) {
+ inner_tok_class += ' table-striped';
+ }
+ tok_class = inner_tok_class == null ? '' : ' class="' + inner_tok_class + '"';
+ }
+
+ return '
\n
\n';
}
case 'blockquote_start': {
var body = '';
@@ -953,6 +1076,9 @@ Parser.prototype.tok = function() {
}
case 'html': {
return this.token.text;
+ /*return !this.token.pre && !this.options.pedantic
+ ? this.inline.output(this.token.text)
+ : this.token.text;*/
}
case 'paragraph': {
return ''
@@ -1051,18 +1177,21 @@ marked.defaults = {
silent: false,
highlight: null,
getLangClass: function(lang) {
- lang = lang.toLowerCase();
- switch (lang) {
- case 'c': return 'sh_c';
- case 'c++': return 'sh_cpp';
- case 'pascal': return 'sh_pascal';
- default: return 'sh_' + lang;
- }
+ lang = lang.toLowerCase();
+ switch (lang) {
+ case 'c': return 'sh_c';
+ case 'c++': return 'sh_cpp';
+ case 'pascal': return 'sh_pascal';
+ default: return 'sh_' + lang;
+ }
},
- getElementClass: function (token) {
- if (token.type === "table")
- return "table table-bordered table-hover table-striped table-text-center";
- return null;
+ getElementClass: function(token) {
+ switch (token.type) {
+ case 'table':
+ return 'table table-bordered table-text-center table-vertical-middle';
+ default:
+ return null;
+ }
}
};
diff --git a/js/soj.js b/js/soj.js
index a0af683..0e2bd66 100644
--- a/js/soj.js
+++ b/js/soj.js
@@ -183,7 +183,7 @@ function getColOfScore(score) {
} else if (score == 100) {
return ColorConverter.toStr(ColorConverter.toRGB(new HSV(120, 100, 80)));
} else {
- return ColorConverter.toStr(ColorConverter.toRGB(new HSV(30 + score * 0.6, 100, 90)));
+ return ColorConverter.toStr(ColorConverter.toRGB(new HSV(30 + score * 0.6, 100, 90 - Math.max(Math.min(score - 30, 90 - score), 0) * 0.5)));
}
}
@@ -284,6 +284,16 @@ function showErrorHelp(name, err) {
}
}
+function showWarningHelp(name, err) {
+ if (err) {
+ $('#div-' + name).addClass('has-warning');
+ $('#help-' + name).text(err);
+ } else {
+ $('#div-' + name).removeClass('has-warning');
+ $('#help-' + name).text('');
+ }
+}
+
function getFormErrorAndShowHelp(name, val) {
var err = val($('#input-' + name).val());
return showErrorHelp(name, err);
@@ -385,6 +395,12 @@ $.fn.uoj_blog_tag = function() {
});
}
+$.fn.uoj_collection_tag = function() {
+ return this.each(function() {
+ $(this).attr('href', '/collection?type=' + encodeURIComponent($(this).text()));
+ });
+}
+
// click zan
function click_zan(zan_id, zan_type, zan_delta, node) {
var loading_node = $('
loading...
');
@@ -451,8 +467,21 @@ function getCountdownStr(t) {
var mm = toFilledStr(x % 60, '0', 2);
x = Math.floor(x / 60);
var hh = x.toString();
+ if (x >= 24) {
+ hh = toFilledStr(x % 24, '0', 2);
+ }
+ x = Math.floor(x / 24);
+ var dd = x.toString();
var res = '';
+ if (x > 0) {
+ res += '' + dd + '';
+ res += ' day';
+ if (dd > 1) {
+ res += 's';
+ }
+ res += ' + ';
+ }
res += '' + hh + '';
res += ':';
res += '' + mm + '';
@@ -539,6 +568,7 @@ $.fn.uoj_highlight = function() {
});
$(this).find(".uoj-problem-tag").uoj_problem_tag();
$(this).find(".uoj-blog-tag").uoj_blog_tag();
+ $(this).find(".uoj-collection-tag").uoj_collection_tag();
$(this).find(".uoj-click-zan-block").click_zan_block();
$(this).find(".countdown").countdown();
$(this).find(".uoj-readmore").readmore({
From 1e63827f97a6587a47f25b297cdf49cc04905391 Mon Sep 17 00:00:00 2001
From: liuhengxi2007 <2019891597@qq.com>
Date: Mon, 7 Jul 2025 19:09:16 +0800
Subject: [PATCH 02/20] =?UTF-8?q?=E6=97=A0=E5=8F=AF=E5=A5=89=E5=91=8A?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.gitignore | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.gitignore b/.gitignore
index 431a4d7..bf6ea2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,3 @@ uploads/*
utility/
pictures/
js/mathjax/
-app/locale/basic/zh-en.php
-app/locale/contests/zh-en.php
-app/locale/problems/zh-en.php
From 1554e9504b1242762858ce3afc4c3a76437d64cb Mon Sep 17 00:00:00 2001
From: liuhengxi2007 <2019891597@qq.com>
Date: Sun, 7 Sep 2025 19:51:25 +0800
Subject: [PATCH 03/20] collection propose
---
app/controllers/collection.php | 2 +-
app/controllers/collection_manage.php | 26 +++----
app/controllers/collection_propose.php | 90 +++++++++++++++++++++++++
app/controllers/hack_list.php | 2 +-
app/controllers/problem_data_manage.php | 4 +-
app/controllers/problem_statistics.php | 14 ++--
app/controllers/submissions_list.php | 6 +-
app/uoj-html-lib.php | 10 +++
app/uoj-validate-lib.php | 8 +++
js/soj.js | 2 +-
10 files changed, 137 insertions(+), 27 deletions(-)
diff --git a/app/controllers/collection.php b/app/controllers/collection.php
index 1659273..774f327 100644
--- a/app/controllers/collection.php
+++ b/app/controllers/collection.php
@@ -117,7 +117,7 @@ function changeProblemState(state, id) {
-
+
diff --git a/app/controllers/collection_manage.php b/app/controllers/collection_manage.php
index 7dc0ebf..2a2de33 100644
--- a/app/controllers/collection_manage.php
+++ b/app/controllers/collection_manage.php
@@ -8,7 +8,7 @@
redirectToLogin();
}
- if(!isProblemCreator(Auth::user()) && !isBlogAllowedUser(Auth::user())) {
+ if(!isProblemCreator(Auth::user())) {
become403Page();
}
@@ -53,37 +53,39 @@ function echoProblem($problem) {
$div_classes = array('table-responsive');
$table_classes = array('table', 'table-bordered', 'table-hover', 'table-striped');
+ $proposal = DB::selectFirst("select * from collection_proposal");
+
$append_form = new UOJForm('append');
- $append_form->addInput('id', 'text', 'id', '',
+ $append_form->addInput('id', 'text', 'id', $proposal['id'],
function($result) {
if(!preg_match('/^-?[a-z0-9]{1,12}$/', $result)) return '题号长度不能超过 12,且只能包含小写字母和数字';
return '';
},
null
);
- $append_form->addInput('title', 'text', 'title', '',
+ $append_form->addInput('title', 'text', 'title', $proposal['title'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);
- $append_form->addInput('url', 'text', 'url', '',
+ $append_form->addInput('url', 'text', 'url', $proposal['url'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);
- $append_form->addInput('tag', 'text', 'tag', '',
+ $append_form->addInput('tag', 'text', 'tag', $proposal['tag'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
},
null
);
- $append_form->addInput('note', 'text', 'note', '',
+ $append_form->addInput('note', 'text', 'note', $proposal['note'],
function($result) {
if(strlen($result) > 100) return '长度不能超过 100 byte';
return '';
@@ -92,15 +94,14 @@ function($result) {
);
$append_form->handle = function() {
- $delete_permission = isProblemCreator(Auth::user());
-
$id = $_POST['id'];
if ($id[0] == '-') {
$id = substr($id, 1);
- if($delete_permission) DB::delete("delete from collection where id='$id'");
- if($delete_permission) DB::delete("delete from collection_tags where collection_id='$id'");
+ DB::delete("delete from collection where id='$id'");
+ DB::delete("delete from collection_tags where collection_id='$id'");
return;
}
+ DB::delete("delete from collection_proposal where id='$id'");
$title = DB::escape($_POST['title']);
$url = DB::escape($_POST['url']);
$tag = DB::escape(strtolower($_POST['tag']));
@@ -117,7 +118,7 @@ function($result) {
DB::insert("insert into collection (id, title, url, note) values ('$id', '$title', '$url', '$note') on duplicate key update" . substr($upd_cmd, 1));
}
if($tag == '-') {
- if($delete_permission) DB::delete("delete from collection_tags where collection_id='$id'");
+ DB::delete("delete from collection_tags where collection_id='$id'");
}
else if($tag != '' && DB::selectCount("select count(*) from collection where id = '$id'")) {
DB::insert("insert ignore into collection_tags (collection_id, tag) values ('$id', '$tag')");
@@ -126,6 +127,7 @@ function($result) {
$append_form->runAtServer();
?>
+
printHTML(); ?>
约定
选择一个题目所属的 OJ 时,按照以下顺序选择:
@@ -147,7 +149,7 @@ function($result) {
| LOJ | loj1 |
| SOJ | soj1 |
| Luogu | lg1001 |
-
| Codeforces Gym | cf111111a |
+
| Codeforces Gym | cf123456a |
';
+
+ echo $pag->pagination();
+?>
+
diff --git a/app/controllers/collection_user_manage.php b/app/controllers/collection_user_manage.php
new file mode 100644
index 0000000..3a36d2b
--- /dev/null
+++ b/app/controllers/collection_user_manage.php
@@ -0,0 +1,185 @@
+';
+ echo '
';
+ echo '';
+ }
+ }
+
+ $cur_tab = isset($_GET['type']) ? $_GET['type'] : 'null';
+
+ $cond = "1";
+
+ $header = '
';
+
+ $pag_config = array('page_len' => 10000);
+ $pag_config['col_names'] = array('*');
+ $username = Auth::id();
+ $pag_config['table_name'] = "collection";
+ $pag_config['cond'] = $cond;
+ $pag_config['tail'] = 'order by id asc';
+ $pag_config['max_extend'] = 5;
+ $pag_config['timeout'] = 1000;
+ $pag = new Paginator($pag_config);
+
+ $div_classes = array('table-responsive');
+ $table_classes = array('table', 'table-bordered', 'table-hover', 'table-striped');
+
+ if($owner == Auth::id()) {
+ $append_form = new UOJForm('append');
+
+ $append_form->addInput('id', 'text', 'id', '',
+ function($result) {
+ if(!preg_match('/^-?[a-z0-9]{1,12}$/', $result)) return '题号长度不能超过 12,且只能包含小写字母和数字';
+ return '';
+ },
+ null
+ );
+ $append_form->addInput('title', 'text', 'title', '',
+ function($result) {
+ if(strlen($result) > 100) return '长度不能超过 100 byte';
+ return '';
+ },
+ null
+ );
+ $append_form->addInput('url', 'text', 'url', '',
+ function($result) {
+ if(strlen($result) > 100) return '长度不能超过 100 byte';
+ return '';
+ },
+ null
+ );
+ $append_form->addInput('tag', 'text', 'tag', '',
+ function($result) {
+ if(strlen($result) > 100) return '长度不能超过 100 byte';
+ return '';
+ },
+ null
+ );
+ $append_form->addInput('note', 'text', 'note', '',
+ function($result) {
+ if(strlen($result) > 100) return '长度不能超过 100 byte';
+ return '';
+ },
+ null
+ );
+
+ $append_form->handle = function() {
+ $id = $_POST['id'];
+ if ($id[0] == '-') {
+ $id = substr($id, 1);
+ DB::delete("delete from collection_user where id='$id' and owner = '$owner'");
+ DB::delete("delete from collection_user_tags where collection_id='$id' and owner = '$owner'");
+ return;
+ }
+ $title = DB::escape($_POST['title']);
+ $url = DB::escape($_POST['url']);
+ $tag = DB::escape(strtolower($_POST['tag']));
+ $note = DB::escape($_POST['note']);
+
+ $upd_cmd = '';
+ if($title != '') $upd_cmd .= ", title='$title'";
+ if($url != '') $upd_cmd .= ", url='$url'";
+ if($note != '') {
+ if($note == '-') $note = '';
+ $upd_cmd .= ", note='$note'";
+ }
+ if($upd_cmd != '') {
+ DB::insert("insert into collection_user (owner, id, title, url, note) values ('$owner', '$id', '$title', '$url', '$note') on duplicate key update" . substr($upd_cmd, 1));
+ }
+ if($tag == '-') {
+ DB::delete("delete from collection_user_tags where collection_id='$id' and owner = '$owner'");
+ }
+ else if($tag != '' && DB::selectCount("select count(*) from collection_user_tags where id = '$id' and owner = '$owner'")) {
+ DB::insert("insert ignore into collection_user_tags (owner, collection_id, tag) values ('$owner', '$id', '$tag')");
+ }
+ };
+ $append_form->runAtServer();
+ }
+?>
+
+printHTML(); ?>
+