ui: 支持客观题配置

This commit is contained in:
undefined committed 2021-04-07 17:29:56 +08:00
1 parent cb91c6ba71
commit ec4971d213
7 files changed
+179 -5

No files matched your search

+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "hydrooj",
"version": "2.21.17",
"version": "2.21.18",
"bin": "bin/hydrooj.js",
"main": "dist/loader.js",
"typings": "dist/loader.d.ts",
@@ -11,7 +11,7 @@
"node": ">=14"
},
"dependencies": {
"@hydrooj/utils": "^1.0.0",
"@hydrooj/utils": "^1.0.1",
"adm-zip": "^0.5.5",
"ansi_up": "^5.0.0",
"cookies": "^0.8.0",
+3
View File
@@ -62,6 +62,9 @@ export class ProblemModel {
if (pid) args.pid = pid;
await bus.serial('problem/before-add', 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);
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 -2
View File
@@ -1,6 +1,6 @@
{
"name": "@hydrooj/ui-default",
"version": "4.5.10",
"version": "4.5.11",
"author": "undefined <i@undefined.moe>",
"license": "AGPL-3.0",
"main": "hydro.js",
@@ -31,7 +31,6 @@
"babel-loader": "^8.2.2",
"babel-plugin-lodash": "^3.3.4",
"babel-plugin-prismjs": "^2.0.1",
"base-64": "^1.0.0",
"chalk": "^4.1.0",
"classnames": "^2.3.1",
"clipboard": "^2.0.8",
@@ -1,3 +1,4 @@
import yaml from 'js-yaml';
import { NamedPage } from 'vj/misc/Page';
import Navigation from 'vj/components/navigation';
import { ActionDialog } from 'vj/components/dialog';
@@ -5,6 +6,7 @@ import loadReactRedux from 'vj/utils/loadReactRedux';
import delay from 'vj/utils/delay';
import i18n from 'vj/utils/i18n';
import request from 'vj/utils/request';
import base64 from 'vj/utils/base64';
class ProblemPageExtender {
constructor() {
@@ -211,6 +213,27 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
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) => {
enterScratchpadMode();
ev.preventDefault();
@@ -224,6 +247,7 @@ const page = new NamedPage(['problem_detail', 'contest_detail_problem', 'homewor
$('[name="problem-sidebar__categories"]').show();
});
$('[name="problem-sidebar__send-to"]').click(() => handleClickCopyProblem());
loadSubjective();
});
export default page;
@@ -1,10 +1,10 @@
import base64 from 'base-64';
import Clipboard from 'clipboard';
import { NamedPage } from 'vj/misc/Page';
import substitute from 'vj/utils/substitute';
import Notification from 'vj/components/notification';
import i18n from 'vj/utils/i18n';
import base64 from 'vj/utils/base64';
const page = new NamedPage('user_detail', async () => {
$('[name="profile_contact_copy"]').get().forEach((el) => {
+105
View File
@@ -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;