mirror of
https://gitcode.com/gh_mirrors/hy/Hydro.git
synced 2026-10-20 17:46:28 +08:00
ui: 支持客观题配置
This commit is contained in:
1 parent
cb91c6ba71
commit
ec4971d213
7 files changed
+179
-5
No files matched your search
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "hydrooj",
|
"name": "hydrooj",
|
||||||
"version": "2.21.17",
|
"version": "2.21.18",
|
||||||
"bin": "bin/hydrooj.js",
|
"bin": "bin/hydrooj.js",
|
||||||
"main": "dist/loader.js",
|
"main": "dist/loader.js",
|
||||||
"typings": "dist/loader.d.ts",
|
"typings": "dist/loader.d.ts",
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
"node": ">=14"
|
"node": ">=14"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hydrooj/utils": "^1.0.0",
|
"@hydrooj/utils": "^1.0.1",
|
||||||
"adm-zip": "^0.5.5",
|
"adm-zip": "^0.5.5",
|
||||||
"ansi_up": "^5.0.0",
|
"ansi_up": "^5.0.0",
|
||||||
"cookies": "^0.8.0",
|
"cookies": "^0.8.0",
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ export class ProblemModel {
|
|||||||
if (pid) args.pid = pid;
|
if (pid) args.pid = pid;
|
||||||
await bus.serial('problem/before-add', args);
|
await bus.serial('problem/before-add', args);
|
||||||
const result = await document.add(domainId, content, owner, document.TYPE_PROBLEM, docId, null, null, args);
|
const result = await document.add(domainId, content, owner, document.TYPE_PROBLEM, docId, null, null, args);
|
||||||
|
args.content = content;
|
||||||
|
args.owner = owner;
|
||||||
|
args.docType = document.TYPE_PROBLEM;
|
||||||
await bus.emit('problem/add', args, result);
|
await bus.emit('problem/add', args, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
import React from 'react';
|
||||||
|
|
||||||
|
export default class MessagePadContainer extends React.PureComponent {
|
||||||
|
Textbox(args, name) {
|
||||||
|
return (
|
||||||
|
<label htmlFor={`textbox${name}`}>
|
||||||
|
{args.desc}
|
||||||
|
<div name={`form_item_${name}`} className="textbox-container">
|
||||||
|
<input type="text" name={name} id={`textbox${name}`} className="textbox"></input>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Radio(args, name) {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{args.desc}
|
||||||
|
{args.choices.map((i) => (
|
||||||
|
<label className="radiobox" htmlFor={`radio${name}`}>
|
||||||
|
<input type="radio" name={name} id={`radio${name}`} value={i} /> {i} <br />
|
||||||
|
</label>
|
||||||
|
))}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<form>
|
||||||
|
{this.props.panel.map((i, name) => (
|
||||||
|
<div className="row">
|
||||||
|
<div className="medium-7 columns form__item end">
|
||||||
|
{i.type === 'textbox' && this.Textbox(i, name)}
|
||||||
|
{i.type === 'radio' && this.Radio(i, name)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<input type="submit" className="button rounded primary" value="提交" />
|
||||||
|
</form>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hydrooj/ui-default",
|
"name": "@hydrooj/ui-default",
|
||||||
"version": "4.5.10",
|
"version": "4.5.11",
|
||||||
"author": "undefined <i@undefined.moe>",
|
"author": "undefined <i@undefined.moe>",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"main": "hydro.js",
|
"main": "hydro.js",
|
||||||
@@ -31,7 +31,6 @@
|
|||||||
"babel-loader": "^8.2.2",
|
"babel-loader": "^8.2.2",
|
||||||
"babel-plugin-lodash": "^3.3.4",
|
"babel-plugin-lodash": "^3.3.4",
|
||||||
"babel-plugin-prismjs": "^2.0.1",
|
"babel-plugin-prismjs": "^2.0.1",
|
||||||
"base-64": "^1.0.0",
|
|
||||||
"chalk": "^4.1.0",
|
"chalk": "^4.1.0",
|
||||||
"classnames": "^2.3.1",
|
"classnames": "^2.3.1",
|
||||||
"clipboard": "^2.0.8",
|
"clipboard": "^2.0.8",
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import yaml from 'js-yaml';
|
||||||
import { NamedPage } from 'vj/misc/Page';
|
import { NamedPage } from 'vj/misc/Page';
|
||||||
import Navigation from 'vj/components/navigation';
|
import Navigation from 'vj/components/navigation';
|
||||||
import { ActionDialog } from 'vj/components/dialog';
|
import { ActionDialog } from 'vj/components/dialog';
|
||||||
@@ -5,6 +6,7 @@ import loadReactRedux from 'vj/utils/loadReactRedux';
|
|||||||
import delay from 'vj/utils/delay';
|
import delay from 'vj/utils/delay';
|
||||||
import i18n from 'vj/utils/i18n';
|
import i18n from 'vj/utils/i18n';
|
||||||
import request from 'vj/utils/request';
|
import request from 'vj/utils/request';
|
||||||
|
import base64 from 'vj/utils/base64';
|
||||||
|
|
||||||
class ProblemPageExtender {
|
class ProblemPageExtender {
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -211,6 +213,27 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
|
|||||||
unmountReact();
|
unmountReact();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function loadSubjective() {
|
||||||
|
try {
|
||||||
|
const props = yaml.load(base64.decode(document.getElementsByClassName('section__body typo')[0].innerText));
|
||||||
|
$('.loader-container').show();
|
||||||
|
const { default: Subjective } = await import('vj/components/subjective-question/index');
|
||||||
|
const React = await import('react');
|
||||||
|
const ReactDOM = await import('react-dom');
|
||||||
|
|
||||||
|
ReactDOM.render(
|
||||||
|
<div className="section__body typo">
|
||||||
|
<Subjective panel={props}></Subjective>
|
||||||
|
</div>,
|
||||||
|
$('.problem-content').get(0),
|
||||||
|
);
|
||||||
|
$('.loader-container').hide();
|
||||||
|
// eslint-disable-next-line no-empty
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$(document).on('click', '[name="problem-sidebar__open-scratchpad"]', (ev) => {
|
$(document).on('click', '[name="problem-sidebar__open-scratchpad"]', (ev) => {
|
||||||
enterScratchpadMode();
|
enterScratchpadMode();
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
@@ -224,6 +247,7 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
|
|||||||
$('[name="problem-sidebar__categories"]').show();
|
$('[name="problem-sidebar__categories"]').show();
|
||||||
});
|
});
|
||||||
$('[name="problem-sidebar__send-to"]').click(() => handleClickCopyProblem());
|
$('[name="problem-sidebar__send-to"]').click(() => handleClickCopyProblem());
|
||||||
|
loadSubjective();
|
||||||
});
|
});
|
||||||
|
|
||||||
export default page;
|
export default page;
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
import base64 from 'base-64';
|
|
||||||
import Clipboard from 'clipboard';
|
import Clipboard from 'clipboard';
|
||||||
|
|
||||||
import { NamedPage } from 'vj/misc/Page';
|
import { NamedPage } from 'vj/misc/Page';
|
||||||
import substitute from 'vj/utils/substitute';
|
import substitute from 'vj/utils/substitute';
|
||||||
import Notification from 'vj/components/notification';
|
import Notification from 'vj/components/notification';
|
||||||
import i18n from 'vj/utils/i18n';
|
import i18n from 'vj/utils/i18n';
|
||||||
|
import base64 from 'vj/utils/base64';
|
||||||
|
|
||||||
const page = new NamedPage('user_detail', async () => {
|
const page = new NamedPage('user_detail', async () => {
|
||||||
$('[name="profile_contact_copy"]').get().forEach((el) => {
|
$('[name="profile_contact_copy"]').get().forEach((el) => {
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
const Base64 = {
|
||||||
|
_keyStr: 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=',
|
||||||
|
|
||||||
|
encode(input) {
|
||||||
|
let output = '';
|
||||||
|
let chr1;
|
||||||
|
let chr2;
|
||||||
|
let chr3;
|
||||||
|
let enc1;
|
||||||
|
let enc2;
|
||||||
|
let enc3;
|
||||||
|
let enc4;
|
||||||
|
let i = 0;
|
||||||
|
input = Base64._utf8_encode(input);
|
||||||
|
while (i < input.length) {
|
||||||
|
chr1 = input.charCodeAt(i++);
|
||||||
|
chr2 = input.charCodeAt(i++);
|
||||||
|
chr3 = input.charCodeAt(i++);
|
||||||
|
enc1 = chr1 >> 2;
|
||||||
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||||
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||||
|
enc4 = chr3 & 63;
|
||||||
|
if (Number.isNaN(chr2)) enc3 = enc4 = 64;
|
||||||
|
else if (Number.isNaN(chr3)) enc4 = 64;
|
||||||
|
output = output
|
||||||
|
+ this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2)
|
||||||
|
+ this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
decode(input) {
|
||||||
|
let output = '';
|
||||||
|
let chr1;
|
||||||
|
let chr2;
|
||||||
|
let chr3;
|
||||||
|
let enc1;
|
||||||
|
let enc2;
|
||||||
|
let enc3;
|
||||||
|
let enc4;
|
||||||
|
let i = 0;
|
||||||
|
input = input.replace(/[^A-Za-z0-9+/=]/g, '');
|
||||||
|
while (i < input.length) {
|
||||||
|
enc1 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc2 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc3 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc4 = this._keyStr.indexOf(input.charAt(i++));
|
||||||
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||||
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||||
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||||
|
output += String.fromCharCode(chr1);
|
||||||
|
if (enc3 !== 64) output += String.fromCharCode(chr2);
|
||||||
|
if (enc4 !== 64) output += String.fromCharCode(chr3);
|
||||||
|
}
|
||||||
|
output = Base64._utf8_decode(output);
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
_utf8_encode(string) {
|
||||||
|
string = string.replace(/\r\n/g, '\n');
|
||||||
|
let utftext = '';
|
||||||
|
for (let n = 0; n < string.length; n++) {
|
||||||
|
const c = string.charCodeAt(n);
|
||||||
|
if (c < 128) {
|
||||||
|
utftext += String.fromCharCode(c);
|
||||||
|
} else if ((c > 127) && (c < 2048)) {
|
||||||
|
utftext += String.fromCharCode((c >> 6) | 192);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
} else {
|
||||||
|
utftext += String.fromCharCode((c >> 12) | 224);
|
||||||
|
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
|
||||||
|
utftext += String.fromCharCode((c & 63) | 128);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return utftext;
|
||||||
|
},
|
||||||
|
|
||||||
|
_utf8_decode(utftext) {
|
||||||
|
let string = '';
|
||||||
|
let i = 0;
|
||||||
|
let c = 0;
|
||||||
|
let c2 = 0;
|
||||||
|
let c3 = 0;
|
||||||
|
while (i < utftext.length) {
|
||||||
|
c = utftext.charCodeAt(i);
|
||||||
|
if (c < 128) {
|
||||||
|
string += String.fromCharCode(c);
|
||||||
|
i++;
|
||||||
|
} else if ((c > 191) && (c < 224)) {
|
||||||
|
c2 = utftext.charCodeAt(i + 1);
|
||||||
|
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
|
||||||
|
i += 2;
|
||||||
|
} else {
|
||||||
|
c2 = utftext.charCodeAt(i + 1);
|
||||||
|
c3 = utftext.charCodeAt(i + 2);
|
||||||
|
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
|
||||||
|
i += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Base64;
|
||||||
|
window.Hydro.utils.base64 = Base64;
|
||||||
Reference in new issue
Block a user