feat: 更新问题页面和提交页面,集成Vditor适配器,优化Markdown渲染

This commit is contained in:
2026-04-10 15:47:26 +08:00
parent 0c7297afd7
commit 40b77471b5
35 changed files with 1996 additions and 1004 deletions

View File

@@ -58,8 +58,7 @@ if ($pr_flag) {
}
</style>
<script src="<?php echo $OJ_CDN_URL . $path_fix . "template/$OJ_TEMPLATE/" ?>clipboard.min.js"></script>
<script src="<?php echo $OJ_CDN_URL . $path_fix . "template/bs3/" ?>marked.min.js"></script>
<script src="<?php echo $OJ_CDN_URL . $path_fix . "template/syzoj/js/" ?>markdown-it.min.js"></script>
<script src="include/vditor-adapter.js"></script>
<div class="padding ">
<div class="ui center aligned grid">
@@ -505,21 +504,34 @@ if ($pr_flag) {
}
});
}
function getFrameSourceValue(frameWindow) {
if (frameWindow.editor && typeof frameWindow.editor.getValue === 'function') {
return frameWindow.editor.getValue();
}
return frameWindow.$("#source").text();
}
function setFrameSourceValue(frameWindow, value) {
if (frameWindow.editor && typeof frameWindow.editor.setValue === 'function') {
frameWindow.editor.setValue(value);
return;
}
frameWindow.$("#source").text(value);
}
function selectOne(num, answer) {
let editor = $("iframe")[0].contentWindow.$("#source");
let old = editor.text();
let frameWindow = $("iframe")[0].contentWindow;
let old = getFrameSourceValue(frameWindow);
let key = num + ".*";
console.log(key);
let rep = old.replace(new RegExp(key), num + " " + answer);
editor.text(rep);
setFrameSourceValue(frameWindow, rep);
}
function selectMulti(num, answer) {
let editor = $("iframe")[0].contentWindow.$("#source");
let old = editor.text();
let frameWindow = $("iframe")[0].contentWindow;
let old = getFrameSourceValue(frameWindow);
let key = num + ".*";
console.log(key);
let rep = old.replace(new RegExp(key), num + " " + answer);
editor.text(rep);
setFrameSourceValue(frameWindow, rep);
}
$(document).ready(function () {
@@ -574,47 +586,22 @@ if ($pr_flag) {
});
}
<?php if (isset($OJ_MARKDOWN) && $OJ_MARKDOWN) { ?>
marked.use({
// 开启异步渲染
async: true,
pedantic: false,
gfm: true,
mangle: false,
headerIds: false
});
// Helper function to decode HTML entities from Markdown source
function decodeHtmlEntities(text) {
var textArea = document.createElement('textarea');
textArea.innerHTML = text;
return textArea.value;
}
$(".md").each(function () {
let raw_markdown_source = $(this).html();
let decoded_markdown_source = decodeHtmlEntities(raw_markdown_source);
<?php if ( $OJ_MARKDOWN == "marked.js") { ?>
let markdown_content = marked.parse(decoded_markdown_source);
<?php } else if ($OJ_MARKDOWN == "markdown-it") { ?>
const md = window.markdownit();
md.set({
html: true,
linkify: true,
typographer: true,
});
let markdown_content = md.render(decoded_markdown_source);
<?php } ?>
$(this).html(markdown_content);
});
// adding note for ```input1 ```output1 in description
function addMarkdownInputOutputLabels() {
for (let i = 1; i < 10; i++) {
$(".language-input" + i).parent().before("<div><?php echo $MSG_Input ?>" + i + ":</div>");
$(".language-output" + i).parent().before("<div><?php echo $MSG_Output ?>" + i + ":</div>");
$(".language-input" + i).parent().each(function () {
if ($(this).prev('.hustoj-md-io-label').length === 0) {
$(this).before("<div class='hustoj-md-io-label'><?php echo $MSG_Input ?>" + i + ":</div>");
}
});
$(".language-output" + i).parent().each(function () {
if ($(this).prev('.hustoj-md-io-label').length === 0) {
$(this).before("<div class='hustoj-md-io-label'><?php echo $MSG_Output ?>" + i + ":</div>");
}
});
}
}
function styleMarkdownTables() {
$(".md table tr td").css({
"border": "1px solid grey",
"text-align": "center",
@@ -629,98 +616,110 @@ if ($pr_flag) {
"background-color": "#9e9e9ea1",
"text-align": "center"
});
}
initMarkdownCodeCopy();
function renderProblemMarkdown() {
<?php if (isset($OJ_MARKDOWN) && $OJ_MARKDOWN) { ?>
return HustOJVditor.renderMarkdownBlocks('.md').then(function () {
addMarkdownInputOutputLabels();
styleMarkdownTables();
initMarkdownCodeCopy();
});
<?php } ?>
//单纯文本1. A. B. C. D. 自动变控件
$('span[class=auto_select]').each(function () {
let i = 1;
let start = 0;
let next = 0;
let raw = $(this).html();
let options = ['A', 'B', 'C', 'D'];
console.log("scanning...");
while (start >= 0) {
start = raw.indexOf("\n" + i + ".", start);
if (start < 0) break;
let end = start;
let type = "radio"
for (let j = 0; j < 4; j++) {
let option = options[j];
end = raw.indexOf(option + ".", start);
next = raw.indexOf("\n" + (i + 1) + ".", start);
console.log("[" + raw.substring(start, end) + "]");
if (end < 0 || (end > next && next > 0)) {
console.log("i:" + i + " j:" + option + " end:" + end + " next:" + next);
end = start;
break;
return Promise.resolve([]);
}
function initializeProblemChoices() {
$('span[class=auto_select]').each(function () {
let i = 1;
let start = 0;
let next = 0;
let raw = $(this).html();
let options = ['A', 'B', 'C', 'D'];
console.log("scanning...");
while (start >= 0) {
start = raw.indexOf("\n" + i + ".", start);
if (start < 0) break;
let end = start;
let type = "radio"
for (let j = 0; j < 4; j++) {
let option = options[j];
end = raw.indexOf(option + ".", start);
next = raw.indexOf("\n" + (i + 1) + ".", start);
console.log("[" + raw.substring(start, end) + "]");
if (end < 0 || (end > next && next > 0)) {
console.log("i:" + i + " j:" + option + " end:" + end + " next:" + next);
end = start;
break;
}
if (j == 0 && raw.substring(start, end).indexOf("多选") > 0) type = "checkbox";
let disp = "<input type=\"" + type + "\" name=\"" + i + "\" value=\"" + option + "\" />" + option + ".";
raw = raw.substring(0, end - 1) + disp + raw.substring(end + 2);
start += disp.length;
}
if (j == 0 && raw.substring(start, end).indexOf("多选") > 0) type = "checkbox";
let disp = "<input type=\"" + type + "\" name=\"" + i + "\" value=\"" + option + "\" />" + option + ".";
//console.log(disp);
raw = raw.substring(0, end - 1) + disp + raw.substring(end + 2);
start += disp.length;
start = end + 1;
i++;
}
start = end + 1;
i++;
}
//console.log(raw);
$(this).html(raw);
});
$(this).html(raw);
});
// subjective problems from hydroOJ markdown and embeded marks
$('span[class="md auto_select"]').each(function () {
let i = 1;
let options = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$(this).find("ul").each(function () {
let type = "radio";
let ol = $(this).prev("ol");
if (ol != undefined && ol.attr("start") != undefined) i = ol.attr("start");
console.log("id[" + i + "]");
if ($(this).html().indexOf("多选") > 0 || (ol != undefined && ol.html() != undefined && ol.html().indexOf("multiselect") > 0)) type = "checkbox";
let j = 0;
$(this).find("li").each(function () {
let option = options[j];
let disp = "<input type=\"" + type + "\" name=\"" + i + "\" value=\"" + option + "\" />" + option + ".";
$(this).prepend(disp);
//console.log(options[j]);
j++;
$('span[class="md auto_select"]').each(function () {
let i = 1;
let options = ['A', 'B', 'C', 'D', 'E', 'F', 'G'];
$(this).find("ul").each(function () {
let type = "radio";
let ol = $(this).prev("ol");
if (ol != undefined && ol.attr("start") != undefined) i = ol.attr("start");
console.log("id[" + i + "]");
if ($(this).html().indexOf("多选") > 0 || (ol != undefined && ol.html() != undefined && ol.html().indexOf("multiselect") > 0)) type = "checkbox";
let j = 0;
$(this).find("li").each(function () {
let option = options[j];
let disp = "<input type=\"" + type + "\" name=\"" + i + "\" value=\"" + option + "\" />" + option + ".";
$(this).prepend(disp);
j++;
});
i++;
});
i++;
let html = $(this).html();
for (; i > 0; i--) {
console.log("searching..." + i);
html = html.replace("{{ input(" + i + ") }}", "<input type='text' size=5 name='" + i + "' placeholder='第" + i + "题' ><br>");
}
html = html.replaceAll("", "&lt;");
html = html.replaceAll("", "&gt;");
$(this).html(html);
});
let html = $(this).html();
for (; i > 0; i--) {
console.log("searching..." + i);
html = html.replace("{{ input(" + i + ") }}", "<input type='text' size=5 name='" + i + "' placeholder='第" + i + "题' ><br>");
}
html = html.replaceAll("", "&lt;");
html = html.replaceAll("", "&gt;");
$(this).html(html);
});
$(".auto_select").find('input[type="text"]').change(function () {
selectOne($(this).attr("name"), $(this).val());
});
$('input[type="radio"]').click(function () {
if ($(this).is(':checked'))
$(".auto_select").find('input[type="text"]').change(function () {
selectOne($(this).attr("name"), $(this).val());
}).css("width", "24px").css("height", "21px");
$('input[type="checkbox"]').click(function () {
let num = $(this).attr("name");
let answer = "";
$("input[type=checkbox][name=" + num + "]").each(function () {
if ($(this).is(':checked'))
answer += $(this).val();
});
selectMulti(num, answer);
}).css("width", "24px").css("height", "21px");
$('input[type="radio"]').click(function () {
if ($(this).is(':checked'))
selectOne($(this).attr("name"), $(this).val());
}).css("width", "24px").css("height", "21px");
$('input[type="checkbox"]').click(function () {
let num = $(this).attr("name");
let answer = "";
$("input[type=checkbox][name=" + num + "]").each(function () {
if ($(this).is(':checked'))
answer += $(this).val();
});
selectMulti(num, answer);
}).css("width", "24px").css("height", "21px");
<?php if ($row['spj'] > 1 || isset($_GET['sid']) || (isset($OJ_AUTO_SHOW_OFF) && $OJ_AUTO_SHOW_OFF)) { ?>
transform();
<?php } ?>
}
window.renderProblemMarkdown = renderProblemMarkdown;
renderProblemMarkdown().catch(function (error) {
console.error('Failed to render problem markdown.', error);
}).then(function () {
initializeProblemChoices();
});
});
</script>