This commit is contained in:
nopy 2024-06-24 20:03:13 +08:00
commit 6e756edee9
103 changed files with 497 additions and 191 deletions

0
.gitignore vendored Executable file → Normal file
View File

BIN
README.md Executable file → Normal file

Binary file not shown.

0
app-dm/.dockerignore Executable file → Normal file
View File

2
app-dm/.gitignore vendored Executable file → Normal file
View File

@ -11,6 +11,8 @@
# production # production
/build /build
# misc # misc
.DS_Store .DS_Store
.env.local .env.local

0
app-dm/Dockerfile Executable file → Normal file
View File

0
app-dm/README.md Executable file → Normal file
View File

0
app-dm/package-lock.json generated Executable file → Normal file
View File

0
app-dm/package.json Executable file → Normal file
View File

0
app-dm/public/favicon.ico Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
app-dm/public/index.html Executable file → Normal file
View File

0
app-dm/public/logo192.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

0
app-dm/public/logo512.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 9.4 KiB

After

Width:  |  Height:  |  Size: 9.4 KiB

0
app-dm/public/manifest.json Executable file → Normal file
View File

0
app-dm/public/robots.txt Executable file → Normal file
View File

0
app-dm/server/config.js Executable file → Normal file
View File

0
app-dm/server/index.js Executable file → Normal file
View File

0
app-dm/server/router.js Executable file → Normal file
View File

0
app-dm/src/TeacherPages/MarkingPages/Marking.css Executable file → Normal file
View File

0
app-dm/src/TeacherPages/MarkingPages/Marking.jsx Executable file → Normal file
View File

0
app-dm/src/TeacherPages/SendTest/SendTest.css Executable file → Normal file
View File

8
app-dm/src/TeacherPages/SendTest/SendTest.jsx Executable file → Normal file
View File

@ -14,7 +14,7 @@ function SendTest(){
const subject = async ()=>{ const subject = async ()=>{
try{ try{
const subject_src=await axios.post('http://127.0.0.1:5000/teacher/return_question',{ const subject_src=await axios.post('/api/teacher/return_question',{
teacher_ID}) teacher_ID})
SetChoiceQuestion(subject_src.data['选择']) SetChoiceQuestion(subject_src.data['选择'])
SetCompletion(subject_src.data['填空']) SetCompletion(subject_src.data['填空'])
@ -41,7 +41,7 @@ function SendTest(){
const click_1= async()=>{ const click_1= async()=>{
try { try {
const select_class_src = await axios.post('http://127.0.0.1:5000/teacher/select_class', { const select_class_src = await axios.post('/api/teacher/select_class', {
teacher_ID teacher_ID
}); });
background.style.display='block' background.style.display='block'
@ -119,7 +119,7 @@ function SendTest(){
// //
const release= async()=>{ const release= async()=>{
try{ try{
const release_src=await axios.post('http://127.0.0.1:5000/teacher/accept_test',{ const release_src=await axios.post('/api/teacher/accept_test',{
teacher_ID, teacher_ID,
ChoiceQuestionSet,// ChoiceQuestionSet,//
CompletionQuestionSet,// CompletionQuestionSet,//
@ -131,7 +131,7 @@ function SendTest(){
} }
) )
alert('发布成功') alert('发布成功')
window.location.href='http://localhost:3000/teacher/managetest' window.location.href='http://36.138.114.105:30294/teacher/managetest'
}catch{ }catch{
alert('发布失败') alert('发布失败')
} }

0
app-dm/src/TeacherPages/SendTrain/SendTrain.css Executable file → Normal file
View File

6
app-dm/src/TeacherPages/SendTrain/SendTrain.jsx Executable file → Normal file
View File

@ -20,7 +20,7 @@ function SendTrain(){
const Train_question_func=async()=>{ const Train_question_func=async()=>{
try{ try{
const Train_question_src=await axios.post('http://127.0.0.1:5000/teacher/fetch_train_question') const Train_question_src=await axios.post('/api/teacher/fetch_train_question')
SetTrainquestion(Train_question_src.data) SetTrainquestion(Train_question_src.data)
}catch{ }catch{
alert('Train_question_func出错') alert('Train_question_func出错')
@ -29,7 +29,7 @@ function SendTrain(){
const SeleactClass= async()=>{ const SeleactClass= async()=>{
try { try {
const select_class_src = await axios.post('http://127.0.0.1:5000/teacher/select_class', { const select_class_src = await axios.post('/api/teacher/select_class', {
teacher_ID teacher_ID
}); });
SetClassData(select_class_src.data['Class']); SetClassData(select_class_src.data['Class']);
@ -66,7 +66,7 @@ function SendTrain(){
// //
const SendTrainTest=async ()=>{ const SendTrainTest=async ()=>{
try{ try{
const SendTrainSrc=await axios.post('http://127.0.0.1:5000/teacher/SendTrainTest',{ const SendTrainSrc=await axios.post('/api/teacher/SendTrainTest',{
TrainChoice, TrainChoice,
TrainCompletion, TrainCompletion,
TrainJudge, TrainJudge,

0
app-dm/src/TeacherPages/TeacherPage.css Executable file → Normal file
View File

6
app-dm/src/TeacherPages/TeacherPage.jsx Executable file → Normal file
View File

@ -15,10 +15,10 @@ function TeacherPage() {
// const is_login = localStorage.getItem('islogin'); // const is_login = localStorage.getItem('islogin');
// if (!is_login) { // if (!is_login) {
// alert(''); // alert('');
// window.location.href = 'http://localhost:3000/signin'; // window.location.href = 'http://36.138.114.105:30294/signin';
// } else { // } else {
// if(teacher_ID.length===8){ // if(teacher_ID.length===8){
// window.location.href='http://localhost:3000' // window.location.href='http://36.138.114.105:30294'
// return // return
// }else{ // }else{
// console.log(teacher_ID); // console.log(teacher_ID);
@ -35,7 +35,7 @@ function TeacherPage() {
// //
const select_class = async () => { const select_class = async () => {
try { try {
const select_class_src = await axios.post('http://127.0.0.1:5000/teacher/select_class', { const select_class_src = await axios.post('/api/teacher/select_class', {
teacher_ID teacher_ID
}); });
setClassData(select_class_src.data['Class']); setClassData(select_class_src.data['Class']);

0
app-dm/src/TeacherPages/Trainmanage/Trainmanage.css Executable file → Normal file
View File

2
app-dm/src/TeacherPages/Trainmanage/Trainmanage.jsx Executable file → Normal file
View File

@ -29,7 +29,7 @@ function TeacherTrainManage(){
<div>发布时间:</div> <div>发布时间:</div>
<div>截至时间:</div> <div>截至时间:</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
) )

2
app-dm/src/TeacherPages/classlistpages/classId.jsx Executable file → Normal file
View File

@ -14,7 +14,7 @@ function TeacherPage() {
const [classdata,setClassData]=useState([]) const [classdata,setClassData]=useState([])
const class_succeed = async () => { const class_succeed = async () => {
try{ try{
const class_scr=await axios.post('http://127.0.0.1:5000/teacher/find_student',{key}) const class_scr=await axios.post('/api/teacher/find_student',{key})
const class_data=class_scr.data const class_data=class_scr.data
setClassData(class_data[1]) setClassData(class_data[1])
setisclick(true) setisclick(true)

0
app-dm/src/TeacherPages/classlistpages/classid.css Executable file → Normal file
View File

View File

View File

@ -18,7 +18,7 @@ function TeacherPage() {
const select_class = async () => { const select_class = async () => {
try { try {
const select_class_src = await axios.post('http://127.0.0.1:5000/teacher/select_class',{ const select_class_src = await axios.post('/api/teacher/select_class',{
teacher_ID teacher_ID
}); });
setClassData(select_class_src.data['Class']); setClassData(select_class_src.data['Class']);
@ -45,7 +45,7 @@ function TeacherPage() {
useEffect(()=>{ useEffect(()=>{
const change_class = async () => { const change_class = async () => {
try { try {
const change_class_src = await axios.post('http://127.0.0.1:5000/teacher/change_class',{ const change_class_src = await axios.post('/api/teacher/change_class',{
teacher_ID, teacher_ID,
selectedValue, selectedValue,
testID testID
@ -74,7 +74,7 @@ function TeacherPage() {
const click_detailed= async()=>{ const click_detailed= async()=>{
// //
try{ try{
const detaileddata_src=await axios.post('http://127.0.0.1:5000/teacher/detaileddata',{ const detaileddata_src=await axios.post('/api/teacher/detaileddata',{
testID, testID,
selectedValue, selectedValue,
teacher_ID teacher_ID

0
app-dm/src/api/index.js Executable file → Normal file
View File

0
app-dm/src/index.js Executable file → Normal file
View File

0
app-dm/src/logo.svg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

2
app-dm/src/nav/nav.jsx Executable file → Normal file
View File

@ -15,7 +15,7 @@ function HeaderNav() {
localStorage.removeItem('islogin') localStorage.removeItem('islogin')
// setisChecked(false) // setisChecked(false)
alert('注销成功') alert('注销成功')
window.location.href='http://localhost:3000/signin' window.location.href='http://36.138.114.105:30294/signin'
}; };
const [isChecked,setisChecked]=useState(false) const [isChecked,setisChecked]=useState(false)

0
app-dm/src/nav/style.css Executable file → Normal file
View File

2
app-dm/src/nav/teacherIndex.jsx Executable file → Normal file
View File

@ -15,7 +15,7 @@ function HeaderNavTeacher() {
localStorage.removeItem('islogin') localStorage.removeItem('islogin')
// setisChecked(false) // setisChecked(false)
alert('注销成功') alert('注销成功')
window.location.href='http://localhost:3000/signin' window.location.href='http://36.138.114.105:30294/signin'
}; };
const [isChecked,setisChecked]=useState(false) const [isChecked,setisChecked]=useState(false)

0
app-dm/src/pages/Home/Home.css Executable file → Normal file
View File

33
app-dm/src/pages/Home/Home.jsx Executable file → Normal file
View File

@ -5,18 +5,12 @@ import React,{ useEffect,useState } from 'react';
import axios from 'axios'; import axios from 'axios';
// //
import { Line } from 'react-chartjs-2'; import { Line } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Tooltip, Legend } from 'chart.js'; import { Chart as ChartJS, CategoryScale, LinearScale, PointElement, LineElement, Tooltip, Legend, Ticks } from 'chart.js';
import { max, min } from 'lodash';
// //
function Home(){ function Home(){
const outlog=()=>{
localStorage.removeItem('islogin')
// setisChecked(false)
alert('注销成功')
window.location.href='http://localhost:3000/signin'
};
const [isChecked,setisChecked]=useState(false) const [isChecked,setisChecked]=useState(false)
// //
// useEffect(()=>{ // useEffect(()=>{
@ -45,14 +39,14 @@ function Home(){
const student_succeed_func = async () => { const student_succeed_func = async () => {
const student_ID=localStorage.getItem('islogin') const student_ID=localStorage.getItem('islogin')
try{ try{
const student_succeed_src=await axios.post('http://127.0.0.1:5000/student',{ const student_succeed_src=await axios.post('/api/student',{
student_ID student_ID
}); });
// //
const student_succeed=student_succeed_src.data const student_succeed=student_succeed_src.data
const lesson_data=(student_succeed['student_lesson']) const lesson_data=(student_succeed['student_lesson'])
setLesson(lesson_data) setLesson(lesson_data)
}catch(error){ }catch(error){
if(student_ID.length===6){ if(student_ID.length===6){
window.location.href='http://localhost:3000/teacher' window.location.href='http://localhost:3000/teacher'
return return
@ -63,9 +57,10 @@ function Home(){
} }
} }
} }
// useEffect(()=>{
// student_succeed_func() useEffect(()=>{
// },[]) student_succeed_func()
},[])
useEffect(()=>{ useEffect(()=>{
if(lesson.length>0){ if(lesson.length>0){
@ -83,10 +78,6 @@ function Home(){
} }
},[lesson]) },[lesson])
const click=()=>{
console.log();
}
//线 //线
// //
const [chartData, setChartData] = useState({ const [chartData, setChartData] = useState({
@ -109,8 +100,7 @@ function Home(){
datasets: [ datasets: [
{ {
label: '总体成绩分析', label: '总体成绩分析',
// data: [10, 20, 30, 40, 50,60,70,80,90,100], data: [62, 79, 71, 49, 70],
data:data,
fill: false, fill: false,
backgroundColor:'#fff', backgroundColor:'#fff',
borderColor: 'rgb(75, 192, 192)', borderColor: 'rgb(75, 192, 192)',
@ -125,6 +115,11 @@ function Home(){
scales: { scales: {
y: { y: {
beginAtZero: true, beginAtZero: true,
min:0,
max:100,
ticks:{
stepSize:10
}
} }
}, },
plugins: { plugins: {

0
app-dm/src/pages/Home/img/ad.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

0
app-dm/src/pages/Home/img/logo.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

0
app-dm/src/pages/Home/img/test.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

0
app-dm/src/pages/ListPages/Analyse/AnalysePages.css Executable file → Normal file
View File

0
app-dm/src/pages/ListPages/Analyse/AnalysePages.jsx Executable file → Normal file
View File

0
app-dm/src/pages/ListPages/Subject/Exam.css Executable file → Normal file
View File

10
app-dm/src/pages/ListPages/Subject/Exam.jsx Executable file → Normal file
View File

@ -19,7 +19,7 @@ function Exam(){
const [testdata,settestdata]=useState('') const [testdata,settestdata]=useState('')
const test_func= async()=>{ const test_func= async()=>{
try{ try{
const test_src= await axios.post('http://127.0.0.1:5000/student/get_test',{student_ID}) const test_src= await axios.post('/api/student/get_test',{student_ID})
const test_data=test_src.data['data'] const test_data=test_src.data['data']
settestdata(test_data) settestdata(test_data)
}catch(error){ }catch(error){
@ -111,9 +111,6 @@ function Exam(){
for(let i of item){ for(let i of item){
if(i[2]===completion_answer[sum]){ if(i[2]===completion_answer[sum]){
setscore(prevscore => prevscore + 2); setscore(prevscore => prevscore + 2);
}else{
} }
} }
} }
@ -132,16 +129,15 @@ function Exam(){
if(isMounted){ if(isMounted){
const score_func=async()=>{ const score_func=async()=>{
try{ try{
const score_entry_src=await axios.post('http://127.0.0.1:5000/student/score_entry',{ const score_entry_src=await axios.post('/api/student/score_entry',{
student_ID, student_ID,
score, score,
examId examId
}) })
console.log('能不能发送');
}catch(error){ }catch(error){
alert(error) alert(error)
} }
window.location.href='http://localhost:3000/subject' window.location.href='http://36.138.114.105:30294/subject'
} }
score_func() score_func()
}else{ }else{

0
app-dm/src/pages/ListPages/Subject/SubjectPage.css Executable file → Normal file
View File

15
app-dm/src/pages/ListPages/Subject/SubjectPage.jsx Executable file → Normal file
View File

@ -17,22 +17,21 @@ function SubjectPage(){
//ID //ID
const test=async()=>{ const test=async()=>{
try{ try{
const test_src= await axios.post('http://127.0.0.1:5000/student/get_test',{student_ID}) const test_src= await axios.post('/api/student/get_test',{student_ID})
settestdata(test_src.data['data']) settestdata(test_src.data['data'])
}catch(error){ }catch(error){
alert(error) alert('test出错')
} }
} }
useEffect(()=>{ useEffect(()=>{
test() test()
},[]) },[])
const [EndTestList,setEndTestList]=useState([]) const [EndTestList,setEndTestList]=useState([])
// //
const end_test=async()=>{ const end_test=async()=>{
try{ try{
const end_test_src=await axios.post('http://127.0.0.1:5000/student/get_end_student',{student_ID}) const end_test_src=await axios.post('/api/student/get_end_student',{student_ID})
const obj=end_test_src.data['result'] const obj=end_test_src.data['result']
setEndTestList(obj) setEndTestList(obj)
}catch(error){ }catch(error){
@ -46,10 +45,6 @@ function SubjectPage(){
// //
const [outtest,setouttest]=useState({}) const [outtest,setouttest]=useState({})
//
const click = () => {
console.log(testdata);
};
// //
useEffect(()=>{ useEffect(()=>{
let test_list= [] let test_list= []
@ -71,7 +66,7 @@ function SubjectPage(){
const find_result_func=async()=>{ const find_result_func=async()=>{
try{ try{
const find_result=await axios.post('http://127.0.0.1:5000/student/fetch_result',{ const find_result=await axios.post('/api/student/fetch_result',{
student_ID student_ID
}) })
setresult(find_result.data['result']) setresult(find_result.data['result'])
@ -97,8 +92,6 @@ function SubjectPage(){
</div> </div>
))} ))}
</div>} </div>}
<button onClick={click}>测试按钮</button>
<h3>已结束或完成的试卷与练习</h3> <h3>已结束或完成的试卷与练习</h3>
{ outtest&& result&&<div className='test-subject'> { outtest&& result&&<div className='test-subject'>
{Object.keys(outtest).map((key)=>{ {Object.keys(outtest).map((key)=>{

33
app-dm/src/pages/ListPages/Training/Operation1.css Executable file → Normal file
View File

@ -83,19 +83,32 @@
/* 前进按钮 */ /* 前进按钮 */
.btn-back1{ .btn-back1{
height: 50px;
position: absolute;
bottom: 50px;
right: 80px;
padding: 0 20px;
display: flex;
align-items: center;
/* border: 1px solid #000; */
box-shadow: 1px 2px 5px gray;
background-color: #efefef;
} }
.btn-back1 p{ .btn-back1 p{
font-size: 20px; font-size: 20px;
margin-left: 5px; margin-left: 5px;
} }
.body-right1 table{
width: 100%;
}
.optionBox{
width: 100%;
background-color: rgb(110, 130, 130);
}
.body-right1 p{
margin: 0px;
font-size: 20px;
}
.optionBox label{
margin-left: 10px;
}
.body-right1-comple{
border-collapse: separate;
border-spacing: 10px; /* 设置行和列之间的间距 */
}
.body-right1-comple tr{
background-color: rgb(110, 130, 130);
}

175
app-dm/src/pages/ListPages/Training/Operation1.jsx Executable file → Normal file
View File

@ -2,21 +2,50 @@ import './Operation1.css'
import { Terminal } from "@xterm/xterm"; import { Terminal } from "@xterm/xterm";
import "@xterm/xterm/css/xterm.css" import "@xterm/xterm/css/xterm.css"
import React,{ MouseEvent, useEffect, useRef, useState } from "react"; import React,{ MouseEvent, useEffect, useRef, useState } from "react";
import { useParams } from 'react-router';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import arrow from '../img/arrow.jpg' import arrow from '../img/arrow.jpg'
import bottom from '../img/bottom.jpg' import bottom from '../img/bottom.jpg'
import top from '../img/top.jpg' import top from '../img/top.jpg'
import axios from 'axios';
function Operation1() { function Operation1() {
const click=()=>{
console.log(score);
}
const clear=()=>{
localStorage.clear('choice_answers');
setchoice_answer({})
localStorage.clear('completion_answer')
setcompletion_answer({})
}
const { operateID } = useParams();
//
const [TrainData,setTrainData]=useState()
const TrainDataFunc=async()=>{
try{
const TrainDataSrc=await axios.post('/api/student/TrainData',{
operateID
})
const returnData=TrainDataSrc.data
setTrainData(returnData)
}catch{
alert('TrainDataFunc出错')
}
}
useEffect(()=>{
TrainDataFunc()
},[])
// //
// const { OperationId } = useParams();
const [test_data, setTestData] = useState(''); const [test_data, setTestData] = useState('');
const [countdown, setCountdown] = useState(0); const [countdown, setCountdown] = useState(0);
// //
useEffect(() => { useEffect(() => {
const examDuration = 60 * 60; // 1 const examDuration = 60 * 90; // 1
setCountdown(examDuration); setCountdown(examDuration);
}, []); }, []);
@ -44,6 +73,88 @@ function Operation1() {
// //
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 handleOptionChange = (event) => {
const selectedValue = event.target.value;
const key = parseInt(event.target.name.replace('group', ''));
const updatedChoiceAnswer = { ...choice_answer, [key]: selectedValue };
setchoice_answer(updatedChoiceAnswer);
};
//
const handleInputChange = (event) => {
const { name, value } = event.target;
setcompletion_answer({
...completion_answer,
[name]: value
});
};
//
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)
}
// localStorage
const saveAnswers = () => {
localStorage.setItem('choice_answers', JSON.stringify(choice_answer));
localStorage.setItem('completion_answer', JSON.stringify(completion_answer));
localStorage.setItem('judge_answer',JSON.stringify(judge_answer))
};
// localStorage
useEffect(() => {
const storedChoiceAnswers = localStorage.getItem('choice_answers');
const storedCompleAnswers = localStorage.getItem('completion_answer');
const storedJudgeAnswers = localStorage.getItem('judge_answer')
if (storedChoiceAnswers) {
const parsedAnswers = JSON.parse(storedChoiceAnswers);
setchoice_answer(parsedAnswers);
}
if (storedCompleAnswers) {
const parsedAnswers = JSON.parse(storedCompleAnswers);
setcompletion_answer(parsedAnswers);
}
if(storedJudgeAnswers){
const parsedAnswers = JSON.parse(storedJudgeAnswers);
setjudge_answer(parsedAnswers);
}
}, []);
//
const [score,setscore]=useState(0)
//
const submit=()=>{
let CHO_sum=0;
let COM_sum=0;
let JUD_sum=0;
for(let item of TrainData['operateID'][0]){
if(item[0][6]===choice_answer[CHO_sum]){
setscore(prevscore=>prevscore+5)
}
CHO_sum++
}
for(let item of TrainData['operateID'][1]){
if (item[0][2]===completion_answer[COM_sum]) {
setscore(prevscore=>prevscore+5)
}
COM_sum++
}
for(let item of TrainData['operateID'][2]){
if (item[0][2]===judge_answer[JUD_sum]) {
setscore(prevscore=>prevscore+5)
}
JUD_sum++
}
}
return ( return (
<div> <div>
<div className='nav-operation1'> <div className='nav-operation1'>
@ -74,12 +185,60 @@ function Operation1() {
</ul> </ul>
</div> </div>
<div className='body-right1'> <div className='body-right1'>
第一页主观题的右边页面 {TrainData && (
<table className='body-right1-choice'>
<p>选择题:</p>
<tbody>
{Object.keys(TrainData['operateID'][0]).map((key) => (
<tr key={key}>
<tr style={{fontSize:'18px'}}>{TrainData['operateID'][0][key][0][1]}</tr>
<div className='optionBox'>
<label><input type="radio" value={TrainData['operateID'][0][key][0][2]} checked={choice_answer[key] === TrainData['operateID'][0][key][0][2]} onChange={handleOptionChange} name={`group${key}`}/><span>A:{TrainData['operateID'][0][key][0][2]}</span></label>
<br />
<label><input type="radio" value={TrainData['operateID'][0][key][0][3]} checked={choice_answer[key] === TrainData['operateID'][0][key][0][3]} onChange={handleOptionChange} name={`group${key}`}/><span>B:{TrainData['operateID'][0][key][0][3]}</span></label>
<br />
<label><input type="radio" value={TrainData['operateID'][0][key][0][4]} checked={choice_answer[key] === TrainData['operateID'][0][key][0][4]} onChange={handleOptionChange} name={`group${key}`}/><span>C:{TrainData['operateID'][0][key][0][4]}</span></label>
<br />
<label><input type="radio" value={TrainData['operateID'][0][key][0][5]} checked={choice_answer[key] === TrainData['operateID'][0][key][0][5]} onChange={handleOptionChange} name={`group${key}`}/><span>D:{TrainData['operateID'][0][key][0][5]}</span></label>
</div>
</tr>
))}
</tbody>
</table>
)}
{TrainData&&(
<table className='body-right1-comple'>
<tbody>
<p>填空题:</p>
{Object.keys(TrainData['operateID'][1]).map((key)=>(
<tr key={key}>{TrainData['operateID'][1][key][0][1]}
<br />
<span>请填入你的答案:</span>
<input type="text" onChange={handleInputChange} name={key} value={completion_answer[key]||''}/>
</tr>
))}
</tbody>
</table>
)}
{TrainData&&(
<table>
<tbody>
<p>判断题:</p>
{Object.keys(TrainData['operateID'][2]).map((key)=>(
<tr key={key}>{TrainData['operateID'][2][key][0][1]}
<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={click}>测试</button><button onClick={clear}>清除测试</button><button onClick={submit}>假提交按钮</button>
<Link to={`/operation2/${operateID}`}><button onClick={saveAnswers}>下一页</button></Link>
</div> </div>
<Link className='btn-back1' to={`/operation2/1`} style={{color:'#000',textDecoration:'none'}}>
<img src={arrow} alt="" width='40px' height='40px' />
<p>下一页</p>
</Link>
</div> </div>
</div> </div>
) )

0
app-dm/src/pages/ListPages/Training/Operation2.css Executable file → Normal file
View File

4
app-dm/src/pages/ListPages/Training/Operation2.jsx Executable file → Normal file
View File

@ -2,6 +2,7 @@ import './Operation2.css'
import { Terminal } from "@xterm/xterm"; import { Terminal } from "@xterm/xterm";
import "@xterm/xterm/css/xterm.css" import "@xterm/xterm/css/xterm.css"
import React,{ MouseEvent, useEffect, useRef, useState } from "react"; import React,{ MouseEvent, useEffect, useRef, useState } from "react";
import { useParams } from 'react-router';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import arrow from '../img/arrow.jpg' import arrow from '../img/arrow.jpg'
import arrow1 from '../img/left.jpg' import arrow1 from '../img/left.jpg'
@ -9,6 +10,7 @@ import bottom from '../img/bottom.jpg'
import top from '../img/top.jpg' import top from '../img/top.jpg'
function Operation2() { function Operation2() {
const { operateID } = useParams();
// //
const terminalObj = useRef(null); const terminalObj = useRef(null);
let sock = null; let sock = null;
@ -122,7 +124,7 @@ function Operation2() {
第二页实训题的右边页面 第二页实训题的右边页面
<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>
</div> </div>
<Link className='btn-back2' to='/operation1/实训一:数据库的安装' style={{color:'#000',textDecoration:'none'}}> <Link className='btn-back2' to={`/operation1/${operateID}`} style={{color:'#000',textDecoration:'none'}}>
<p>上一页</p> <p>上一页</p>
<img src={arrow1} alt="" width='40px' height='40px' /> <img src={arrow1} alt="" width='40px' height='40px' />
</Link> </Link>

17
app-dm/src/pages/ListPages/Training/TrainingPage.css Executable file → Normal file
View File

@ -48,16 +48,16 @@
} }
.exam-btn-training{ .exam-btn-training{
position: relative; position: absolute;
margin-top: 50px; margin-left: 260px;
margin-left: 250px;
border-radius: 15px; border-radius: 15px;
margin-top: -10px;
font-size: 17px; font-size: 17px;
border: none; border: none;
display: inline-block; display: inline-block;
padding: 3px 32px; padding: 3px 26px;
background-color: rgba(175, 235, 230, 0.929); background-color: rgba(175, 235, 230, 0.929);
color: #000; color: #000;
text-decoration: none; text-decoration: none;
box-shadow: 3px 3px 5px rgba(127, 170, 166, 0.929); box-shadow: 3px 3px 5px rgba(127, 170, 166, 0.929);
} }
@ -69,6 +69,13 @@
.exam-btn-training:active{ .exam-btn-training:active{
color:rgba(86, 117, 114, 0.929); color:rgba(86, 117, 114, 0.929);
} }
.bottomP{
color: red;
font-size: 20px;
margin-top: 350px;
margin-left: 70px;
letter-spacing: 20px;
}

View File

@ -1,43 +1,53 @@
import React,{ useState } from 'react'; import React,{ useState , useEffect} from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import '../Training/TrainingPage.css' import '../Training/TrainingPage.css'
import axios from 'axios';
const list3=[
{'train':'实训一:数据库的安装',id:'1'},
{'train':'实训二web前端开发和数据库的结合',id:'2'}
]
const list4=[ const list4=[
{'train':'实训3待定',id:'3'}, {'train':'实训3待定',id:'3'},
{'train':'实训4待定',id:'4'} {'train':'实训4待定',id:'4'}
] ]
// //
function SubjectPage(){ function SubjectPage(){
const student_ID=localStorage.getItem('islogin')
const [title,setTitle]=useState()
//
const FetchTrainFunc=async()=>{
try{
const FetchTrainSrc=await axios.post('api/student/FetchTrainTitle',{
student_ID
})
setTitle(FetchTrainSrc.data['title'])
}catch{
alert('FetchTrainFunc出错')
}
}
useEffect(()=>{
FetchTrainFunc()
},[])
return( return(
<div className="body-right-training"> <div className="body-right-training">
<h3>未完成练习</h3> <h3>未完成实训项目</h3>
<div className='test-training'> {title&&<div className='test-training'>
{list3.map((item) =>( {Object.keys(title).map((key)=>(
<div className='test-box-training'key={item.id}> <div className='test-box-training' key={key}>
<p>{item.train}</p> <p>实训:{eval(title[key][0][11])}</p>
<span>发布者陈老师</span> <span>发布者:陈老师</span>
<Link to={`/operation1/${item.train}`} className="exam-btn-training"> <div>发布时间:{title[key][0][5]}</div>
<div>截至时间:{title[key][0][6]}</div>
<Link to={`/operation1/${title[key][0][10]}`} className="exam-btn-training">
开始实训 开始实训
</Link> </Link>
</div>))} </div>
</div> ))}
<h3>已完成练习</h3> </div>}
<div className='test-training'> <button onClick={()=>{
{list4.map((item) => ( console.log(title[0][0][11]);
<div className='test-box-training'key={item.id}> }}></button>
<p>{item.train}</p> <p className='bottomP'>提醒:请及时完成实训内容</p>
<div>
{item.title}
</div>
</div>))}
</div>
</div> </div>
)}; )};

0
app-dm/src/pages/ListPages/img/bottom.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

0
app-dm/src/pages/ListPages/img/right.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

0
app-dm/src/pages/ListPages/img/top.jpg Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

0
app-dm/src/pages/SighUp/SignUpForm.css Executable file → Normal file
View File

2
app-dm/src/pages/SighUp/SignUpForm.jsx Executable file → Normal file
View File

@ -62,7 +62,7 @@ import axios from 'axios';
alert('学号错误') alert('学号错误')
return return
} }
const register_func=await axios.post('http://127.0.0.1:5000/register',{ const register_func=await axios.post('/api/register',{
name, name,
ID, ID,
password, password,

0
app-dm/src/pages/SighUp/SignUpPage.jsx Executable file → Normal file
View File

0
app-dm/src/pages/SighUp/注册页面右.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 205 KiB

After

Width:  |  Height:  |  Size: 205 KiB

0
app-dm/src/pages/SignIn/SignInPage.css Executable file → Normal file
View File

6
app-dm/src/pages/SignIn/SignInPage.jsx Executable file → Normal file
View File

@ -12,7 +12,7 @@ function SignInPage(){
const login = async () => { const login = async () => {
try { try {
const login_data = await axios.post('http://127.0.0.1:5000/login', { const login_data = await axios.post('/api/login', {
ID, ID,
password password
}); });
@ -21,11 +21,11 @@ function SignInPage(){
if (data.result === '登录成功' && data.user==='user'){ if (data.result === '登录成功' && data.user==='user'){
localStorage.setItem('islogin',ID) localStorage.setItem('islogin',ID)
alert('用户登录成功') alert('用户登录成功')
window.location.href='http://localhost:3000'// window.location.href='http://36.138.114.105:30294'//
}else if(data.result==='登录成功'&&data.user==='teacher'){ }else if(data.result==='登录成功'&&data.user==='teacher'){
localStorage.setItem('islogin',ID) localStorage.setItem('islogin',ID)
alert('教师登录成功') alert('教师登录成功')
window.location.href='http://localhost:3000/teacher'// window.location.href='http://36.138.114.105:30294/teacher'//
}else{ }else{
alert('账号或密码错误') alert('账号或密码错误')
setID('') setID('')

0
app-dm/src/pages/SignIn/登录页面左.png Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 304 KiB

After

Width:  |  Height:  |  Size: 304 KiB

0
app-dm/src/postcss.config.js Executable file → Normal file
View File

0
app-dm/src/reportWebVitals.js Executable file → Normal file
View File

View File

@ -21,7 +21,7 @@ import ClassID from '../TeacherPages/classlistpages/classId';
import ManageTest from '../TeacherPages/teachermanagetest/ManageTest'; import ManageTest from '../TeacherPages/teachermanagetest/ManageTest';
import SendTest from '../TeacherPages/SendTest/SendTest'; import SendTest from '../TeacherPages/SendTest/SendTest';
import Marking from '../TeacherPages/MarkingPages/Marking'; import Marking from '../TeacherPages/MarkingPages/Marking';
import TrainManage from '../TeacherPages/SendTest/trainmanage'; import SendTrain from '../TeacherPages/SendTrain/SendTrain';
// (exam)使 // (exam)使
const MainLayout = ({ headerNav:HeaderNav }) => { const MainLayout = ({ headerNav:HeaderNav }) => {
@ -54,7 +54,7 @@ function App() {
<Route path="/teacher" element={<MainLayout headerNav={HeaderNavTeacher} />}> <Route path="/teacher" element={<MainLayout headerNav={HeaderNavTeacher} />}>
<Route index element={<TeacherPage/>} /> <Route index element={<TeacherPage/>} />
<Route path='managetest' element={<ManageTest />}/> <Route path='managetest' element={<ManageTest />}/>
<Route path='managetest/:ClassID' element={<ManageTest />}/> {/* <Route path='managetest/:ClassID' element={<ManageTest />}/> */}
<Route path="classID/:key" element={<ClassID />} /> <Route path="classID/:key" element={<ClassID />} />
<Route path='mark' element={<Marking/>}/> <Route path='mark' element={<Marking/>}/>
<Route path='trainmanage' element={<TrainManage/>}/> <Route path='trainmanage' element={<TrainManage/>}/>
@ -71,8 +71,7 @@ function App() {
<Route path='/teacher/sendtest' element={<SendTest />}/> <Route path='/teacher/sendtest' element={<SendTest />}/>
<Route path='operation1/:operateID' element={<Operation1/>}/> <Route path='operation1/:operateID' element={<Operation1/>}/>
<Route path='operation2/:operateID' element={<Operation2/>}/> <Route path='operation2/:operateID' element={<Operation2/>}/>
<Route path='teacher/SendTrain' element={<SendTrain/>}/>
{/* 独立的顶级路由如登录页面也不包含HeaderNav */} {/* 独立的顶级路由如登录页面也不包含HeaderNav */}
{/* 登录页面 */} {/* 登录页面 */}
<Route path="signin" element={<SignInPage />} /> <Route path="signin" element={<SignInPage />} />

11
app-dm/src/setupProxy.js Normal file
View File

@ -0,0 +1,11 @@
const { createProxyMiddleware } = require('http-proxy-middleware');
module.exports = function(app) {
app.use(
'/api', // 如果请求路径匹配'/api',则进行代理
createProxyMiddleware({
target: 'http://localhost:5000', // 目标后端服务地址
changeOrigin: true,
})
);
};

0
app-dm/src/setupTests.js Executable file → Normal file
View File

0
app-dm/src/utils/request.js Executable file → Normal file
View File

0
app-dm/src/vite.config.js Executable file → Normal file
View File

0
app-dm/tailwind.config.js Executable file → Normal file
View File

54
build.sh Executable file → Normal file
View File

@ -1,3 +1,51 @@
docker compose build #!/bin/bash
docker compose build build-dmpython
docker compose build build-frontend # 获取当前文件夹名字
current_dir=$(basename "$PWD")
# 确保有稳定的网络环境
ensure_network() {
read -p "请确保有稳定的网络环境[Y/N] " confirm
if [[ ! $confirm =~ ^[yY]([eE][sS])?$ ]]; then
exit 1
fi
}
# 打包镜像
build_image() {
local service_name=$1
echo "打包${service_name}镜像"
docker compose build "$service_name"
}
# 推送镜像
push_image() {
read -p "是否要推送到《达梦启元云原生大数据平台》? [Y/N] " confirm
if [[ $confirm =~ ^[yY]([eE][sS])?$ ]]; then
echo "tag"
docker tag "${current_dir}-flask-app" 36.138.114.105:31000/cnsof50011836/flask-app
echo "pushing"
docker push 36.138.114.105:31000/cnsof50011836/flask-app
echo "pushed"
else
echo "用户选择不推送镜像"
fi
}
# 主流程
main() {
echo "打包中"
ensure_network
build_image base
build_image base-dm
build_image build-dmpython
build_image build-frontend
build_image flask-app
push_image
echo "脚本结束"
}
main

23
docker-compose.yml Executable file → Normal file
View File

@ -1,8 +1,14 @@
services: services:
base:
build: ./docker/base
image: base
base-dm: base-dm:
build: ./docker/base-dm build: ./docker/base-dm
image: base-dm image: base-dm
depends_on:
- base
build-dmpython: build-dmpython:
build: ./docker/build-dmpython build: ./docker/build-dmpython
@ -28,20 +34,3 @@ services:
retries: 3 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
nginx-proxy:
build: ./docker/nginx
restart: always
volumes:
- ./docker/nginx/default.conf:/tmp/default.conf
environment:
- FLASK_SERVER_ADDR=flask-app:8000
ports:
- "80:80"
depends_on:
- flask-app
healthcheck:
test: ["CMD-SHELL", "curl --silent --fail localhost:80/health-check || exit 1"]
interval: 10s
timeout: 10s
retries: 3
command: /app/start.sh

33
docker/base-dm/Dockerfile Executable file → Normal file
View File

@ -1,35 +1,16 @@
FROM ubuntu FROM base
# apt安装时防止卡死在交互界面
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 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) \
&& 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 \ RUN useradd -m -s /bin/bash dmdba \
# 修改用户密码 # 修改用户密码
&& echo "dmdba:123456" | chpasswd \ && echo "dmdba:123456" | chpasswd
&& pip config set global.index-url https://mirrors.bfsu.edu.cn/pypi/web/simple \
&& echo "**** clean up ****" && \
apt-get clean && \
rm -rf \
/config/* \
/tmp/* \
/var/lib/apt/lists/* \
/var/tmp/*
# 传入安装包并解压
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 \ RUN 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 \
&& rm -f dm8_20240408_x86_rh7_64.iso \ && rm -f dm8_20240408_x86_rh7_64.iso \
&& chmod +x DMInstall.bin && chmod +x DMInstall.bin
USER dmdba

22
docker/base/Dockerfile Normal file
View File

@ -0,0 +1,22 @@
FROM ubuntu
# apt安装时防止卡死在交互界面
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 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) \
&& 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 \
&& pip config set global.index-url https://mirrors.bfsu.edu.cn/pypi/web/simple \
&& echo "**** clean up ****" && \
apt-get clean && \
rm -rf \
/config/* \
/tmp/* \
/var/lib/apt/lists/* \
/var/tmp/*

0
docker/build-dmpython/Dockerfile Executable file → Normal file
View File

2
docker/build-dmpython/auto_install.xml Executable file → Normal file
View File

@ -115,7 +115,7 @@
</DB_PARAMS> </DB_PARAMS>
<!--是否创建数据库实例的服务,取值范围: Y/N y/n不允许为空不初始化数据库将忽略此节点。非root用户不能创建数据库服务。 --> <!--是否创建数据库实例的服务,取值范围: Y/N y/n不允许为空不初始化数据库将忽略此节点。非root用户不能创建数据库服务。 -->
<CREATE_DB_SERVICE>Y</CREATE_DB_SERVICE> <CREATE_DB_SERVICE>N</CREATE_DB_SERVICE>
<!--是否启动数据库,取值范围: Y/N y/n不允许为空不创建数据库服务将忽略此节点。 --> <!--是否启动数据库,取值范围: Y/N y/n不允许为空不创建数据库服务将忽略此节点。 -->
<STARTUP_DB_SERVICE>N</STARTUP_DB_SERVICE> <STARTUP_DB_SERVICE>N</STARTUP_DB_SERVICE>

0
docker/code-server/.editorconfig Executable file → Normal file
View File

0
docker/code-server/LICENSE Executable file → Normal file
View File

0
docker/code-server/package_versions.txt Executable file → Normal file
View File

View File

View File

View File

0
docker/nginx/Dockerfile Executable file → Normal file
View File

0
docker/nginx/default.conf Executable file → Normal file
View File

0
docker/nginx/nginx.conf Executable file → Normal file
View File

0
docker/nginx/start.sh Executable file → Normal file
View File

0
docker/ssh-server/Dockerfile Executable file → Normal file
View File

24
python/Dockerfile Executable file → Normal file
View File

@ -1,13 +1,13 @@
FROM base-dm FROM base
# 升级pip # 升级pip
RUN pip install --upgrade pip RUN pip install --upgrade pip
# 创建一个用户运行flask # 创建一个用户运行flask
RUN adduser flask RUN adduser flask && \
RUN chown -R flask:flask /home/flask chown -R flask:flask /home/flask && \
RUN 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 && \
RUN chown -R flask:flask /var/log/flask-app chown -R flask:flask /var/log/flask-app
WORKDIR /home/flask WORKDIR /home/flask
USER flask USER flask
@ -16,18 +16,18 @@ COPY --chown=flask:flask . .
# venv # venv
ENV VIRTUAL_ENV=/home/flask/venv ENV VIRTUAL_ENV=/home/flask/venv
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
# 安装包 # 安装包
RUN python3 -m venv "$VIRTUAL_ENV"
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
RUN export FLASK_APP=main.py
COPY --from=build-dmpython --chown=flask:flask /home/dmdba/build_artifacts/dmPython-2.5.5-cp310-cp310-linux_x86_64.whl . COPY --from=build-dmpython --chown=flask:flask /home/dmdba/build_artifacts/dmPython-2.5.5-cp310-cp310-linux_x86_64.whl .
RUN python3 -m venv "$VIRTUAL_ENV" && \
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 && \
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/
RUN pip3 install dmPython-2.5.5-cp310-cp310-linux_x86_64.whl && rm dmPython-2.5.5-cp310-cp310-linux_x86_64.whl
RUN MAKEFLAGS="-j$(nproc)" pip install -r requirements.txt
USER root
# 暴露端口 # 暴露端口
EXPOSE 5000 EXPOSE 5000
CMD ["python", "main.py"] CMD ["gunicorn", "-w", "3", "-t", "60", "-b", "0.0.0.0:8000", "app:app"]

54
python/app.py Executable file → Normal file
View File

@ -8,7 +8,7 @@ CORS(app, resources={r"/*": {"origins": "*"}})
app.config['SECRET_KEY'] = '350625' app.config['SECRET_KEY'] = '350625'
@app.route('/student', methods=['POST']) # 检测历史是否登录过登录则直接进入index反之则进去login界面 @app.route('/api/student', methods=['POST']) # 检测历史是否登录过登录则直接进入index反之则进去login界面
def student(): # 判断是否已经登录 def student(): # 判断是否已经登录
ID_data = request.json ID_data = request.json
ID = ID_data['student_ID'] ID = ID_data['student_ID']
@ -17,13 +17,11 @@ def student(): # 判断是否已经登录
return jsonify({'student_succeed': student_succeed, 'student_lesson': student_lesson}) return jsonify({'student_succeed': student_succeed, 'student_lesson': student_lesson})
@app.route('/login', methods=['POST']) # 登录功能 @app.route('/api/login', methods=['POST']) # 登录功能
def login(): def login():
login_data = request.json # 获取前端发送过来的数据 login_data = request.json # 获取前端发送过来的数据
ID = login_data['ID'] # 解析数据 ID = login_data['ID'] # 解析数据
password = login_data['password'] password = login_data['password']
print(ID)
print(password)
if len(ID) == 8: # 根据长度判断,长度为十则是学生 if len(ID) == 8: # 根据长度判断,长度为十则是学生
try: try:
en_password, password = student_login_func(ID, password) en_password, password = student_login_func(ID, password)
@ -65,7 +63,7 @@ def login():
# postman # postman
@app.route('/logout', methods=['POST']) # 退出登录功能 @app.route('/api/logout', methods=['POST']) # 退出登录功能
def logout(): # 退出登录 def logout(): # 退出登录
ID = session['id'] ID = session['id']
print(ID) print(ID)
@ -73,7 +71,7 @@ def logout(): # 退出登录
return jsonify({'result': '注销成功'}) return jsonify({'result': '注销成功'})
@app.route('/register', methods=['POST']) # 注册功能实现 @app.route('/api/register', methods=['POST']) # 注册功能实现
def register(): def register():
register_data = request.json # 获取前端发送过来的数据 register_data = request.json # 获取前端发送过来的数据
name = register_data['name'] name = register_data['name']
@ -88,7 +86,7 @@ def register():
return jsonify({'result': '注册成功'}) return jsonify({'result': '注册成功'})
@app.route('/student/get_lesson', methods=['GET']) @app.route('/api/student/get_lesson', methods=['GET'])
def get_lesson(): # 获取课程 def get_lesson(): # 获取课程
student_id = session.get('id') student_id = session.get('id')
student_lesson = get_lesson_func(student_id) student_lesson = get_lesson_func(student_id)
@ -97,27 +95,27 @@ def get_lesson(): # 获取课程
# 学生获取试卷 # 学生获取试卷
@app.route('/student/get_test', methods=['POST']) @app.route('/api/student/get_test', methods=['POST'])
def get_test(): # 获取试卷以及历史试卷 def get_test(): # 获取试卷以及历史试卷
data = request.json data = request.json
ID = data['student_ID'] ID = data['student_ID']
return jsonify({"data": fetch_test_func(ID)}) return jsonify({"data": fetch_test_func(ID)})
@app.route('/student/fetch_result', methods=['POST']) # 查找成绩 @app.route('/api/student/fetch_result', methods=['POST']) # 查找成绩
def fetch_result(): def fetch_result():
data = request.json data = request.json
ID = data['student_ID'] ID = data['student_ID']
return jsonify({'result': fetch_result_func(ID)}) return jsonify({'result': fetch_result_func(ID)})
@app.route('/student/get_end_student', methods=['POST']) @app.route('/api/student/get_end_student', methods=['POST'])
def get_end_student(): def get_end_student():
data = request.json data = request.json
ID = data['student_ID'] ID = data['student_ID']
return jsonify({'result': find_end_test(ID)}) return jsonify({'result': find_end_test(ID)})
@app.route('/student/score_entry', methods=['POST']) @app.route('/api/student/score_entry', methods=['POST'])
def score_entry(): def score_entry():
data = request.json data = request.json
ID = data['student_ID'] ID = data['student_ID']
@ -128,8 +126,24 @@ def score_entry():
return jsonify({'result': '成功'}) return jsonify({'result': '成功'})
@app.route('/api/student/FetchTrainTitle',methods=['POST'])
def FetchTrainTitle():
data = request.json
ID = data['student_ID']
title=FetchTrainTitleFunc(ID)
return jsonify({'title': title})
@app.route('/api/student/TrainData',methods=['POST'])
def TrainData():
examID=request.json['operateID']
result=FetchTrainTestFunc(examID)
return result
# 以下为教师功能————————————————————————————————————————————————————————————————————— # 以下为教师功能—————————————————————————————————————————————————————————————————————
@app.route('/teacher/return_question', methods=['POST']) @app.route('/api/teacher/return_question', methods=['POST'])
def return_question(): def return_question():
data = request.json data = request.json
ID = data['teacher_ID'] ID = data['teacher_ID']
@ -139,7 +153,7 @@ def return_question():
return jsonify({'选择': choice_question, '填空': completion_question, '判断': t_or_f_question}) return jsonify({'选择': choice_question, '填空': completion_question, '判断': t_or_f_question})
@app.route('/teacher/select_class', methods=['POST']) @app.route('/api/teacher/select_class', methods=['POST'])
def select_class(): # 查找每个老师管理的班级 以及在考试管理查找默认班级 def select_class(): # 查找每个老师管理的班级 以及在考试管理查找默认班级
teacher_id = request.json['teacher_ID'] teacher_id = request.json['teacher_ID']
# testID =request.json['testID'] # testID =request.json['testID']
@ -148,23 +162,23 @@ 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('/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']
ClassID=request.json['selectedValue'] ClassID=request.json['selectedValue']
return jsonify({'default': find_default_class_func(ClassID,teacher_id)}) return jsonify({'default': find_default_class_func(ClassID,teacher_id)})
@app.route('/teacher/detaileddata', methods=['POST']) @app.route('/api/teacher/detaileddata', methods=['POST'])
def detaileddata(): def detaileddata():
data=request.json data=request.json
ClassID=data['selectedValue'] ClassID=data['selectedValue']
testID=data['testID'] testID=data['testID']
return jsonify({'data':detailed_class(testID,ClassID)}) return jsonify({'data':detailed_class(testID,ClassID)})
@app.route('/teacher/', methods=['POST']) @app.route('/api/teacher/', methods=['POST'])
def find_test(): def find_test():
return return
@app.route('/teacher/find_student', methods=['POST']) @app.route('/api/teacher/find_student', methods=['POST'])
def find_student(): # 获取班级学生的具体信息 def find_student(): # 获取班级学生的具体信息
student_list = [] student_list = []
Data = request.json Data = request.json
@ -175,7 +189,7 @@ def find_student(): # 获取班级学生的具体信息
return [student_succeed, student_list] return [student_succeed, student_list]
@app.route('/teacher/accept_test', methods=['POST']) # 在前端发布成功之后要存入数据库 @app.route('/api/teacher/accept_test', methods=['POST']) # 在前端发布成功之后要存入数据库
def accept_test(): def accept_test():
data = request.json data = request.json
choice_list = data['ChoiceQuestionSet'] choice_list = data['ChoiceQuestionSet']
@ -190,11 +204,11 @@ def accept_test():
print('添加成功') print('添加成功')
return jsonify({'result': '发布成功'}) return jsonify({'result': '发布成功'})
@app.route('/teacher/fetch_train_question',methods=["POST"]) @app.route('/api/teacher/fetch_train_question',methods=["POST"])
def fetch_train_question(): def fetch_train_question():
return train_question() return train_question()
@app.route('/teacher/SendTrainTest',methods=["POST"]) @app.route('/api/teacher/SendTrainTest',methods=["POST"])
def SendTrainTest(): def SendTrainTest():
data=request.json data=request.json
TrainChoice=data['TrainChoice'] TrainChoice=data['TrainChoice']

0
python/requirements.txt Executable file → Normal file
View File

Some files were not shown because too many files have changed in this diff Show More