This commit is contained in:
nopy 2024-07-01 21:48:29 +08:00
parent 634321d69d
commit 1beb4fdb86
30 changed files with 758 additions and 155 deletions

2
.gitignore vendored
View File

@ -1,4 +1,2 @@
.idea .idea
node_modules node_modules
__pycache__
public

View File

@ -38,6 +38,7 @@
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"redux": "^5.0.1", "redux": "^5.0.1",
"socket.io-client": "^4.7.5",
"stream": "^0.0.2", "stream": "^0.0.2",
"swr": "^2.2.5", "swr": "^2.2.5",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
@ -4009,6 +4010,11 @@
"@sinonjs/commons": "^1.7.0" "@sinonjs/commons": "^1.7.0"
} }
}, },
"node_modules/@socket.io/component-emitter": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz",
"integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA=="
},
"node_modules/@surma/rollup-plugin-off-main-thread": { "node_modules/@surma/rollup-plugin-off-main-thread": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", "resolved": "https://registry.npmmirror.com/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz",
@ -5441,7 +5447,7 @@
}, },
"node_modules/@xterm/xterm": { "node_modules/@xterm/xterm": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmmirror.com/@xterm/xterm/-/xterm-5.5.0.tgz", "resolved": "https://registry.npmjs.org/@xterm/xterm/-/xterm-5.5.0.tgz",
"integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==" "integrity": "sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A=="
}, },
"node_modules/@xtuc/ieee754": { "node_modules/@xtuc/ieee754": {
@ -7865,6 +7871,46 @@
"node": ">= 0.8" "node": ">= 0.8"
} }
}, },
"node_modules/engine.io-client": {
"version": "6.5.4",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.4.tgz",
"integrity": "sha512-GeZeeRjpD2qf49cZQ0Wvh/8NJNfeXkXXcoGh+F77oEAgo9gUHwT1fCRxSNU+YEEaysOJTnsFHmM5oAcPy4ntvQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.0.0"
}
},
"node_modules/engine.io-client/node_modules/ws": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/engine.io-parser": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.2.tgz",
"integrity": "sha512-RcyUFKA93/CXH20l4SoVvzZfrSDMOTUS3bWVpTt2FuFP+XYrL8i8oonHP7WInRyVHXh0n/ORtoeiE1os+8qkSw==",
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/enhanced-resolve": { "node_modules/enhanced-resolve": {
"version": "5.16.0", "version": "5.16.0",
"resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz",
@ -16477,6 +16523,32 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/socket.io-client": {
"version": "4.7.5",
"resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz",
"integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.2",
"engine.io-client": "~6.5.2",
"socket.io-parser": "~4.2.4"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/socket.io-parser": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz",
"integrity": "sha512-/GbIKmo8ioc+NIWIhwdecY0ge+qVBSMdgxGygevmdHj24bsfgtCmcUUcQ5ZzcylGFHsN3k4HB4Cgkl96KVnuew==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/sockjs": { "node_modules/sockjs": {
"version": "0.3.24", "version": "0.3.24",
"resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz", "resolved": "https://registry.npmmirror.com/sockjs/-/sockjs-0.3.24.tgz",
@ -18912,6 +18984,14 @@
"resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz", "resolved": "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz",
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==" "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw=="
}, },
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/y18n": { "node_modules/y18n": {
"version": "5.0.8", "version": "5.0.8",
"resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz",

View File

@ -32,6 +32,7 @@
"react-scripts": "^5.0.1", "react-scripts": "^5.0.1",
"recharts": "^2.12.7", "recharts": "^2.12.7",
"redux": "^5.0.1", "redux": "^5.0.1",
"socket.io-client": "^4.7.5",
"stream": "^0.0.2", "stream": "^0.0.2",
"swr": "^2.2.5", "swr": "^2.2.5",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",

View File

@ -0,0 +1,89 @@
import { Terminal } from "@xterm/xterm";
import "@xterm/xterm/css/xterm.css";
import React, { useEffect, useState, useRef } from 'react';
import { useLocation } from 'react-router-dom';
import io, { Socket } from "socket.io-client";
function base64Decode(encoded: string): string {
return atob(encoded);
}
export default function WebSSH() {
const location = useLocation();
const terminalObj = useRef<HTMLDivElement | null>(null);
const [terminal, setTerminal] = useState<Terminal | null>(null);
const [socket, setSocket] = useState<Socket | null>(null);
const [ip, setIp] = useState("");
const [port, setPort] = useState("");
const [password, setPassword] = useState("");
useEffect(() => {
const params = new URLSearchParams(location.search);
const encodedIp = params.get("ip");
const encodedPort = params.get("port");
const encodedPassword = params.get("password");
if (encodedIp && encodedPort && encodedPassword) {
setIp(base64Decode(encodedIp));
setPort(base64Decode(encodedPort));
setPassword(base64Decode(encodedPassword));
}
}, [location]);
useEffect(() => {
if (terminal === null) {
setTerminal(new Terminal());
}
}, []);
useEffect(() => {
if (terminal !== null) {
terminal.open(terminalObj.current as HTMLDivElement);
const newSocket = io("ws://36.138.114.105:32087");
setSocket(newSocket);
terminal.onData((data) => {
newSocket.emit("input", data);
});
terminal.onSelectionChange(() => {
if (terminal.hasSelection()) {
navigator.clipboard.writeText(terminal.getSelection());
}
});
setInterval(() => {
newSocket.emit("heartbeat");
}, 1000);
newSocket.on("output", (data: string) => {
terminal.write(data);
});
return () => {
newSocket.disconnect();
};
}
}, [terminal]);
useEffect(() => {
if (socket && ip && port && password) {
socket.emit("connect_ssh", { ip, port, password });
}
}, [socket, ip, port, password]);
function pasteContent(event: React.MouseEvent) {
navigator.clipboard.readText().then((content) => {
socket?.emit("input", content);
});
event.preventDefault();
}
return (
<div>
<div ref={terminalObj} onContextMenu={pasteContent} style={{ height: "100vh", width: "100%" }}>
</div>
</div>
);
}

View File

@ -202,9 +202,8 @@
.calendar-box span{ .calendar-box span{
position: absolute; position: absolute;
/* top: 20px; */ top: 400px;
top: 380px; right: 185px;
right: 160px;
} }
.calendar1{ .calendar1{
width: 100px; width: 100px;

View File

@ -3,7 +3,8 @@ import { Link } from 'react-router-dom';
import './SendTrain.css' import './SendTrain.css'
import axios from 'axios'; import axios from 'axios';
import DatePicker from 'react-datepicker'; import DatePicker from 'react-datepicker';
import 'react-datepicker/dist/react-datepicker.css'; import "react-datepicker/dist/react-datepicker.css";
function SendTrain(){ function SendTrain(){
const teacher_ID=localStorage.getItem('islogin') const teacher_ID=localStorage.getItem('islogin')
@ -138,29 +139,17 @@ function SendTrain(){
} }
// //
//
const [startDate, setStartDate] = useState(new Date()); const [startDate, setStartDate] = useState(new Date());
const [endDate, setEndDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date());
// //
const formatDate = (date) => {
return date.toLocaleDateString();
};
//
const handleStartDateChange = (date) => { const handleStartDateChange = (date) => {
setStartDate(date); setStartDate(date);
}; };
//
const handleEndDateChange = (date) => { const handleEndDateChange = (date) => {
setEndDate(date); setEndDate(date);
}; };
//
const calculateTotalDays = () => {
const differenceInTime = endDate - startDate;
const differenceInDays = Math.floor(differenceInTime / (1000 * 60 * 60 * 24));
return differenceInDays;
};
useEffect(() => {
console.log(calculateTotalDays());
}, [startDate, endDate]);
return( return(
<div className='SendTrain_body'> <div className='SendTrain_body'>
@ -346,27 +335,32 @@ function SendTrain(){
{/* 日历 */} {/* 日历 */}
<p>请填写考试开始截止日期</p> <p>请填写考试开始截止日期</p>
<div className='calendar-box'> <div className='calendar-box'>
{/* 开始时间输入框 */}
<div className='start-date-input'>
{/* 日历组件 */}
<div className='calendar-picker'>
<DatePicker <DatePicker
selected={startDate} selected={startDate}
onChange={handleStartDateChange} onChange={handleStartDateChange}
dateFormat="yyyy/MM/dd" dateFormat="yyyy-MM-dd HH:mm"
placeholderText="选择开始日期" showTimeSelect
popperPlacement="left-start" timeIntervals={10} //
className='calendar1' timeCaption="time"
minDate={new Date()} //
/> />
<span>-</span>
<DatePicker <DatePicker
selected={endDate} selected={endDate}
onChange={handleEndDateChange} onChange={handleEndDateChange}
dateFormat="yyyy/MM/dd" dateFormat="yyyy-MM-dd HH:mm"
placeholderText="选择结束日期" showTimeSelect
minDate={startDate} // timeIntervals={10}
withFullScreenPortal={false} // timeCaption="time"
popperPlacement="left-start" minDate={startDate || new Date()} //
className='calendar2'
/> />
</div> </div>
<p className='data-num'>总天数{calculateTotalDays()}</p>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -11,11 +11,10 @@ import { max, min } from 'lodash';
// //
function Home(){ function Home(){
const [isChecked,setisChecked]=useState(false)
const student_ID=localStorage.getItem('islogin') const student_ID=localStorage.getItem('islogin')
if(student_ID==null){ if(student_ID==null){
window.location.href='http://localhost:3000/signin'
alert('未登录,请先前往登录') alert('未登录,请先前往登录')
window.location.href='http://36.138.114.105:30294/'
} }
// //
const [lesson, setLesson] = useState([]); const [lesson, setLesson] = useState([]);

View File

@ -120,3 +120,12 @@
margin-top: 5px; margin-top: 5px;
cursor: pointer; cursor: pointer;
} }
.body-right1-exam{
width: 1414px;
height: 1540px;
position: absolute;
top: 64px;
left: 230px;
border-radius: 10px;
background-color: #f7f8fa;
}

View File

@ -10,10 +10,66 @@ import top from '../img/top.jpg'
import axios from 'axios'; import axios from 'axios';
function Exam() { function Exam() {
// //
const [countdown, setCountdown] = useState(null); const [countdown, setCountdown] = useState(null);
const {examId}=useParams()
const student_ID=localStorage.getItem('islogin')
const [score,setscore]=useState(0)
const [isEntry,setisEntry]=useState(false)
//
const [TestData,setTestData]=useState()
const TestFunc=async ()=>{
try{
const TestSrc=await axios.post('/api/student/TestData',{
examId
})
const data=TestSrc.data
setTestData(data)
}catch{
alert('TestSrc出错')
}
}
useEffect(()=>{
TestFunc()
},[])
//
const scoreEntry=async()=>{
try{
const scoreEntrySrc=await axios.post('/api/student/score_entry',{
student_ID,
examId,
score
})
}catch{
alert('scoreEntry出错')
}
}
useEffect(()=>{
if(isEntry){
scoreEntry()
}
},[score])
function daojishi(){
if(localStorage.getItem('time')){
setCountdown(localStorage.getItem('time'))
}else{
if(TestData){
setCountdown(60 * parseInt(TestData['examID'][3]))
}
}
}
useEffect(()=>{
daojishi()
console.log('a');
},[TestData])
// //
useEffect(() => { useEffect(() => {
@ -24,18 +80,21 @@ function Exam() {
} else { } else {
clearInterval(interval); clearInterval(interval);
alert('考试时间到!'); alert('考试时间到!');
correct()
window.location.href='http://localhost:3000/subject'
} }
}, 1000); }, 1000);
return () => clearInterval(interval); return () => clearInterval(interval);
}, [countdown]); }, [countdown]);
// useEffect(()=>{ useEffect(()=>{
// if(countdown<0){ if(countdown<0){
// console.log('c'); localStorage.removeItem('time')
// setCountdown(60 * parseInt(TrainData['operateID'][4])) setCountdown(60 * parseInt(TestData['examID'][3]))
// localStorage.removeItem('time')
// } }
// },[TrainData]) },[TestData])
// //
const formatTime = (seconds) => { const formatTime = (seconds) => {
@ -48,6 +107,109 @@ function Exam() {
// //
const [isSubjectDropdownOpen, setIsSubjectDropdownOpen] = useState(false); const [isSubjectDropdownOpen, setIsSubjectDropdownOpen] = useState(false);
//
const [choice_answer,setchoice_answer]=useState({})
const [completion_answer,setcompletion_answer]=useState({})
const [judge_answer,setjudge_answer]=useState({})
//
const [answeredChoice, setAnsweredChoice] = useState([]);
const [answeredComple, setAnsweredComple] = useState([]);
const [answeredJudge, setAnsweredJudge] = useState([]);
//
const handleOptionChange = (event) => {
const selectedValue = event.target.value;
const key = parseInt(event.target.name.replace('group', ''));
const updatedChoiceAnswer = { ...choice_answer, [key]: selectedValue };
setchoice_answer(updatedChoiceAnswer);
//
if (!answeredChoice.includes(key)) {
setAnsweredChoice([...answeredChoice, key]);
}
};
//
const handleInputChange = (event) => {
const { name, value } = event.target;
setcompletion_answer({
...completion_answer,
[name]: value
});
if (!answeredComple.includes(parseInt(name))) {
setAnsweredComple([...answeredComple, parseInt(name)]);
}
};
//
const handleJudgeOption=(event)=>{
const judgeoption=event.target.value;
const key=parseInt(event.target.name.replace('judge',''))
const updatedJudgeAnswer={ ...judge_answer,[key]:judgeoption}
setjudge_answer(updatedJudgeAnswer)
if (!answeredJudge.includes(key)) {
setAnsweredJudge([...answeredJudge, key]);
}
}
//
const correct=()=>{
let CHO_sum=0;
let COM_sum=0;
let JUD_sum=0;
for(let item of TestData['examID'][0]){
if(item[0][6]===choice_answer[CHO_sum]){
setscore(prevscore=>prevscore+5)
}
CHO_sum++
}
for(let item of TestData['examID'][1]){
if (item[0][2]===completion_answer[COM_sum]) {
setscore(prevscore=>prevscore+5)
}
COM_sum++
}
for(let item of TestData['examID'][2]){
if (item[0][2]===judge_answer[JUD_sum]) {
setscore(prevscore=>prevscore+5)
}
JUD_sum++
}
setisEntry(true)
}
const submit=()=>{
correct()
setCountdown(0)
localStorage.removeItem('time')
alert('提交成功')
window.location.href='http://localhost:3000/subject'
}
//
const [isFixed,setIsFixed]=useState(false)
//
const handleScroll = () => {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
const fixedThreshold = 100; // 100px
if (scrollTop > fixedThreshold) {
setIsFixed(true);
} else {
setIsFixed(false);
}
};
//
useEffect(() => {
window.addEventListener('scroll', handleScroll);
return () => {
window.removeEventListener('scroll', handleScroll);
};
}, []);
return ( return (
<div> <div>
<div className='nav-exam'> <div className='nav-exam'>
@ -78,32 +240,99 @@ function Exam() {
</ul> </ul>
{/* 题目预览框 */} {/* 题目预览框 */}
{/* 根据isFixed状态来设置countBox的类 */} {/* 根据isFixed状态来设置countBox的类 */}
{/* <div className={`countBox ${isFixed ? 'fixed-count-box' : ''}`}> <div className={`countBox ${isFixed ? 'fixed-count-box' : ''}`}> {/* 根据isFixed状态来设置countBox的类 */}
{TrainData&&<table> {TestData&&<table>
<tr>选择题:</tr> <tr>选择题:</tr>
<div> <div>
{Object.keys(TrainData['operateID'][0]).map((key,index)=>( {Object.keys(TestData['examID'][0]).map((key,index)=>(
<td key={key} className={answeredChoice.includes(index) ? 'answered' : ''}>{index+1}</td> <td key={key} className={answeredChoice.includes(index) ? 'answered' : ''}>{index+1}</td>
))} ))}
</div> </div>
<tr>填空题</tr> <tr>填空题</tr>
<div> <div>
{Object.keys(TrainData['operateID'][1]).map((key,index)=>( {Object.keys(TestData['examID'][1]).map((key,index)=>(
<td key={key} className={answeredComple.includes(index) ? 'answered' : ''}>{index+1}</td> <td key={key} className={answeredComple.includes(index) ? 'answered' : ''}>{index+1}</td>
))} ))}
</div> </div>
<tr>判断题</tr> <tr>判断题</tr>
<div> <div>
{Object.keys(TrainData['operateID'][2]).map((key,index)=>( {Object.keys(TestData['examID'][2]).map((key,index)=>(
<td key={key} className={answeredJudge.includes(index) ? 'answered' : ''}>{index+1}</td> <td key={key} className={answeredJudge.includes(index) ? 'answered' : ''}>{index+1}</td>
))} ))}
</div> </div>
</table>} </table>}
</div> */}
</div> </div>
{/* <div className='body-right1-exam'>
</div> */} </div>
<div className='body-right1'>
{TestData&&<table>
<p>选择题</p>
<tbody>
{Object.keys(TestData['examID'][0]).map((key,index) => (
<tr key={key}>
<tr className='test-title'>{index+1}.{TestData['examID'][0][key][0][1]}</tr>
<div className='optionBox'>
<label>
<input type="radio" value={TestData['examID'][0][key][0][2]} checked={choice_answer[key] === TestData['examID'][0][key][0][2]} onChange={handleOptionChange} name={`group${key}`}/>
<span>A.{TestData['examID'][0][key][0][2]}</span>
</label>
<br />
<label>
<input type="radio" value={TestData['examID'][0][key][0][3]} checked={choice_answer[key] === TestData['examID'][0][key][0][3]} onChange={handleOptionChange} name={`group${key}`}/>
<span>B.{TestData['examID'][0][key][0][3]}</span>
</label>
<br />
<label>
<input type="radio" value={TestData['examID'][0][key][0][4]} checked={choice_answer[key] === TestData['examID'][0][key][0][4]} onChange={handleOptionChange} name={`group${key}`}/>
<span>C.{TestData['examID'][0][key][0][4]}</span>
</label>
<br />
<label>
<input type="radio" value={TestData['examID'][0][key][0][5]} checked={choice_answer[key] === TestData['examID'][0][key][0][5]} onChange={handleOptionChange} name={`group${key}`}/>
<span>D.{TestData['examID'][0][key][0][5]}</span>
</label>
</div>
</tr>
))}
</tbody>
</table>}
{TestData&&(
<table className='body-right1-comple'>
<tbody>
<p>填空题</p>
{Object.keys(TestData['examID'][1]).map((key,index)=>(
<tr key={key}>
<tr className='test-title1'>{index+1}.{TestData['examID'][1][key][0][1]}</tr>
{/* <br /> */}
<div className='input-box'>
<span>请填入你的答案</span>
<input type="text" onChange={handleInputChange} name={key} value={completion_answer[key]||''}/>
</div>
</tr>
))}
</tbody>
</table>
)}
{TestData&&(
<table>
<tbody>
<p>判断题</p>
{Object.keys(TestData['examID'][2]).map((key,index)=>(
<tr key={key} className='panduan-box'>
<tr>{index+1}.{TestData['examID'][2][key][0][1]}</tr>
<tr>
<label><input type="radio" name={`judge${key}`} checked={judge_answer[key] === 'true'} onChange={handleJudgeOption} value={true} />T</label>
<label><input type="radio" name={`judge${key}`} checked={judge_answer[key] === 'false'} onChange={handleJudgeOption} value={false} />F</label>
</tr>
</tr>
))}
</tbody>
</table>
)}
<button onClick={submit}>提交</button>
</div>
</div> </div>
</div> </div>
) )

View File

@ -57,9 +57,8 @@ function SubjectPage(){
))} ))}
</div>} </div>}
<h3>已结束或完成的试卷与练习</h3> <h3>已结束或完成的试卷与练习</h3>
{ testdata&& result&&<div className='test-subject'> <div className='test-subject'>
{Object.keys(testdata).map((key)=>{ { Object.keys(testdata).slice(-3).reverse().map((key) => (
return(
<div className='test-box' key={key}> <div className='test-box' key={key}>
<p>试卷ID:{testdata[key][0][3]}</p> <p>试卷ID:{testdata[key][0][3]}</p>
<span>发布者:{'小陈老师'}</span> <span>发布者:{'小陈老师'}</span>
@ -67,9 +66,9 @@ function SubjectPage(){
<div>截至时间:{testdata[key][1][0][6]}</div> <div>截至时间:{testdata[key][1][0][6]}</div>
<div id='score'>{testdata[key][0][5]}</div> <div id='score'>{testdata[key][0][5]}</div>
</div> </div>
) ))}
})} </div>
</div>} <button>更多历史</button>
{ NotFalse&& result&&<div className='test-subject'> { NotFalse&& result&&<div className='test-subject'>
{Object.keys(NotFalse).map((key)=>{ {Object.keys(NotFalse).map((key)=>{
return( return(

View File

@ -16,19 +16,9 @@ function Operation1() {
console.log(60 * parseInt(TrainData['operateID'][4])); console.log(60 * parseInt(TrainData['operateID'][4]));
} }
const clear=()=>{ const clear=()=>{
localStorage.removeItem('choice_answers'); ['time', 'choice_answers', 'completion_answer', 'judge_answer',
setchoice_answer({}) 'answeredChoice', 'answeredComple', 'answeredJudge', 'RemainingTime', 'TrainData']
localStorage.removeItem('completion_answer') .forEach(item => localStorage.removeItem(item));
setcompletion_answer({})
localStorage.removeItem('judge_answer')
setjudge_answer({})
localStorage.removeItem('answeredChoice')
setAnsweredChoice([])
localStorage.removeItem('answeredComple')
setAnsweredComple([])
localStorage.removeItem('answeredJudge')
setAnsweredJudge([])
localStorage.removeItem('RemainingTime')
} }
const { operateID } = useParams(); const { operateID } = useParams();
@ -85,7 +75,6 @@ function Operation1() {
useEffect(()=>{ useEffect(()=>{
if(countdown<0){ if(countdown<0){
console.log('c');
setCountdown(60 * parseInt(TrainData['operateID'][4])) setCountdown(60 * parseInt(TrainData['operateID'][4]))
localStorage.removeItem('time') localStorage.removeItem('time')
} }

View File

@ -146,8 +146,16 @@ function Operation2() {
const tijiao = ()=>{ const tijiao = ()=>{
setCountdown(0) setCountdown(0)
localStorage.removeItem('time') localStorage.removeItem('time')
localStorage.removeItem('choice_answers');
localStorage.removeItem('completion_answer')
localStorage.removeItem('judge_answer')
localStorage.removeItem('answeredChoice')
localStorage.removeItem('answeredComple')
localStorage.removeItem('answeredJudge')
localStorage.removeItem('RemainingTime')
alert('提交成功') alert('提交成功')
window.location.href='http://localhost:3000/train' window.location.href='http://localhost:3000/train'
localStorage.removeItem('TrainData')
} }
return ( return (
@ -184,7 +192,7 @@ function Operation2() {
<button onClick={click}>测试按钮</button> <button onClick={click}>测试按钮</button>
{/* 前端连接数据库⬇ */} {/* 前端连接数据库⬇ */}
{ !isTrue&&<div> { !isTrue&&TrainData&&<div>
<Link to={Src}>{TrainData['operateID'][3][0]}</Link> <Link to={Src}>{TrainData['operateID'][3][0]}</Link>
<br /> <br />
点击以上链接前往实训 点击以上链接前往实训
@ -192,7 +200,7 @@ function Operation2() {
{/* 前端连接数据库 ⬆*/} {/* 前端连接数据库 ⬆*/}
{/* 达梦数据库连接 ⬇*/} {/* 达梦数据库连接 ⬇*/}
{ isTrue&& { isTrue&&TrainData&&
<div> <div>
<p>{TrainData['operateID'][3][0]}</p> <p>{TrainData['operateID'][3][0]}</p>
<div style={{width: "1430px",position:'absolute',right:'0'}} ref={terminalObj} onContextMenu={pasteContent}></div> <div style={{width: "1430px",position:'absolute',right:'0'}} ref={terminalObj} onContextMenu={pasteContent}></div>

View File

@ -23,11 +23,12 @@ import ClassID from '../TeacherPages/classlistpages/classId';
import ManageTest from '../TeacherPages/TestManage/ManageTest'; import ManageTest from '../TeacherPages/TestManage/ManageTest';
import SendTest from '../TeacherPages/TestManage/SendTest'; import SendTest from '../TeacherPages/TestManage/SendTest';
import Marking from '../TeacherPages/MarkingPages/Marking'; import Marking from '../TeacherPages/MarkingPages/Marking';
import SendTrain from '../TeacherPages/TrainManage/SendTrain'
import TrainManage from '../TeacherPages/TrainManage/Trainmanage'
import StudentLink from '../TeacherPages/MarkingPages/StudentLink'; import StudentLink from '../TeacherPages/MarkingPages/StudentLink';
import SendTrain from '../TeacherPages/TrainManage/SendTrain';
import TrainManage from '../TeacherPages/TrainManage/Trainmanage';
import Test from "../TeacherPages/teacherManagetest/Test.tsx"
// (exam)使 // (exam)使
const MainLayout = ({ headerNav:HeaderNav }) => { const MainLayout = ({ headerNav:HeaderNav }) => {
return ( return (
@ -69,6 +70,7 @@ function App() {
<Route path="/classID/:key" element={<MainLayout headerNav={HeaderNavTeacher} />}> <Route path="/classID/:key" element={<MainLayout headerNav={HeaderNavTeacher} />}>
<Route index element={<ClassID/>} /> <Route index element={<ClassID/>} />
</Route> </Route>
<Route path="test" element={<Test />}/>
{/* 页面使用单独的布局不包含HeaderNav和HeaderNavTeacher */} {/* 页面使用单独的布局不包含HeaderNav和HeaderNavTeacher */}
<Route path="exam/:examId" element={<Exam />} />{/* 练习-考试页面 */} <Route path="exam/:examId" element={<Exam />} />{/* 练习-考试页面 */}

View File

@ -20,13 +20,14 @@ build_image() {
# 推送镜像 # 推送镜像
push_image() { push_image() {
local service_name=$1
read -p "是否要推送到《达梦启元云原生大数据平台》? [Y/N] " confirm read -p "是否要推送到《达梦启元云原生大数据平台》? [Y/N] " confirm
if [[ $confirm =~ ^[yY]([eE][sS])?$ ]]; then if [[ $confirm =~ ^[yY]([eE][sS])?$ ]]; then
echo "tag" echo "${service_name} tag"
docker tag "${current_dir}-flask-app" 36.138.114.105:31000/cnsof50011836/flask-app docker tag "${service_name}" 36.138.114.105:31000/cnsof50011836/$service_name
echo "pushing" echo "${service_name} pushing"
docker push 36.138.114.105:31000/cnsof50011836/flask-app docker push 36.138.114.105:31000/cnsof50011836/$service_name
echo "pushed" echo "${service_name} pushed"
else else
echo "用户选择不推送镜像" echo "用户选择不推送镜像"
fi fi
@ -43,7 +44,8 @@ main() {
build_image build-frontend build_image build-frontend
build_image flask-app build_image flask-app
push_image push_image flask-app
push_image base-dm
echo "脚本结束" echo "脚本结束"
} }

View File

@ -23,14 +23,11 @@ services:
flask-app: flask-app:
build: ./python build: ./python
restart: always restart: always
image: flask-app
depends_on: depends_on:
- base-dm - base-dm
ports: ports:
- '8000:8000' - '8000:8000'
healthcheck: - '8765:8765'
test: ["CMD-SHELL", "curl --silent --fail localhost:8000/flask-health-check || exit 1"]
interval: 10s
timeout: 10s
retries: 3
command: gunicorn -w 3 -t 60 -b 0.0.0.0:8000 app:app command: gunicorn -w 3 -t 60 -b 0.0.0.0:8000 app:app

View File

@ -6,8 +6,8 @@ RUN useradd -m -s /bin/bash dmdba \
WORKDIR /home/dmdba WORKDIR /home/dmdba
# 传入安装包并解压 # 传入安装包并解压
RUN wget https://download.dameng.com/eco/adapter/DM8/202405/dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip RUN wget https://download.dameng.com/eco/adapter/DM8/202405/dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \
RUN unzip dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \ && unzip dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \
&& chown -R dmdba:dmdba /home/dmdba \ && chown -R dmdba:dmdba /home/dmdba \
&& rm -f dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \ && rm -f dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \
&& 7z x dm8_20240408_x86_rh7_64.iso \ && 7z x dm8_20240408_x86_rh7_64.iso \

View File

@ -9,6 +9,8 @@ RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.l
&& apt-get install -y python3.10-venv libssl-dev sudo vim python3-pip ssh wget unzip p7zip* language-pack-zh-hans language-selector-common locales locales-all \ && apt-get install -y python3.10-venv libssl-dev sudo vim python3-pip ssh wget unzip p7zip* language-pack-zh-hans language-selector-common locales locales-all \
# 设置中文环境 # 设置中文环境
&& apt install -y $(check-language-support) \ && apt install -y $(check-language-support) \
&& sed -i 's/^#PermitRootLogin prohibit-password/PermitRootLogin yes/' /etc/ssh/sshd_config \
&& sudo sed -i 's/^UsePAM yes/UsePAM no/' /etc/ssh/sshd_config \
&& echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \ && echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \
&& sudo /usr/sbin/update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 \ && sudo /usr/sbin/update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 \
&& locale-gen \ && locale-gen \

View File

@ -1,26 +1 @@
FROM ubuntu FROM base-dm
ENV DEBIAN_FRONTEND=noninteractive
ENV LANG=zh_CN.UTF-8
ENV LC_ALL=zh_CN.UTF-8
# 基础软件安装
RUN sed -i 's@//.*archive.ubuntu.com@//mirrors.ustc.edu.cn@g' /etc/apt/sources.list \
&& apt-get -y update && apt-get -y upgrade \
&& apt-get install -y sudo vim python3-pip ssh wget unzip p7zip* language-pack-zh-hans language-selector-common locales locales-all \
# 设置中文环境
&& apt install -y $(check-language-support) \
&& echo "zh_CN.UTF-8 UTF-8" >> /etc/locale.gen \
&& sudo /usr/sbin/update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 \
&& locale-gen \
# 添加用户
&& useradd -m -s /bin/bash dmdba \
# 修改用户密码
&& echo "dmdba:123456" | chpasswd
# 传入安装包并解压
WORKDIR /home/dmdba
RUN wget https://download.dameng.com/eco/adapter/DM8/202405/dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip
RUN unzip dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \
&& chown -R dmdba:dmdba /home/dmdba \
&& rm -f dm8_20240408_x86_rh7_64_ent_8.1.3.140.zip \
&& 7z x dm8_20240408_x86_rh7_64.iso \
&& rm -f dm8_20240408_x86_rh7_64.iso \
&& chmod +x DMInstall.bin

27
python/.devenv Normal file
View File

@ -0,0 +1,27 @@
SHELL=/bin/bash
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_SERVICE_PORT=443
HOSTNAME=flask-app-deployment-76d66d98b8-s6hxs
DMCCA_CANVAS_NAME=flask-app
PWD=/home/flask
LOGNAME=flask
TZ=Asia/Shanghai
HOME=/home/flask
LANG=zh_CN.UTF-8
KUBERNETES_PORT_443_TCP=tcp://10.96.0.1:443
VIRTUAL_ENV=/home/flask/venv
TERM=xterm
USER=flask
DMCCA_CANVAS_NAMESPACE=cnsof50011836-system
SHLVL=2
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_ADDR=10.96.0.1
KUBERNETES_SERVICE_HOST=10.96.0.1
LC_ALL=zh_CN.UTF-8
KUBERNETES_PORT=tcp://10.96.0.1:443
KUBERNETES_PORT_443_TCP_PORT=443
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
MAIL=/var/mail/flask
DEBIAN_FRONTEND=noninteractive
OLDPWD=/root
_=/usr/bin/printenv

3
python/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.idea
__pycache__
public

View File

@ -4,10 +4,12 @@ FROM base
RUN pip install --upgrade pip RUN pip install --upgrade pip
# 创建一个用户运行flask # 创建一个用户运行flask
RUN adduser flask && \ RUN useradd -m -s /bin/bash flask && \
chown -R flask:flask /home/flask && \ chown -R flask:flask /home/flask && \
mkdir -p /var/log/flask-app && touch /var/log/flask-app/flask-app.err.log && touch /var/log/flask-app/flask-app.out.log && \ mkdir -p /var/log/flask-app && touch /var/log/flask-app/flask-app.err.log && touch /var/log/flask-app/flask-app.out.log && \
chown -R flask:flask /var/log/flask-app chown -R flask:flask /var/log/flask-app && \
service ssh start && \
service ssh restart
WORKDIR /home/flask WORKDIR /home/flask
USER flask USER flask
@ -24,10 +26,12 @@ RUN python3 -m venv "$VIRTUAL_ENV" && \
export FLASK_APP=app.py && \ export FLASK_APP=app.py && \
pip3 install dmPython-2.5.5-cp310-cp310-linux_x86_64.whl && rm dmPython-2.5.5-cp310-cp310-linux_x86_64.whl && \ pip3 install dmPython-2.5.5-cp310-cp310-linux_x86_64.whl && rm dmPython-2.5.5-cp310-cp310-linux_x86_64.whl && \
MAKEFLAGS="-j$(nproc)" pip install -r requirements.txt MAKEFLAGS="-j$(nproc)" pip install -r requirements.txt
COPY --from=build-dmpython /home/dmdba/build_artifacts/libdmdpi.so /usr/lib/ COPY --from=build-dmpython /home/dmdba/build_artifacts/libdmdpi.so /usr/lib/
COPY --from=build-frontend /usr/src/app/build/ /home/flask/public/ COPY --from=build-frontend /usr/src/app/build/ /home/flask/public/
# 暴露端口 # 暴露端口
EXPOSE 5000 EXPOSE 8000 22 8765
USER root
CMD ["gunicorn", "-w", "3", "-t", "60", "-b", "0.0.0.0:8000", "app:app"] CMD ["gunicorn", "-w", "3", "-t", "60", "-b", "0.0.0.0:8000", "app:app"]

View File

@ -1,12 +1,28 @@
import subprocess
import threading
import time
import paramiko
from teacher_func import * from teacher_func import *
from student_func import * from student_func import *
from flask import Flask, render_template, request, jsonify, send_from_directory, session from flask import Flask, render_template, request, jsonify, send_from_directory, session
from flask_cors import CORS from flask_cors import CORS
from flask_socketio import SocketIO, emit, disconnect
import logging
logging.basicConfig(level=logging.DEBUG)
app = Flask(__name__, static_folder="public") app = Flask(__name__, static_folder="public")
CORS(app, resources={r"/*": {"origins": "*"}}) CORS(app)
cors = CORS(app, resource={
r"/*":{
"origins":"*"
}
})
app.config['SECRET_KEY'] = '350625' app.config['SECRET_KEY'] = '350625'
socketio = SocketIO(app, cors_allowed_origins="*")
clients = {}
@app.route('/api/student', methods=['POST']) # 检测历史是否登录过登录则直接进入index反之则进去login界面 @app.route('/api/student', methods=['POST']) # 检测历史是否登录过登录则直接进入index反之则进去login界面
def student(): # 判断是否已经登录 def student(): # 判断是否已经登录
@ -103,10 +119,11 @@ def get_test(): # 获取试卷以及历史试卷
result2=falseTest_func(ID) result2=falseTest_func(ID)
return jsonify({"True":result1,'FalseTest':result2}) return jsonify({"True":result1,'FalseTest':result2})
@app.route('/api/student/get_testID',methods=['POST']) @app.route('/api/student/TestData',methods=['POST'])
def get_testID(): # 获取试卷ID def TestData(): # 获取试卷ID
ID=request.json['student_ID'] examID=request.json['examId']
return jsonify({'data': 'a'}) result=TestDataFunc(examID)
return result
@app.route('/api/student/fetch_result', methods=['POST']) # 查找成绩 @app.route('/api/student/fetch_result', methods=['POST']) # 查找成绩
@ -115,11 +132,7 @@ def fetch_result():
ID = data['student_ID'] ID = data['student_ID']
return jsonify({'result': fetch_result_func(ID)}) return jsonify({'result': fetch_result_func(ID)})
@app.route('/api/student/get_end_student', methods=['POST'])
def get_end_student():
data = request.json
ID = data['student_ID']
return jsonify({'result': find_end_test(ID)})
@app.route('/api/student/score_entry', methods=['POST']) @app.route('/api/student/score_entry', methods=['POST'])
@ -183,6 +196,12 @@ def select_class(): # 查找每个老师管理的班级 以及在考试管理
# print(testID) # print(testID)
return jsonify({'Class': class_dic,'default': find_default_class_func(default_class, teacher_id)}) return jsonify({'Class': class_dic,'default': find_default_class_func(default_class, teacher_id)})
@app.route('/api/teacher/marktrain',methods=['POST'])
def mark(): # 批阅试卷
ClassID=request.json['ClassID']
teacher_ID=request.json['teacher_ID']
return jsonify({'MarkClass': MarkTrainFunc(ClassID,teacher_ID)})
@app.route('/api/teacher/change_class', methods=['POST']) @app.route('/api/teacher/change_class', methods=['POST'])
def change_class(): # 查找每个老师管理的班级 以及在考试管理查找默认班级 def change_class(): # 查找每个老师管理的班级 以及在考试管理查找默认班级
teacher_id = request.json['teacher_ID'] teacher_id = request.json['teacher_ID']
@ -242,6 +261,7 @@ def SendTrainTest():
Train=data['Train'] Train=data['Train']
teacher_id=data['teacher_ID'] teacher_id=data['teacher_ID']
SendTrainTestFunc(TrainChoice, TrainCompletion, TrainJudge, Hour, Min, StopTime,Class,Train,teacher_id) SendTrainTestFunc(TrainChoice, TrainCompletion, TrainJudge, Hour, Min, StopTime,Class,Train,teacher_id)
TeacherMark(Class,teacher_id)
return '发布成功' return '发布成功'
@ -250,7 +270,6 @@ def Find_details():
data=request.json data=request.json
ID=data['ID'] ID=data['ID']
result=Find_details_Func(ID) result=Find_details_Func(ID)
print(result)
return jsonify({'TestScore':result}) return jsonify({'TestScore':result})
@ -260,7 +279,56 @@ def catch_all(path = "index.html"):
return send_from_directory("public", path) return send_from_directory("public", path)
@socketio.on('connect_ssh')
def handle_connect_ssh(data):
ip = data['ip']
port = int(data['port'])
password = data['password']
client_id = request.sid
ssh_client = paramiko.SSHClient()
ssh_client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
ssh_client.connect(ip, port=port, username='your-username', password=password)
transport = ssh_client.get_transport()
channel = transport.open_session()
channel.get_pty()
channel.invoke_shell()
clients[client_id] = {
'ssh_client': ssh_client,
'channel': channel
}
socketio.start_background_task(target=read_from_channel, channel=channel, client_id=client_id)
except Exception as e:
emit('output', f'Connection failed: {str(e)}')
def read_from_channel(channel, client_id):
while True:
if channel.recv_ready():
data = channel.recv(1024).decode('utf-8')
socketio.emit('output', data, room=client_id)
@socketio.on('input')
def handle_input(data):
client_id = request.sid
if client_id in clients:
clients[client_id]['channel'].send(data)
@socketio.on('disconnect')
def handle_disconnect():
client_id = request.sid
if client_id in clients:
clients[client_id]['channel'].close()
clients[client_id]['ssh_client'].close()
del clients[client_id]
if __name__ == '__main__': if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True) socketio.run(app, host='0.0.0.0', port=5000 ,allow_unsafe_werkzeug=True)

View File

@ -0,0 +1,19 @@
apiVersion: v1
kind: Pod
metadata:
name: NAME
namespace: ""
labels:
app: NAME
spec:
containers:
- name: base-dm
image: harbor.dameng.io/cnsof50011836/base-dm
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: '1'
memory: 1Gi
requests:
cpu: '0.25'
memory: 0.5G

View File

View File

@ -2,3 +2,7 @@ Flask==2.3.0
Flask_Cors==4.0.0 Flask_Cors==4.0.0
pycryptodome==3.19.0 pycryptodome==3.19.0
gunicorn gunicorn
kubernetes
websockets
paramiko
flask-socketio

View File

@ -117,10 +117,9 @@ def get_lesson_func(id):
def student_succeed_func(ID): def student_succeed_func(ID):
cursor = db.cursor() cursor = db.cursor()
cursor.execute(f'SELECT * FROM STUDENT WHERE ID={ID}') cursor.execute(f'SELECT * FROM STUDENT WHERE ID={ID}')# 报错
student_succeed = cursor.fetchall()[0] student_succeed = cursor.fetchall()[0]
student_succeeds = student_succeed[0], student_succeed[1], student_succeed[3], student_succeed[4] student_succeeds = student_succeed[0], student_succeed[1], student_succeed[3], student_succeed[4]
print(student_succeeds)
cursor.close() cursor.close()
return student_succeeds return student_succeeds
@ -128,17 +127,27 @@ def student_succeed_func(ID):
# fetch_testID('20240101') # fetch_testID('20240101')
def fetch_test_func(ID):#获取试卷 def fetch_test_func(ID):#获取试卷
cursor = db.cursor() cursor = db.cursor()
correct=[]
TrueTestDic={} TrueTestDic={}
TruetestID=[] TruetestID=[]
cursor.execute(f"SELECT * FROM STUDENT_TEST WHERE STUDENT_ID=? AND TF='true'",(ID)) cursor.execute(f"SELECT * FROM STUDENT_TEST WHERE STUDENT_ID=? AND TF='true'",(ID))
for i in cursor.fetchall(): for i in cursor.fetchall():
correct.append(i)
correct=correct[::-1][:3]
for i in correct:
TruetestID.append(i[3]) TruetestID.append(i[3])
TrueTestDic[i[3]]=i TrueTestDic[i[3]]=i
TruetestID=TruetestID[::-1][:3]
for index in TruetestID: for index in TruetestID:
cursor.execute(f"SELECT * FROM TEST_BANK WHERE ID=?",(index)) cursor.execute(f"SELECT * FROM TEST_BANK WHERE ID=?",(index))
TrueTestDic[index]=TrueTestDic[index],cursor.fetchall() TrueTestDic[index]=TrueTestDic[index],cursor.fetchall()
# print(TrueTestDic) # print(TrueTestDic)
return TrueTestDic return TrueTestDic
# fetch_test_func('20240101') # fetch_test_func('20240101')
@ -166,6 +175,53 @@ def falseTest_func(ID):
# falseTest_func('20240101') # falseTest_func('20240101')
def TestDataFunc(examID):
cursor = db.cursor()
cursor.execute(f"SELECT * FROM TEST_BANK WHERE ID=?",(examID,))
TestID=cursor.fetchall()[0]
ChoiceList=json.loads(TestID[0])
CompleList=json.loads(TestID[1])
JudgeList=json.loads(TestID[2])
Choice=[]
Comple=[]
Judge=[]
CHOICE=[str(x) for x in ChoiceList]
COMPLE=[str(x) for x in CompleList]
JUDGE=[str(x) for x in JudgeList]
for i in CHOICE:
cursor.execute(f"SELECT * FROM CHOICE_QUESTION_BANK WHERE ID=?",(i))
Choice.append(cursor.fetchall())
for i in COMPLE:
cursor.execute(f"SELECT * FROM COMPLETION_QUESTION_BANK WHERE ID=?",(i))
Comple.append(cursor.fetchall())
for i in JUDGE:
cursor.execute(f"SELECT * FROM T_OR_F_QUESTION_BANK WHERE ID=?",(i))
Judge.append(cursor.fetchall())
HOUR=TestID[3]
MIN=TestID[4]
if int(HOUR)==0:
time=int(MIN)
elif int(MIN)==0:
time=int(HOUR)*60
else:
time=int(HOUR)*60+int(MIN)
dic={'examID':[Choice,Comple,Judge,time]}
# print(dic)
return dic
# TestDataFunc('35')
# 查找学生已经完成的记录 # 查找学生已经完成的记录
def find_end_test(ID): def find_end_test(ID):
cursor = db.cursor() cursor = db.cursor()
@ -196,12 +252,22 @@ def FetchTrainTitleFunc(ID):
titles.append(i[2]) titles.append(i[2])
for i in titles: for i in titles:
cursor.execute('SELECT * FROM TRAINTEST WHERE ID=? ',(i)) cursor.execute('SELECT * FROM TRAINTEST WHERE ID=? AND STOPTIME>? ',(i,Time))
title.append(cursor.fetchall()) result=cursor.fetchall()
title.append(result)
if result:
pass
else:
cursor.execute("UPDATE TRAINSCORE SET TF='true' , RESULT='0' , TRAINRESULT='0' WHERE TEST_ID=? AND STUDENT_ID=?",(i,ID))
title = [item for item in title if item]
print(title)
db.commit()
cursor.close() cursor.close()
return title return title
# FetchTrainTitleFunc("20240101")
def FetchTrainTestFunc(operateID): def FetchTrainTestFunc(operateID):

View File

@ -7,6 +7,8 @@ import datetime
db = dmPython.connect(user='SYSDBA', password='dameng!!', host="36.138.114.105", port="32522") db = dmPython.connect(user='SYSDBA', password='dameng!!', host="36.138.114.105", port="32522")
#获取题目 #获取题目
def choice_question_func(ID): def choice_question_func(ID):
question_cursor = db.cursor() question_cursor = db.cursor()
@ -218,6 +220,9 @@ def train_question():
# print(Train) # print(Train)
return Train return Train
testID=None
TrainName=""
# train_question() # train_question()
def SendTrainTestFunc(TrainChoice,TrainCompletion,TrainJudge,Hour,Min,StopTime,Class,Train,teacher_id): def SendTrainTestFunc(TrainChoice,TrainCompletion,TrainJudge,Hour,Min,StopTime,Class,Train,teacher_id):
TrainChoice = json.dumps(TrainChoice) TrainChoice = json.dumps(TrainChoice)
@ -225,6 +230,8 @@ def SendTrainTestFunc(TrainChoice,TrainCompletion,TrainJudge,Hour,Min,StopTime,C
TrainJudge = json.dumps(TrainJudge) TrainJudge = json.dumps(TrainJudge)
Class=json.dumps(Class) Class=json.dumps(Class)
Train=json.dumps(Train) Train=json.dumps(Train)
global TrainName
TrainName=Train
# 获取当前时间 # 获取当前时间
now_time = datetime.datetime.now().replace(microsecond=0) now_time = datetime.datetime.now().replace(microsecond=0)
end_time = now_time + datetime.timedelta(days=int(StopTime)) end_time = now_time + datetime.timedelta(days=int(StopTime))
@ -258,13 +265,27 @@ def SendTrainTestFunc(TrainChoice,TrainCompletion,TrainJudge,Hour,Min,StopTime,C
(i, i[0:6], test_id, end,one)) (i, i[0:6], test_id, end,one))
# 发布实训的时候根据实训不同给予不同链接 # 发布实训的时候根据实训不同给予不同链接
cursor.execute(f"SELECT ID FROM TRAINTEST WHERE RELEASETIME=? ", (now_time))
test_id = cursor.fetchall()[0][0]
global testID
testID=test_id
print('分配成功') print('分配成功')
db.commit() db.commit()
cursor.close() cursor.close()
return '发布成功' return '发布成功'
def TeacherMark(CLASS,ID):
global testID
global TrainName
cursor = db.cursor()
strClass=str(CLASS)
if TrainName.find(r'["\u524d\u7aef\u4e0e\u6570\u636e\u5e93\u7ed3\u5408"]') != -1:
for i in eval(strClass):
cursor.execute(f'INSERT INTO TEACHERMARK VALUES(?,?,?,?) ', (ID,testID,'false', i))
db.commit()
cursor.close()
# def Find_dic(dic): # def Find_dic(dic):
# # 获取字典的键,并按照从大到小的顺序排序 # # 获取字典的键,并按照从大到小的顺序排序
# keys_sorted = sorted(dic.keys(), reverse=True) # keys_sorted = sorted(dic.keys(), reverse=True)
@ -291,3 +312,17 @@ def Find_details_Func(ID):
return dic return dic
# print(Find_details('20240101')) # print(Find_details('20240101'))
#获取未批改的卷子
def MarkTrainFunc(ClassID,teacher_ID):
dic={}
cursor = db.cursor()
cursor.execute(f"SELECT * FROM TEACHERMARK WHERE CLASS=? AND TEACHERID=? AND TF='false'", (ClassID,teacher_ID))
for i in cursor.fetchall():
cursor.execute(f"SELECT * FROM TRAINTEST WHERE ID=? ", (i[1],))
dic[i[1]]=cursor.fetchall()
# print(dic)
return dic
# MarkTrainFunc('202401','111111')

5
python/test.py Normal file
View File

@ -0,0 +1,5 @@
TrainName='["\u524d\u7aef\u4e0e\u6570\u636e\u5e93\u7ed3\u5408"]'
print(TrainName)
print(type(TrainName))
if TrainName == '["\u524d\u7aef\u4e0e\u6570\u636e\u5e93\u7ed3\u5408"]':
print('yes')