From 1beb4fdb86d8ac253c097360493ae20b568562a8 Mon Sep 17 00:00:00 2001 From: nopy <646880214@qq.com> Date: Mon, 1 Jul 2024 21:48:29 +0800 Subject: [PATCH] 7.1 --- .gitignore | 4 +- app-dm/package-lock.json | 82 +++++- app-dm/package.json | 1 + app-dm/src/TeacherPages/TestManage/Test.tsx | 89 ++++++ .../TeacherPages/Trainmanage/SendTrain.css | 5 +- .../TeacherPages/Trainmanage/SendTrain.jsx | 68 ++--- .../TeacherPages/teacherManagetest/Test.css | 0 .../TeacherPages/teacherManagetest/Test.tsx | 0 app-dm/src/pages/Home/Home.jsx | 3 +- app-dm/src/pages/ListPages/Subject/Exam.css | 9 + app-dm/src/pages/ListPages/Subject/Exam.jsx | 265 ++++++++++++++++-- .../pages/ListPages/Subject/SubjectPage.jsx | 23 +- .../pages/ListPages/Training/Operation1.jsx | 17 +- .../pages/ListPages/Training/Operation2.jsx | 12 +- app-dm/src/router/index.jsx | 6 +- build.sh | 14 +- docker-compose.yml | 7 +- docker/base-dm/Dockerfile | 4 +- docker/base/Dockerfile | 2 + docker/ssh-server/Dockerfile | 27 +- python/.devenv | 27 ++ python/.gitignore | 3 + python/Dockerfile | 10 +- python/app.py | 94 ++++++- python/assets/type0-pod.yaml | 19 ++ python/assets/type0-service.yaml | 0 python/requirements.txt | 6 +- python/student_func.py | 74 ++++- python/teacher_func.py | 37 ++- python/test.py | 5 + 30 files changed, 758 insertions(+), 155 deletions(-) create mode 100644 app-dm/src/TeacherPages/TestManage/Test.tsx create mode 100644 app-dm/src/TeacherPages/teacherManagetest/Test.css create mode 100644 app-dm/src/TeacherPages/teacherManagetest/Test.tsx create mode 100644 python/.devenv create mode 100644 python/.gitignore create mode 100644 python/assets/type0-pod.yaml create mode 100644 python/assets/type0-service.yaml create mode 100644 python/test.py diff --git a/.gitignore b/.gitignore index cdd94a1..7dc4f0e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ .idea -node_modules -__pycache__ -public \ No newline at end of file +node_modules \ No newline at end of file diff --git a/app-dm/package-lock.json b/app-dm/package-lock.json index a462fec..0261786 100644 --- a/app-dm/package-lock.json +++ b/app-dm/package-lock.json @@ -38,6 +38,7 @@ "react-scripts": "^5.0.1", "recharts": "^2.12.7", "redux": "^5.0.1", + "socket.io-client": "^4.7.5", "stream": "^0.0.2", "swr": "^2.2.5", "tailwindcss": "^3.4.3", @@ -4009,6 +4010,11 @@ "@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": { "version": "2.2.3", "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": { "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==" }, "node_modules/@xtuc/ieee754": { @@ -7865,6 +7871,46 @@ "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": { "version": "5.16.0", "resolved": "https://registry.npmmirror.com/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", @@ -16477,6 +16523,32 @@ "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": { "version": "0.3.24", "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", "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": { "version": "5.0.8", "resolved": "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz", diff --git a/app-dm/package.json b/app-dm/package.json index 89c2d69..4053782 100644 --- a/app-dm/package.json +++ b/app-dm/package.json @@ -32,6 +32,7 @@ "react-scripts": "^5.0.1", "recharts": "^2.12.7", "redux": "^5.0.1", + "socket.io-client": "^4.7.5", "stream": "^0.0.2", "swr": "^2.2.5", "tailwindcss": "^3.4.3", diff --git a/app-dm/src/TeacherPages/TestManage/Test.tsx b/app-dm/src/TeacherPages/TestManage/Test.tsx new file mode 100644 index 0000000..cb17197 --- /dev/null +++ b/app-dm/src/TeacherPages/TestManage/Test.tsx @@ -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(null); + const [terminal, setTerminal] = useState(null); + const [socket, setSocket] = useState(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 ( +
+
+
+
+ ); +} diff --git a/app-dm/src/TeacherPages/Trainmanage/SendTrain.css b/app-dm/src/TeacherPages/Trainmanage/SendTrain.css index 79e556a..6147350 100644 --- a/app-dm/src/TeacherPages/Trainmanage/SendTrain.css +++ b/app-dm/src/TeacherPages/Trainmanage/SendTrain.css @@ -202,9 +202,8 @@ .calendar-box span{ position: absolute; - /* top: 20px; */ - top: 380px; - right: 160px; + top: 400px; + right: 185px; } .calendar1{ width: 100px; diff --git a/app-dm/src/TeacherPages/Trainmanage/SendTrain.jsx b/app-dm/src/TeacherPages/Trainmanage/SendTrain.jsx index 4094c03..122d3ba 100644 --- a/app-dm/src/TeacherPages/Trainmanage/SendTrain.jsx +++ b/app-dm/src/TeacherPages/Trainmanage/SendTrain.jsx @@ -3,7 +3,8 @@ import { Link } from 'react-router-dom'; import './SendTrain.css' import axios from 'axios'; import DatePicker from 'react-datepicker'; -import 'react-datepicker/dist/react-datepicker.css'; +import "react-datepicker/dist/react-datepicker.css"; + function SendTrain(){ const teacher_ID=localStorage.getItem('islogin') @@ -138,29 +139,17 @@ function SendTrain(){ } // 日历 - // 用于存储开始日期和结束日期的状态 const [startDate, setStartDate] = useState(new Date()); const [endDate, setEndDate] = useState(new Date()); - // 格式化日期显示 - const formatDate = (date) => { - return date.toLocaleDateString(); - }; - // 选择日期时更新状态 + // 处理开始时间选择 const handleStartDateChange = (date) => { setStartDate(date); }; + + // 处理结束时间选择 const handleEndDateChange = (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(
@@ -346,30 +335,35 @@ function SendTrain(){ {/* 日历 */}

请填写考试开始、截止日期

- - - - + {/* 开始时间输入框 */} +
+ {/* 日历组件 */} +
+ + +
+ +
-

总天数:{calculateTotalDays()}天

- + ) } diff --git a/app-dm/src/TeacherPages/teacherManagetest/Test.css b/app-dm/src/TeacherPages/teacherManagetest/Test.css new file mode 100644 index 0000000..e69de29 diff --git a/app-dm/src/TeacherPages/teacherManagetest/Test.tsx b/app-dm/src/TeacherPages/teacherManagetest/Test.tsx new file mode 100644 index 0000000..e69de29 diff --git a/app-dm/src/pages/Home/Home.jsx b/app-dm/src/pages/Home/Home.jsx index bb83281..3368983 100644 --- a/app-dm/src/pages/Home/Home.jsx +++ b/app-dm/src/pages/Home/Home.jsx @@ -11,11 +11,10 @@ import { max, min } from 'lodash'; // 首页 function Home(){ - const [isChecked,setisChecked]=useState(false) const student_ID=localStorage.getItem('islogin') if(student_ID==null){ + window.location.href='http://localhost:3000/signin' alert('未登录,请先前往登录') - window.location.href='http://36.138.114.105:30294/' } //课表数据 const [lesson, setLesson] = useState([]); diff --git a/app-dm/src/pages/ListPages/Subject/Exam.css b/app-dm/src/pages/ListPages/Subject/Exam.css index 247fb2f..5751808 100644 --- a/app-dm/src/pages/ListPages/Subject/Exam.css +++ b/app-dm/src/pages/ListPages/Subject/Exam.css @@ -119,4 +119,13 @@ margin-left: 5px; margin-top: 5px; cursor: pointer; +} +.body-right1-exam{ + width: 1414px; + height: 1540px; + position: absolute; + top: 64px; + left: 230px; + border-radius: 10px; + background-color: #f7f8fa; } \ No newline at end of file diff --git a/app-dm/src/pages/ListPages/Subject/Exam.jsx b/app-dm/src/pages/ListPages/Subject/Exam.jsx index 17f52a8..8058205 100644 --- a/app-dm/src/pages/ListPages/Subject/Exam.jsx +++ b/app-dm/src/pages/ListPages/Subject/Exam.jsx @@ -10,10 +10,66 @@ import top from '../img/top.jpg' import axios from 'axios'; function Exam() { - - //倒计时 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(() => { @@ -24,19 +80,22 @@ function Exam() { } else { clearInterval(interval); alert('考试时间到!'); + correct() + window.location.href='http://localhost:3000/subject' } }, 1000); return () => clearInterval(interval); }, [countdown]); - // useEffect(()=>{ - // if(countdown<0){ - // console.log('c'); - // setCountdown(60 * parseInt(TrainData['operateID'][4])) - // localStorage.removeItem('time') - // } - // },[TrainData]) + useEffect(()=>{ + if(countdown<0){ + localStorage.removeItem('time') + setCountdown(60 * parseInt(TestData['examID'][3])) + } + },[TestData]) + + // 转换秒数为时分秒格式 const formatTime = (seconds) => { const hours = Math.floor(seconds / 3600); @@ -48,6 +107,109 @@ function Exam() { // 下拉菜单 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 (
@@ -78,32 +240,99 @@ function Exam() { {/* 题目预览框 */} {/* 根据isFixed状态来设置countBox的类 */} - {/*
- {TrainData&& +
{/* 根据isFixed状态来设置countBox的类 */} + {TestData&&
选择题:
- {Object.keys(TrainData['operateID'][0]).map((key,index)=>( + {Object.keys(TestData['examID'][0]).map((key,index)=>(
))} 填空题:
- {Object.keys(TrainData['operateID'][1]).map((key,index)=>( + {Object.keys(TestData['examID'][1]).map((key,index)=>(
))} 判断题:
- {Object.keys(TrainData['operateID'][2]).map((key,index)=>( + {Object.keys(TestData['examID'][2]).map((key,index)=>(
))}
{index+1}
{index+1}
{index+1}
} -
*/} +
+ +
+
+ {TestData&& +

选择题

+ + {Object.keys(TestData['examID'][0]).map((key,index) => ( + + {index+1}.{TestData['examID'][0][key][0][1]} +
+ +
+ +
+ +
+ +
+ + ))} + +
} + + {TestData&&( + + +

填空题

+ {Object.keys(TestData['examID'][1]).map((key,index)=>( + + {index+1}.{TestData['examID'][1][key][0][1]} + {/*
*/} +
+ 请填入你的答案: + +
+ + ))} + +
+ )} + + {TestData&&( + + +

判断题

+ {Object.keys(TestData['examID'][2]).map((key,index)=>( + + {index+1}.{TestData['examID'][2][key][0][1]} + + + + + + ))} + +
+ )} +
- {/*
- -
*/} ) diff --git a/app-dm/src/pages/ListPages/Subject/SubjectPage.jsx b/app-dm/src/pages/ListPages/Subject/SubjectPage.jsx index 89a99ef..6544e5f 100644 --- a/app-dm/src/pages/ListPages/Subject/SubjectPage.jsx +++ b/app-dm/src/pages/ListPages/Subject/SubjectPage.jsx @@ -57,19 +57,18 @@ function SubjectPage(){ ))} }

已结束或完成的试卷与练习

- { testdata&& result&&
- {Object.keys(testdata).map((key)=>{ - return( -
-

试卷ID:{testdata[key][0][3]}

- 发布者:{'小陈老师'} -
发布时间:{testdata[key][1][0][5]}
-
截至时间:{testdata[key][1][0][6]}
-
{testdata[key][0][5]}
+
+ { Object.keys(testdata).slice(-3).reverse().map((key) => ( +
+

试卷ID:{testdata[key][0][3]}

+ 发布者:{'小陈老师'} +
发布时间:{testdata[key][1][0][5]}
+
截至时间:{testdata[key][1][0][6]}
+
{testdata[key][0][5]}
- ) - })} -
} + ))} +
+ { NotFalse&& result&&
{Object.keys(NotFalse).map((key)=>{ return( diff --git a/app-dm/src/pages/ListPages/Training/Operation1.jsx b/app-dm/src/pages/ListPages/Training/Operation1.jsx index 688f01c..d88685b 100644 --- a/app-dm/src/pages/ListPages/Training/Operation1.jsx +++ b/app-dm/src/pages/ListPages/Training/Operation1.jsx @@ -16,19 +16,9 @@ function Operation1() { console.log(60 * parseInt(TrainData['operateID'][4])); } const clear=()=>{ - localStorage.removeItem('choice_answers'); - setchoice_answer({}) - localStorage.removeItem('completion_answer') - setcompletion_answer({}) - localStorage.removeItem('judge_answer') - setjudge_answer({}) - localStorage.removeItem('answeredChoice') - setAnsweredChoice([]) - localStorage.removeItem('answeredComple') - setAnsweredComple([]) - localStorage.removeItem('answeredJudge') - setAnsweredJudge([]) - localStorage.removeItem('RemainingTime') + ['time', 'choice_answers', 'completion_answer', 'judge_answer', + 'answeredChoice', 'answeredComple', 'answeredJudge', 'RemainingTime', 'TrainData'] + .forEach(item => localStorage.removeItem(item)); } const { operateID } = useParams(); @@ -85,7 +75,6 @@ function Operation1() { useEffect(()=>{ if(countdown<0){ - console.log('c'); setCountdown(60 * parseInt(TrainData['operateID'][4])) localStorage.removeItem('time') } diff --git a/app-dm/src/pages/ListPages/Training/Operation2.jsx b/app-dm/src/pages/ListPages/Training/Operation2.jsx index 95e3699..bee25e5 100644 --- a/app-dm/src/pages/ListPages/Training/Operation2.jsx +++ b/app-dm/src/pages/ListPages/Training/Operation2.jsx @@ -146,8 +146,16 @@ function Operation2() { const tijiao = ()=>{ setCountdown(0) 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('提交成功') window.location.href='http://localhost:3000/train' + localStorage.removeItem('TrainData') } return ( @@ -184,7 +192,7 @@ function Operation2() { {/* 前端连接数据库⬇ */} - { !isTrue&&
+ { !isTrue&&TrainData&&
{TrainData['operateID'][3][0]}
点击以上链接前往实训 @@ -192,7 +200,7 @@ function Operation2() { {/* 前端连接数据库 ⬆*/} {/* 达梦数据库连接 ⬇*/} - { isTrue&& + { isTrue&&TrainData&&

{TrainData['operateID'][3][0]}

diff --git a/app-dm/src/router/index.jsx b/app-dm/src/router/index.jsx index a2c4596..0eb7d11 100755 --- a/app-dm/src/router/index.jsx +++ b/app-dm/src/router/index.jsx @@ -23,11 +23,12 @@ import ClassID from '../TeacherPages/classlistpages/classId'; import ManageTest from '../TeacherPages/TestManage/ManageTest'; import SendTest from '../TeacherPages/TestManage/SendTest'; 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 SendTrain from '../TeacherPages/TrainManage/SendTrain'; +import TrainManage from '../TeacherPages/TrainManage/Trainmanage'; +import Test from "../TeacherPages/teacherManagetest/Test.tsx" // 定义一个组件来包裹除了特定页面(exam)外的所有页面使其有导航 const MainLayout = ({ headerNav:HeaderNav }) => { return ( @@ -69,6 +70,7 @@ function App() { }> } /> + }/> {/* 页面使用单独的布局,不包含HeaderNav和HeaderNavTeacher */} } />{/* 练习-考试页面 */} diff --git a/build.sh b/build.sh index 029e22f..38c1c27 100644 --- a/build.sh +++ b/build.sh @@ -20,13 +20,14 @@ build_image() { # 推送镜像 push_image() { + local service_name=$1 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" + echo "${service_name} tag" + docker tag "${service_name}" 36.138.114.105:31000/cnsof50011836/$service_name + echo "${service_name} pushing" + docker push 36.138.114.105:31000/cnsof50011836/$service_name + echo "${service_name} pushed" else echo "用户选择不推送镜像" fi @@ -43,7 +44,8 @@ main() { build_image build-frontend build_image flask-app - push_image + push_image flask-app + push_image base-dm echo "脚本结束" } diff --git a/docker-compose.yml b/docker-compose.yml index 7b095cd..4d5bc3e 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -23,14 +23,11 @@ services: flask-app: build: ./python restart: always + image: flask-app depends_on: - base-dm ports: - '8000:8000' - healthcheck: - test: ["CMD-SHELL", "curl --silent --fail localhost:8000/flask-health-check || exit 1"] - interval: 10s - timeout: 10s - retries: 3 + - '8765:8765' command: gunicorn -w 3 -t 60 -b 0.0.0.0:8000 app:app diff --git a/docker/base-dm/Dockerfile b/docker/base-dm/Dockerfile index 1d30f8f..24689fc 100644 --- a/docker/base-dm/Dockerfile +++ b/docker/base-dm/Dockerfile @@ -6,8 +6,8 @@ RUN useradd -m -s /bin/bash 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 unzip 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 \ +&& 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 \ diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile index f73ec32..c03eea3 100644 --- a/docker/base/Dockerfile +++ b/docker/base/Dockerfile @@ -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 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 \ && sudo /usr/sbin/update-locale LANG=zh_CN.UTF-8 LC_ALL=zh_CN.UTF-8 \ && locale-gen \ diff --git a/docker/ssh-server/Dockerfile b/docker/ssh-server/Dockerfile index 048c94f..a005bc5 100644 --- a/docker/ssh-server/Dockerfile +++ b/docker/ssh-server/Dockerfile @@ -1,26 +1 @@ -FROM ubuntu -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 +FROM base-dm \ No newline at end of file diff --git a/python/.devenv b/python/.devenv new file mode 100644 index 0000000..4139b95 --- /dev/null +++ b/python/.devenv @@ -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 \ No newline at end of file diff --git a/python/.gitignore b/python/.gitignore new file mode 100644 index 0000000..ebed232 --- /dev/null +++ b/python/.gitignore @@ -0,0 +1,3 @@ +.idea +__pycache__ +public \ No newline at end of file diff --git a/python/Dockerfile b/python/Dockerfile index 4d0eac3..db826f5 100644 --- a/python/Dockerfile +++ b/python/Dockerfile @@ -4,10 +4,12 @@ FROM base RUN pip install --upgrade pip # 创建一个用户运行flask -RUN adduser flask && \ +RUN useradd -m -s /bin/bash 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 && \ -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 USER flask @@ -24,10 +26,12 @@ 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-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"] \ No newline at end of file diff --git a/python/app.py b/python/app.py index f8825ef..055440e 100644 --- a/python/app.py +++ b/python/app.py @@ -1,12 +1,28 @@ +import subprocess +import threading +import time + +import paramiko + from teacher_func import * from student_func import * + from flask import Flask, render_template, request, jsonify, send_from_directory, session 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") -CORS(app, resources={r"/*": {"origins": "*"}}) +CORS(app) +cors = CORS(app, resource={ + r"/*":{ + "origins":"*" + } +}) app.config['SECRET_KEY'] = '350625' +socketio = SocketIO(app, cors_allowed_origins="*") +clients = {} @app.route('/api/student', methods=['POST']) # 检测历史是否登录过,登录则直接进入index,反之则进去login界面 def student(): # 判断是否已经登录 @@ -103,10 +119,11 @@ def get_test(): # 获取试卷以及历史试卷 result2=falseTest_func(ID) return jsonify({"True":result1,'FalseTest':result2}) -@app.route('/api/student/get_testID',methods=['POST']) -def get_testID(): # 获取试卷ID - ID=request.json['student_ID'] - return jsonify({'data': 'a'}) +@app.route('/api/student/TestData',methods=['POST']) +def TestData(): # 获取试卷ID + examID=request.json['examId'] + result=TestDataFunc(examID) + return result @app.route('/api/student/fetch_result', methods=['POST']) # 查找成绩 @@ -115,11 +132,7 @@ def fetch_result(): ID = data['student_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']) @@ -183,6 +196,12 @@ def select_class(): # 查找每个老师管理的班级 以及在考试管理 # print(testID) 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']) def change_class(): # 查找每个老师管理的班级 以及在考试管理查找默认班级 teacher_id = request.json['teacher_ID'] @@ -242,6 +261,7 @@ def SendTrainTest(): Train=data['Train'] teacher_id=data['teacher_ID'] SendTrainTestFunc(TrainChoice, TrainCompletion, TrainJudge, Hour, Min, StopTime,Class,Train,teacher_id) + TeacherMark(Class,teacher_id) return '发布成功' @@ -250,7 +270,6 @@ def Find_details(): data=request.json ID=data['ID'] result=Find_details_Func(ID) - print(result) return jsonify({'TestScore':result}) @@ -260,7 +279,56 @@ def catch_all(path = "index.html"): 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__': - 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) + diff --git a/python/assets/type0-pod.yaml b/python/assets/type0-pod.yaml new file mode 100644 index 0000000..667ef74 --- /dev/null +++ b/python/assets/type0-pod.yaml @@ -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 \ No newline at end of file diff --git a/python/assets/type0-service.yaml b/python/assets/type0-service.yaml new file mode 100644 index 0000000..e69de29 diff --git a/python/requirements.txt b/python/requirements.txt index 1eddad4..a785c55 100644 --- a/python/requirements.txt +++ b/python/requirements.txt @@ -1,4 +1,8 @@ Flask==2.3.0 Flask_Cors==4.0.0 pycryptodome==3.19.0 -gunicorn \ No newline at end of file +gunicorn +kubernetes +websockets +paramiko +flask-socketio \ No newline at end of file diff --git a/python/student_func.py b/python/student_func.py index e1f72d0..af1d9a2 100644 --- a/python/student_func.py +++ b/python/student_func.py @@ -117,10 +117,9 @@ def get_lesson_func(id): def student_succeed_func(ID): 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_succeeds = student_succeed[0], student_succeed[1], student_succeed[3], student_succeed[4] - print(student_succeeds) cursor.close() return student_succeeds @@ -128,17 +127,27 @@ def student_succeed_func(ID): # fetch_testID('20240101') def fetch_test_func(ID):#获取试卷 cursor = db.cursor() + correct=[] TrueTestDic={} TruetestID=[] cursor.execute(f"SELECT * FROM STUDENT_TEST WHERE STUDENT_ID=? AND TF='true'",(ID)) for i in cursor.fetchall(): + correct.append(i) + + correct=correct[::-1][:3] + + for i in correct: TruetestID.append(i[3]) TrueTestDic[i[3]]=i + TruetestID=TruetestID[::-1][:3] + for index in TruetestID: cursor.execute(f"SELECT * FROM TEST_BANK WHERE ID=?",(index)) TrueTestDic[index]=TrueTestDic[index],cursor.fetchall() + # print(TrueTestDic) + return TrueTestDic # fetch_test_func('20240101') @@ -166,6 +175,53 @@ def falseTest_func(ID): # 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): cursor = db.cursor() @@ -196,12 +252,22 @@ def FetchTrainTitleFunc(ID): titles.append(i[2]) for i in titles: - cursor.execute('SELECT * FROM TRAINTEST WHERE ID=? ',(i)) - title.append(cursor.fetchall()) + cursor.execute('SELECT * FROM TRAINTEST WHERE ID=? AND STOPTIME>? ',(i,Time)) + 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() return title +# FetchTrainTitleFunc("20240101") def FetchTrainTestFunc(operateID): diff --git a/python/teacher_func.py b/python/teacher_func.py index b2a4399..63ae1e9 100644 --- a/python/teacher_func.py +++ b/python/teacher_func.py @@ -7,6 +7,8 @@ import datetime db = dmPython.connect(user='SYSDBA', password='dameng!!', host="36.138.114.105", port="32522") + + #获取题目 def choice_question_func(ID): question_cursor = db.cursor() @@ -218,6 +220,9 @@ def train_question(): # print(Train) return Train + +testID=None +TrainName="" # train_question() def SendTrainTestFunc(TrainChoice,TrainCompletion,TrainJudge,Hour,Min,StopTime,Class,Train,teacher_id): TrainChoice = json.dumps(TrainChoice) @@ -225,6 +230,8 @@ def SendTrainTestFunc(TrainChoice,TrainCompletion,TrainJudge,Hour,Min,StopTime,C TrainJudge = json.dumps(TrainJudge) Class=json.dumps(Class) Train=json.dumps(Train) + global TrainName + TrainName=Train # 获取当前时间 now_time = datetime.datetime.now().replace(microsecond=0) 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)) # 发布实训的时候根据实训不同给予不同链接 - + cursor.execute(f"SELECT ID FROM TRAINTEST WHERE RELEASETIME=? ", (now_time)) + test_id = cursor.fetchall()[0][0] + global testID + testID=test_id print('分配成功') db.commit() cursor.close() 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): # # 获取字典的键,并按照从大到小的顺序排序 # keys_sorted = sorted(dic.keys(), reverse=True) @@ -291,3 +312,17 @@ def Find_details_Func(ID): return dic # 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') diff --git a/python/test.py b/python/test.py new file mode 100644 index 0000000..cfbe974 --- /dev/null +++ b/python/test.py @@ -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')