From 87e0aa098b7b12777d662080ee32d7fafcaba7e6 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Thu, 19 Dec 2019 09:34:34 +0800 Subject: [PATCH 01/61] =?UTF-8?q?=E5=A4=B4=E9=83=A8=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E5=8A=A0=E4=B8=8A=E5=AD=A6=E6=A0=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/colleges_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/colleges_controller.rb b/app/controllers/colleges_controller.rb index 71009d2dd..51a8b7123 100644 --- a/app/controllers/colleges_controller.rb +++ b/app/controllers/colleges_controller.rb @@ -21,7 +21,7 @@ class CollegesController < ApplicationController # 实训总数 @shixuns_count = Shixun.visible.joins('left join user_extensions on user_extensions.user_id = shixuns.user_id') .where(user_extensions: { school_id: current_school.id }).count - render json: { teachers_count: @teachers_count, students_count: @students_count, courses_count: @courses_count, shixuns_count: @shixuns_count } + render json: { teachers_count: @teachers_count, students_count: @students_count, courses_count: @courses_count, shixuns_count: @shixuns_count, school: current_school.name } end def shixun_time From 1f58b60a0d80d438bd31cbef4908a20a4d658515 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 14:52:45 +0800 Subject: [PATCH 02/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/App.js | 12 +- public/react/src/college/College.js | 1222 +++++++++++++++++ .../college/colleagechart/Colleagechart.js | 84 ++ .../college/colleagechart/Colleagechartzu.js | 149 ++ .../src/college/colleagecss/colleage.css | 213 +++ 5 files changed, 1679 insertions(+), 1 deletion(-) create mode 100644 public/react/src/college/College.js create mode 100644 public/react/src/college/colleagechart/Colleagechart.js create mode 100644 public/react/src/college/colleagechart/Colleagechartzu.js create mode 100644 public/react/src/college/colleagecss/colleage.css diff --git a/public/react/src/App.js b/public/react/src/App.js index 4694d57da..ecb45cd1a 100644 --- a/public/react/src/App.js +++ b/public/react/src/App.js @@ -300,6 +300,11 @@ const Developer = Loadable({ loader: () => import('./modules/developer'), loading: Loading }) +// 学院统计 +const College = Loadable({ + loader: () => import('./college/College'), + loading: Loading +}) // 开发者编辑模块 const NewOrEditTask = Loadable({ @@ -614,7 +619,10 @@ class App extends Component { {/*/>*/} - + () + }/> {/* jupyter */} + () } /> + () diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js new file mode 100644 index 000000000..c503d5387 --- /dev/null +++ b/public/react/src/college/College.js @@ -0,0 +1,1222 @@ +import React, {Component} from "react"; +import {Link, NavLink} from 'react-router-dom'; +import {WordsBtn, ActionBtn,SnackbarHOC,getImageUrl} from 'educoder'; +import axios from 'axios'; +import { + notification, + Spin, + Table, + Pagination, +} from "antd"; +import Colleagechart from './colleagechart/Colleagechart' +import Colleagechartzu from './colleagechart/Colleagechartzu' +import {TPMIndexHOC} from "../modules/tpm/TPMIndexHOC"; +import NoneData from './../modules/courses/coursesPublic/NoneData'; + +import './colleagecss/colleage.css'; +import Shixunechart from "../modules/courses/shixunHomework/shixunreport/Shixunechart"; +class College extends Component { + constructor(props) { + super(props); + // this.answerMdRef = React.createRef(); + this.state = { + coursesloading:false, + columns: [ + { + title: '名称', + dataIndex: 'name', + key: 'name', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth247", + render: (text, record) => ( + { + record.name + } + ) + }, + { + title: '管理教师', + dataIndex: 'teachers', + key: 'teachers', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth340", + render: (text, record) => ( + + { + record.teachers + } + + ) + }, + { + title: '评测次数', + dataIndex: 'times', + key: 'times', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth175", + render: (text, record) => ( + + { + record.evaluating_count + } + + ), + }, + { + title: '学生', + key: 'student', + dataIndex: 'student', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth255", + render: (text, record) => ( + + { + record.student_count + } + + ) + }, + { + title: '实训作业', + dataIndex: 'training', + key: 'training', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.shixun_work_count + } + + ) + + }, + { + title: '资源', + dataIndex: 'resources', + key: 'resources', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.attachment_count + } + + ), + }, + { + title: '帖子', + dataIndex: 'posts', + key: 'posts', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + { + record.message_count + } + ) + }, + { + title: '其它任务', + dataIndex: 'othertasks', + key: 'othertasks', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.other_work_count + } + + ) + }, + { + title: '状态', + dataIndex: 'states', + key: 'states', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.is_end? + "已结束" + : + "正在进行" + } + + ) + }, + { + title: '时间', + dataIndex: 'timemy', + key: 'timemy', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.activity_time + } + + ) + }, + ], + page:1, + limit:10, + total_users:50, + teachersloading:false, + teacherranking:[ + { + title: '排名', + dataIndex: 'ranking', + key: 'ranking', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.id + } + + ) + }, + { + title: '姓名', + dataIndex: 'name', + key: 'name', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth105", + render: (text, record) => ( + { + record.name + } + + ) + }, + { + title: '管理课堂', + dataIndex: 'classroom', + key: 'classroom', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth175", + render: (text, record) => ( + + { + record.course_count + } + + ), + }, + { + title: '已发布实训作业', + key: 'assignment', + dataIndex: 'assignment', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth255", + render: (text, record) => ( + + { + record.shixun_work_count + } + + ) + }, + { + title: '未发布实训作业', + dataIndex: 'released', + key: 'released', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.un_shixun_work_count + } + + ) + + }, + { + title: '学生数', + dataIndex: 'studentnumber', + key: 'studentnumber', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.student_count + } + + ), + }, + { + title: '完成率', + dataIndex: 'completionrate', + key: 'completionrate', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.complete_rate+"%" + } + + ) + }, + { + title: '发布实训', + dataIndex: 'releasetraining', + key: 'releasetraining', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.publish_shixun_count + } + + ) + } + ], + studentranking:[ + { + title: '排名', + dataIndex: 'ranking', + key: 'ranking', + align: 'center', + className: "edu-txt-center font-14", + width:'100px', + render: (text, record) => ( + + { + record.id===1? + :record.id===2? + + :record.id===3? + + :record.id + } + + ) + }, + { + title: '姓名', + dataIndex: 'name', + key: 'name', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth105", + width:'100px', + render: (text, record) => ( + { + record.name + } + + ) + }, + { + title: '学号', + dataIndex: 'studentid', + key: 'studentid', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth175", + render: (text, record) => ( + + { + record.student_id + } + + ), + }, + { + title: '完成实训', + key: 'training', + dataIndex: 'training', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth255", + render: (text, record) => ( + + { + record.shixun_count + } + + ) + }, + { + title: '在学实训', + dataIndex: 'learning', + key: 'learning', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.study_shixun_count + } + + ) + + }, + { + title: '金币', + dataIndex: 'goldcoin', + key: 'goldcoin', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.grade + } + + ), + }, + { + title: '经验值', + dataIndex: 'empirical', + key: 'empirical', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.experience + } + + ) + }, + ], + school:"", + teachers_count:null, + students_count:null, + courses_count:null, + shixuns_count:null, + shixun_report_count:null, + shixun_time:null, + courses:null, + course_count:0, + pages:1, + limits:10, + teachers:null, + teacher_count:0, + students:null, + student_count:0, + shixun_chart_data:null, + shixun_chart_datanames:null + } + + } + + + componentDidMount(){ + console.log("College"); + console.log(this.props.match.params.id); + this.gettop(); + this.Numberofinternshipreports(); + this.Actualcombattimeoftrainees(); + this.Classnumber(1,10); + this.Teacherranking(1,10); + this.Studentranking(1,10); + this.Onlinetraining(); + this.Hottest(); + } + //头部 + gettop=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/statistics.json`; + axios.get(url).then((response) => { + if(response===null||response===undefined){ + this.setState({ + teachers_count:0, + students_count:0, + courses_count:0, + shixuns_count:0, + school:"", + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + teachers_count:0, + students_count:0, + courses_count:0, + shixuns_count:0, + school:"", + }) + }else{ + this.setState({ + teachers_count:response.data.teachers_count, + students_count:response.data.students_count, + courses_count:response.data.courses_count, + shixuns_count:response.data.shixuns_count, + school:response.data.school, + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + teachers_count:0, + students_count:0, + courses_count:0, + shixuns_count:0, + school:"", + }) + }); + } + + //获取实训报告数 + Numberofinternshipreports=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/shixun_report_count.json`; + axios.get(url).then((response) => { + if(response===null||response===undefined){ + this.setState({ + shixun_report_count:0, + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + shixun_report_count:0, + }) + }else{ + if (response.data.status === -1){ + this.setState({ + shixun_report_count:0, + }) + return + } + this.setState({ + shixun_report_count:response.data.shixun_report_count, + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + shixun_report_count:0, + }) + }); + } + + //学员实战时间 + Actualcombattimeoftrainees=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/shixun_time.json`; + axios.get(url).then((response) => { + if(response===null||response===undefined){ + this.setState({ + shixun_time:0, + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + shixun_time:0, + }) + }else{ + if (response.data.status === -1){ + this.setState({ + shixun_time:0, + }) + return + } + this.setState({ + shixun_time:response.data.shixun_time, + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + shixun_time:0, + }) + }); + } + + //课堂信息 + Classnumber=(page,per_page)=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/course_statistics.json`; + this.setState({ + coursesloading:true + }) + axios.get(url,{params:{ + page:page, + per_page:per_page, + } + }).then((response) => { + if(response===null||response===undefined){ + this.setState({ + courses:[], + course_count:0 + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + courses:[], + course_count:0 + }) + }else{ + if (response.data.status === -1){ + this.setState({ + courses:[], + course_count:0 + }) + return + } + this.setState({ + courses:response.data.courses, + course_count:response.data.course_count, + page:page, + limit:per_page + }) + } + this.setState({ + coursesloading:false + }) + }).catch((error) => { + this.setState({ + courses:[], + course_count:0, + coursesloading:false + }) + }); + } + + //教师排名 + Teacherranking=(page,per_page)=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/teachers.json`; + this.setState({ + teachersloading:true + }) + axios.get(url,{params:{ + page:page, + per_page:per_page, + } + }).then((response) => { + if(response===null||response===undefined){ + this.setState({ + teachers:[], + teacher_count:0 + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + teachers:[], + teacher_count:0 + }) + }else{ + if (response.data.status === -1){ + this.setState({ + teachers:[], + teacher_count:0 + }) + return + } + let teachers=[]; + if(response.data.teachers){ + for(let i=0;i { + this.setState({ + teachers:[], + teacher_count:0, + teachersloading:false + }) + }); + } + //学生排名 + + Studentranking=(page,per_page)=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/student_shixun.json`; + this.setState({ + studentsloading:true + }) + axios.get(url,{params:{ + page:page, + per_page:per_page, + } + }).then((response) => { + if(response===null||response===undefined){ + this.setState({ + students:[], + student_count:0, + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + students:[], + student_count:0, + }) + }else{ + if (response.data.status === -1){ + this.setState({ + students:[], + student_count:0, + }) + return + } + let students=[]; + if(response.data.teachers){ + for(let i=0;i { + this.setState({ + students:[], + student_count:0, + studentsloading:false + }) + }); + } + + //在线实训情况 + Onlinetraining=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/shixun_chart_data.json`; + axios.get(url).then((response) => { + this.setState({ + shixun_chart_data:response.data.data, + shixun_chart_datanames:response.data.names + }) + }).catch((error) => { + + }); + } + //最热测评 + Hottest=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/student_hot_evaluations.json`; + axios.get(url).then((response) => { + this.setState({ + studentionsnames:response.data.names, + studentionsvalues:response.data.values + }) + }).catch((error) => { + + }); + } + + table1handleChange(){ + + } + + //塞选 + paginationonChange=(pageNumber)=>{ + this.Classnumber(pageNumber,10); + } + + paginationonChanges=(pageNumber)=>{ + this.Teacherranking(pageNumber,10); + } + paginationonChangess=(pageNumber)=>{ + this.Studentranking(pageNumber,10); + } + render() { + let {columns,page,limit,total_users,teacherranking,studentranking, + teachers_count,students_count, courses_count, shixuns_count,shixun_report_count,shixun_time,courses,course_count,school,teachers, + pages,limits, teacher_count,teachersloading,coursesloading,pagess,limitss,studentsloading,students,student_count,shixun_chart_data, + shixun_chart_datanames, studentionsnames,studentionsvalues + } = this.state; + + return ( +
+
+
+
{school}
+
+
+ {/*//教师1*/} +
+ 教师 +
+
+ {teachers_count?teachers_count:0} +
+
+ +
+
+ 学生 +
+
+ {students_count?students_count:0} +
+
+ +
+
+ 课堂 +
+
+ {courses_count?courses_count:0} +
+
+ +
+
+ 共建实训 +
+
+ {shixuns_count?shixuns_count:0} +
+
+ {/*//教师2*/} + + + + +
+
+
+
+

+ 基本使用情况 +

+ {/*基本使用情况1*/} +
+

+ 教师 +

+

+ 学生 +

+

+ 课堂 +

+

+ 共建实训 +

+

+ 实习报告 +

+

+ 学员实战时间 +

+
+ + + {/*基本使用情况2*/} +
+
+ { + teachers_count? +
{teachers_count}
+ : + + } +
+
+ { + students_count? +
{students_count}
+ : + + } +
+
+ { + courses_count? +
{courses_count}
+ : + + } +
+
+ { + shixuns_count? +
{shixuns_count}
+ : + + } +
+
+ { + shixun_report_count? +
{shixun_report_count}
+ : + + } +
+
+ { + shixun_time? +
{shixun_time}
+ : + + } +
+
+ {/*基本使用情况3结束*/} +
+ + +
+

+ 课堂 +

+ { + courses===null? +
+ +
+ + : + JSON.stringify(courses) === "[]" ? + + + + : +
+
+ +
+ {courses === undefined ? "" : } + + + { + course_count>=11? +
+
+ +
+ +
+ :"" + } + + + } + + + + + +
+
+

+ 教师排名 +

+ { + teachers===null? +
+ +
+ + : + JSON.stringify(teachers) === "[]" ? + + + + : +
+ +
+ {teachers === undefined ? "" :
} + + + } + + + + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + + {/*
*/} + + +
+

+ 在线实训情况 +

+ { + shixun_chart_data===null? +
+ +
+ + : + JSON.stringify(shixun_chart_data) === "[]" ? + + + + : + + + + } + +
+
+ + + +
+
+

+ 学生排名 +

+ { + students === null ? +
+ +
+ + : + JSON.stringify(students) === "[]" ? + + + + : +
+ +
+ {students === undefined ? "" :
} + + + } + {/*
*/} + {/*
*/} + {/* */} + {/*
*/} + + {/*
*/} + + + + +
+ +
+

+ 最热评测 +

+ { + studentionsnames===null? +
+ +
+ + : + JSON.stringify(studentionsnames) === "[]" ? + + + + : + + + + } + + +
+
+ + + ) + } +} +export default SnackbarHOC() (TPMIndexHOC ( College )); + + diff --git a/public/react/src/college/colleagechart/Colleagechart.js b/public/react/src/college/colleagechart/Colleagechart.js new file mode 100644 index 000000000..1e2767f5a --- /dev/null +++ b/public/react/src/college/colleagechart/Colleagechart.js @@ -0,0 +1,84 @@ +import React, {Component} from "react"; +import {WordsBtn} from 'educoder'; +import {Table} from "antd"; +import {Link,Switch,Route,Redirect} from 'react-router-dom'; +const echarts = require('echarts'); + + + +function startechart(data,datanane){ + var effChart = echarts.init(document.getElementById('shixun_skill_chart')); + + var option = { + + tooltip : { + trigger: 'item', + formatter: "{a}
{b} : {c} ({d}%)" + }, + legend: { + // orient: 'vertical', + // top: 'middle', + bottom: 40, + left: 'center', + data: datanane + }, + series : [ + { + type: 'pie', + radius : '65%', + center: ['50%', '35%'], + selectedMode: 'single', + data:data, + itemStyle: { + emphasis: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } + } + ] + }; + effChart.setOption(option); +} +class Colleagechart extends Component { + + constructor(props) { + super(props); + this.state = { + } + } + + componentDidMount() { + startechart(this.props.data,this.props.datanane) + } + + + componentDidUpdate = (prevProps) => { + if (prevProps.data!= this.props.data) { + startechart(this.props.data,this.props.datanane) + } + } + + + render() { + let {data}=this.props; + + return ( +
+ +
+
+ + + + +
+ + ) + } +} + +export default Colleagechart; diff --git a/public/react/src/college/colleagechart/Colleagechartzu.js b/public/react/src/college/colleagechart/Colleagechartzu.js new file mode 100644 index 000000000..c65d2f6f2 --- /dev/null +++ b/public/react/src/college/colleagechart/Colleagechartzu.js @@ -0,0 +1,149 @@ +import React, {Component} from "react"; +import {WordsBtn} from 'educoder'; +import {Table} from "antd"; +import {Link,Switch,Route,Redirect} from 'react-router-dom'; +const echarts = require('echarts'); + + + +function startechart(names, values){ + var effChart = echarts.init(document.getElementById('shixun_skill_charts')); + + var Color = ['#962e66', '#623363', '#CCCCCC', '#9A9A9A', '#FF8080', '#FF80C2', '#B980FF', '#80B9FF', '#6FE9FF', '#4DE8B4', '#F8EF63', '#FFB967']; + + var option = { + backgroundColor: '#fff', + grid: { + left: '3%', + right: '4%', + bottom: '10%', + containLabel: true + }, + + tooltip: { + show: "true", + trigger: 'item', + formatter: '{c0}', + backgroundColor: 'rgba(0,0,0,0.7)', // 背景 + padding: [8, 10], //内边距 + extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影 + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + xAxis: { + type: 'value', + axisTick: { + show: false + }, + axisLine: { + show: true, + lineStyle: { + color: '#CCCCCC' + } + }, + splitLine: { + show: false, + lineStyle: { + color: '#CCCCCC' + } + }, + axisLabel: { + textStyle: { + color: '#656565', + fontWeight: 'normal', + fontSize: '12' + }, + formatter: '{value}' + } + }, + yAxis: { + type: 'category', + axisLine: { + lineStyle: { + color: '#cccccc' + } + }, + splitLine: { + show: false + }, + axisTick: { + show: false + }, + splitArea: { + show: false + }, + axisLabel: { + inside: false, + textStyle: { + color: '#656565', + fontWeight: 'normal', + fontSize: '12' + } + }, + data: names + }, + series: [{ + name: '', + type: 'bar', + itemStyle: { + normal: { + show: true, + color: function(params) { + return Color[params.dataIndex] + }, + barBorderRadius: 50, + borderWidth: 0, + borderColor: '#333' + } + }, + barGap: '0%', + barCategoryGap: '50%', + data: values + } + + ] + }; + effChart.setOption(option); +} +class Colleagechartzu extends Component { + + constructor(props) { + super(props); + this.state = { + } + } + + componentDidMount() { + startechart(this.props.data,this.props.datavule) + } + + + componentDidUpdate = (prevProps) => { + if (prevProps.data!= this.props.data) { + startechart(this.props.data,this.props.datavule) + } + } + + + render() { + let {data}=this.props; + + return ( +
+ +
+
+ + + + +
+ + ) + } +} + +export default Colleagechartzu; diff --git a/public/react/src/college/colleagecss/colleage.css b/public/react/src/college/colleagecss/colleage.css new file mode 100644 index 000000000..031396896 --- /dev/null +++ b/public/react/src/college/colleagecss/colleage.css @@ -0,0 +1,213 @@ +.yslstatistic-header { + width: 100%; + height: 240px; + background-image: url('/images/educoder/statistics.jpg'); + background-size: 100% 100%; +} +.yslborder{ + border: 1px solid; +} +.yslstatistic-header-title{ + flex: 1; + display: flex; + align-items: center; + color: #4CACFF; + font-size: 32px; +} +.yslstatistic-header-content{ + width: 100%; + display: flex; + justify-content: space-around; +} +.yslstatistic-header-item{ + margin-bottom: 22px; + display: flex; + flex-direction: column; + align-items: center; + color: #fff; +} +.yslstatistic-header-item-label{ + color: #989898; +} + +.yslstatistic-base-item-label{ + width: 200px; + text-align: center; + font-size: 16px; + height: 48px; + line-height: 48px; + color: #686868; + background: #F5F5F5; + border-top: 1px solid #EBEBEB; +} +.yslstatistic-base-item-labels{ + width: 200px; + text-align: center; + height: 100px; + line-height: 100px; + background: #ffffff; + border-top: 1px solid #EBEBEB; + border-bottom: 1px solid #EBEBEB; +} +.yslstatistic-base-item-labelsp{ + color: #000000; + font-size: 24px; +} +.yslstatistic-base-item-labelsspan{ + color: #000000; + margin-left: 5px; + font-size: 16px; +} +.jibenshiyong100{ + width: 100%; +} + +.yslstatistic-header-item-content{ + font-size: 24px; +} +/* 中间居中 */ +.intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +/* 简单居中 */ +.intermediatecenterysls{ + display: flex; + align-items: center; +} +.spacearound{ + display: flex; + justify-content: space-around; + +} +.spacebetween{ + display: flex; + justify-content: space-between; +} +/* 头顶部居中 */ +.topcenter{ + display: -webkit-flex; + flex-direction: column; + align-items: center; + +} + + +/* x轴正方向排序 */ +/* 一 二 三 四 五 六 七 八 */ +.sortinxdirection{ + display: flex; + flex-direction:row; +} +/* x轴反方向排序 */ +/* 八 七 六 五 四 三 二 一 */ +.xaxisreverseorder{ + display: flex; + flex-direction:row-reverse; +} +/* 垂直布局 正方向*/ +/* 一 + 二 + 三 + 四 + 五 + 六 + 七 + 八 */ +.verticallayout{ + display: flex; + flex-direction:column; +} +/* 垂直布局 反方向*/ +.reversedirection{ + display: flex; + flex-direction:column-reverse; +} + +.h4{ + font-size: 1.5rem; + font-weight: 500 !important; +} +.ysllinjibenshiyong{ + font-weight: 500; + line-height: 1.2; + padding: 2rem 1.25rem; + border-bottom: unset; + background:#fff; +} +.linjibenshiyong{ + font-weight: 500; + line-height: 1.2; + padding: 2rem 1.25rem; + border-bottom: unset; + background:#fff; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.yslslinjibenshiyong{ + font-weight: 500; + line-height: 1.2; + border-bottom: unset; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.yinyin{ + background: #fff; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.edu-back-eeee{ + background:#EEEEEE !important; +} +.mt-4{ + margin-top: 1.5rem !important; +} + +.statistic-label{ + padding: 2rem 1.25rem; + font-size: 1.5rem; + font-weight: 400 !important; +} +.mb50{ + padding-bottom: 50px !important; +} +.mt40{ + margin-top: 40px; +} +.mb80{ + margin-bottom: 80px; +} +.task-hide{overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} +a:hover{ + color:#0056b3; +} +.color-blue{ + color: #4CACFF; +} + +.color-huang{ + color:#ffc107 !important +} +.maxnamewidth105{ + max-width: 105px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.maxnamewidth247{ + max-width: 247px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.maxnamewidth340{ + max-width: 340px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} From 95d9635ed4ae1db9acac8e86858fef13005db8c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 14:58:17 +0800 Subject: [PATCH 03/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/college/College.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index c503d5387..0f562d00d 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -417,6 +417,8 @@ class College extends Component { student_count:0, shixun_chart_data:null, shixun_chart_datanames:null + studentionsnames:null, + studentionsvalues:null } } From e3f9a0e2fdc75d1b197b46e784c7c2346de969d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 14:58:41 +0800 Subject: [PATCH 04/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/college/College.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index 0f562d00d..2327d5489 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -416,7 +416,7 @@ class College extends Component { students:null, student_count:0, shixun_chart_data:null, - shixun_chart_datanames:null + shixun_chart_datanames:null, studentionsnames:null, studentionsvalues:null } From 074fce56f7d555354aff809aae87828af671a06d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 15:11:24 +0800 Subject: [PATCH 05/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/college/College.js | 47 +++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 6 deletions(-) diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index 2327d5489..44649c3cf 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -741,12 +741,30 @@ class College extends Component { const id =this.props.match.params.id; const url=`/colleges/${id}/shixun_chart_data.json`; axios.get(url).then((response) => { + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + shixun_chart_data:[], + shixun_chart_datanames:[] + }) + }else{ + if (response.data.status === -1){ + this.setState({ + shixun_chart_data:[], + shixun_chart_datanames:[] + }) + return + } + this.setState({ shixun_chart_data:response.data.data, shixun_chart_datanames:response.data.names }) + } }).catch((error) => { - + this.setState({ + shixun_chart_data:[], + shixun_chart_datanames:[] + }) }); } //最热测评 @@ -754,12 +772,29 @@ class College extends Component { const id =this.props.match.params.id; const url=`/colleges/${id}/student_hot_evaluations.json`; axios.get(url).then((response) => { + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + studentionsnames: [], + studentionsvalues: [] + }) + }else { + if (response.data.status === -1) { + this.setState({ + studentionsnames: [], + studentionsvalues: [] + }) + return + } + this.setState({ + studentionsnames: response.data.names, + studentionsvalues: response.data.values + }) + } + }).catch((error) => { this.setState({ - studentionsnames:response.data.names, - studentionsvalues:response.data.values + studentionsnames: [], + studentionsvalues: [] }) - }).catch((error) => { - }); } @@ -839,7 +874,7 @@ class College extends Component { -
+

基本使用情况

From 66d3ad03568e923f5480239c88bbb58dbf3d63ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 15:16:42 +0800 Subject: [PATCH 06/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/college/College.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index 44649c3cf..eaed9747c 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -299,11 +299,11 @@ class College extends Component { render: (text, record) => ( { - record.id===1? + record.id===1? :record.id===2? - + :record.id===3? - + :record.id } From 04d1d7095d3e980c49ccaebd8efbff2180324f68 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Thu, 19 Dec 2019 15:31:19 +0800 Subject: [PATCH 07/61] =?UTF-8?q?=E5=AD=A6=E6=A0=A1=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/colleges_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/colleges_controller.rb b/app/controllers/colleges_controller.rb index 51a8b7123..2be7f3cd4 100644 --- a/app/controllers/colleges_controller.rb +++ b/app/controllers/colleges_controller.rb @@ -158,7 +158,7 @@ class CollegesController < ApplicationController return true if current_user.admin_or_business? # 超级管理员|运营 return true if current_college.is_a?(Department) && current_college.member?(current_user) # 部门管理员 return true if current_user.is_teacher? && current_user.school_id == current_school.id # 学校老师 - return true if current_school.customers.exists? && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id) + # return true if current_school.customers.exists? && current_user.partner&.partner_customers&.exists?(customer_id: current_school.customer_id) false end From 9c3bff5e9f96170f1b714c199b0760c5bb9aef7f Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Thu, 19 Dec 2019 15:37:04 +0800 Subject: [PATCH 08/61] =?UTF-8?q?=E5=AD=A6=E6=A0=A1=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E9=A1=B5=E9=9D=A2=E6=8E=A5=E5=8F=A3=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/colleges_controller.rb | 8 ++++---- app/views/colleges/student_shixun.json.jbuilder | 2 +- app/views/colleges/teachers.json.jbuilder | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/controllers/colleges_controller.rb b/app/controllers/colleges_controller.rb index 2be7f3cd4..707255866 100644 --- a/app/controllers/colleges_controller.rb +++ b/app/controllers/colleges_controller.rb @@ -44,8 +44,8 @@ class CollegesController < ApplicationController (SELECT count(c.id) FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.user_id=users.id AND m.role in (1,2,3) and c.school_id = #{current_school.id} AND c.is_delete = 0) as course_count FROM `users`, user_extensions ue where ue.school_id=#{current_school.id} and users.id=ue.user_id and ue.identity=0 ORDER BY publish_shixun_count desc, course_count desc, id desc LIMIT 10") # ).order("publish_shixun_count desc, experience desc").limit(10) - @teacher_count = UserExtension.where(school_id: current_school.id) - .select('SUM(IF(identity=0, 1, 0)) AS teachers_count').first.teachers_count + # @teacher_count = UserExtension.where(school_id: current_school.id) + # .select('SUM(IF(identity=0, 1, 0)) AS teachers_count').first.teachers_count @teachers = @teachers.map do |teacher| course_ids = Course.find_by_sql("SELECT c.id FROM courses c, course_members m WHERE c.id != 1309 and m.course_id = c.id AND m.role in (1,2,3) AND m.user_id=#{teacher.id} AND c.is_delete = 0 and c.school_id = #{current_school.id}") @@ -99,7 +99,7 @@ class CollegesController < ApplicationController @course_count = courses.size courses = courses.left_joins(practice_homeworks: { student_works: { myshixun: :games } }) - .select('courses.id, courses.name, courses.is_end, sum(games.evaluate_count) evaluating_count') + .select('courses.id, courses.name, courses.is_end, IFNULL(sum(games.evaluate_count), 0) evaluating_count') .group('courses.id').order('is_end asc, evaluating_count desc') @courses = paginate courses @@ -117,7 +117,7 @@ class CollegesController < ApplicationController # 学生实训 def student_shixun - @student_count = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).count + # @student_count = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).count @students = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id, identity: 1 }).includes(:user_extension).order('experience desc').limit(10) student_ids = @students.map(&:id) diff --git a/app/views/colleges/student_shixun.json.jbuilder b/app/views/colleges/student_shixun.json.jbuilder index 431603afa..97e418148 100644 --- a/app/views/colleges/student_shixun.json.jbuilder +++ b/app/views/colleges/student_shixun.json.jbuilder @@ -7,4 +7,4 @@ json.teachers @students do |student| json.grade student.grade json.experience student.experience end -json.student_count @student_count \ No newline at end of file +# json.student_count @student_count \ No newline at end of file diff --git a/app/views/colleges/teachers.json.jbuilder b/app/views/colleges/teachers.json.jbuilder index 29b383fa4..1308f0cf4 100644 --- a/app/views/colleges/teachers.json.jbuilder +++ b/app/views/colleges/teachers.json.jbuilder @@ -8,4 +8,4 @@ json.teachers @teachers do |teacher| json.complete_rate teacher['complete_rate'] json.publish_shixun_count teacher['publish_shixun_count'] end -json.teacher_count @teacher_count \ No newline at end of file +# json.teacher_count @teacher_count \ No newline at end of file From 3130adbb319c0d0416e5df5864b60bcd23ce0799 Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Thu, 19 Dec 2019 15:54:11 +0800 Subject: [PATCH 09/61] =?UTF-8?q?=E4=BD=9C=E4=B8=9A=E7=9A=84=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E8=BF=87=E6=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/homework_commons_controller.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/controllers/homework_commons_controller.rb b/app/controllers/homework_commons_controller.rb index 8a1c07ddf..638971dfc 100644 --- a/app/controllers/homework_commons_controller.rb +++ b/app/controllers/homework_commons_controller.rb @@ -167,7 +167,11 @@ class HomeworkCommonsController < ApplicationController if params[:work_status].present? params_work_status = params[:work_status] work_status = params_work_status.map{|status| status.to_i} - @student_works = @student_works.where(compelete_status: work_status) + if @homework.homework_type == "practice" + @student_works = @student_works.where(compelete_status: work_status) + else + @student_works = @student_works.where(work_status: work_status) + end end # 分班情况 From 6567a517cf16f4e07bada8f1b0748d4bd4dc1e3d Mon Sep 17 00:00:00 2001 From: cxt <853663049@qq.com> Date: Thu, 19 Dec 2019 16:36:14 +0800 Subject: [PATCH 10/61] =?UTF-8?q?=E9=A2=98=E5=BA=93=E7=9A=84=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E7=BB=93=E6=9E=84=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/models/curriculum.rb | 4 ---- app/models/curriculum_direction.rb | 4 ---- app/models/item_bank.rb | 2 -- app/models/knowledge_point.rb | 5 ----- app/models/knowledge_point_container.rb | 3 --- .../20191218070922_create_curriculum_directions.rb | 9 --------- db/migrate/20191218071017_create_curriculums.rb | 10 ---------- db/migrate/20191218071111_create_knowledge_points.rb | 11 ----------- ...191218071343_create_knowledge_point_containers.rb | 12 ------------ spec/models/curriculum_direction_spec.rb | 5 ----- spec/models/curriculum_spec.rb | 5 ----- spec/models/knowledge_point_container_spec.rb | 5 ----- spec/models/knowledge_point_spec.rb | 5 ----- 13 files changed, 80 deletions(-) delete mode 100644 app/models/curriculum.rb delete mode 100644 app/models/curriculum_direction.rb delete mode 100644 app/models/knowledge_point.rb delete mode 100644 app/models/knowledge_point_container.rb delete mode 100644 db/migrate/20191218070922_create_curriculum_directions.rb delete mode 100644 db/migrate/20191218071017_create_curriculums.rb delete mode 100644 db/migrate/20191218071111_create_knowledge_points.rb delete mode 100644 db/migrate/20191218071343_create_knowledge_point_containers.rb delete mode 100644 spec/models/curriculum_direction_spec.rb delete mode 100644 spec/models/curriculum_spec.rb delete mode 100644 spec/models/knowledge_point_container_spec.rb delete mode 100644 spec/models/knowledge_point_spec.rb diff --git a/app/models/curriculum.rb b/app/models/curriculum.rb deleted file mode 100644 index 0b78814bc..000000000 --- a/app/models/curriculum.rb +++ /dev/null @@ -1,4 +0,0 @@ -class Curriculum < ApplicationRecord - belongs_to :curriculum_direction - has_many :knowledge_points, dependent: :destroy -end diff --git a/app/models/curriculum_direction.rb b/app/models/curriculum_direction.rb deleted file mode 100644 index 1c9211559..000000000 --- a/app/models/curriculum_direction.rb +++ /dev/null @@ -1,4 +0,0 @@ -class CurriculumDirection < ApplicationRecord - has_many :curriculums - has_many :knowledge_points -end diff --git a/app/models/item_bank.rb b/app/models/item_bank.rb index 32c349e34..8078a55e0 100644 --- a/app/models/item_bank.rb +++ b/app/models/item_bank.rb @@ -3,8 +3,6 @@ class ItemBank < ApplicationRecord # item_type: 0 单选 1 多选 2 判断 3 填空 4 简答 5 实训 6 编程 enum item_type: { SINGLE: 0, MULTIPLE: 1, JUDGMENT: 2, COMPLETION: 3, SUBJECTIVE: 4, PRACTICAL: 5, PROGRAM: 6 } - belongs_to :curriculum - belongs_to :curriculum_direction belongs_to :user has_one :item_analysis, dependent: :destroy diff --git a/app/models/knowledge_point.rb b/app/models/knowledge_point.rb deleted file mode 100644 index 3d75b66a1..000000000 --- a/app/models/knowledge_point.rb +++ /dev/null @@ -1,5 +0,0 @@ -class KnowledgePoint < ApplicationRecord - belongs_to :curriculum_direction - belongs_to :curriculum - has_many :knowledge_point_containers, dependent: :destroy -end diff --git a/app/models/knowledge_point_container.rb b/app/models/knowledge_point_container.rb deleted file mode 100644 index ea73d00e7..000000000 --- a/app/models/knowledge_point_container.rb +++ /dev/null @@ -1,3 +0,0 @@ -class KnowledgePointContainer < ApplicationRecord - belongs_to :knowledge_point -end diff --git a/db/migrate/20191218070922_create_curriculum_directions.rb b/db/migrate/20191218070922_create_curriculum_directions.rb deleted file mode 100644 index 9203aa435..000000000 --- a/db/migrate/20191218070922_create_curriculum_directions.rb +++ /dev/null @@ -1,9 +0,0 @@ -class CreateCurriculumDirections < ActiveRecord::Migration[5.2] - def change - create_table :curriculum_directions do |t| - t.string :name - - t.timestamps - end - end -end diff --git a/db/migrate/20191218071017_create_curriculums.rb b/db/migrate/20191218071017_create_curriculums.rb deleted file mode 100644 index 885f2a676..000000000 --- a/db/migrate/20191218071017_create_curriculums.rb +++ /dev/null @@ -1,10 +0,0 @@ -class CreateCurriculums < ActiveRecord::Migration[5.2] - def change - create_table :curriculums do |t| - t.string :name - t.references :curriculum_direction, index: true - - t.timestamps - end - end -end diff --git a/db/migrate/20191218071111_create_knowledge_points.rb b/db/migrate/20191218071111_create_knowledge_points.rb deleted file mode 100644 index 2f748d266..000000000 --- a/db/migrate/20191218071111_create_knowledge_points.rb +++ /dev/null @@ -1,11 +0,0 @@ -class CreateKnowledgePoints < ActiveRecord::Migration[5.2] - def change - create_table :knowledge_points do |t| - t.string :name - t.references :curriculum_direction, index: true - t.references :curriculum, index: true - - t.timestamps - end - end -end diff --git a/db/migrate/20191218071343_create_knowledge_point_containers.rb b/db/migrate/20191218071343_create_knowledge_point_containers.rb deleted file mode 100644 index 0b6944ea7..000000000 --- a/db/migrate/20191218071343_create_knowledge_point_containers.rb +++ /dev/null @@ -1,12 +0,0 @@ -class CreateKnowledgePointContainers < ActiveRecord::Migration[5.2] - def change - create_table :knowledge_point_containers do |t| - t.references :knowledge_point - t.integer :container_id - t.string :container_type - - t.timestamps - end - add_index :knowledge_point_containers, [:knowledge_point_id, :container_id, :container_type], name: "container_index", unique: true - end -end diff --git a/spec/models/curriculum_direction_spec.rb b/spec/models/curriculum_direction_spec.rb deleted file mode 100644 index 40cab64ca..000000000 --- a/spec/models/curriculum_direction_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe CurriculumDirection, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/curriculum_spec.rb b/spec/models/curriculum_spec.rb deleted file mode 100644 index b03089a91..000000000 --- a/spec/models/curriculum_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe Curriculum, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/knowledge_point_container_spec.rb b/spec/models/knowledge_point_container_spec.rb deleted file mode 100644 index 3e151062f..000000000 --- a/spec/models/knowledge_point_container_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe KnowledgePointContainer, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end diff --git a/spec/models/knowledge_point_spec.rb b/spec/models/knowledge_point_spec.rb deleted file mode 100644 index d85138a0f..000000000 --- a/spec/models/knowledge_point_spec.rb +++ /dev/null @@ -1,5 +0,0 @@ -require 'rails_helper' - -RSpec.describe KnowledgePoint, type: :model do - pending "add some examples to (or delete) #{__FILE__}" -end From f8b9f369ec0dee0f7a7910f024f4541283a650b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Thu, 19 Dec 2019 16:44:21 +0800 Subject: [PATCH 11/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/public/js/jupyter.js | 11 +++ public/react/src/modules/page/VNC.css | 25 ++++++ .../src/modules/page/component/FloatButton.js | 2 +- public/react/src/modules/tpm/TPMBanner.js | 4 +- public/react/src/modules/tpm/jupyter/index.js | 90 +++++++++++++++---- .../react/src/modules/tpm/jupyter/index.scss | 3 +- public/react/src/redux/actions/actionTypes.js | 3 +- public/react/src/redux/actions/index.js | 6 +- public/react/src/redux/actions/jupyter.js | 8 ++ .../react/src/redux/reducers/commonReducer.js | 8 +- 10 files changed, 134 insertions(+), 26 deletions(-) create mode 100644 public/react/public/js/jupyter.js diff --git a/public/react/public/js/jupyter.js b/public/react/public/js/jupyter.js new file mode 100644 index 000000000..8d76a9a7f --- /dev/null +++ b/public/react/public/js/jupyter.js @@ -0,0 +1,11 @@ +//用于嵌入到jupyter pod中的js +//guange 2019.12.18 + +window.onload=function(){ + require(["base/js/namespace"],function(Jupyter) { + Jupyter.notebook.save_checkpoint(); + }); +} + + + \ No newline at end of file diff --git a/public/react/src/modules/page/VNC.css b/public/react/src/modules/page/VNC.css index cf47d7207..e29335242 100644 --- a/public/react/src/modules/page/VNC.css +++ b/public/react/src/modules/page/VNC.css @@ -14,4 +14,29 @@ color: #fff; left: 13px; user-select: none; +} + +.jupyter_float_button { + background-image: url(./images/float_switch.jpg); + height: 112px; + width: 38px; + position: absolute; + right: 0px; + top: 32%; + cursor: pointer; + left:auto; + z-index: 99999999; +} + +.jupyter_float_button .text { + position: relative; + writing-mode: vertical-rl; + top: 36px; + color: #fff; + left: 13px; + user-select: none; +} + +.newjupyter_float_button{ + right: 257px; } \ No newline at end of file diff --git a/public/react/src/modules/page/component/FloatButton.js b/public/react/src/modules/page/component/FloatButton.js index 4e7f794c6..7cc8288a7 100644 --- a/public/react/src/modules/page/component/FloatButton.js +++ b/public/react/src/modules/page/component/FloatButton.js @@ -1,5 +1,5 @@ import React, { Component } from 'react'; - +import '../VNC.css' const $ = window.$; class FloatButton extends Component { componentDidMount() { diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index a31ca5952..b498c4d22 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -851,8 +851,6 @@ class TPMBanner extends Component { - { - this.props.is_jupyter===true?"": @@ -917,7 +915,7 @@ class TPMBanner extends Component {
- } + { diff --git a/public/react/src/modules/tpm/jupyter/index.js b/public/react/src/modules/tpm/jupyter/index.js index cd947df85..7425a4732 100644 --- a/public/react/src/modules/tpm/jupyter/index.js +++ b/public/react/src/modules/tpm/jupyter/index.js @@ -9,10 +9,11 @@ import './index.scss'; import React, { useEffect, useState } from 'react'; import SplitPane from 'react-split-pane'; -import { Button, Modal } from 'antd'; +import { Button, Modal,Drawer } from 'antd'; import { connect } from 'react-redux'; +import FloatButton from '../../page/component/FloatButton'; import UserInfo from '../../developer/components/userInfo'; import actions from '../../../redux/actions'; import LeftPane from './leftPane'; @@ -39,7 +40,9 @@ function JupyterTPI (props) { changeLoadingState, changeGetJupyterUrlState, jupyter_identifier, - changeCurrentPage + changeCurrentPage, + changeshowDrawer, + drawervisible, } = props; const {identifier} = params; @@ -107,6 +110,28 @@ function JupyterTPI (props) { }) } + + // 重置环境 + const handleEnvironmentTpi = () => { + Modal.confirm({ + title: '重置环境', + content: ( +

+ 你在本文件中修改的内容将丢失,
+ 是否确定重置环境? +

+ ), + okText: '确定', + cancelText: '取消', + onOk () { + // console.log('调用重置代码....', myIdentifier); + // if (myIdentifier) { + // syncJupyterCode(myIdentifier, '重置成功'); + // } + } + }) + } + // 退出实训 const handleClickQuitTpi = () => { // console.log(jupyterInfo); @@ -138,6 +163,13 @@ function JupyterTPI (props) { getJupyterTpiDataSet(jupyter_identifier); } + const swtichFirstDrawer = () => { + changeshowDrawer(!drawervisible) + } + + const firstDrawerWidth = ()=>{ + return 260 + }; return (
@@ -151,9 +183,17 @@ function JupyterTPI (props) { + >重置实训 + + +

+
- -
- -
+ + {/*
*/} + {/* */} + {/*
*/} -
+ {"数据集"} + + +

Some contents...

+

Some contents...

+

Some contents...

+
); @@ -199,7 +252,7 @@ const mapStateToProps = (state) => { jupyter_pagination, jupyter_identifier } = state.jupyterReducer; - const { loading } = state.commonReducer; + const { loading ,drawervisible} = state.commonReducer; return { loading, jupyter_info, @@ -208,7 +261,8 @@ const mapStateToProps = (state) => { jupyter_tpi_url_state, total: jupyter_data_set_count, pagination: jupyter_pagination, - jupyter_identifier + jupyter_identifier, + drawervisible, }; } @@ -221,7 +275,9 @@ const mapDispatchToProps = (dispatch) => ({ getJupyterTpiUrl: (identifier) => dispatch(actions.getJupyterTpiUrl(identifier)), saveJupyterTpi: () => dispatch(actions.saveJupyterTpi()), changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag)), - changeCurrentPage: (current) => dispatch(actions.changeCurrentPage(current)) + changeCurrentPage: (current) => dispatch(actions.changeCurrentPage(current)), + //展开Drawer + changeshowDrawer: (type) => dispatch(actions.changeshowDrawer(type)) }); export default connect( diff --git a/public/react/src/modules/tpm/jupyter/index.scss b/public/react/src/modules/tpm/jupyter/index.scss index 430bb1c6e..5fdfcb02c 100644 --- a/public/react/src/modules/tpm/jupyter/index.scss +++ b/public/react/src/modules/tpm/jupyter/index.scss @@ -9,7 +9,7 @@ -webkit-background-clip: padding; background-clip: padding-box; } - + .Resizer:hover { -webkit-transition: all 2s ease; transition: all 2s ease; @@ -56,6 +56,7 @@ line-height: 60px; background-color: #070F1A; padding-left: 30px; + z-index:999999; .jupyter_title{ display: flex; flex-direction: column; diff --git a/public/react/src/redux/actions/actionTypes.js b/public/react/src/redux/actions/actionTypes.js index 55aa42799..999fb7339 100644 --- a/public/react/src/redux/actions/actionTypes.js +++ b/public/react/src/redux/actions/actionTypes.js @@ -57,7 +57,8 @@ const types = { SAVE_JUPYTER_INFO: 'SAVE_JUPYTER_INFO', // 保存 jupyter 信息 CHANGE_JUPYTER_URL_STATE: 'CHANGE_JUPYTER_URL_STATE', // 获取url返回的状态值 SAVE_JUPYTER_TPI: 'SAVE_JUPYTER_TPI', // 保存 jupyter tpi - CHANGE_JUPYTER_CURRENT_PAGE: 'CHANGE_JUPYTER_CURRENT_PAGE' + CHANGE_JUPYTER_CURRENT_PAGE: 'CHANGE_JUPYTER_CURRENT_PAGE', + CHANGE_SHOW_DRAWER: 'CHANGE_SHOW_DRAWER', } export default types; diff --git a/public/react/src/redux/actions/index.js b/public/react/src/redux/actions/index.js index ad33061ba..40aec251a 100644 --- a/public/react/src/redux/actions/index.js +++ b/public/react/src/redux/actions/index.js @@ -70,7 +70,8 @@ import { syncJupyterCode, changeGetJupyterUrlState, saveJupyterTpi, - changeCurrentPage + changeCurrentPage, + changeshowDrawer, } from './jupyter'; export default { @@ -123,6 +124,7 @@ export default { syncJupyterCode, changeGetJupyterUrlState, saveJupyterTpi, - changeCurrentPage + changeCurrentPage, + changeshowDrawer // isUpdateCodeCtx } \ No newline at end of file diff --git a/public/react/src/redux/actions/jupyter.js b/public/react/src/redux/actions/jupyter.js index 57c12e6d3..73bc30a42 100644 --- a/public/react/src/redux/actions/jupyter.js +++ b/public/react/src/redux/actions/jupyter.js @@ -154,4 +154,12 @@ export const changeCurrentPage = (current) => { type: types.CHANGE_JUPYTER_CURRENT_PAGE, payload: current } +} + +// 改变当前页数 +export const changeshowDrawer = (type) => { + return { + type: types.CHANGE_SHOW_DRAWER, + payload: type + } } \ No newline at end of file diff --git a/public/react/src/redux/reducers/commonReducer.js b/public/react/src/redux/reducers/commonReducer.js index 8a2e927cc..4d38b75ad 100644 --- a/public/react/src/redux/reducers/commonReducer.js +++ b/public/react/src/redux/reducers/commonReducer.js @@ -14,7 +14,8 @@ const initialState = { excuteState: '', // 代码执行状态 submitLoading: false, // 提交按钮状态 publishLoading: false, // 发布 - isMySource: false + isMySource: false, + drawervisible:false } const commonReducer = (state = initialState, action) => { @@ -50,6 +51,11 @@ const commonReducer = (state = initialState, action) => { ...state, isMySource: action.payload } + case types.CHANGE_SHOW_DRAWER: + return { + ...state, + drawervisible: action.payload + } default: return state; } From e47eda0150a8bc51f7a12f56f31876405243169f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 16:53:50 +0800 Subject: [PATCH 12/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/AppConfig.js | 38 +++++++++---------- public/react/src/college/College.js | 8 ++-- .../college/colleagechart/Colleagechart.js | 6 +-- .../college/colleagechart/Colleagechartzu.js | 6 +-- 4 files changed, 29 insertions(+), 29 deletions(-) diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index ac39562a7..c51c0d5e1 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -19,25 +19,25 @@ function locationurl(list){ let hashTimeout // TODO 开发期多个身份切换 -let debugType ="" -if (isDev) { - const _search = window.location.search; - let parsed = {}; - if (_search) { - parsed = queryString.parse(_search); - } - debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' : - window.location.search.indexOf('debug=s') != -1 ? 'student' : - window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin' -} -// 超管 -// debugType="admin"; -// 老师 -//ebugType="teacher"; -// 学生 -// debugType="student"; - -window._debugType = debugType; +// let debugType ="" +// if (isDev) { +// const _search = window.location.search; +// let parsed = {}; +// if (_search) { +// parsed = queryString.parse(_search); +// } +// debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' : +// window.location.search.indexOf('debug=s') != -1 ? 'student' : +// window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin' +// } +// // 超管 +// // debugType="admin"; +// // 老师 +// //ebugType="teacher"; +// // 学生 +// // debugType="student"; +// +// window._debugType = debugType; export function initAxiosInterceptors(props) { initOnlineOfflineListener() diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index eaed9747c..c204ab65b 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -1037,7 +1037,7 @@ class College extends Component {

教师排名 @@ -1112,7 +1112,7 @@ class College extends Component {

@@ -1145,7 +1145,7 @@ class College extends Component {

学生排名 @@ -1218,7 +1218,7 @@ class College extends Component {

{b} : {c} ({d}%)" + formatter: "{d}%
" }, legend: { // orient: 'vertical', // top: 'middle', - bottom: 40, + bottom: 50, left: 'center', data: datanane }, @@ -68,7 +68,7 @@ class Colleagechart extends Component {
diff --git a/public/react/src/college/colleagechart/Colleagechartzu.js b/public/react/src/college/colleagechart/Colleagechartzu.js index c65d2f6f2..ff1b6fb6b 100644 --- a/public/react/src/college/colleagechart/Colleagechartzu.js +++ b/public/react/src/college/colleagechart/Colleagechartzu.js @@ -15,8 +15,8 @@ function startechart(names, values){ backgroundColor: '#fff', grid: { left: '3%', - right: '4%', - bottom: '10%', + right: '10%', + bottom: '15%', containLabel: true }, @@ -133,7 +133,7 @@ class Colleagechartzu extends Component {
From a0af31b2455869f5e654a58312eac490e2a10300 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 16:54:09 +0800 Subject: [PATCH 13/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/AppConfig.js | 38 +++++++++++++++++------------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index c51c0d5e1..ac39562a7 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -19,25 +19,25 @@ function locationurl(list){ let hashTimeout // TODO 开发期多个身份切换 -// let debugType ="" -// if (isDev) { -// const _search = window.location.search; -// let parsed = {}; -// if (_search) { -// parsed = queryString.parse(_search); -// } -// debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' : -// window.location.search.indexOf('debug=s') != -1 ? 'student' : -// window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin' -// } -// // 超管 -// // debugType="admin"; -// // 老师 -// //ebugType="teacher"; -// // 学生 -// // debugType="student"; -// -// window._debugType = debugType; +let debugType ="" +if (isDev) { + const _search = window.location.search; + let parsed = {}; + if (_search) { + parsed = queryString.parse(_search); + } + debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' : + window.location.search.indexOf('debug=s') != -1 ? 'student' : + window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || 'admin' +} +// 超管 +// debugType="admin"; +// 老师 +//ebugType="teacher"; +// 学生 +// debugType="student"; + +window._debugType = debugType; export function initAxiosInterceptors(props) { initOnlineOfflineListener() From 0a34988f409da02fed284eca16afb6daeba5decb Mon Sep 17 00:00:00 2001 From: jingquan huang Date: Thu, 19 Dec 2019 17:05:57 +0800 Subject: [PATCH 14/61] =?UTF-8?q?=E5=AE=9E=E9=AA=8C=E7=8E=AF=E5=A2=83?= =?UTF-8?q?=E4=B8=BA=E7=A9=BA=E7=9A=84=E6=8F=90=E9=86=92=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controllers/myshixuns_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/myshixuns_controller.rb b/app/controllers/myshixuns_controller.rb index 987f4873a..0e9ba477a 100644 --- a/app/controllers/myshixuns_controller.rb +++ b/app/controllers/myshixuns_controller.rb @@ -247,7 +247,7 @@ class MyshixunsController < ApplicationController def update_file begin @hide_code = Shixun.where(id: @myshixun.shixun_id).pluck(:hide_code).first - tip_exception("技术平台为空!") if @myshixun.mirror_name.blank? + tip_exception("实验环境不能为空,请查看实训模板的环境配置项是否正确!") if (@myshixun.mirror_name.blank? || @myshixun.mirror_name.first.to_s == "-1") path = params[:path].strip unless params[:path].blank? game_id = params[:game_id] game = Game.find(game_id) From 85bc2079d2578e8a9cac29ccccc53a1ecd02cbca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 17:13:26 +0800 Subject: [PATCH 15/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/college/College.js | 14 +++++++------- .../src/college/colleagechart/Colleagechart.js | 2 +- .../src/college/colleagechart/Colleagechartzu.js | 4 ++-- public/react/src/college/colleagecss/colleage.css | 4 ++-- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index c204ab65b..bc43252b7 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -824,8 +824,8 @@ class College extends Component {
{school}
@@ -874,7 +874,7 @@ class College extends Component {
-
+

基本使用情况

@@ -956,7 +956,7 @@ class College extends Component {
-
+

课堂

@@ -974,7 +974,7 @@ class College extends Component { : -
+
diff --git a/public/react/src/modules/tpm/TPMIndex.js b/public/react/src/modules/tpm/TPMIndex.js index d79bae95b..e032bb91f 100644 --- a/public/react/src/modules/tpm/TPMIndex.js +++ b/public/react/src/modules/tpm/TPMIndex.js @@ -385,6 +385,9 @@ class TPMIndex extends Component { margin:0 40px 0 0; padding:0px; } + .ant-popover{ + z-index:1000 !important; + } ` } diff --git a/public/react/src/modules/tpm/TPMsettings/LearningSettings.js b/public/react/src/modules/tpm/TPMsettings/LearningSettings.js index 681cbc956..a98f68223 100644 --- a/public/react/src/modules/tpm/TPMsettings/LearningSettings.js +++ b/public/react/src/modules/tpm/TPMsettings/LearningSettings.js @@ -215,9 +215,9 @@ export default class Shixuninformation extends Component { multi_webssh: false }) } else { - this.setState({ - multi_webssh: true - }) + // this.setState({ + // multi_webssh: true + // }) } this.setState({ opensshRadio: e.target.value diff --git a/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js b/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js index 200880019..75ed88852 100644 --- a/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js +++ b/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js @@ -50,7 +50,10 @@ class Shixuninformation extends Component { } componentDidMount() { - + let anchorElement = document.getElementById("newcourseContentMD"); + if(anchorElement){ + this.scrollToAnchor("newcourseContentMD"); + } } componentDidUpdate(prevProps, prevState) { @@ -113,6 +116,7 @@ class Shixuninformation extends Component { selectright: this.props.data && this.props.data.shixun.choice_small_type, }) this.contentMdRef.current.setValue(this.props.data && this.props.data.shixun.description); + } } } @@ -807,16 +811,20 @@ class Shixuninformation extends Component { )} + + + diff --git a/public/react/src/modules/tpm/component/TPMRightSection.js b/public/react/src/modules/tpm/component/TPMRightSection.js index 1d2a93796..88894794b 100644 --- a/public/react/src/modules/tpm/component/TPMRightSection.js +++ b/public/react/src/modules/tpm/component/TPMRightSection.js @@ -63,6 +63,8 @@ class TPMRightSection extends Component { if(TPMRightSectionData&&TPMRightSectionData.complete_count!=null){ Progresssum=(parseInt(TPMRightSectionData&&TPMRightSectionData.complete_count) / parseInt(TPMRightSectionData&&TPMRightSectionData.challenge_count))*100; } + + return (
{ @@ -97,11 +99,11 @@ class TPMRightSection extends Component {
- {TPMRightSectionData&&TPMRightSectionData.complete_count!=null?
+ {this.props&&this.props.status>1?
学习统计 - 已完成 {TPMRightSectionData&&TPMRightSectionData.complete_count} 个 / 共 {TPMRightSectionData&&TPMRightSectionData.challenge_count} 关 + 已完成 {TPMRightSectionData&&TPMRightSectionData.complete_count===null?0:TPMRightSectionData&&TPMRightSectionData.complete_count} 个 / 共 {TPMRightSectionData&&TPMRightSectionData.challenge_count} 关
diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js index 307823ee8..e7b7ef261 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js @@ -34,7 +34,8 @@ class Challenges extends Component { operationstrue:false, isSpin:false, boxoffsetHeigh:0, - opentitletype:true + opentitletype:true, + isopentitletype:"Less", } } @@ -73,15 +74,17 @@ class Challenges extends Component { boxoffsetHeigh=box.offsetHeight if(boxoffsetHeigh<260){ this.setState({ - opentitletype:false, + isopentitletype:"Less", boxoffsetHeigh:boxoffsetHeigh }) }else{ this.setState({ + opentitletype:true, + isopentitletype:"greater", boxoffsetHeigh:boxoffsetHeigh }) } - + console.log(boxoffsetHeigh) } } @@ -322,7 +325,8 @@ class Challenges extends Component { opentitle=()=>{ this.setState({ - opentitletype:!this.state.opentitletype + opentitletype:!this.state.opentitletype, + }) } @@ -434,7 +438,8 @@ class Challenges extends Component {

- {this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> + + {this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 阅读全文 :this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 收起全文 diff --git a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css index 688dbb422..b059ab406 100644 --- a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css +++ b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.css @@ -184,4 +184,13 @@ .fontneweees { color: #BBBBBB; +} + +.maxfont450{ + width: 450px; + max-width:450px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + cursor: default; } \ No newline at end of file diff --git a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js index 15a956a0b..17b083cf7 100644 --- a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js +++ b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js @@ -11,11 +11,9 @@ import NoneData from "../../../courses/coursesPublic/NoneData"; import './Collaborators.css'; -const $ = window.$; - const RadioGroup = Radio.Group; -const Search = Input.Search; + class Collaborators extends Component { constructor(props) { @@ -685,7 +683,7 @@ class Collaborators extends Component {

{/*

{item.user.identity}

*/}

{item.user.school_name}

+ className={item.user.school_name === null || item.user.school_name === "" ? "" : " font-16 color888hezuo maxfont450"}>{item.user.school_name}

发布实训项目  {item.user.user_shixuns_count}

diff --git a/public/react/src/modules/tpm/shixuns/ShixunCardList.js b/public/react/src/modules/tpm/shixuns/ShixunCardList.js index 3676ed361..937e96894 100644 --- a/public/react/src/modules/tpm/shixuns/ShixunCardList.js +++ b/public/react/src/modules/tpm/shixuns/ShixunCardList.js @@ -218,7 +218,7 @@ class ShixunCardList extends Component { id="hot" onClick={(e)=>this.latestHot(e,3)}>最热
- {shixuntype===true?"":this.getUser("/shixuns/new")}>+新建实训项目} + {shixuntype===true?"":this.getUser("/shixuns/new")}>+新建实训项目} {/*
Date: Thu, 19 Dec 2019 17:55:39 +0800 Subject: [PATCH 17/61] =?UTF-8?q?=E5=AE=9E=E8=AE=AD=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/challengesnew/TPManswer.js | 4 ++-- public/react/src/modules/tpm/challengesnew/TPManswer2.js | 4 ++-- .../react/src/modules/tpm/challengesnew/TPMchallengesnew.js | 4 ++-- public/react/src/modules/tpm/challengesnew/TPMevaluation.js | 4 ++-- public/react/src/modules/tpm/challengesnew/TPMquestion.js | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/public/react/src/modules/tpm/challengesnew/TPManswer.js b/public/react/src/modules/tpm/challengesnew/TPManswer.js index 9c9a23a12..9187e09b0 100644 --- a/public/react/src/modules/tpm/challengesnew/TPManswer.js +++ b/public/react/src/modules/tpm/challengesnew/TPManswer.js @@ -302,11 +302,11 @@ export default class TPManswer extends Component { className="color-grey-6 fr font-15 mt3">返回 {prev_challenge === undefined ? "" : - 上一关 + 上一关 } {next_challenge === undefined ? "" : - 下一关 + 下一关 } 返回 {prev_challenge === undefined ? "" : - 上一关 + 上一关 } {next_challenge === undefined ? "" : - 下一关 + 下一关 } 返回 { next_challenge===undefined?"": - 下一关 + 下一关 } { prev_challenge===undefined?"": - 上一关 + 上一关 } diff --git a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js index d70f22a0a..34eb1a075 100644 --- a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js +++ b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js @@ -824,11 +824,11 @@ export default class TPMevaluation extends Component { className="color-grey-6 fr font-15 mt3">返回 {prev_challenge === undefined ? "" : - 上一关 + 上一关 } {next_challenge === undefined ? "" : - 下一关 + 下一关 } 返回 { prev_challenge===undefined?"": - 上一关 + 上一关 } { next_challenge===undefined?"": - 下一关 + 下一关 } Date: Thu, 19 Dec 2019 18:02:44 +0800 Subject: [PATCH 18/61] =?UTF-8?q?=E5=AE=9E=E8=AE=AD=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/component/TPMright.css | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/react/src/modules/tpm/component/TPMright.css b/public/react/src/modules/tpm/component/TPMright.css index a75160bf5..0d6b306fd 100644 --- a/public/react/src/modules/tpm/component/TPMright.css +++ b/public/react/src/modules/tpm/component/TPMright.css @@ -119,9 +119,14 @@ .padd252020px{ padding: 25px 20px 15px; } + .rightjinengs{ height: 35px; margin-top: 20px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; } .borderbottomf4{ From 0712932812985d2486b2f2c3cc9647ddb598742e Mon Sep 17 00:00:00 2001 From: tangjiang <465264938@qq.com> Date: Thu, 19 Dec 2019 18:03:42 +0800 Subject: [PATCH 19/61] update oj --- public/react/package.json | 1 + .../common/components/comment/CommentForm.js | 116 ++++++++++++ .../common/components/comment/CommentIcon.js | 32 ++++ .../common/components/comment/CommentItem.js | 165 +++++++++++++++++ .../common/components/comment/CommentList.js | 20 +++ .../src/common/components/comment/index.js | 22 +++ .../src/common/components/comment/index.scss | 111 ++++++++++++ .../src/common/quillForEditor/ImageBlot.js | 54 ++++++ .../src/common/quillForEditor/deepEqual.js | 47 +++++ .../react/src/common/quillForEditor/index.js | 166 ++++++++++++++++++ .../react/src/common/reactQuill/ImageBlot.js | 54 ++++++ .../react/src/common/reactQuill/ReactQuill.js | 45 +++++ .../react/src/common/reactQuill/deepEqual.js | 47 +++++ public/react/src/common/reactQuill/flatten.js | 26 +++ public/react/src/common/reactQuill/index.js | 108 ++++++++++++ public/react/src/common/reactQuill/index.scss | 32 ++++ public/react/src/common/reactQuill/lib.js | 13 ++ .../src/common/reactQuill/useDeepEqualMemo.js | 27 +++ .../src/common/reactQuill/useMountQuill.js | 148 ++++++++++++++++ .../react/src/common/reactQuill/useQuill.js | 60 +++++++ .../src/common/reactQuill/useQuillOnChange.js | 33 ++++ .../common/reactQuill/useQuillPlaceholder.js | 22 +++ .../common/reactQuill/useQuillValueSync.js | 31 ++++ .../src/modules/developer/DeveloperHome.js | 21 ++- .../components/controlSetting/index.js | 6 +- .../components/controlSetting/index.scss | 7 +- .../developer/components/execResult/index.js | 14 +- .../developer/components/initTabCtx/index.js | 7 +- .../components/initTabCtx/index.scss | 3 +- .../components/monacoSetting/index.js | 3 +- .../components/myMonacoEditor/index.js | 57 ++++-- .../components/myMonacoEditor/index.scss | 33 ++-- .../modules/developer/newOrEditTask/index.js | 102 ++++++----- .../developer/newOrEditTask/index.scss | 16 +- .../leftpane/editorTab/AddTestDemo.js | 24 ++- .../newOrEditTask/leftpane/editorTab/index.js | 53 +++--- .../leftpane/editorTab/index.scss | 5 + .../developer/newOrEditTask/leftpane/index.js | 22 --- .../newOrEditTask/leftpane/prevTab/index.js | 77 +++----- .../newOrEditTask/rightpane/index.scss | 2 +- .../modules/developer/split_pane_resizer.scss | 6 +- .../modules/developer/studentStudy/index.js | 56 ++++-- .../modules/developer/studentStudy/index.scss | 2 +- .../studentStudy/leftpane/comment/index.js | 13 +- .../studentStudy/leftpane/comment/index.scss | 8 + .../developer/studentStudy/leftpane/index.js | 63 ++----- .../studentStudy/leftpane/index.scss | 7 + .../leftpane/taskDescription/index.js | 18 +- .../developer/studentStudy/rightpane/index.js | 27 ++- public/react/src/redux/actions/actionTypes.js | 5 +- public/react/src/redux/actions/ojForUser.js | 45 ++++- public/react/src/redux/actions/ojForm.js | 20 ++- .../src/redux/reducers/ojForUserReducer.js | 24 ++- .../react/src/redux/reducers/ojFormReducer.js | 4 +- public/react/src/services/ojService.js | 15 +- 55 files changed, 1849 insertions(+), 296 deletions(-) create mode 100644 public/react/src/common/components/comment/CommentForm.js create mode 100644 public/react/src/common/components/comment/CommentIcon.js create mode 100644 public/react/src/common/components/comment/CommentItem.js create mode 100644 public/react/src/common/components/comment/CommentList.js create mode 100644 public/react/src/common/components/comment/index.js create mode 100644 public/react/src/common/components/comment/index.scss create mode 100644 public/react/src/common/quillForEditor/ImageBlot.js create mode 100644 public/react/src/common/quillForEditor/deepEqual.js create mode 100644 public/react/src/common/quillForEditor/index.js create mode 100644 public/react/src/common/reactQuill/ImageBlot.js create mode 100644 public/react/src/common/reactQuill/ReactQuill.js create mode 100644 public/react/src/common/reactQuill/deepEqual.js create mode 100644 public/react/src/common/reactQuill/flatten.js create mode 100644 public/react/src/common/reactQuill/index.js create mode 100644 public/react/src/common/reactQuill/index.scss create mode 100644 public/react/src/common/reactQuill/lib.js create mode 100644 public/react/src/common/reactQuill/useDeepEqualMemo.js create mode 100644 public/react/src/common/reactQuill/useMountQuill.js create mode 100644 public/react/src/common/reactQuill/useQuill.js create mode 100644 public/react/src/common/reactQuill/useQuillOnChange.js create mode 100644 public/react/src/common/reactQuill/useQuillPlaceholder.js create mode 100644 public/react/src/common/reactQuill/useQuillValueSync.js create mode 100644 public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss diff --git a/public/react/package.json b/public/react/package.json index 66db5e6f8..144292feb 100644 --- a/public/react/package.json +++ b/public/react/package.json @@ -61,6 +61,7 @@ "prop-types": "^15.6.1", "qs": "^6.6.0", "quill": "^1.3.7", + "quill-delta-to-html": "^0.11.0", "raf": "3.4.0", "rc-form": "^2.1.7", "rc-pagination": "^1.16.2", diff --git a/public/react/src/common/components/comment/CommentForm.js b/public/react/src/common/components/comment/CommentForm.js new file mode 100644 index 000000000..73e36cff9 --- /dev/null +++ b/public/react/src/common/components/comment/CommentForm.js @@ -0,0 +1,116 @@ +/* + * @Description: 评论表单 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:32:55 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 17:51:44 + */ +import React, { useState } from 'react'; +import { Form, Button, Input } from 'antd'; +import QuillForEditor from '../../quillForEditor'; +import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html' +const FormItem = Form.Item; + +function CommentForm (props) { + + const { + commentCtxChagne, + onCancel, + onSubmit, + form + } = props; + + const { getFieldDecorator } = form; + const [ctx, setCtx] = useState(''); + + const options = [ + ['bold', 'italic', 'underline'], + [{header: [1,2,3,false]}], + ['blockquote', 'code-block'], + ['link', 'image'], + ['formula'] + ]; + // const { form: { getFieldDecorator } } = props; + const [showQuill, setShowQuill] = useState(false); + // 点击输入框 + const handleInputClick = () => { + setShowQuill(true); + } + // 取消 + const handleCancle = () => { + setShowQuill(false); + onCancel && onCancel(); + } + + // 编辑器内容变化时 + const handleContentChange = (content) => { + setCtx(content); + try { + const _html = new QuillDeltaToHtmlConverter(content.ops, {}).convert(); + // props.form.setFieldsValue({'comment': _html.replace(/<\/?[^>]*>/g, '')}); + props.form.setFieldsValue({'comment': _html}); + } catch (error) { + console.log(error); + } + } + // 发送 + const handleSubmit = (e) => { + e.preventDefault(); + props.form.validateFields((err, values) => { + if (!err) { + setShowQuill(false); + const content = ctx; + props.form.setFieldsValue({'comment': ''}); + setCtx(''); + console.log(content); + onSubmit && onSubmit(content); + } + }); + } + return ( +
+ + { + getFieldDecorator('comment', { + rules: [ + { required: true, message: '评论内容不能为空'} + ], + })( + + ) + } + + + + + + + + + ); +} + +export default Form.create()(CommentForm); diff --git a/public/react/src/common/components/comment/CommentIcon.js b/public/react/src/common/components/comment/CommentIcon.js new file mode 100644 index 000000000..5440e2579 --- /dev/null +++ b/public/react/src/common/components/comment/CommentIcon.js @@ -0,0 +1,32 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-18 10:49:46 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 11:39:23 + */ +import './index.scss'; +import React from 'react'; +import { Icon } from 'antd'; +function CommentIcon ({ + type, // 图标类型 + count, // 评论数 + iconClick, + ...props +}) { + + // 点击图标 + const handleSpanClick = () => { + iconClick && iconClick(); + } + + return ( + + + { count } + + ) +} + +export default CommentIcon; diff --git a/public/react/src/common/components/comment/CommentItem.js b/public/react/src/common/components/comment/CommentItem.js new file mode 100644 index 000000000..19da645f5 --- /dev/null +++ b/public/react/src/common/components/comment/CommentItem.js @@ -0,0 +1,165 @@ +/* + * @Description: 评论单列 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:35:17 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-19 18:02:28 + */ +import './index.scss'; +import React, { useState } from 'react'; +import CommentIcon from './CommentIcon'; +import { getImageUrl, CNotificationHOC } from 'educoder' +import { Icon } from 'antd'; +import moment from 'moment'; +// import QuillForEditor from '../../quillForEditor'; +import CommentForm from './CommentForm'; + +// import {ModalConfirm} from '../ModalConfirm'; +function CommentItem ({ + options, + confirm +}) { + // 显示评论输入框 + const [showQuill, setShowQuill] = useState(false); + // 加载更多评论内容 + const [showMore, setShowMore] = useState(false); + // 箭头方向 + const [arrow, setArrow] = useState(false); + // 删除评论 + const deleteComment = () => { + console.log('删除评论...'); + confirm({ + title: '提示', + content: (

确定要删除该条回复吗?

), + onOk () { + console.log('点击了删除'); + } + }); + // ModalConfirm('提示', (

确定要删除该条回复吗?

), () => { + // console.log('点击了删除'); + // }); + } + + // 评论头像 + const commentAvatar = (url) => ( + + ); + + // 评论信息 + const commentInfo = () => ( +

+ 用户名 + {moment(new Date(), 'YYYYMMDD HHmmss').fromNow()} + +

+ ); + + // 评论内容 + const commentCtx = (ctx) => ( +

+ 这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容 +

+ ); + + // 加载更多 + const handleOnLoadMore = () => { + if (!arrow) { + // 展开所有 + } else { + // 收起 + } + setArrow(!arrow); + }; + + // 评论追加内容 + const commentAppend = () => { + + return ( +
    +
  • + {commentAvatar()} +
    + {commentInfo()} + {commentCtx()} +
    +
  • +
  • + {commentAvatar()} +
    + {commentInfo()} + {commentCtx()} +
    +
  • +
  • + {commentAvatar()} +
    + {commentInfo()} + {commentCtx()} +
    +
  • + +
  • +

    展开其余23条评论

    +

    + +

    +
  • +
+ ); + }; + // 点击图标 + const handleIconClick = () => {} + + // 点击评论icon + const handleClickMessage = () => { + setShowQuill(true); + } + + // 点击取消 + const handleClickCancel = () => { + setShowQuill(false); + } + + // 点击保存 + const handleClickSubmit = (content) => { + // 保存并关闭 + setShowQuill(false); + console.log('获取保存内容', content); + } + + return ( +
  • + {commentAvatar()} +
    + {commentInfo()} + {commentCtx()} + + {commentAppend()} + +
    + + {/* 回复 */} + + {/* 点赞 */} + +
    + +
    + +
    +
    +
  • + ); +} + +export default CNotificationHOC() (CommentItem); diff --git a/public/react/src/common/components/comment/CommentList.js b/public/react/src/common/components/comment/CommentList.js new file mode 100644 index 000000000..9d8cde87b --- /dev/null +++ b/public/react/src/common/components/comment/CommentList.js @@ -0,0 +1,20 @@ +/* + * @Description: 评论列表页 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:34:00 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 11:48:09 + */ +import './index.scss'; +import React from 'react'; +import CommentItem from './CommentItem'; +function CommentList ({}) { + return ( +
      + +
    + ); +} + +export default CommentList; diff --git a/public/react/src/common/components/comment/index.js b/public/react/src/common/components/comment/index.js new file mode 100644 index 000000000..f0ecf3309 --- /dev/null +++ b/public/react/src/common/components/comment/index.js @@ -0,0 +1,22 @@ +/* + * @Description: 评论组件 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:31:33 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 11:47:39 + */ +import React from 'react'; +import CommentForm from './CommentForm'; +import CommentList from './CommentList'; +function Comment (props) { + + return ( + + + + + ); +} + +export default Comment; diff --git a/public/react/src/common/components/comment/index.scss b/public/react/src/common/components/comment/index.scss new file mode 100644 index 000000000..816e6da6c --- /dev/null +++ b/public/react/src/common/components/comment/index.scss @@ -0,0 +1,111 @@ +$bdColor: rgba(244,244,244,1); +$bgColor: rgba(250,250,250,1); +$lh14: 14px; +$lh22: 22px; +$fz14: 14px; +$fz12: 12px; +$ml: 20px; + +.comment_list_wrapper{ + box-sizing: border-box; + border-top: 1px solid $bdColor; + + .comment_item_area{ + display: flex; + padding: 20px 0; + box-sizing: border-box; + border-bottom: 1px solid $bdColor; + .flex-image{ + width: 48px; + height: 48px; + border-radius: 50%; + } + .item-desc{ + flex: 1; + margin-left: $ml; + } + .item-header{ + font-size: $fz14; + line-height: $lh14; + color: #333; + .item-time{ + font-size: $fz12; + line-height: $lh14; + margin-left: $ml; + } + .item-close{ + float: right; + cursor: pointer; + } + } + .item-ctx{ + line-height: $lh22; + font-size: $fz12; + color: #333; + margin-top: 10px; + } + .comment_icon_area{ + display: flex; + justify-content: flex-end; + margin-top: 10px; + + .comment-icon-margin{ + margin-left: 30px; + } + } + + .comment_item_quill{ + margin-top: 20px; + } + } + .comment_icon_count{ + cursor: pointer; + font-size: 12px; + line-height: 1.5; + + .comment_icon{ + color: #333; + } + .comment_count{ + color: #999999; + margin-left: 10px; + transition: color .3s; + } + + &:hover{ + .comment_icon, + .comment_count{ + color: #5091FF; + } + } + } + .comment_item_append_list{ + position: relative; + background-color: $bgColor; + border-radius: 5px; + padding: 0 15px 10px; + margin: 15px 0; + &::before { + position: absolute; + left: 15px; + bottom: 100%; + height: 0; + width: 0; + content: ''; + // border: 5px solid transparent; + border: 10px solid transparent; + border-bottom-color: $bgColor; + } + + .comment_item_loadmore{ + padding-top: 10px; + cursor: pointer; + .loadmore-txt, + .loadmore-icon{ + color: #999; + text-align: center; + font-size: $fz12; + } + } + } +} \ No newline at end of file diff --git a/public/react/src/common/quillForEditor/ImageBlot.js b/public/react/src/common/quillForEditor/ImageBlot.js new file mode 100644 index 000000000..091bd2c1f --- /dev/null +++ b/public/react/src/common/quillForEditor/ImageBlot.js @@ -0,0 +1,54 @@ +/* + * @Description: 重写图片 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-16 15:50:45 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 16:44:48 + */ +import Quill from "quill"; + +const BlockEmbed = Quill.import('blots/block/embed'); + +export default class ImageBlot extends BlockEmbed { + + static create(value) { + + const node = super.create(); + + node.setAttribute('alt', value.alt); + node.setAttribute('src', value.url); + + if (value.width) { + node.setAttribute('width', value.width); + } + if (value.height) { + node.setAttribute('height', value.height); + } + // 宽度和高度都不存在时, + if (!value.width && !value.height) { + node.setAttribute('display', 'block'); + node.setAttribute('width', '100%'); + } + // 给图片添加点击事件 + node.onclick = () => { + value.onClick && value.onClick(value.url); + } + return node; + } + + static value (node) { + + return { + alt: node.getAttribute('alt'), + url: node.getAttribute('src'), + onclick: node.onclick, + // width: node.width, + // height: node.height, + display: node.getAttribute('display') + }; + } +} + +ImageBlot.blotName = 'image'; +ImageBlot.tagName = 'img'; \ No newline at end of file diff --git a/public/react/src/common/quillForEditor/deepEqual.js b/public/react/src/common/quillForEditor/deepEqual.js new file mode 100644 index 000000000..6f2b276bf --- /dev/null +++ b/public/react/src/common/quillForEditor/deepEqual.js @@ -0,0 +1,47 @@ +function deepEqual (prev, current) { + if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined + return true; + } + + if ((!prev && current) + || (prev && !current) + || (!prev && !current) + ) { + return false; + } + + if (Array.isArray(prev)) { + if (!Array.isArray(current)) return false; + if (prev.length !== current.length) return false; + + for (let i = 0; i < prev.length; i++) { + if (!deepEqual(current[i], prev[i])) { + return false; + } + } + return true; + } + + if (typeof current === 'object') { + if (typeof prev !== 'object') return false; + const prevKeys = Object.keys(prev); + const curKeys = Object.keys(current); + + if (prevKeys.length !== curKeys.length) return false; + + prevKeys.sort(); + curKeys.sort(); + + for (let i = 0; i < prevKeys.length; i++) { + if (prevKeys[i] !== curKeys[i]) return false; + const key = prevKeys[i]; + if (!deepEqual(prev[key], current[key])) return false; + } + + return true; + } + + return false; +} + +export default deepEqual; diff --git a/public/react/src/common/quillForEditor/index.js b/public/react/src/common/quillForEditor/index.js new file mode 100644 index 000000000..6e6c01886 --- /dev/null +++ b/public/react/src/common/quillForEditor/index.js @@ -0,0 +1,166 @@ +/* + * @Description: quill 编辑器 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-18 08:49:30 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-19 16:58:50 + */ +import 'quill/dist/quill.core.css'; // 核心样式 +import 'quill/dist/quill.snow.css'; // 有工具栏 +import 'quill/dist/quill.bubble.css'; // 无工具栏 +import 'katex/dist/katex.min.css'; // katex 表达式样式 +import React, { useState, useRef, useEffect } from 'react'; +import Quill from 'quill'; +import katex from 'katex'; +import deepEqual from './deepEqual.js' +import { fetchUploadImage } from '../../services/ojService.js'; +import { getImageUrl } from 'educoder' +import ImageBlot from './ImageBlot'; + +window.Quill = Quill; +window.katex = katex; +Quill.register(ImageBlot); + +function QuillForEditor ({ + placeholder, + readOnly, + options, + value, + imgAttrs = {}, // 指定图片的宽高 + style = {}, + wrapStyle = {}, + showUploadImage, + onContentChange +}) { + // toolbar 默认值 + const defaultConfig = [ + ['bold', 'italic', 'underline'], + [{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表 + [{script: 'sub'}, {script: 'super'}], + [{ 'color': [] }, { 'background': [] }], + [{header: [1,2,3,4,5,false]}], + ['blockquote', 'code-block'], + ['link', 'image', 'video'], + ['formula'], + ['clean'] + ]; + + const editorRef = useRef(null); + // quill 实例 + const [quill, setQuill] = useState(null); + const [selection, setSelection] = useState(null); + + // 文本内容变化时 + const handleOnChange = content => { + // console.log('编辑器内容====》》》》', content); + onContentChange && onContentChange(content); + }; + + const renderOptions = options || defaultConfig; + // quill 配置信息 + const quillOption = { + modules: { + toolbar: renderOptions + }, + readOnly, + placeholder, + theme: readOnly ? 'bubble' : 'snow' + }; + + + useEffect(() => { + const _quill = new Quill(editorRef.current, quillOption); + setQuill(_quill); + + // 处理图片上传功能 + _quill.getModule('toolbar').addHandler('image', (e) => { + const input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/*'); + input.click(); + + input.onchange = async (e) => { + const file = input.files[0]; // 获取文件信息 + const formData = new FormData(); + formData.append('file', file); + + const range = _quill.getSelection(true); + let fileUrl = ''; // 保存上传成功后图片的url + // 上传文件 + const result = await fetchUploadImage(formData); + // 获取上传图片的url + if (result.data && result.data.id) { + fileUrl = getImageUrl(`api/attachments/${result.data.id}`); + } + // 根据id获取文件路径 + const { width, height } = imgAttrs; + // console.log('上传图片的url:', fileUrl); + if (fileUrl) { + _quill.insertEmbed(range.index, 'image', { + url: fileUrl, + alt: '图片信息', + onClick: showUploadImage, + width, + height + }); + } + } + }); + }, []); + + // 设置值 + useEffect(() => { + if (!quill) return + const previous = quill.getContents() + const current = value + + if (!deepEqual(previous, current)) { + setSelection(quill.getSelection()) + if (typeof value === 'string') { + quill.clipboard.dangerouslyPasteHTML(value, 'api') + } else { + quill.setContents(value) + } + } + }, [quill, value, setQuill]); + + // 清除选择区域 + useEffect(() => { + if (quill && selection) { + quill.setSelection(selection) + setSelection(null) + } + }, [quill, selection, setSelection]); + + // 设置placeholder值 + useEffect(() => { + if (!quill || !quill.root) return; + quill.root.dataset.placeholder = placeholder; + }, [quill, placeholder]); + + // 处理内容变化 + useEffect(() => { + if (!quill) return; + if (typeof handleOnChange !== 'function') return; + let handler; + quill.on( + 'text-change', + (handler = () => { + handleOnChange(quill.getContents()); // getContents: 检索编辑器内容 + }) + ); + return () => { + quill.off('text-change', handler); + } + }, [quill, handleOnChange]); + + // 返回结果 + return ( +
    +
    +
    + ); +} + +export default QuillForEditor; diff --git a/public/react/src/common/reactQuill/ImageBlot.js b/public/react/src/common/reactQuill/ImageBlot.js new file mode 100644 index 000000000..091bd2c1f --- /dev/null +++ b/public/react/src/common/reactQuill/ImageBlot.js @@ -0,0 +1,54 @@ +/* + * @Description: 重写图片 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-16 15:50:45 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 16:44:48 + */ +import Quill from "quill"; + +const BlockEmbed = Quill.import('blots/block/embed'); + +export default class ImageBlot extends BlockEmbed { + + static create(value) { + + const node = super.create(); + + node.setAttribute('alt', value.alt); + node.setAttribute('src', value.url); + + if (value.width) { + node.setAttribute('width', value.width); + } + if (value.height) { + node.setAttribute('height', value.height); + } + // 宽度和高度都不存在时, + if (!value.width && !value.height) { + node.setAttribute('display', 'block'); + node.setAttribute('width', '100%'); + } + // 给图片添加点击事件 + node.onclick = () => { + value.onClick && value.onClick(value.url); + } + return node; + } + + static value (node) { + + return { + alt: node.getAttribute('alt'), + url: node.getAttribute('src'), + onclick: node.onclick, + // width: node.width, + // height: node.height, + display: node.getAttribute('display') + }; + } +} + +ImageBlot.blotName = 'image'; +ImageBlot.tagName = 'img'; \ No newline at end of file diff --git a/public/react/src/common/reactQuill/ReactQuill.js b/public/react/src/common/reactQuill/ReactQuill.js new file mode 100644 index 000000000..1b4209409 --- /dev/null +++ b/public/react/src/common/reactQuill/ReactQuill.js @@ -0,0 +1,45 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:09:42 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 08:46:20 + */ +import 'quill/dist/quill.core.css'; // 核心样式 +import 'quill/dist/quill.snow.css'; // 有工具栏 +import 'quill/dist/quill.bubble.css'; // 无工具栏 +import 'katex/dist/katex.min.css'; // katex 表达式样式 +import React, { useState, useReducer, useEffect } from 'react'; +import useQuill from './useQuill'; + +function ReactQuill ({ + disallowColors, // 不可见时颜色 + placeholder, // 提示信息 + uploadImage, // 图片上传 + onChange, // 内容变化时 + options, // 配置信息 + value, // 显示的内容 + style, + showUploadImage // 显示上传图片 +}) { + + const [element, setElement] = useState(); // quill 渲染节点 + + useQuill({ + disallowColors, + placeholder, + uploadImage, + onChange, + options, + value, + showUploadImage, + element + }); + + return ( +
    + ); +} + +export default ReactQuill; diff --git a/public/react/src/common/reactQuill/deepEqual.js b/public/react/src/common/reactQuill/deepEqual.js new file mode 100644 index 000000000..6f2b276bf --- /dev/null +++ b/public/react/src/common/reactQuill/deepEqual.js @@ -0,0 +1,47 @@ +function deepEqual (prev, current) { + if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined + return true; + } + + if ((!prev && current) + || (prev && !current) + || (!prev && !current) + ) { + return false; + } + + if (Array.isArray(prev)) { + if (!Array.isArray(current)) return false; + if (prev.length !== current.length) return false; + + for (let i = 0; i < prev.length; i++) { + if (!deepEqual(current[i], prev[i])) { + return false; + } + } + return true; + } + + if (typeof current === 'object') { + if (typeof prev !== 'object') return false; + const prevKeys = Object.keys(prev); + const curKeys = Object.keys(current); + + if (prevKeys.length !== curKeys.length) return false; + + prevKeys.sort(); + curKeys.sort(); + + for (let i = 0; i < prevKeys.length; i++) { + if (prevKeys[i] !== curKeys[i]) return false; + const key = prevKeys[i]; + if (!deepEqual(prev[key], current[key])) return false; + } + + return true; + } + + return false; +} + +export default deepEqual; diff --git a/public/react/src/common/reactQuill/flatten.js b/public/react/src/common/reactQuill/flatten.js new file mode 100644 index 000000000..237cb543f --- /dev/null +++ b/public/react/src/common/reactQuill/flatten.js @@ -0,0 +1,26 @@ +/* + * @Description: 将多维数组转变成一维数组 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:35:01 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:36:22 + */ +function flatten (array) { + return flatten.rec(array, []); +} + +flatten.rec = function flatten (array, result) { + + for (let item of array) { + if (Array.isArray(item)) { + flatten(item, result); + } else { + result.push(item); + } + } + + return result; +} + +export default flatten; diff --git a/public/react/src/common/reactQuill/index.js b/public/react/src/common/reactQuill/index.js new file mode 100644 index 000000000..56a1a8d1f --- /dev/null +++ b/public/react/src/common/reactQuill/index.js @@ -0,0 +1,108 @@ +/* + * @Description: 入口文件 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 10:41:48 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 20:34:40 + */ +import React, { useState, useCallback, useEffect } from 'react'; +import ReactQuill from './lib'; + +function Wrapper (props) { + // 默认工具栏配置项 + const toolbarConfig = [ + ['bold', 'italic', 'underline'], + [{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表 + [{script: 'sub'}, {script: 'super'}], + [{header: [1,2,3,4,5,false]}], + ['blockquote', 'code-block'], + ['link', 'image', 'video'], + ['formula'], + ['clean'] + ]; + + const [placeholder] = useState(props.placeholder || 'placeholder'); + const [disableBold] = useState(false); + const [value, setValue] = useState(props.value || ''); + const [toolbar, setToolbar] = useState(toolbarConfig); + const [theme, setTheme] = useState(props.theme || 'snow'); + const [readOnly] = useState(props.readOnly || false); + + const { + onContentChagne, // 当编辑器内容变化时调用该函数 + showUploadImage, // 显示上传图片, 返回url,主要用于点击图片放大 + } = props; + + // 配置信息 + const options = { + modules: { + toolbar: toolbar, + clipboard: { + matchVisual: false + } + }, + readOnly: readOnly, + theme: theme + } + // 配置信息 + useEffect (() => { + if (props.options) { + setToolbar(props.options); + } + setTheme(props.theme || 'snow'); + setValue(props.value); + }, [props]); + + // 当内容变化时 + const handleOnChange = useCallback( + contents => { + if (disableBold) { + setValue({ + ops: contents.ops.map(x => { + x = {...x}; + if (x && x.attributes && x.attributes.bold) { + x.attributes = { ...x.attributes }; + delete x.attributes.bold; + if (!Object.keys(x.attributes).length) { + delete x.attributes; + } + } + return x; + }) + }); + } else { + setValue(contents); + } + onContentChagne && onContentChagne(contents); + }, [disableBold] + ); + + // 图片上传 + const handleUploadImage = (files) => { + console.log('选择的图片信息', files); + } + + // 显示图片 + const handleShowUploadImage = (url) => { + // console.log('上传的图片url:', url); + showUploadImage && showUploadImage(url); + } + + return ( + + handleShowUploadImage(url)} + /> + + ); +} + +export default Wrapper; +// ReactDOM.render(, document.querySelector('#root')); diff --git a/public/react/src/common/reactQuill/index.scss b/public/react/src/common/reactQuill/index.scss new file mode 100644 index 000000000..b6da52bf5 --- /dev/null +++ b/public/react/src/common/reactQuill/index.scss @@ -0,0 +1,32 @@ +#quill-toolbar{ + .quill-btn{ + vertical-align: middle; + } + .quill_image{ + display: inline-block; + position: relative; + vertical-align: middle; + width: 28px; + height: 24px; + overflow: hidden; + .image_input{ + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + opacity: 0; + } + .ql-image{ + position: relative; + left: 0; + top: 0; + } + } +} + +.react_quill_area{ + .ql-toolbar:not(:last-child) { + display: none; + } +} \ No newline at end of file diff --git a/public/react/src/common/reactQuill/lib.js b/public/react/src/common/reactQuill/lib.js new file mode 100644 index 000000000..430a95bb7 --- /dev/null +++ b/public/react/src/common/reactQuill/lib.js @@ -0,0 +1,13 @@ +/* + * @Description: 导出 ReactQuill + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:08:24 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:37:13 + */ +import ReactQuill from './ReactQuill'; +import useQuill from './useQuill'; + +export default ReactQuill; +export { useQuill }; diff --git a/public/react/src/common/reactQuill/useDeepEqualMemo.js b/public/react/src/common/reactQuill/useDeepEqualMemo.js new file mode 100644 index 000000000..948e21781 --- /dev/null +++ b/public/react/src/common/reactQuill/useDeepEqualMemo.js @@ -0,0 +1,27 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-12 19:48:55 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:38:16 + */ +import { useState, useEffect } from 'react'; +import deepEqual from './deepEqual'; + +function useDeepEqual (input) { + + const [value, setValue] = useState(input); + + useEffect(() => { + + if (!deepEqual(input, value)) { + setValue(input) + } + + }, [input, value]); + + return value; +} + +export default useDeepEqual; diff --git a/public/react/src/common/reactQuill/useMountQuill.js b/public/react/src/common/reactQuill/useMountQuill.js new file mode 100644 index 000000000..c2313c480 --- /dev/null +++ b/public/react/src/common/reactQuill/useMountQuill.js @@ -0,0 +1,148 @@ +/* + * @Description: 创建 reactQuill实例 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:31:42 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 20:42:05 + */ +import Quill from 'quill'; // 导入quill +import { useState, useEffect, useMemo } from 'react'; +import flatten from './flatten.js'; +import useDeepEqualMemo from './useDeepEqualMemo'; +import Katex from 'katex'; +import ImageBlot from './ImageBlot'; +import { fetchUploadImage } from '../../services/ojService.js'; +import { getImageUrl } from 'educoder' +window.katex = Katex; + +Quill.register(ImageBlot); + +function useMountQuill ({ + element, + options: passedOptions, + uploadImage, + showUploadImage, + imgAttrs = {} // 指定图片的宽高属性 +}) { + + // 是否引入 katex + const [katexLoaded, setKatexLoaded] = useState(Boolean(window.katex)) + const [quill, setQuill] = useState(null); + + const options = useDeepEqualMemo(passedOptions); + console.log('use mount quill: ', passedOptions); + + // 判断options中是否包含公式 + const requireKatex = useMemo(() => { + return flatten(options.modules.toolbar).includes('formula'); + }, [options]); + + // 加载katex + useEffect(() => { + if (!requireKatex) return; + if (katexLoaded) return; + + const interval = setInterval(() => { + if (window.katex) { + setKatexLoaded(true); + clearInterval(interval); + } + }); + + return () => { // 定义回调清除定时器 + clearInterval(interval); + } + + }, [ + setKatexLoaded, + katexLoaded, + requireKatex + ]); + + // 加载 quill + useEffect(() => { + if (!element) return; + if (requireKatex && !katexLoaded) { + element.innerHTML = ` +
    + Loading Katex... +
    + ` + } + // 清空内容 + element.innerHTML = ''; + console.log(element); + // 创建 quill 节点 + const quillNode = document.createElement('div'); + element.appendChild(quillNode); // 将quill节点追回到 element 元素中 + + const quill = new Quill(element, options); + setQuill(quill); + // 加载上传图片功能 + if (typeof uploadImage === 'function') { + quill.getModule('toolbar').addHandler('image', (e) => { + // 创建type类型输入框加载本地图片 + const input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/*'); + input.click(); + + input.onchange = async (e) => { + const file = input.files[0]; // 获取文件信息 + const formData = new FormData(); + formData.append('file', file); + + // const reader = new FileReader(); + // reader.readAsDataURL(file); + // console.log('文件信息===>>', reader); + // reader.onload = function (e) { + // debugger; + // console.log('文件信息===>>', e.target.result); + // const image = new Image(); + // image.src = e.target.result; + + // image.onload = function () { + // // file.width = + // console.log(image.width, image.height); + // } + // } + + const range = quill.getSelection(true); + let fileUrl = ''; // 保存上传成功后图片的url + // 上传文件 + const result = await fetchUploadImage(formData); + // 获取上传图片的url + if (result.data && result.data.id) { + fileUrl = getImageUrl(`api/attachments/${result.data.id}`); + } + // 根据id获取文件路径 + const { width, height } = imgAttrs; + // console.log('上传图片的url:', fileUrl); + if (fileUrl) { + quill.insertEmbed(range.index, 'image', { + url: fileUrl, + alt: '', + onClick: showUploadImage, + width, + height + }); + } + } + }); + } + + return () => { + element.innerHTML = ''; + } + }, [ + element, + options, + requireKatex, + katexLoaded, + ]); + + return quill; +} + +export default useMountQuill; diff --git a/public/react/src/common/reactQuill/useQuill.js b/public/react/src/common/reactQuill/useQuill.js new file mode 100644 index 000000000..b959dbc52 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuill.js @@ -0,0 +1,60 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:09:50 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 15:46:50 + */ +import useQuillPlaceholder from './useQuillPlaceholder'; +import useQuillValueSync from './useQuillValueSync'; +import useQuillOnChange from './useQuillOnChange'; +import useMountQuill from './useMountQuill'; +import { useEffect } from 'react'; + +function useQuill ({ + disallowColors, + placeholder, + uploadImage, + onChange, + options, + value, + element, + showUploadImage +}) { + + // 获取 quill 实例 + const quill = useMountQuill({ + element, + options, + uploadImage, + showUploadImage + }); + + useEffect(() => { + if (disallowColors && quill) { + quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => { + delta.ops = delta.ops.map(op => { + if (op.attributes && op.attributes.color) { + const { color, ...attributes } = op.attributes; + return { + ...op, + attributes + } + } + return op; + }); + return delta; + }); + } + }, [ + disallowColors, + quill + ]); + + useQuillPlaceholder(quill, placeholder); + useQuillValueSync(quill, value); + useQuillOnChange(quill, onChange); +} + +export default useQuill; diff --git a/public/react/src/common/reactQuill/useQuillOnChange.js b/public/react/src/common/reactQuill/useQuillOnChange.js new file mode 100644 index 000000000..45333a4e1 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuillOnChange.js @@ -0,0 +1,33 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-12 19:49:11 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:39:27 + */ +import { useEffect } from 'react'; + +function useQuillOnChange (quill, onChange) { + + useEffect(() => { + + if (!quill) return; + if (typeof onChange !== 'function') return; + + let handler; + + quill.on( + 'text-change', + (handler = () => { + onChange(quill.getContents()); // getContents: 检索编辑器内容 + }) + ); + + return () => { + quill.off('text-change', handler); + } + }, [quill, onChange]); +} + +export default useQuillOnChange; diff --git a/public/react/src/common/reactQuill/useQuillPlaceholder.js b/public/react/src/common/reactQuill/useQuillPlaceholder.js new file mode 100644 index 000000000..ccc341568 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuillPlaceholder.js @@ -0,0 +1,22 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:28:34 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:39:48 + */ +import { useEffect } from 'react' + +function useQuillPlaceholder ( + quill, + placeholder +) { + + useEffect(() => { + if (!quill || !quill.root) return; + quill.root.dataset.placeholder = placeholder; + }, [quill, placeholder]); +} + +export default useQuillPlaceholder; diff --git a/public/react/src/common/reactQuill/useQuillValueSync.js b/public/react/src/common/reactQuill/useQuillValueSync.js new file mode 100644 index 000000000..696d88949 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuillValueSync.js @@ -0,0 +1,31 @@ +import { useEffect, useState } from 'react' +import deepEqual from './deepEqual.js' + +function useQuillValueSync(quill, value) { + const [selection, setSelection] = useState(null) + + useEffect(() => { + if (!quill) return + + const previous = quill.getContents() + const current = value + + if (!deepEqual(previous, current)) { + setSelection(quill.getSelection()) + if (typeof value === 'string') { + quill.clipboard.dangerouslyPasteHTML(value, 'api') + } else { + quill.setContents(value) + } + } + }, [quill, value, setSelection]) + + useEffect(() => { + if (quill && selection) { + quill.setSelection(selection) + setSelection(null) + } + }, [quill, selection, setSelection]) +} + +export default useQuillValueSync diff --git a/public/react/src/modules/developer/DeveloperHome.js b/public/react/src/modules/developer/DeveloperHome.js index 5f787659e..73a5c37a1 100644 --- a/public/react/src/modules/developer/DeveloperHome.js +++ b/public/react/src/modules/developer/DeveloperHome.js @@ -16,7 +16,7 @@ import MultipTags from './components/multiptags'; // import { Link } from 'react-router-dom'; import CONST from '../../constants'; import { withRouter } from 'react-router'; -import { toStore } from 'educoder'; +import { toStore, CNotificationHOC } from 'educoder'; // import MyIcon from '../../common/components/MyIcon'; const {tagBackground, diffText} = CONST; @@ -249,17 +249,26 @@ class DeveloperHome extends React.PureComponent { // 删除 handleClickDelete = (record) => { const { deleteItem } = this.props; - Modal.confirm({ - title: '删除', + this.props.confirm({ + title: '提示', content: `确定要删除${record.name}吗?`, - okText: '确定', - cancelText: '取消', onOk () { // 调用删除接口 console.log(record.identifier); deleteItem(record.identifier); } }); + // Modal.confirm({ + // title: '删除', + // content: `确定要删除${record.name}吗?`, + // okText: '确定', + // cancelText: '取消', + // onOk () { + // // 调用删除接口 + // console.log(record.identifier); + // deleteItem(record.identifier); + // } + // }); } // table条件变化时 handleTableChange = (pagination, filters, sorter) => { @@ -562,5 +571,5 @@ const mapDispatchToProps = (dispatch) => ({ export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(DeveloperHome)); +)(CNotificationHOC() (DeveloperHome))); // export default DeveloperHome; diff --git a/public/react/src/modules/developer/components/controlSetting/index.js b/public/react/src/modules/developer/components/controlSetting/index.js index 587e1bee9..b5c9222ef 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.js +++ b/public/react/src/modules/developer/components/controlSetting/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 16:02:36 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:32:33 + * @LastEditTime: 2019-12-19 10:47:44 */ import './index.scss'; import React, { useState, useRef } from 'react'; @@ -30,7 +30,7 @@ const ControlSetting = (props) => { // debuggerCode, // startDebuggerCode, // 外部存入 onDebuggerCode, - updateCode, + // updateCode, onSubmitForm } = props; const [defaultActiveKey, setDefaultActiveKey] = useState('1'); // 当前选中的tab @@ -84,7 +84,7 @@ const ControlSetting = (props) => { diff --git a/public/react/src/modules/developer/components/controlSetting/index.scss b/public/react/src/modules/developer/components/controlSetting/index.scss index 97838ce5c..31beda8a5 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.scss +++ b/public/react/src/modules/developer/components/controlSetting/index.scss @@ -2,7 +2,8 @@ position: absolute; bottom: 0; width: 100%; - background:rgba(30,30,30,1); + // background: red; + // background:rgba(30,30,30,1); // height: 56px; .control_tab{ position: absolute; @@ -52,8 +53,8 @@ height: 56px; padding-right: 30px; padding-left: 10px; - // background: #000; - background:rgba(48,48,48,1); + background: rgba(18,28,36,1); + // background:rgba(48,48,48,1); } .setting_drawer{ diff --git a/public/react/src/modules/developer/components/execResult/index.js b/public/react/src/modules/developer/components/execResult/index.js index 32bbbee91..6f9341b9a 100644 --- a/public/react/src/modules/developer/components/execResult/index.js +++ b/public/react/src/modules/developer/components/execResult/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-28 08:44:54 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-10 09:24:02 + * @LastEditTime: 2019-12-19 10:44:16 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -38,6 +38,15 @@ function ExecResult (props) {
    ); + + const renderError = () => ( +
    + + 未知异常 + +
    + ) + const renderFinish = () => { const { error_line, @@ -60,6 +69,7 @@ function ExecResult (props) { ) } + // console.log('执行结果====》》》》', status); const excuteCtx = (state) => { if (state === 0) { return ( @@ -118,6 +128,8 @@ function ExecResult (props) { setRenderCtx(() => (readerLoaded)); } else if ('finish' === excuteState) { setRenderCtx(() => (renderFinish)); + } else if ('error' === excuteState) { + setRenderCtx(() => (renderError)) } }, [excuteState]); diff --git a/public/react/src/modules/developer/components/initTabCtx/index.js b/public/react/src/modules/developer/components/initTabCtx/index.js index 3834a3e11..3e707daa1 100644 --- a/public/react/src/modules/developer/components/initTabCtx/index.js +++ b/public/react/src/modules/developer/components/initTabCtx/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 19:46:14 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:38:42 + * @LastEditTime: 2019-12-19 10:47:05 */ import './index.scss'; import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react'; @@ -26,6 +26,7 @@ function InitTabCtx (props, ref) { const { inputValue, onDebuggerCode } = props; + console.log('default value', inputValue); useImperativeHandle(ref, () => ({ handleTestCodeFormSubmit: (cb) => { // console.log('父组件调用我啦~~~~~~~~~'); @@ -33,6 +34,10 @@ function InitTabCtx (props, ref) { } })); + useEffect(() => { + console.log('初始值: ========', props); + }, [props]); + // 渲染文本提示信息 const renderText = () => (请在这里添加测试用例,点击“调试代码”时将从这里读取输入来测试你的代码...); // 渲染表单信息 diff --git a/public/react/src/modules/developer/components/initTabCtx/index.scss b/public/react/src/modules/developer/components/initTabCtx/index.scss index 449db1d2a..5427aa374 100644 --- a/public/react/src/modules/developer/components/initTabCtx/index.scss +++ b/public/react/src/modules/developer/components/initTabCtx/index.scss @@ -49,7 +49,8 @@ } .input_textarea_style{ - background:rgba(30,30,30,1) !important; + // background:rgba(30,30,30,1) !important; + background:rgba(7,15,25,1) !important; color: #fff; border-color: transparent; outline: none; diff --git a/public/react/src/modules/developer/components/monacoSetting/index.js b/public/react/src/modules/developer/components/monacoSetting/index.js index a101819e0..c1215f9af 100644 --- a/public/react/src/modules/developer/components/monacoSetting/index.js +++ b/public/react/src/modules/developer/components/monacoSetting/index.js @@ -4,10 +4,11 @@ * @Github: * @Date: 2019-11-25 17:50:33 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-06 16:51:48 + * @LastEditTime: 2019-12-19 15:26:46 */ import React, { useState } from 'react'; import { fromStore, toStore } from 'educoder'; +import { Icon } from 'antd'; // import { Select } from 'antd'; // const { Option } = Select; const SettingDrawer = (props) => { diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.js b/public/react/src/modules/developer/components/myMonacoEditor/index.js index 60f54ee0a..df3c2b5e3 100644 --- a/public/react/src/modules/developer/components/myMonacoEditor/index.js +++ b/public/react/src/modules/developer/components/myMonacoEditor/index.js @@ -4,12 +4,12 @@ * @Github: * @Date: 2019-11-27 15:02:52 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 16:16:56 + * @LastEditTime: 2019-12-19 17:52:31 */ import './index.scss'; import React, { useState, useRef, useEffect } from 'react'; -import { Drawer, Modal } from 'antd'; -import { fromStore } from 'educoder'; +import { Drawer, Modal, Icon, Badge } from 'antd'; +import { fromStore, CNotificationHOC } from 'educoder'; import { connect } from 'react-redux'; import MonacoEditor from '@monaco-editor/react'; import SettingDrawer from '../../components/monacoSetting'; @@ -19,16 +19,25 @@ import MyIcon from '../../../../common/components/MyIcon'; // import actions from '../../../../redux/actions'; const { fontSetting, opacitySetting } = CONST; +const maps = { + 'c': 'main.c', + 'c++': 'main.cc', + 'java': 'main.java', + 'pythone': 'main.py' +}; function MyMonacoEditor (props, ref) { const { + notice, language, identifier, + hadCodeUpdate, showOrHideControl, // saveUserInputCode, onCodeChange, - onRestoreInitialCode + onRestoreInitialCode, + onUpdateNotice } = props; const [showDrawer, setShowDrawer] = useState(false); // 控制配置滑框 @@ -50,7 +59,7 @@ function MyMonacoEditor (props, ref) { }, [props]); useEffect(() => { - setHeight(showOrHideControl ? 'calc(100% - 382px)' : 'calc(100% - 56px)'); + setHeight(showOrHideControl ? 'calc(100% - 378px)' : 'calc(100% - 56px)'); }, [showOrHideControl]); // 控制侧边栏设置的显示 @@ -93,28 +102,51 @@ function MyMonacoEditor (props, ref) { // 恢复初始代码 const handleRestoreCode = () => { - Modal.confirm({ + props.confirm({ + title: '提示', content: '确定要恢复代码吗?', - okText: '确定', - cancelText: '取消', onOk () { onRestoreInitialCode && onRestoreInitialCode(); } }) + // Modal.confirm({ + // content: '确定要恢复代码吗?', + // okText: '确定', + // cancelText: '取消', + // onOk () { + // onRestoreInitialCode && onRestoreInitialCode(); + // } + // }) + } + + const handleUpdateNotice = () => { + if (props.notice) { + onUpdateNotice && onUpdateNotice(); + } } const renderRestore = identifier ? ( ) : ''; + + // lex_has_save ${hadCodeUpdate} ? : '' + const _classnames = hadCodeUpdate ? `flex_strict flex_has_save` : 'flex_strict'; return (
    {/* 未保存时 ? '学员初始代码文件' : main.x */} - {identifier ? '' : '学员初始代码文件'} - {identifier ? '已保存' : ''} + {identifier ? language ? maps[language.toLowerCase()] : '' : '学员初始代码文件'} + {identifier ? '已保存' : ''} + + + {renderRestore} - {/* */}
    @@ -161,4 +192,4 @@ const mapDispatchToProps = (dispatch) => ({ export default connect( mapStateToProps, mapDispatchToProps -)(MyMonacoEditor); +)(CNotificationHOC() (MyMonacoEditor)); diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.scss b/public/react/src/modules/developer/components/myMonacoEditor/index.scss index 7a7c4f030..61689b51e 100644 --- a/public/react/src/modules/developer/components/myMonacoEditor/index.scss +++ b/public/react/src/modules/developer/components/myMonacoEditor/index.scss @@ -1,19 +1,17 @@ .monaco_editor_area{ height: 100%; - background-color: rgba(30,30,30,1); + background-color: rgba(7,15,25,1); .code_title{ display: flex; align-items: center; - // justify-content: space-between; - // background: #000; - // background: #333333; - background-color: rgba(48,48,48,1); + background-color: rgba(18,28,36,1); color: #fff; height: 56px; padding: 0 30px; .flex_strict{ flex: 1; } + .flex_normal{ color: #E51C24; cursor: pointer; @@ -25,21 +23,21 @@ .flex_strict, .flex_normal, .code-icon{ - color: #888; + color: #666; } } } .setting_drawer{ - // .ant-drawer-body{ - // // height: calc(100vh - 120px); - // // overflow-y: auto; - // } + .ant-drawer-close{ + color: #ffffff; + } .ant-drawer-content{ top: 120px; bottom: 56px; height: calc(100vh - 176px); - background: #333333; + // background: #333333; + background: rgba(7,15,25,1); color: #fff; .setting_h2{ color: #fff; @@ -57,4 +55,17 @@ color: #fff; } } +} + +.flex_has_save{ + // animation: blink 3s line 3; + animation-name: blink; + animation-duration: .4s; + animation-iteration-count: 3; +} + +@keyframes blink{ + 50% { + color: #fff; + } } \ No newline at end of file diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js index bc905fdf7..1c451c669 100644 --- a/public/react/src/modules/developer/newOrEditTask/index.js +++ b/public/react/src/modules/developer/newOrEditTask/index.js @@ -13,11 +13,11 @@ import { Button, Modal } from 'antd'; import LeftPane from './leftpane'; import RightPane from './rightpane'; import { withRouter } from 'react-router'; -import { toStore } from 'educoder'; +import { toStore, CNotificationHOC } from 'educoder'; import UserInfo from '../components/userInfo'; // import RightPane from './rightpane/index'; import actions from '../../../redux/actions'; -import {ModalConfirm} from '../../../common/components/ModalConfirm'; +// import {ModalConfirm} from '../../../common/components/ModalConfirm'; const NewOrEditTask = (props) => { const { @@ -69,10 +69,13 @@ const NewOrEditTask = (props) => { // 模拟挑战 const imitationChallenge = () => { + // 调用 start 接口, 成功后跳转到模拟页面 + startProgramQuestion(identifier, props); } // 开始挑战 const startChallenge = () => { - // 调用 start 接口, 成功后跳转到模拟页面 + // 调用 start 接口, 成功后跳转到开启实战 + // TODO startProgramQuestion(identifier, props); } @@ -82,27 +85,38 @@ const NewOrEditTask = (props) => { props.clearOJFormStore(); // 清空描述信息 toStore('oj_description', ''); - setInterval(function () { - props.history.push('/problems'); - }, 500); + props.history.push('/problems'); } // 发布 const handleClickPublish = () => { - ModalConfirm('提示', (

    发布后即可应用到自己管理的课堂
    是否确认发布?

    ), () => { - changePublishLoadingStatus(true); - handlePublish(props, 'publish'); + // ModalConfirm('提示', (

    发布后即可应用到自己管理的课堂
    是否确认发布?

    ), () => { + // changePublishLoadingStatus(true); + // handlePublish(props, 'publish'); + // }); + props.confirm({ + title: '提示', + content: (

    发布后即可应用到自己管理的课堂
    是否确认发布?

    ), + onOk () { + changePublishLoadingStatus(true); + handlePublish(props, 'publish'); + } }); - - } // 撤销发布 const handleClickCancelPublish = () => { - ModalConfirm('提示', (

    是否确认撤销发布?

    ), () => { - changePublishLoadingStatus(true); - handleCancelPublish(props, identifier); + // ModalConfirm('提示', (

    是否确认撤销发布?

    ), () => { + // changePublishLoadingStatus(true); + // handleCancelPublish(props, identifier); + // }); + props.confirm({ + title: '提示', + content: ((

    是否确认撤销发布?

    )), + onOk () { + changePublishLoadingStatus(true); + handleCancelPublish(props, identifier); + } }); - } // 取消保存/取消按钮 @@ -125,6 +139,7 @@ const NewOrEditTask = (props) => { const renderPubOrFight = () => { const pubButton = isPublish ? ( ); - // 更新 - // const updateBtn = isPublish - // ? '' - // : ( - // - // ); - return ( - - - {pubButton} - {challengeBtn} - - ) + if (isPublish) { + return ( + + {pubButton} + + {challengeBtn} + + ); + } else { + return ( + + + {pubButton} + {challengeBtn} + + ); + } + } // 渲染退出 const renderQuit = () => { return identifier ? ( ) : '' @@ -255,4 +271,4 @@ const mapDispatchToProps = (dispatch) => ({ export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(NewOrEditTask)); +)(CNotificationHOC() (NewOrEditTask))); diff --git a/public/react/src/modules/developer/newOrEditTask/index.scss b/public/react/src/modules/developer/newOrEditTask/index.scss index ba0ed8503..ad668fcc8 100644 --- a/public/react/src/modules/developer/newOrEditTask/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/index.scss @@ -10,9 +10,23 @@ align-items: center; justify-content: center; height: 56px; - background: #333333; + // background: #333333; + background: rgba(18,28,36,1); > button{ margin-right: 20px; } } +.quite_btn{ + position: absolute; + right: 10px; + top: 15px; + margin-left: 30px; + color: #888888; + transition: all .3s; + cursor: pointer; + &:hover{ + color: #5091FF; + } +} + diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js index 4c4131fa9..8e7aa70fc 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js @@ -4,13 +4,14 @@ * @Github: * @Date: 2019-11-21 09:19:38 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 11:58:46 + * @LastEditTime: 2019-12-19 17:54:28 */ import './index.scss'; import React, { useState } from 'react'; -import { Collapse, Icon, Input, Form, Button, Modal } from 'antd'; +import { Collapse, Icon, Input, Form, Button } from 'antd'; import { connect } from 'react-redux'; import actions from '../../../../../redux/actions'; +import { CNotificationHOC} from 'educoder'; const { Panel } = Collapse; const { TextArea } = Input; const FormItem = Form.Item; @@ -31,15 +32,22 @@ const AddTestDemo = (props) => { // console.log('点击的删除按钮') e.preventDefault(); e.stopPropagation(); - Modal.confirm({ - title: '删除', + props.confirm({ + title: '提示', content: '确定要删除当前测试用例吗?', - okText: '确定', - cancelText: '取消', onOk() { onDeleteTest(testCase); } - }) + }); + // Modal.confirm({ + // title: '删除', + // content: '确定要删除当前测试用例吗?', + // okText: '确定', + // cancelText: '取消', + // onOk() { + // onDeleteTest(testCase); + // } + // }) } // 输入框值改变时 @@ -189,4 +197,4 @@ const mapDispatchToProps = (dispatch) => ({ export default connect( mapStateToProps, mapDispatchToProps -)(Form.create()(AddTestDemo)); +)(Form.create()(CNotificationHOC()(AddTestDemo))); diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js index 762d1d3ba..da31754bd 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js @@ -4,21 +4,20 @@ * @Github: * @Date: 2019-11-20 10:35:40 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 11:39:52 + * @LastEditTime: 2019-12-19 17:23:10 */ -import 'quill/dist/quill.core.css'; -import 'quill/dist/quill.bubble.css'; -import 'quill/dist/quill.snow.css'; import './index.scss'; // import 'katex/dist/katex.css'; import React from 'react'; import { Form, Input, Select, InputNumber, Button } from 'antd'; import { connect } from 'react-redux'; import AddTestDemo from './AddTestDemo'; -import QuillEditor from '../../../quillEditor'; +// import QuillEditor from '../../../quillEditor'; import actions from '../../../../../redux/actions'; import CONST from '../../../../../constants'; -import { fromStore, toStore } from 'educoder'; // 保存和读取store值 +import { toStore } from 'educoder'; // 保存和读取store值 +// import Wrapper from '../../../../../common/reactQuill'; +import QuillForEditor from '../../../../../common/quillForEditor'; const scrollIntoView = require('scroll-into-view'); const {jcLabel} = CONST; const FormItem = Form.Item; @@ -26,9 +25,9 @@ const { Option } = Select; const maps = { language: [ { title: 'C', key: 'C' }, - // { title: 'C++', key: 'C++' }, - // { title: 'Python', key: 'Python' }, - // { title: 'Java', key: 'Java' } + { title: 'C++', key: 'C++' }, + { title: 'Python', key: 'Python' }, + { title: 'Java', key: 'Java' } ], difficult: [ { title: '简单', key: '1' }, @@ -146,9 +145,6 @@ class EditTab extends React.Component { testCasesValidate, openTestCodeIndex = [] } = this.props; - // console.log('当前位置: ', position); - // console.log('OJForm: ', ojForm); - // console.log('当前位置: ', testCases); // 表单label const myLabel = (name, subTitle) => { if (subTitle) { @@ -185,7 +181,6 @@ class EditTab extends React.Component { }; const renderTestCase = () => { return this.props.testCases.map((item, i) => { - console.log(111); return { + console.log('描述信息为: ', content); + // 保存获取的描述信息至redux中 + this.handleChangeDescription(content); + } // 编辑器配置信息 const quillConfig = [ [{ header: [1, 2, 3, 4, 5, 6, false] }], ['bold', 'italic', 'underline', 'strike'], // 切换按钮 ['blockquote', 'code-block'], // 代码块 - [{ 'list': 'ordered' }, { 'list': 'bullet' }], // 列表 + [{align: []}, { 'list': 'ordered' }, { 'list': 'bullet' }], // 列表 [{ 'script': 'sub'}, { 'script': 'super' }], [{ 'color': [] }, { 'background': [] }], // 字体颜色与背景色 - ['formula', 'image', 'video'], // 数学公式、图片、视频 + ['image', 'formula'], // 数学公式、图片、视频 ['clean'], // 清除格式 ]; + return (
    @@ -267,7 +270,7 @@ class EditTab extends React.Component { help={ojFormValidate.timeLimit.errMsg} colon={ false } > - + - +
    + +
    +
    {/* */} + {/* 添加测试用例 */} diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss index f8fa3bd71..17f3eae34 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss @@ -49,6 +49,11 @@ .test_demo_ctx, .editor_form{ margin: 0 30px; + + .ant-form-explain{ + margin-top: 5px; + margin-left: -10px; + } } .test_demo_title{ display: flex; diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/index.js index 8b10413a9..781b82699 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/index.js @@ -34,28 +34,6 @@ function LeftPane (props) { const [defaultActiveKey, setDefaultActiveKey] = useState('editor'); - // const tabArrs = [ - // { title: '编辑', key: 'editor', content: () }, - // { title: '预览', key: 'prev', content: () }, - // // { title: '提交记录', key: 'commit', content: () }, - // ]; - - // const tabs = tabArrs.map((tab) => { - // const Comp = tab.content; - // return ( - // - // { Comp } - // - // ) - // }); - - // tab切换时 - // const handleTabChange = (key) => { - // setDefaultActiveKey(key); - // } - - // 执行表单提交函数 - const renderComp = useMemo(() => { return Comp[defaultActiveKey]; }, [defaultActiveKey]); diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js index c45628973..6b41d3489 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js @@ -4,74 +4,47 @@ * @Github: * @Date: 2019-11-24 10:09:55 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-04 23:38:37 + * @LastEditTime: 2019-12-18 10:02:24 */ import './index.scss'; import React, { useEffect, useState, useRef } from 'react'; import { connect } from 'react-redux'; import {Empty} from 'antd'; -// import QuillEditor from '../../../quillEditor'; -const Quill = window.Quill; +// import Wrapper from '../../../../../common/reactQuill'; +import QuillForEditor from '../../../../../common/quillForEditor'; const PrevTab = (props) => { - const { - description - } = props; const prevRef = useRef(null); - const [desc, setDesc] = useState(''); - const [renderCtx, setRenderCtx] = useState(() => { - return function () { - return ''; - } - }); - - // 空内容 - const renderTxt = () => ( -
    - -
    - ); + // const [desc, setDesc] = useState(''); + const [renderCtx, setRenderCtx] = useState(() => ''); + // 渲染内容 - const renderQuill = () => ( -
    -
    - ); - useEffect(() => { - setDesc(description); - }, [description]); - - useEffect(() => { - if (description) { - setRenderCtx(() => renderQuill); - let count = 0; - let timer = setInterval(() => { - count++; - if (count >= 10 || prevRef.current) { - clearInterval(timer); - timer = null; - if (prevRef.current) { - const quillEditor = new Quill(prevRef.current, { - readOnly: true, - theme: 'bubble' - }); - quillEditor.container.firstChild.innerHTML = description; - } - } - }, 50); + if (props.description) { + setRenderCtx(() => ( +
    + +
    + )); } else { - setRenderCtx(() => renderTxt); + setRenderCtx(() => ( +
    + +
    + )); } - - }, [description]); + }, [props]); return (
    - {renderCtx()} + {renderCtx}
    ) diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss b/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss index 48f5a7bb9..ea2f37c20 100644 --- a/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss @@ -1,7 +1,7 @@ .right_pane_code_wrap{ position: relative; // justify-content: center; - background-color: #222; + // background-color: #222; height: 100%; // height: calc(100vh - 178px); .code-title, diff --git a/public/react/src/modules/developer/split_pane_resizer.scss b/public/react/src/modules/developer/split_pane_resizer.scss index 498370dd6..2898d966c 100644 --- a/public/react/src/modules/developer/split_pane_resizer.scss +++ b/public/react/src/modules/developer/split_pane_resizer.scss @@ -8,7 +8,8 @@ .record_detail_header{ height: 65px; // background:rgba(34,34,34,1); - background: #1E1E1E; + // background: #1E1E1E; + background: rgba(7,15,25,1); padding:0 30px; } @@ -123,7 +124,8 @@ .split-pane-area, .split-pane-left{ .ant-tabs-nav-wrap{ - padding: 0 30px; + // padding: 0 30px; + padding: 0 20px; } .ant-tabs-bar{ margin: 0; diff --git a/public/react/src/modules/developer/studentStudy/index.js b/public/react/src/modules/developer/studentStudy/index.js index e4b296a20..1db9f7f28 100644 --- a/public/react/src/modules/developer/studentStudy/index.js +++ b/public/react/src/modules/developer/studentStudy/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-23 10:53:19 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:19:15 + * @LastEditTime: 2019-12-19 17:51:19 */ import './index.scss'; import React, { useEffect, useState } from 'react'; @@ -15,10 +15,10 @@ import RightPane from './rightpane'; // import { Link } from 'react-router-dom'; // import { getImageUrl } from 'educoder' // import RightPane from '../newOrEditTask/rightpane'; -import { Icon, Modal } from 'antd'; +import { Icon } from 'antd'; import UserInfo from '../components/userInfo'; import actions from '../../../redux/actions'; -import { fromStore} from 'educoder'; +import { fromStore, CNotificationHOC} from 'educoder'; import { withRouter } from 'react-router'; function StudentStudy (props) { @@ -51,23 +51,39 @@ function StudentStudy (props) { const { hack = {} } = props; if (hack.modify_code && hasUpdate) { // 代码更改,提示是否需要更新代码 setHasUpdate(false); - Modal.confirm({ - title: '提示', - content: ( -

    - 代码文件有更新啦
    - 还未提交的代码,请自行保存 -

    - ), - okText: '立即更新', - cancelText: '稍后再说', - onOk () { - restoreInitialCode(id, '更新成功'); - } - }); + handleUpdateNotice(); } }, [props, hasUpdate, setHasUpdate]); + const handleUpdateNotice = () => { + console.log(props); + props.confirm({ + title: '提示', + content: ( +

    + 代码文件有更新啦
    + 还未提交的代码,请自行保存 +

    + ), + onOk () { + restoreInitialCode(id, '更新成功'); + } + }) + // Modal.confirm({ + // title: '提示', + // content: ( + //

    + // 代码文件有更新啦
    + // 还未提交的代码,请自行保存 + //

    + // ), + // okText: '立即更新', + // cancelText: '稍后再说', + // onOk () { + // restoreInitialCode(id, '更新成功'); + // } + // }); + } const _hack_id = hack_identifier || fromStore('hack_identifier'); // 处理编辑 @@ -117,7 +133,9 @@ function StudentStudy (props) {
    - +
    @@ -151,6 +169,6 @@ const mapDispatchToProps = (dispatch) => ({ export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(StudentStudy)); +)(CNotificationHOC()(StudentStudy))); diff --git a/public/react/src/modules/developer/studentStudy/index.scss b/public/react/src/modules/developer/studentStudy/index.scss index bbf66aebb..68835f2ce 100644 --- a/public/react/src/modules/developer/studentStudy/index.scss +++ b/public/react/src/modules/developer/studentStudy/index.scss @@ -5,6 +5,6 @@ .right_pane_code_wrap{ position: relative; - background-color: #222; + // background-color: #222; height: 100%; } diff --git a/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js index 329e8fba1..ca7160117 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js @@ -4,15 +4,18 @@ * @Github: * @Date: 2019-11-27 09:49:35 * @LastEditors: tangjiang - * @LastEditTime: 2019-11-27 09:52:53 + * @LastEditTime: 2019-12-17 17:46:05 */ +import './index.scss'; import React from 'react'; - -const Comment = (props) => { +import Comment from '../../../../../common/components/comment'; +const CommentTask = (props) => { return ( -

    Comment

    +
    + +
    ) } -export default Comment; +export default CommentTask; diff --git a/public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss new file mode 100644 index 000000000..ba9c132d9 --- /dev/null +++ b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss @@ -0,0 +1,8 @@ +.task_comment_task{ + background: #fff; + padding: 20px 30px 0; + height: calc(100vh - 177px); + box-sizing: border-box; + overflow-y: auto; + border-bottom: 1px solid rgba(244,244,244,1); +} \ No newline at end of file diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.js b/public/react/src/modules/developer/studentStudy/leftpane/index.js index 69f49b9b1..347f4b4f8 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/index.js @@ -4,11 +4,11 @@ * @Github: * @Date: 2019-11-23 11:33:41 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-09 19:57:21 + * @LastEditTime: 2019-12-19 18:03:22 // */ import './index.scss'; import React, { useState, useEffect, useMemo } from 'react'; -import { Tabs, Divider } from 'antd'; +import { Divider } from 'antd'; import { connect } from 'react-redux'; import Comment from './comment'; import CommitRecord from './commitRecord'; @@ -19,17 +19,10 @@ import actions from '../../../../redux/actions'; const LeftPane = (props) => { - const { hack, userCodeTab, changeUserCodeTab } = props; + const { hack, userCodeTab } = props; const { pass_count, submit_count } = hack; - const [defaultActiveKey, setDefaultActiveKey] = useState('task'); + const [defaultActiveKey, setDefaultActiveKey] = useState('comment'); - console.log(pass_count, submit_count); - const tabArrs = [ - { title: '任务描述', key: 'task', content: () }, - { title: '提交记录', key: 'record', content: () }, - // { title: '评论', key: 'comment', content: () }, - ]; - const navItem = [ { title: '任务描述', @@ -38,38 +31,30 @@ const LeftPane = (props) => { { title: '提交记录', key: 'record' - } + }, + // { + // title: '评论', + // key: 'comment' + // } ]; const Comp = { task: (), - record: () + record: (), + comment: () }; useEffect(() => { + console.log('====>>>>', userCodeTab); setDefaultActiveKey(userCodeTab); }, [userCodeTab]) - // const tabs = tabArrs.map((tab) => { - // const Comp = tab.content; - // return ( - // - // { Comp } - // - // ) - // }); - - // // tab切换时 - // const handleTabChange = (key) => { - // // setDefaultActiveKey(key); - // changeUserCodeTab(key); - // } - const renderComp = useMemo(() => { return Comp[defaultActiveKey]; - }, [defaultActiveKey]); + }, [defaultActiveKey, setDefaultActiveKey]); const renderNavItem = navItem.map((item) => { + const _classes = item.key === defaultActiveKey ? 'add_editor_item active' : 'add_editor_item'; return (
  • { return ( - {/* - { tabs } - -
    -
    - - - -
    -
    - - - -
    -
    */}
      { renderNavItem }
    @@ -126,11 +96,6 @@ const LeftPane = (props) => {
  • - {/*
    - - - -
    */}
    ); diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/index.scss index 9e6f019f6..1582c033f 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/index.scss +++ b/public/react/src/modules/developer/studentStudy/leftpane/index.scss @@ -13,6 +13,8 @@ bottom: 0px; height: 56px; width: 100%; + box-sizing: border-box; + border-top: 1px solid rgba(244,244,244,1); // background: pink; padding: 0 30px; // background-color: rgba(250,250,250,1); @@ -79,4 +81,9 @@ margin-right: 5px; } } +} + +.add_editor_list_area{ + box-sizing: border-box; + border-bottom: 1px solid rgba(244,244,244,1); } \ No newline at end of file diff --git a/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js b/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js index 28fe51765..981770b8c 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js @@ -4,14 +4,15 @@ * @Github: * @Date: 2019-11-27 09:49:30 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-09 19:21:55 + * @LastEditTime: 2019-12-19 09:22:52 */ import '../index.scss'; import React from 'react'; import { Tag } from 'antd'; import { Link } from 'react-router-dom'; import { connect } from 'react-redux'; -import QuillEditor from '../../../quillEditor'; +import QuillForEditor from '../../../../../common/quillForEditor'; + import CONST from '../../../../../constants'; const {tagBackground, diffText} = CONST; @@ -36,22 +37,15 @@ const TaskDescription = (props) => {

    出题者: - {username} + {username}

    -
    - {/* */} - {/*
    */}
    ) } diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js index 669a8a693..5661ea32e 100644 --- a/public/react/src/modules/developer/studentStudy/rightpane/index.js +++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 14:59:51 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 16:50:40 + * @LastEditTime: 2019-12-19 15:06:49 */ import React, { useState, useEffect } from 'react'; import {connect} from 'react-redux'; @@ -20,8 +20,11 @@ const RightPane = (props) => { submitUserCode, input, hack, + notice, updateCode, + hadCodeUpdate, editor_code, + updateNotice, saveUserInputCode, restoreInitialCode, saveUserCodeForInterval @@ -48,7 +51,8 @@ const RightPane = (props) => { // 代码块内容变化时 const handleCodeChange = (code) => { // 保存用户提交的代码块 - console.log(code); + // console.log(code); + setEditorCode(code); if (!timer) { timer = setInterval(() => { clearInterval(timer); @@ -69,13 +73,21 @@ const RightPane = (props) => { restoreInitialCode(identifier, '恢复初始代码成功'); } + // 更新代码 + const handleUpdateNotice = () => { + updateNotice && updateNotice(); + }; + return (
    { const mapStateToProps = (state) => { - const {user_program_identifier, hack, userTestInput, editor_code} = state.ojForUserReducer; + const { + user_program_identifier, + hack, + userTestInput, + editor_code, + notice, + hadCodeUpdate + } = state.ojForUserReducer; // const { language, code } = hack; return { hack, + notice, + hadCodeUpdate, editor_code, input: userTestInput, submitInput: hack.input, diff --git a/public/react/src/redux/actions/actionTypes.js b/public/react/src/redux/actions/actionTypes.js index 0f33b435c..c872486e2 100644 --- a/public/react/src/redux/actions/actionTypes.js +++ b/public/react/src/redux/actions/actionTypes.js @@ -22,7 +22,8 @@ const types = { SAVE_OJ_FORM: 'SAVE_OJ_FORM', // 保存表单 ADD_TEST_CASE: 'ADD_TEST_CASE', // 添加测试用例 DELETE_TEST_CASE: 'DELETE_TEST_CASE', // 删除测试用例 - SAVE_TEST_CASE: '保存测试用例', // 保存测试用例 + SAVE_TEST_CASE: 'SAVE_TEST_CASE', // 保存测试用例 + SAVE_USE_TEST_CASE_VALUE: 'SAVE_USE_TEST_CASE_VALUE', // 用户自定义测试用例值 CLEAR_JSFORM_STORE: 'CLEAR_JSFORM_STORE', // 清空测试用例 SAVE_EDIT_OJ_FORM_AND_TEST_CASE: 'SAVE_EDIT_OJ_FORM_AND_TEST_CASE', // 保存根据id获取的表单及测试用例值 TEST_CODE_STATUS: 'TEST_CODE_STATUS', // 代码调试状态 @@ -50,6 +51,8 @@ const types = { SAVE_USER_INFO: 'SAVE_USER_INFO', // 只在用户信息 SAVE_HACK_IDENTIFIER: 'SAVE_HACK_IDENTIFIER', // 用户界面跑到编辑界面需要用的id值 SAVE_EDITOR_CODE: 'SAVE_EDITOR_CODE', // 保存详情页面中编辑时的代码 + SAVE_NOTICE_COUNT: 'SAVE_NOTICE_COUNT', // 保存代码块是否更新 + AUTO_UPDATE_CODE: 'AUTO_UPDATE_CODE', // 自动更新代码 } export default types; diff --git a/public/react/src/redux/actions/ojForUser.js b/public/react/src/redux/actions/ojForUser.js index 79e2045d6..9cb814d80 100644 --- a/public/react/src/redux/actions/ojForUser.js +++ b/public/react/src/redux/actions/ojForUser.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:42:11 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 16:49:42 + * @LastEditTime: 2019-12-19 15:11:56 */ import types from "./actionTypes"; import { Base64 } from 'js-base64'; @@ -82,6 +82,20 @@ export const getUserProgramDetail = (identifier, type) => { payload: data }); } + // 保存默认测试用例 + dispatch({ + type: types.SAVE_USE_TEST_CASE_VALUE, + payload: data.test_case || {} + }); + // 代码是否更新 + let _modify_code = false; + if (data.hack) { + _modify_code = data.hack.modify_code; + } + dispatch({ + type: types.SAVE_NOTICE_COUNT, + payload: _modify_code + }) // 保存用户登录信息 dispatch({ type: types.SAVE_USER_INFO, @@ -94,13 +108,29 @@ export const getUserProgramDetail = (identifier, type) => { export const saveUserCodeForInterval = (identifier, code) => { return (dispatch) => { + dispatch({ + type: types.AUTO_UPDATE_CODE, + payload: true + }); fetchUpdateCode(identifier, { code: Base64.encode(code) }).then(res => { if (res.data.status === 401) { return; }; + + setTimeout(() => { + dispatch({ + type: types.AUTO_UPDATE_CODE, + payload: false + }) + }, 1000); console.log('代码保存成功', res); + }).catch(() => { + dispatch({ + type: types.AUTO_UPDATE_CODE, + payload: false + }) }); } } @@ -259,7 +289,11 @@ export const debuggerCode = (identifier,value, type) => { }).catch(() => { dispatch({ type: types.TEST_CODE_STATUS, - payload: '' + payload: 'error' + }); + dispatch({ + type: types.LOADING_STATUS, + payload: false }); dispatch({ type: types.SUBMIT_LOADING_STATUS, @@ -400,6 +434,10 @@ export const restoreInitialCode = (identifier, msg) => { message: '提示', description: msg }); + dispatch({ + type: types.SAVE_NOTICE_COUNT, + payload: false + }); } }); } @@ -412,3 +450,6 @@ export const saveEditorCodeForDetail = (code) => { payload: code } } + +// 更新通知状态 + diff --git a/public/react/src/redux/actions/ojForm.js b/public/react/src/redux/actions/ojForm.js index 3eaac9023..740bad895 100644 --- a/public/react/src/redux/actions/ojForm.js +++ b/public/react/src/redux/actions/ojForm.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-20 16:35:46 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 16:56:22 + * @LastEditTime: 2019-12-19 17:20:48 */ import types from './actionTypes'; import CONST from '../../constants'; @@ -15,7 +15,7 @@ import { cancelPublicTask } from '../../services/ojService'; import { Base64 } from 'js-base64'; -import { message, notification, Modal } from 'antd'; +import { notification } from 'antd'; import { toStore } from 'educoder'; const { jcLabel } = CONST; // 表单字段映射 @@ -160,7 +160,7 @@ export const validateOjForm = (props, type) => { if (testCases.length === 0) { hasSuccess = false; notification['error']({ - message: '必填', + message: '提示', description: '测试用例必须输入!' }); } @@ -200,7 +200,7 @@ export const validateOjForm = (props, type) => { let paramsObj = {}; const hack = { // 编程题干 name, - description, + description: JSON.stringify(description), difficult, category, 'open_or_not': openOrNot, @@ -449,9 +449,13 @@ export const testCaseInputChange = (value, index) => { let validate = emptyValidate('input', value)['input']; if (!validate.errMsg) { // 唯一性校验 + let _errMsg = ''; const {testCases} = getState().ojFormReducer; const bool = testCases.some((item, i) => { if (i !== index) { + if (item['input'] === value) { + _errMsg=`与测试用例${index}的输入值重复了,请重新填写`; + } return item['input'] === value; } else { return false; @@ -460,7 +464,7 @@ export const testCaseInputChange = (value, index) => { if (bool) { validate = { validateStatus: 'error', - errMsg: '输入值必须唯一' + errMsg: _errMsg }; } } @@ -492,8 +496,12 @@ export const testCaseOutputChange = (value, index) => { if (!validate.errMsg) { // 唯一性校验 const {testCases} = getState().ojFormReducer; + let _errMsg = ''; const bool = testCases.some((item, i) => { if (i !== index) { + if (item['output'] === value) { + _errMsg=`与测试用例${index}的输入值重复了,请重新填写`; + } return item['output'] === value; } else { return false; @@ -502,7 +510,7 @@ export const testCaseOutputChange = (value, index) => { if (bool) { validate = { validateStatus: 'error', - errMsg: '输入值必须唯一' + errMsg: _errMsg }; } } diff --git a/public/react/src/redux/reducers/ojForUserReducer.js b/public/react/src/redux/reducers/ojForUserReducer.js index 6520f8954..60e7e6fd1 100644 --- a/public/react/src/redux/reducers/ojForUserReducer.js +++ b/public/react/src/redux/reducers/ojForUserReducer.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:41:48 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-10 10:09:59 + * @LastEditTime: 2019-12-19 14:49:03 */ import types from "../actions/actionTypes"; import { Base64 } from 'js-base64'; @@ -21,7 +21,9 @@ const initialState = { userTestInput: '', // 用户自定义输入值 recordDetail: {}, // 根据id号获取的记录详情 hack_identifier: '', // 用户界面编辑时 - editor_code: '' // 保存编辑代码 + editor_code: '', // 保存编辑代码 + notice: false, // 通知 + hadCodeUpdate: false, // 更新代码 }; const ojForUserReducer = (state = initialState, action) => { @@ -36,7 +38,8 @@ const ojForUserReducer = (state = initialState, action) => { const { hack, test_case } = action.payload; const { code }= hack; let tempCode = Base64.decode(code) - Object.assign(hack, {code: tempCode}); + let tempDesc = JSON.parse(hack.description); + Object.assign(hack, {code: tempCode, description: tempDesc}); return { ...state, hack: Object.assign({}, hack), @@ -121,6 +124,21 @@ const ojForUserReducer = (state = initialState, action) => { ...state, editor_code: action.payload } + case types.SAVE_USE_TEST_CASE_VALUE: + return { + ...state, + userTestInput: action.payload.input + } + case types.SAVE_NOTICE_COUNT: + return { + ...state, + notice: action.payload + }; + case types.AUTO_UPDATE_CODE: + return { + ...state, + hadCodeUpdate: action.payload + }; default: return state; } diff --git a/public/react/src/redux/reducers/ojFormReducer.js b/public/react/src/redux/reducers/ojFormReducer.js index c2ba0f4d8..39af4a5f8 100644 --- a/public/react/src/redux/reducers/ojFormReducer.js +++ b/public/react/src/redux/reducers/ojFormReducer.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-20 16:40:32 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 11:54:35 + * @LastEditTime: 2019-12-17 16:19:04 */ import { Base64 } from 'js-base64'; import types from '../actions/actionTypes'; @@ -176,7 +176,7 @@ const ojFormReducer = (state = initialState, action) => { const currentOjForm = { name, // 任务名称 language, - description, + description: JSON.parse(description), difficult, category, openOrNot: 1, diff --git a/public/react/src/services/ojService.js b/public/react/src/services/ojService.js index e13b66397..373805b73 100644 --- a/public/react/src/services/ojService.js +++ b/public/react/src/services/ojService.js @@ -4,10 +4,11 @@ * @Github: * @Date: 2019-11-20 10:55:38 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:03:47 + * @LastEditTime: 2019-12-17 14:10:37 */ import axios from 'axios'; +import { func } from 'prop-types'; export async function fetchOJList (params) { console.log('传递的参数: ', params); @@ -125,3 +126,15 @@ export async function fetchUserInfoForNew () { const url = `/problems/new.json`; return axios.get(url); } + +// 文件上传 +export async function fetchUploadImage (file) { + const url = `/attachments.json`; + return axios.post(url, file) +} + +// 根据id号获取图片url +export async function fetchUploadImageUrl (id) { + const url = `/attachments/${id}`; + return axios.get(url); +} From c69f06b746b1e41c577530df9d33357073210aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Thu, 19 Dec 2019 18:24:30 +0800 Subject: [PATCH 20/61] =?UTF-8?q?=E6=96=B0=E7=89=88=E5=AD=A6=E9=99=A2?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/App.js | 10 +- public/react/src/college/College.js | 1259 +++++++++++++++++ .../college/colleagechart/Colleagechart.js | 84 ++ .../college/colleagechart/Colleagechartzu.js | 149 ++ .../src/college/colleagecss/colleage.css | 213 +++ 5 files changed, 1714 insertions(+), 1 deletion(-) create mode 100644 public/react/src/college/College.js create mode 100644 public/react/src/college/colleagechart/Colleagechart.js create mode 100644 public/react/src/college/colleagechart/Colleagechartzu.js create mode 100644 public/react/src/college/colleagecss/colleage.css diff --git a/public/react/src/App.js b/public/react/src/App.js index 4694d57da..03cad7110 100644 --- a/public/react/src/App.js +++ b/public/react/src/App.js @@ -71,6 +71,11 @@ const Otherlogin=Loadable({ loader: () => import('./modules/login/Otherlogin'), loading: Loading, }) +// 学院统计 +const College = Loadable({ + loader: () => import('./college/College'), + loading: Loading +}) const Otherloginstart=Loadable({ loader: () => import('./modules/login/Otherloginstart'), @@ -614,7 +619,10 @@ class App extends Component { {/*/>*/} - + () + }/> {/* jupyter */} ( + { + record.name + } + ) + }, + { + title: '管理教师', + dataIndex: 'teachers', + key: 'teachers', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth340", + render: (text, record) => ( + + { + record.teachers + } + + ) + }, + { + title: '评测次数', + dataIndex: 'times', + key: 'times', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth175", + render: (text, record) => ( + + { + record.evaluating_count + } + + ), + }, + { + title: '学生', + key: 'student', + dataIndex: 'student', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth255", + render: (text, record) => ( + + { + record.student_count + } + + ) + }, + { + title: '实训作业', + dataIndex: 'training', + key: 'training', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.shixun_work_count + } + + ) + + }, + { + title: '资源', + dataIndex: 'resources', + key: 'resources', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.attachment_count + } + + ), + }, + { + title: '帖子', + dataIndex: 'posts', + key: 'posts', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + { + record.message_count + } + ) + }, + { + title: '其它任务', + dataIndex: 'othertasks', + key: 'othertasks', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.other_work_count + } + + ) + }, + { + title: '状态', + dataIndex: 'states', + key: 'states', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.is_end? + "已结束" + : + "正在进行" + } + + ) + }, + { + title: '时间', + dataIndex: 'timemy', + key: 'timemy', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.activity_time + } + + ) + }, + ], + page:1, + limit:10, + total_users:50, + teachersloading:false, + teacherranking:[ + { + title: '排名', + dataIndex: 'ranking', + key: 'ranking', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.id + } + + ) + }, + { + title: '姓名', + dataIndex: 'name', + key: 'name', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth105", + render: (text, record) => ( + { + record.name + } + + ) + }, + { + title: '管理课堂', + dataIndex: 'classroom', + key: 'classroom', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth175", + render: (text, record) => ( + + { + record.course_count + } + + ), + }, + { + title: '已发布实训作业', + key: 'assignment', + dataIndex: 'assignment', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth255", + render: (text, record) => ( + + { + record.shixun_work_count + } + + ) + }, + { + title: '未发布实训作业', + dataIndex: 'released', + key: 'released', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.un_shixun_work_count + } + + ) + + }, + { + title: '学生数', + dataIndex: 'studentnumber', + key: 'studentnumber', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.student_count + } + + ), + }, + { + title: '完成率', + dataIndex: 'completionrate', + key: 'completionrate', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.complete_rate+"%" + } + + ) + }, + { + title: '发布实训', + dataIndex: 'releasetraining', + key: 'releasetraining', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.publish_shixun_count + } + + ) + } + ], + studentranking:[ + { + title: '排名', + dataIndex: 'ranking', + key: 'ranking', + align: 'center', + className: "edu-txt-center font-14", + width:'100px', + render: (text, record) => ( + + { + record.id===1? + :record.id===2? + + :record.id===3? + + :record.id + } + + ) + }, + { + title: '姓名', + dataIndex: 'name', + key: 'name', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth105", + width:'100px', + render: (text, record) => ( + { + record.name + } + + ) + }, + { + title: '学号', + dataIndex: 'studentid', + key: 'studentid', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth175", + render: (text, record) => ( + + { + record.student_id + } + + ), + }, + { + title: '完成实训', + key: 'training', + dataIndex: 'training', + align: 'center', + className: "edu-txt-center font-14 maxnamewidth255", + render: (text, record) => ( + + { + record.shixun_count + } + + ) + }, + { + title: '在学实训', + dataIndex: 'learning', + key: 'learning', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.study_shixun_count + } + + ) + + }, + { + title: '金币', + dataIndex: 'goldcoin', + key: 'goldcoin', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.grade + } + + ), + }, + { + title: '经验值', + dataIndex: 'empirical', + key: 'empirical', + align: 'center', + className: "edu-txt-center font-14", + render: (text, record) => ( + + { + record.experience + } + + ) + }, + ], + school:"", + teachers_count:null, + students_count:null, + courses_count:null, + shixuns_count:null, + shixun_report_count:null, + shixun_time:null, + courses:null, + course_count:0, + pages:1, + limits:10, + teachers:null, + teacher_count:0, + students:null, + student_count:0, + shixun_chart_data:null, + shixun_chart_datanames:null, + studentionsnames:null, + studentionsvalues:null + } + + } + + + componentDidMount(){ + console.log("College"); + console.log(this.props.match.params.id); + this.gettop(); + this.Numberofinternshipreports(); + this.Actualcombattimeoftrainees(); + this.Classnumber(1,10); + this.Teacherranking(1,10); + this.Studentranking(1,10); + this.Onlinetraining(); + this.Hottest(); + } + //头部 + gettop=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/statistics.json`; + axios.get(url).then((response) => { + if(response===null||response===undefined){ + this.setState({ + teachers_count:0, + students_count:0, + courses_count:0, + shixuns_count:0, + school:"", + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + teachers_count:0, + students_count:0, + courses_count:0, + shixuns_count:0, + school:"", + }) + }else{ + this.setState({ + teachers_count:response.data.teachers_count, + students_count:response.data.students_count, + courses_count:response.data.courses_count, + shixuns_count:response.data.shixuns_count, + school:response.data.school, + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + teachers_count:0, + students_count:0, + courses_count:0, + shixuns_count:0, + school:"", + }) + }); + } + + //获取实训报告数 + Numberofinternshipreports=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/shixun_report_count.json`; + axios.get(url).then((response) => { + if(response===null||response===undefined){ + this.setState({ + shixun_report_count:0, + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + shixun_report_count:0, + }) + }else{ + if (response.data.status === -1){ + this.setState({ + shixun_report_count:0, + }) + return + } + this.setState({ + shixun_report_count:response.data.shixun_report_count, + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + shixun_report_count:0, + }) + }); + } + + //学员实战时间 + Actualcombattimeoftrainees=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/shixun_time.json`; + axios.get(url).then((response) => { + if(response===null||response===undefined){ + this.setState({ + shixun_time:0, + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + shixun_time:0, + }) + }else{ + if (response.data.status === -1){ + this.setState({ + shixun_time:0, + }) + return + } + this.setState({ + shixun_time:response.data.shixun_time, + }) + } + }).catch((error) => { + console.log(error) + this.setState({ + shixun_time:0, + }) + }); + } + + //课堂信息 + Classnumber=(page,per_page)=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/course_statistics.json`; + this.setState({ + coursesloading:true + }) + axios.get(url,{params:{ + page:page, + per_page:per_page, + } + }).then((response) => { + if(response===null||response===undefined){ + this.setState({ + courses:[], + course_count:0 + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + courses:[], + course_count:0 + }) + }else{ + if (response.data.status === -1){ + this.setState({ + courses:[], + course_count:0 + }) + return + } + this.setState({ + courses:response.data.courses, + course_count:response.data.course_count, + page:page, + limit:per_page + }) + } + this.setState({ + coursesloading:false + }) + }).catch((error) => { + this.setState({ + courses:[], + course_count:0, + coursesloading:false + }) + }); + } + + //教师排名 + Teacherranking=(page,per_page)=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/teachers.json`; + this.setState({ + teachersloading:true + }) + axios.get(url,{params:{ + page:page, + per_page:per_page, + } + }).then((response) => { + if(response===null||response===undefined){ + this.setState({ + teachers:[], + teacher_count:0 + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + teachers:[], + teacher_count:0 + }) + }else{ + if (response.data.status === -1){ + this.setState({ + teachers:[], + teacher_count:0 + }) + return + } + let teachers=[]; + if(response.data.teachers){ + for(let i=0;i { + this.setState({ + teachers:[], + teacher_count:0, + teachersloading:false + }) + }); + } + //学生排名 + + Studentranking=(page,per_page)=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/student_shixun.json`; + this.setState({ + studentsloading:true + }) + axios.get(url,{params:{ + page:page, + per_page:per_page, + } + }).then((response) => { + if(response===null||response===undefined){ + this.setState({ + students:[], + student_count:0, + }) + return + } + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + students:[], + student_count:0, + }) + }else{ + if (response.data.status === -1){ + this.setState({ + students:[], + student_count:0, + }) + return + } + let students=[]; + if(response.data.teachers){ + for(let i=0;i { + this.setState({ + students:[], + student_count:0, + studentsloading:false + }) + }); + } + + //在线实训情况 + Onlinetraining=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/shixun_chart_data.json`; + axios.get(url).then((response) => { + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + shixun_chart_data:[], + shixun_chart_datanames:[] + }) + }else{ + if (response.data.status === -1){ + this.setState({ + shixun_chart_data:[], + shixun_chart_datanames:[] + }) + return + } + + this.setState({ + shixun_chart_data:response.data.data, + shixun_chart_datanames:response.data.names + }) + } + }).catch((error) => { + this.setState({ + shixun_chart_data:[], + shixun_chart_datanames:[] + }) + }); + } + //最热测评 + Hottest=()=>{ + const id =this.props.match.params.id; + const url=`/colleges/${id}/student_hot_evaluations.json`; + axios.get(url).then((response) => { + if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { + this.setState({ + studentionsnames: [], + studentionsvalues: [] + }) + }else { + if (response.data.status === -1) { + this.setState({ + studentionsnames: [], + studentionsvalues: [] + }) + return + } + this.setState({ + studentionsnames: response.data.names, + studentionsvalues: response.data.values + }) + } + }).catch((error) => { + this.setState({ + studentionsnames: [], + studentionsvalues: [] + }) + }); + } + + table1handleChange(){ + + } + + //塞选 + paginationonChange=(pageNumber)=>{ + this.Classnumber(pageNumber,10); + } + + paginationonChanges=(pageNumber)=>{ + this.Teacherranking(pageNumber,10); + } + paginationonChangess=(pageNumber)=>{ + this.Studentranking(pageNumber,10); + } + render() { + let {columns,page,limit,total_users,teacherranking,studentranking, + teachers_count,students_count, courses_count, shixuns_count,shixun_report_count,shixun_time,courses,course_count,school,teachers, + pages,limits, teacher_count,teachersloading,coursesloading,pagess,limitss,studentsloading,students,student_count,shixun_chart_data, + shixun_chart_datanames, studentionsnames,studentionsvalues + } = this.state; + + return ( +
    +
    +
    +
    {school}
    +
    +
    + {/*//教师1*/} +
    + 教师 +
    +
    + {teachers_count?teachers_count:0} +
    +
    + +
    +
    + 学生 +
    +
    + {students_count?students_count:0} +
    +
    + +
    +
    + 课堂 +
    +
    + {courses_count?courses_count:0} +
    +
    + +
    +
    + 共建实训 +
    +
    + {shixuns_count?shixuns_count:0} +
    +
    + {/*//教师2*/} + + + + +
    +
    +
    +
    +

    + 基本使用情况 +

    + {/*基本使用情况1*/} +
    +

    + 教师 +

    +

    + 学生 +

    +

    + 课堂 +

    +

    + 共建实训 +

    +

    + 实习报告 +

    +

    + 学员实战时间 +

    +
    + + + {/*基本使用情况2*/} +
    +
    + { + teachers_count? +
    {teachers_count}
    + : + + } +
    +
    + { + students_count? +
    {students_count}
    + : + + } +
    +
    + { + courses_count? +
    {courses_count}
    + : + + } +
    +
    + { + shixuns_count? +
    {shixuns_count}
    + : + + } +
    +
    + { + shixun_report_count? +
    {shixun_report_count}
    + : + + } +
    +
    + { + shixun_time? +
    {shixun_time}
    + : + + } +
    +
    + {/*基本使用情况3结束*/} +
    + + +
    +

    + 课堂 +

    + { + courses===null? +
    + +
    + + : + JSON.stringify(courses) === "[]" ? + + + + : +
    +
    + +
    + {courses === undefined ? "" :
    } + + + { + course_count>=11? +
    +
    + +
    + +
    + :"" + } + + + } + + + + + +
    +
    +

    + 教师排名 +

    + { + teachers===null? +
    + +
    + + : + JSON.stringify(teachers) === "[]" ? + + + + : +
    + +
    + {teachers === undefined ? "" :
    } + + + } + + + + {/*
    */} + {/*
    */} + {/* */} + {/*
    */} + + {/*
    */} + + +
    +

    + 在线实训情况 +

    + { + shixun_chart_data===null? +
    + +
    + + : + JSON.stringify(shixun_chart_data) === "[]" ? + + + + : + + + + } + +
    +
    + + + +
    +
    +

    + 学生排名 +

    + { + students === null ? +
    + +
    + + : + JSON.stringify(students) === "[]" ? + + + + : +
    + +
    + {students === undefined ? "" :
    } + + + } + {/*
    */} + {/*
    */} + {/* */} + {/*
    */} + + {/*
    */} + + + + +
    + +
    +

    + 最热评测 +

    + { + studentionsnames===null? +
    + +
    + + : + JSON.stringify(studentionsnames) === "[]" ? + + + + : + + + + } + + +
    +
    + + + ) + } +} +export default SnackbarHOC() (TPMIndexHOC ( College )); + + diff --git a/public/react/src/college/colleagechart/Colleagechart.js b/public/react/src/college/colleagechart/Colleagechart.js new file mode 100644 index 000000000..fca01280a --- /dev/null +++ b/public/react/src/college/colleagechart/Colleagechart.js @@ -0,0 +1,84 @@ +import React, {Component} from "react"; +import {WordsBtn} from 'educoder'; +import {Table} from "antd"; +import {Link,Switch,Route,Redirect} from 'react-router-dom'; +const echarts = require('echarts'); + + + +function startechart(data,datanane){ + var effChart = echarts.init(document.getElementById('shixun_skill_chart')); + + var option = { + + tooltip : { + trigger: 'item', + formatter: "{d}%
    " + }, + legend: { + // orient: 'vertical', + // top: 'middle', + bottom: 50, + left: 'center', + data: datanane + }, + series : [ + { + type: 'pie', + radius : '65%', + center: ['50%', '35%'], + selectedMode: 'single', + data:data, + itemStyle: { + emphasis: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } + } + ] + }; + effChart.setOption(option); +} +class Colleagechart extends Component { + + constructor(props) { + super(props); + this.state = { + } + } + + componentDidMount() { + startechart(this.props.data,this.props.datanane) + } + + + componentDidUpdate = (prevProps) => { + if (prevProps.data!= this.props.data) { + startechart(this.props.data,this.props.datanane) + } + } + + + render() { + let {data}=this.props; + + return ( +
    + +
    +
    + + + + +
    + + ) + } +} + +export default Colleagechart; diff --git a/public/react/src/college/colleagechart/Colleagechartzu.js b/public/react/src/college/colleagechart/Colleagechartzu.js new file mode 100644 index 000000000..5c0269700 --- /dev/null +++ b/public/react/src/college/colleagechart/Colleagechartzu.js @@ -0,0 +1,149 @@ +import React, {Component} from "react"; +import {WordsBtn} from 'educoder'; +import {Table} from "antd"; +import {Link,Switch,Route,Redirect} from 'react-router-dom'; +const echarts = require('echarts'); + + + +function startechart(names, values){ + var effChart = echarts.init(document.getElementById('shixun_skill_charts')); + + var Color = ['#962e66', '#623363', '#CCCCCC', '#9A9A9A', '#FF8080', '#FF80C2', '#B980FF', '#80B9FF', '#6FE9FF', '#4DE8B4', '#F8EF63', '#FFB967']; + + var option = { + backgroundColor: '#fff', + grid: { + left: '3%', + right: '8%', + bottom: '15%', + containLabel: true + }, + + tooltip: { + show: "true", + trigger: 'item', + formatter: '{c0}', + backgroundColor: 'rgba(0,0,0,0.7)', // 背景 + padding: [8, 10], //内边距 + extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影 + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + xAxis: { + type: 'value', + axisTick: { + show: false + }, + axisLine: { + show: true, + lineStyle: { + color: '#CCCCCC' + } + }, + splitLine: { + show: false, + lineStyle: { + color: '#CCCCCC' + } + }, + axisLabel: { + textStyle: { + color: '#656565', + fontWeight: 'normal', + fontSize: '12' + }, + formatter: '{value}' + } + }, + yAxis: { + type: 'category', + axisLine: { + lineStyle: { + color: '#cccccc' + } + }, + splitLine: { + show: false + }, + axisTick: { + show: false + }, + splitArea: { + show: false + }, + axisLabel: { + inside: false, + textStyle: { + color: '#656565', + fontWeight: 'normal', + fontSize: '12' + } + }, + data: names + }, + series: [{ + name: '', + type: 'bar', + itemStyle: { + normal: { + show: true, + color: function(params) { + return Color[params.dataIndex] + }, + barBorderRadius: 50, + borderWidth: 0, + borderColor: '#333' + } + }, + barGap: '0%', + barCategoryGap: '50%', + data: values + } + + ] + }; + effChart.setOption(option); +} +class Colleagechartzu extends Component { + + constructor(props) { + super(props); + this.state = { + } + } + + componentDidMount() { + startechart(this.props.data,this.props.datavule) + } + + + componentDidUpdate = (prevProps) => { + if (prevProps.data!= this.props.data) { + startechart(this.props.data,this.props.datavule) + } + } + + + render() { + let {data}=this.props; + + return ( +
    + +
    +
    + + + + +
    + + ) + } +} + +export default Colleagechartzu; diff --git a/public/react/src/college/colleagecss/colleage.css b/public/react/src/college/colleagecss/colleage.css new file mode 100644 index 000000000..801b86603 --- /dev/null +++ b/public/react/src/college/colleagecss/colleage.css @@ -0,0 +1,213 @@ +.yslstatistic-header { + width: 100%; + height: 240px; + background-image: url('/images/educoder/statistics.jpg'); + background-size: 100% 100%; +} +.yslborder{ + border: 1px solid; +} +.yslstatistic-header-title{ + flex: 1; + display: flex; + align-items: center; + color: #4CACFF; + font-size: 32px; +} +.yslstatistic-header-content{ + width: 100%; + display: flex; + justify-content: space-around; +} +.yslstatistic-header-item{ + margin-bottom: 22px; + display: flex; + flex-direction: column; + align-items: center; + color: #fff; +} +.yslstatistic-header-item-label{ + color: #989898; +} + +.yslstatistic-base-item-label{ + width: 217px; + text-align: center; + font-size: 16px; + height: 48px; + line-height: 48px; + color: #686868; + background: #F5F5F5; + border-top: 1px solid #EBEBEB; +} +.yslstatistic-base-item-labels{ + width: 217px; + text-align: center; + height: 100px; + line-height: 100px; + background: #ffffff; + border-top: 1px solid #EBEBEB; + border-bottom: 1px solid #EBEBEB; +} +.yslstatistic-base-item-labelsp{ + color: #000000; + font-size: 24px; +} +.yslstatistic-base-item-labelsspan{ + color: #000000; + margin-left: 5px; + font-size: 16px; +} +.jibenshiyong100{ + width: 100%; +} + +.yslstatistic-header-item-content{ + font-size: 24px; +} +/* 中间居中 */ +.intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +/* 简单居中 */ +.intermediatecenterysls{ + display: flex; + align-items: center; +} +.spacearound{ + display: flex; + justify-content: space-around; + +} +.spacebetween{ + display: flex; + justify-content: space-between; +} +/* 头顶部居中 */ +.topcenter{ + display: -webkit-flex; + flex-direction: column; + align-items: center; + +} + + +/* x轴正方向排序 */ +/* 一 二 三 四 五 六 七 八 */ +.sortinxdirection{ + display: flex; + flex-direction:row; +} +/* x轴反方向排序 */ +/* 八 七 六 五 四 三 二 一 */ +.xaxisreverseorder{ + display: flex; + flex-direction:row-reverse; +} +/* 垂直布局 正方向*/ +/* 一 + 二 + 三 + 四 + 五 + 六 + 七 + 八 */ +.verticallayout{ + display: flex; + flex-direction:column; +} +/* 垂直布局 反方向*/ +.reversedirection{ + display: flex; + flex-direction:column-reverse; +} + +.h4{ + font-size: 1.5rem; + font-weight: 500 !important; +} +.ysllinjibenshiyong{ + font-weight: 500; + line-height: 1.2; + padding: 2rem 1.25rem; + border-bottom: unset; + background:#fff; +} +.linjibenshiyong{ + font-weight: 500; + line-height: 1.2; + padding: 2rem 1.25rem; + border-bottom: unset; + background:#fff; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.yslslinjibenshiyong{ + font-weight: 500; + line-height: 1.2; + border-bottom: unset; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.yinyin{ + background: #fff; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.edu-back-eeee{ + background:#EEEEEE !important; +} +.mt-4{ + margin-top: 1.5rem !important; +} + +.statistic-label{ + padding: 2rem 1.25rem; + font-size: 1.5rem; + font-weight: 400 !important; +} +.mb50{ + padding-bottom: 50px !important; +} +.mt40{ + margin-top: 40px; +} +.mb80{ + margin-bottom: 80px; +} +.task-hide{overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} +a:hover{ + color:#0056b3; +} +.color-blue{ + color: #4CACFF; +} + +.color-huang{ + color:#ffc107 !important +} +.maxnamewidth105{ + max-width: 105px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.maxnamewidth247{ + max-width: 247px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.maxnamewidth340{ + max-width: 340px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} From 893c4840f77c29288819cd6f2e5ed51ec9f8525b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Thu, 19 Dec 2019 18:55:19 +0800 Subject: [PATCH 21/61] =?UTF-8?q?=E5=AE=9E=E8=AE=AD=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/TPMBanner.js | 16 ++++++---------- public/react/src/modules/tpm/TPMIndex.js | 8 +------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index 141bd87d9..77b82c6c6 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -58,15 +58,6 @@ class TPMBanner extends Component { } } - // star_info:[0, 0, 0, 0, 0, 0], - // star_infos:[0, 0, 0, 0, 0, 0], - // shixunsDetails:{}, - // shixunId: undefined, - // componentWillReceiveProps(newProps, newContext){ - // this.setState({ - // shixunsDetails: newProps.shixunsDetails - // }); - // } IEVersion = () => { var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 @@ -141,8 +132,11 @@ class TPMBanner extends Component { }) } } + } } + + componentDidMount() { let thiisie = this.IEVersion(); @@ -155,6 +149,7 @@ class TPMBanner extends Component { isIE: false }) } + } /* @@ -784,7 +779,8 @@ class TPMBanner extends Component { }; // // console.log(this.props.shixunsDetails&&this.props.shixunsDetails.is_jupyter) - + console.log(this.props) + console.log(this.state) return ( shixunsDetails === undefined ? "" : diff --git a/public/react/src/modules/tpm/TPMIndex.js b/public/react/src/modules/tpm/TPMIndex.js index e032bb91f..c44d8ce51 100644 --- a/public/react/src/modules/tpm/TPMIndex.js +++ b/public/react/src/modules/tpm/TPMIndex.js @@ -207,6 +207,7 @@ class TPMIndex extends Component { propaedeutics:response.data.propaedeutics, status: response.data.shixun_status, secret_repository: response.data.secret_repository, + public:response.data.public, is_jupyter:response.data.is_jupyter=== undefined||response.data.is_jupyter===null?false:response.data.is_jupyter, }); @@ -295,10 +296,6 @@ class TPMIndex extends Component { // this.getnavdatas() } - // componentDidUpdate=()=>{ - // this.getnavdatas() - // } - setLoadingContent = (isLoadingContent) => { this.setState({ loadingContent: isLoadingContent }) } @@ -307,9 +304,6 @@ class TPMIndex extends Component { getnavdatas=()=>{ let selectedKeys; const {location} = this.props; - - console.log(location.pathname) - if(location.pathname.indexOf('/challenges')!=-1){ selectedKeys="1" }else if(location.pathname.indexOf('/propaedeutics')!=-1){ From 8fb90e6e20dca4f7d4176d5202c4f564045c2a6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Thu, 19 Dec 2019 18:56:56 +0800 Subject: [PATCH 22/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/App.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/public/react/src/App.js b/public/react/src/App.js index 07c68e5e0..07fd13e49 100644 --- a/public/react/src/App.js +++ b/public/react/src/App.js @@ -71,11 +71,7 @@ const Otherlogin=Loadable({ loader: () => import('./modules/login/Otherlogin'), loading: Loading, }) -// 学院统计 -const College = Loadable({ - loader: () => import('./college/College'), - loading: Loading -}) + const Otherloginstart=Loadable({ loader: () => import('./modules/login/Otherloginstart'), From ae415cf38249725235db370da0eb3d593ad1d7ce Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 19 Dec 2019 19:29:54 +0800 Subject: [PATCH 23/61] 1 --- app/controllers/hacks_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb index cab952a04..dbddd9105 100644 --- a/app/controllers/hacks_controller.rb +++ b/app/controllers/hacks_controller.rb @@ -12,6 +12,7 @@ class HacksController < ApplicationController user_hack = @hack.hack_user_lastest_codes.mine(current_user.id) identifier = if user_hack.present? + logger.info("#####user_hack_id:#{user_hack.id}") user_hack.identifier else user_identifier = generate_identifier HackUserLastestCode, 12 From 992045a5cffc9571f7d311d2b86cd56cd2ef607c Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 19 Dec 2019 19:34:54 +0800 Subject: [PATCH 24/61] 1 --- app/models/hack_user_lastest_code.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/models/hack_user_lastest_code.rb b/app/models/hack_user_lastest_code.rb index b4a707603..830f16dde 100644 --- a/app/models/hack_user_lastest_code.rb +++ b/app/models/hack_user_lastest_code.rb @@ -8,7 +8,7 @@ class HackUserLastestCode < ApplicationRecord belongs_to :user has_many :hack_user_codes, dependent: :destroy has_one :hack_user_debug - scope :mine, ->(author_id){ find_by(user_id: author_id) } + scope :mine, ->(author_id){ where(user_id: author_id).first } scope :mine_hack, ->(author_id){ where(user_id: author_id) } scope :passed, -> {where(status: 1)} From 0074b6d183e5b3a293f341b9ad73196bf79e947e Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 19 Dec 2019 19:36:18 +0800 Subject: [PATCH 25/61] 1 --- app/controllers/hacks_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb index dbddd9105..a2ca85f34 100644 --- a/app/controllers/hacks_controller.rb +++ b/app/controllers/hacks_controller.rb @@ -10,6 +10,7 @@ class HacksController < ApplicationController # 未发布的编程题,只能作者、或管理员访问 start_hack_auth user_hack = @hack.hack_user_lastest_codes.mine(current_user.id) + logger.info("#user_hack: #{user_hack}") identifier = if user_hack.present? logger.info("#####user_hack_id:#{user_hack.id}") From a0deef9d09a42d4388a0ba8340e43b5bf2156603 Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 19 Dec 2019 19:38:05 +0800 Subject: [PATCH 26/61] 1 --- app/controllers/hacks_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/hacks_controller.rb b/app/controllers/hacks_controller.rb index a2ca85f34..b7f6a30a2 100644 --- a/app/controllers/hacks_controller.rb +++ b/app/controllers/hacks_controller.rb @@ -9,7 +9,7 @@ class HacksController < ApplicationController def start # 未发布的编程题,只能作者、或管理员访问 start_hack_auth - user_hack = @hack.hack_user_lastest_codes.mine(current_user.id) + user_hack = @hack.hack_user_lastest_codes.where(user_id: current_user.id).first logger.info("#user_hack: #{user_hack}") identifier = if user_hack.present? From b7db555654fa0f7122c23e950c4396ca0e90cac8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Thu, 19 Dec 2019 20:08:59 +0800 Subject: [PATCH 27/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tpm/shixunchild/Challenges/Challenges.js | 23 +++++++++-- .../Challenges/Challengesjupyter.js | 39 ++++++++++++++----- .../Collaborators/Collaborators.js | 2 +- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js index e7b7ef261..0480c208a 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js @@ -53,6 +53,13 @@ class Challenges extends Component { ChallengesDataList: response.data, sumidtype: false, }); + + if(response.data.description=== ""||response.data.description===null||response.data.description===undefined){ + this.setState({ + isopentitletype:"Less", + }) + } + } } }).catch((error) => { @@ -72,7 +79,7 @@ class Challenges extends Component { let box=document.getElementById("shixunchallengesid"); if(box){ boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh<260){ + if(boxoffsetHeigh<300){ this.setState({ isopentitletype:"Less", boxoffsetHeigh:boxoffsetHeigh @@ -338,6 +345,7 @@ class Challenges extends Component { } let id = this.props.match.params.shixunId; const antIcon = ; + return ( {AccountProfiletype===true? -

    + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined? +

    + {this.props.identity < 5?:} +

    暂时还没有相关数据哦!

    +
    + :

    {ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":

    } -

    +

    } diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index fcdbed408..c8cbc2fbc 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { Link } from "react-router-dom"; -import { markdownToHTML, configShareForCustom} from 'educoder' +import { markdownToHTML, configShareForCustom,getImageUrl} from 'educoder' import { Divider, Tooltip } from 'antd'; import LoadingSpin from '../../../../common/LoadingSpin'; import 'antd/lib/pagination/style/index.css'; @@ -23,7 +23,8 @@ class Challengesjupyter extends Component { booljupyterurls:false, loading:false, boxoffsetHeigh:0, - opentitletype:true + opentitletype:true, + isopentitletype:"Less", } } @@ -41,6 +42,11 @@ class Challengesjupyter extends Component { ChallengesDataList: response.data, sumidtype: false, }); + if(response.data.description=== ""||response.data.description===null||response.data.description===undefined){ + this.setState({ + isopentitletype:"Less", + }) + } } } }).catch((error) => { @@ -55,13 +61,15 @@ class Challengesjupyter extends Component { let box=document.getElementById("shixunchallengesid"); if(box){ boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh<260){ + if(boxoffsetHeigh<300){ this.setState({ - opentitletype:false, + isopentitletype:"Less", boxoffsetHeigh:boxoffsetHeigh }) }else{ this.setState({ + isopentitletype:"greater", + opentitletype:true, boxoffsetHeigh:boxoffsetHeigh }) } @@ -229,7 +237,7 @@ class Challengesjupyter extends Component { { ` #shixunchallengesid{ - max-height: 260px; + max-height: 300px; overflow: hidden; } ` @@ -239,9 +247,22 @@ class Challengesjupyter extends Component {

    - {ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"": -

    - } + {/*{ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":*/} + {/*
    */} + {/*}*/} + + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined? +
    + {this.props.identity < 5?:} +

    暂时还没有相关数据哦!

    +
    + :

    + {ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"": +

    + } +

    }

    { booljupyterurls===true? @@ -259,7 +280,7 @@ class Challengesjupyter extends Component { }
    - {this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> + {this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 阅读全文 :this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 收起全文 diff --git a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js index 17b083cf7..9799d060c 100644 --- a/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js +++ b/public/react/src/modules/tpm/shixunchild/Collaborators/Collaborators.js @@ -656,7 +656,7 @@ class Collaborators extends Component { 用户头像 -

    {item.user.shixun_manager === true ? "创建者" : ""}

    From e6a0239c2970eb3c31c830ed0de4bbe14aa84a0c Mon Sep 17 00:00:00 2001 From: tangjiang <465264938@qq.com> Date: Thu, 19 Dec 2019 20:11:12 +0800 Subject: [PATCH 28/61] update oj --- .../components/controlSetting/index.js | 20 ++++++++++++------- .../components/monacoSetting/index.js | 4 ++-- .../components/myMonacoEditor/index.js | 4 ++-- .../newOrEditTask/rightpane/index.scss | 3 ++- .../modules/developer/studentStudy/index.js | 9 +++++++-- .../developer/studentStudy/rightpane/index.js | 9 +++++++-- public/react/src/redux/actions/common.js | 4 ++-- public/react/src/redux/actions/index.js | 4 ++-- .../src/redux/reducers/ojForUserReducer.js | 9 +++++++-- 9 files changed, 44 insertions(+), 22 deletions(-) diff --git a/public/react/src/modules/developer/components/controlSetting/index.js b/public/react/src/modules/developer/components/controlSetting/index.js index b5c9222ef..1d4d7834c 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.js +++ b/public/react/src/modules/developer/components/controlSetting/index.js @@ -4,10 +4,10 @@ * @Github: * @Date: 2019-11-27 16:02:36 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 10:47:44 + * @LastEditTime: 2019-12-19 19:47:32 */ import './index.scss'; -import React, { useState, useRef } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { Tabs, Button, Icon } from 'antd'; import { connect } from 'react-redux'; import InitTabCtx from '../initTabCtx'; @@ -23,10 +23,11 @@ const ControlSetting = (props) => { submitLoading, identifier, excuteState, + showOrHideControl, commitRecordDetail, changeLoadingState, changeSubmitLoadingStatus, - showOrHideControl, + changeShowOrHideControl, // debuggerCode, // startDebuggerCode, // 外部存入 onDebuggerCode, @@ -44,10 +45,14 @@ const ControlSetting = (props) => { setDefaultActiveKey(key); } + useEffect(() => { + setShowTextResult(props.showOrHideControl); + }, [props]); + // 显示/隐藏tab const handleShowControl = () => { setShowTextResult(!showTextResult); - showOrHideControl(!showTextResult); + changeShowOrHideControl(!showTextResult); } // 调试代码 @@ -55,7 +60,7 @@ const ControlSetting = (props) => { // console.log(formRef.current.handleTestCodeFormSubmit); // 调出控制台界面 setShowTextResult(true); - showOrHideControl(true); + changeShowOrHideControl(true); formRef.current.handleTestCodeFormSubmit(() => { setDefaultActiveKey('2'); }); @@ -131,19 +136,20 @@ const ControlSetting = (props) => { const mapStateToProps = (state) => { const {commonReducer, ojForUserReducer} = state; - const {loading, excuteState, submitLoading } = commonReducer; + const {loading, excuteState, submitLoading, showOrHideControl } = commonReducer; const { commitRecordDetail } = ojForUserReducer; return { loading, submitLoading, excuteState, + showOrHideControl, // identifier: user_program_identifier, commitRecordDetail // 提交详情 }; }; // changeSubmitLoadingStatus const mapDispatchToProps = (dispatch) => ({ - showOrHideControl: (flag) => dispatch(actions.showOrHideControl(flag)), + changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)), changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag)), changeSubmitLoadingStatus: (flag) => dispatch(actions.changeSubmitLoadingStatus(flag)), debuggerCode: (identifier, values) => dispatch(actions.debuggerCode(identifier, values)), diff --git a/public/react/src/modules/developer/components/monacoSetting/index.js b/public/react/src/modules/developer/components/monacoSetting/index.js index c1215f9af..669439577 100644 --- a/public/react/src/modules/developer/components/monacoSetting/index.js +++ b/public/react/src/modules/developer/components/monacoSetting/index.js @@ -4,11 +4,11 @@ * @Github: * @Date: 2019-11-25 17:50:33 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 15:26:46 + * @LastEditTime: 2019-12-19 19:32:08 */ import React, { useState } from 'react'; import { fromStore, toStore } from 'educoder'; -import { Icon } from 'antd'; +// import { Icon } from 'antd'; // import { Select } from 'antd'; // const { Option } = Select; const SettingDrawer = (props) => { diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.js b/public/react/src/modules/developer/components/myMonacoEditor/index.js index df3c2b5e3..948d5a4f5 100644 --- a/public/react/src/modules/developer/components/myMonacoEditor/index.js +++ b/public/react/src/modules/developer/components/myMonacoEditor/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 15:02:52 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 17:52:31 + * @LastEditTime: 2019-12-19 19:36:24 */ import './index.scss'; import React, { useState, useRef, useEffect } from 'react'; @@ -146,7 +146,7 @@ function MyMonacoEditor (props, ref) { > - {renderRestore} + {renderRestore} { + changeShowOrHideControl(false); props.saveEditorCodeForDetail(); props.history.push(`/problems/${_hack_id}/edit`); } // 处理退出 const handleClickQuit = () => { + // 将控制台关闭 + changeShowOrHideControl(false); props.saveEditorCodeForDetail(); props.history.push('/problems'); } @@ -164,6 +168,7 @@ const mapDispatchToProps = (dispatch) => ({ saveEditorCodeForDetail: (code) => dispatch(actions.saveEditorCodeForDetail(code)), // 恢复初始代码 restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)), + changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)) }); export default withRouter(connect( diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js index 5661ea32e..af46d0aef 100644 --- a/public/react/src/modules/developer/studentStudy/rightpane/index.js +++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 14:59:51 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 15:06:49 + * @LastEditTime: 2019-12-19 19:13:05 */ import React, { useState, useEffect } from 'react'; import {connect} from 'react-redux'; @@ -32,6 +32,7 @@ const RightPane = (props) => { const [editorCode, setEditorCode] = useState(''); + let initFlag = true; useEffect(() => { if (editor_code) { setEditorCode(editor_code); @@ -51,8 +52,12 @@ const RightPane = (props) => { // 代码块内容变化时 const handleCodeChange = (code) => { // 保存用户提交的代码块 - // console.log(code); setEditorCode(code); + // 第一次回填代码内容时不更新; + if (initFlag) { + initFlag = false; + return; + } if (!timer) { timer = setInterval(() => { clearInterval(timer); diff --git a/public/react/src/redux/actions/common.js b/public/react/src/redux/actions/common.js index bcd451481..b95d2d2bb 100644 --- a/public/react/src/redux/actions/common.js +++ b/public/react/src/redux/actions/common.js @@ -4,12 +4,12 @@ * @Github: * @Date: 2019-11-27 16:30:50 * @LastEditors: tangjiang - * @LastEditTime: 2019-11-28 21:15:34 + * @LastEditTime: 2019-12-19 19:42:10 */ import types from "./actionTypes"; // 切换控制台显示与隐藏 -export const showOrHideControl = (flag) => { +export const changeShowOrHideControl = (flag) => { return { type: types.SHOW_OR_HIDE_CONTROL, payload: flag diff --git a/public/react/src/redux/actions/index.js b/public/react/src/redux/actions/index.js index ad33061ba..b42c4c2b6 100644 --- a/public/react/src/redux/actions/index.js +++ b/public/react/src/redux/actions/index.js @@ -52,7 +52,7 @@ import { } from './ojForUser'; import { - showOrHideControl, + changeShowOrHideControl, changeLoadingState, changeSubmitLoadingStatus, changePublishLoadingStatus, @@ -97,7 +97,7 @@ export default { testCaseOutputChange, debuggerCode, startProgramQuestion, - showOrHideControl, + changeShowOrHideControl, changeLoadingState, getUserCommitRecord, getUserCommitRecordDetail, diff --git a/public/react/src/redux/reducers/ojForUserReducer.js b/public/react/src/redux/reducers/ojForUserReducer.js index 60e7e6fd1..0c7594dd2 100644 --- a/public/react/src/redux/reducers/ojForUserReducer.js +++ b/public/react/src/redux/reducers/ojForUserReducer.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:41:48 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 14:49:03 + * @LastEditTime: 2019-12-19 20:10:39 */ import types from "../actions/actionTypes"; import { Base64 } from 'js-base64'; @@ -38,7 +38,12 @@ const ojForUserReducer = (state = initialState, action) => { const { hack, test_case } = action.payload; const { code }= hack; let tempCode = Base64.decode(code) - let tempDesc = JSON.parse(hack.description); + let tempDesc; + try { + tempDesc = JSON.parse(hack.description); + } catch (error) { + tempDesc = hack.description; + } Object.assign(hack, {code: tempCode, description: tempDesc}); return { ...state, From 1cdd29cfd29e1afac3582e38e4e5a70420a7e89c Mon Sep 17 00:00:00 2001 From: daiao <358551898@qq.com> Date: Thu, 19 Dec 2019 20:20:46 +0800 Subject: [PATCH 29/61] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E5=AD=97=E6=AE=B5?= =?UTF-8?q?=E9=95=BF=E5=BA=A6=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../20191219120819_modify_description_for_hacks.rb | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 db/migrate/20191219120819_modify_description_for_hacks.rb diff --git a/db/migrate/20191219120819_modify_description_for_hacks.rb b/db/migrate/20191219120819_modify_description_for_hacks.rb new file mode 100644 index 000000000..3cc45fd5d --- /dev/null +++ b/db/migrate/20191219120819_modify_description_for_hacks.rb @@ -0,0 +1,10 @@ +class ModifyDescriptionForHacks < ActiveRecord::Migration[5.2] + def change + change_column :hacks, :description, :longtext + change_column :hack_codes, :code, :longtext + change_column :hack_user_lastest_codes, :code, :longtext + change_column :hack_user_codes, :code, :longtext + change_column :hack_user_debugs, :code, :longtext + + end +end From e176abc4bbc759ad634aa409ec03f7f60ed01555 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Thu, 19 Dec 2019 20:42:41 +0800 Subject: [PATCH 30/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/tpm/shixunchild/Challenges/Challenges.js | 4 ++-- .../modules/tpm/shixunchild/Challenges/Challengesjupyter.js | 6 +++--- .../modules/tpm/shixunchild/Collaborators/Collaborators.js | 3 ++- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js index 0480c208a..8890efbd2 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js @@ -407,10 +407,10 @@ class Challenges extends Component { 简介 {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status < 3 ? - +
    {/**/} 编辑 - :""} + :""} {this.props.user && this.props.user.main_site === true ? this.props.identity < 5?实训制作指南 : "":""} diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index c8cbc2fbc..e04ad17c9 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -227,10 +227,10 @@ class Challengesjupyter extends Component {
    简介 - + 编辑 - +
    {this.state.opentitletype===true? +
    + {courses === undefined ? "" :
    } + + + { + course_count>=11? +
    +
    + +
    + +
    + :"" + } + + + } + + + + + +
    +
    +

    + 教师排名 +

    + { + teachers===null? +
    + +
    + + : + JSON.stringify(teachers) === "[]" ? + + + + : +
    + +
    + {teachers === undefined ? "" :
    } + + + } + + + + {/*
    */} + {/*
    */} + {/* */} + {/*
    */} + + {/*
    */} + + +
    +

    + 在线实训情况 +

    + { + shixun_chart_data===null? +
    + +
    + + : + JSON.stringify(shixun_chart_data) === "[]" ? + + + + : + + + + } + +
    +
    + + + +
    +
    +

    + 学生排名 +

    + { + students === null ? +
    + +
    + + : + JSON.stringify(students) === "[]" ? + + + + : +
    + +
    + {students === undefined ? "" :
    } + + + } + {/*
    */} + {/*
    */} + {/* */} + {/*
    */} + + {/*
    */} + + + + +
    + +
    +

    + 最热评测 +

    + { + studentionsnames===null? +
    + +
    + + : + JSON.stringify(studentionsnames) === "[]" ? + + + + : + + + + } + + +
    +
    + + + ) + } +} +export default SnackbarHOC() (TPMIndexHOC ( College )); + + diff --git a/public/react/src/college/colleagechart/Colleagechart.js b/public/react/src/college/colleagechart/Colleagechart.js new file mode 100644 index 000000000..fca01280a --- /dev/null +++ b/public/react/src/college/colleagechart/Colleagechart.js @@ -0,0 +1,84 @@ +import React, {Component} from "react"; +import {WordsBtn} from 'educoder'; +import {Table} from "antd"; +import {Link,Switch,Route,Redirect} from 'react-router-dom'; +const echarts = require('echarts'); + + + +function startechart(data,datanane){ + var effChart = echarts.init(document.getElementById('shixun_skill_chart')); + + var option = { + + tooltip : { + trigger: 'item', + formatter: "{d}%
    " + }, + legend: { + // orient: 'vertical', + // top: 'middle', + bottom: 50, + left: 'center', + data: datanane + }, + series : [ + { + type: 'pie', + radius : '65%', + center: ['50%', '35%'], + selectedMode: 'single', + data:data, + itemStyle: { + emphasis: { + shadowBlur: 10, + shadowOffsetX: 0, + shadowColor: 'rgba(0, 0, 0, 0.5)' + } + } + } + ] + }; + effChart.setOption(option); +} +class Colleagechart extends Component { + + constructor(props) { + super(props); + this.state = { + } + } + + componentDidMount() { + startechart(this.props.data,this.props.datanane) + } + + + componentDidUpdate = (prevProps) => { + if (prevProps.data!= this.props.data) { + startechart(this.props.data,this.props.datanane) + } + } + + + render() { + let {data}=this.props; + + return ( +
    + +
    +
    + + + + +
    + + ) + } +} + +export default Colleagechart; diff --git a/public/react/src/college/colleagechart/Colleagechartzu.js b/public/react/src/college/colleagechart/Colleagechartzu.js new file mode 100644 index 000000000..5c0269700 --- /dev/null +++ b/public/react/src/college/colleagechart/Colleagechartzu.js @@ -0,0 +1,149 @@ +import React, {Component} from "react"; +import {WordsBtn} from 'educoder'; +import {Table} from "antd"; +import {Link,Switch,Route,Redirect} from 'react-router-dom'; +const echarts = require('echarts'); + + + +function startechart(names, values){ + var effChart = echarts.init(document.getElementById('shixun_skill_charts')); + + var Color = ['#962e66', '#623363', '#CCCCCC', '#9A9A9A', '#FF8080', '#FF80C2', '#B980FF', '#80B9FF', '#6FE9FF', '#4DE8B4', '#F8EF63', '#FFB967']; + + var option = { + backgroundColor: '#fff', + grid: { + left: '3%', + right: '8%', + bottom: '15%', + containLabel: true + }, + + tooltip: { + show: "true", + trigger: 'item', + formatter: '{c0}', + backgroundColor: 'rgba(0,0,0,0.7)', // 背景 + padding: [8, 10], //内边距 + extraCssText: 'box-shadow: 0 0 3px rgba(255, 255, 255, 0.4);', //添加阴影 + axisPointer: { // 坐标轴指示器,坐标轴触发有效 + type: 'shadow' // 默认为直线,可选为:'line' | 'shadow' + } + }, + xAxis: { + type: 'value', + axisTick: { + show: false + }, + axisLine: { + show: true, + lineStyle: { + color: '#CCCCCC' + } + }, + splitLine: { + show: false, + lineStyle: { + color: '#CCCCCC' + } + }, + axisLabel: { + textStyle: { + color: '#656565', + fontWeight: 'normal', + fontSize: '12' + }, + formatter: '{value}' + } + }, + yAxis: { + type: 'category', + axisLine: { + lineStyle: { + color: '#cccccc' + } + }, + splitLine: { + show: false + }, + axisTick: { + show: false + }, + splitArea: { + show: false + }, + axisLabel: { + inside: false, + textStyle: { + color: '#656565', + fontWeight: 'normal', + fontSize: '12' + } + }, + data: names + }, + series: [{ + name: '', + type: 'bar', + itemStyle: { + normal: { + show: true, + color: function(params) { + return Color[params.dataIndex] + }, + barBorderRadius: 50, + borderWidth: 0, + borderColor: '#333' + } + }, + barGap: '0%', + barCategoryGap: '50%', + data: values + } + + ] + }; + effChart.setOption(option); +} +class Colleagechartzu extends Component { + + constructor(props) { + super(props); + this.state = { + } + } + + componentDidMount() { + startechart(this.props.data,this.props.datavule) + } + + + componentDidUpdate = (prevProps) => { + if (prevProps.data!= this.props.data) { + startechart(this.props.data,this.props.datavule) + } + } + + + render() { + let {data}=this.props; + + return ( +
    + +
    +
    + + + + +
    + + ) + } +} + +export default Colleagechartzu; diff --git a/public/react/src/college/colleagecss/colleage.css b/public/react/src/college/colleagecss/colleage.css new file mode 100644 index 000000000..801b86603 --- /dev/null +++ b/public/react/src/college/colleagecss/colleage.css @@ -0,0 +1,213 @@ +.yslstatistic-header { + width: 100%; + height: 240px; + background-image: url('/images/educoder/statistics.jpg'); + background-size: 100% 100%; +} +.yslborder{ + border: 1px solid; +} +.yslstatistic-header-title{ + flex: 1; + display: flex; + align-items: center; + color: #4CACFF; + font-size: 32px; +} +.yslstatistic-header-content{ + width: 100%; + display: flex; + justify-content: space-around; +} +.yslstatistic-header-item{ + margin-bottom: 22px; + display: flex; + flex-direction: column; + align-items: center; + color: #fff; +} +.yslstatistic-header-item-label{ + color: #989898; +} + +.yslstatistic-base-item-label{ + width: 217px; + text-align: center; + font-size: 16px; + height: 48px; + line-height: 48px; + color: #686868; + background: #F5F5F5; + border-top: 1px solid #EBEBEB; +} +.yslstatistic-base-item-labels{ + width: 217px; + text-align: center; + height: 100px; + line-height: 100px; + background: #ffffff; + border-top: 1px solid #EBEBEB; + border-bottom: 1px solid #EBEBEB; +} +.yslstatistic-base-item-labelsp{ + color: #000000; + font-size: 24px; +} +.yslstatistic-base-item-labelsspan{ + color: #000000; + margin-left: 5px; + font-size: 16px; +} +.jibenshiyong100{ + width: 100%; +} + +.yslstatistic-header-item-content{ + font-size: 24px; +} +/* 中间居中 */ +.intermediatecenter{ + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; +} +/* 简单居中 */ +.intermediatecenterysls{ + display: flex; + align-items: center; +} +.spacearound{ + display: flex; + justify-content: space-around; + +} +.spacebetween{ + display: flex; + justify-content: space-between; +} +/* 头顶部居中 */ +.topcenter{ + display: -webkit-flex; + flex-direction: column; + align-items: center; + +} + + +/* x轴正方向排序 */ +/* 一 二 三 四 五 六 七 八 */ +.sortinxdirection{ + display: flex; + flex-direction:row; +} +/* x轴反方向排序 */ +/* 八 七 六 五 四 三 二 一 */ +.xaxisreverseorder{ + display: flex; + flex-direction:row-reverse; +} +/* 垂直布局 正方向*/ +/* 一 + 二 + 三 + 四 + 五 + 六 + 七 + 八 */ +.verticallayout{ + display: flex; + flex-direction:column; +} +/* 垂直布局 反方向*/ +.reversedirection{ + display: flex; + flex-direction:column-reverse; +} + +.h4{ + font-size: 1.5rem; + font-weight: 500 !important; +} +.ysllinjibenshiyong{ + font-weight: 500; + line-height: 1.2; + padding: 2rem 1.25rem; + border-bottom: unset; + background:#fff; +} +.linjibenshiyong{ + font-weight: 500; + line-height: 1.2; + padding: 2rem 1.25rem; + border-bottom: unset; + background:#fff; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.yslslinjibenshiyong{ + font-weight: 500; + line-height: 1.2; + border-bottom: unset; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.yinyin{ + background: #fff; + box-shadow:0px 6px 12px 0px rgba(0,0,0,0.1); + border-radius:2px; +} +.edu-back-eeee{ + background:#EEEEEE !important; +} +.mt-4{ + margin-top: 1.5rem !important; +} + +.statistic-label{ + padding: 2rem 1.25rem; + font-size: 1.5rem; + font-weight: 400 !important; +} +.mb50{ + padding-bottom: 50px !important; +} +.mt40{ + margin-top: 40px; +} +.mb80{ + margin-bottom: 80px; +} +.task-hide{overflow:hidden; white-space: nowrap; text-overflow:ellipsis;} +a:hover{ + color:#0056b3; +} +.color-blue{ + color: #4CACFF; +} + +.color-huang{ + color:#ffc107 !important +} +.maxnamewidth105{ + max-width: 105px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.maxnamewidth247{ + max-width: 247px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} +.maxnamewidth340{ + max-width: 340px; + overflow:hidden; + text-overflow:ellipsis; + white-space:nowrap; + cursor: default; +} diff --git a/public/react/src/common/components/comment/CommentForm.js b/public/react/src/common/components/comment/CommentForm.js new file mode 100644 index 000000000..73e36cff9 --- /dev/null +++ b/public/react/src/common/components/comment/CommentForm.js @@ -0,0 +1,116 @@ +/* + * @Description: 评论表单 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:32:55 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 17:51:44 + */ +import React, { useState } from 'react'; +import { Form, Button, Input } from 'antd'; +import QuillForEditor from '../../quillForEditor'; +import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html' +const FormItem = Form.Item; + +function CommentForm (props) { + + const { + commentCtxChagne, + onCancel, + onSubmit, + form + } = props; + + const { getFieldDecorator } = form; + const [ctx, setCtx] = useState(''); + + const options = [ + ['bold', 'italic', 'underline'], + [{header: [1,2,3,false]}], + ['blockquote', 'code-block'], + ['link', 'image'], + ['formula'] + ]; + // const { form: { getFieldDecorator } } = props; + const [showQuill, setShowQuill] = useState(false); + // 点击输入框 + const handleInputClick = () => { + setShowQuill(true); + } + // 取消 + const handleCancle = () => { + setShowQuill(false); + onCancel && onCancel(); + } + + // 编辑器内容变化时 + const handleContentChange = (content) => { + setCtx(content); + try { + const _html = new QuillDeltaToHtmlConverter(content.ops, {}).convert(); + // props.form.setFieldsValue({'comment': _html.replace(/<\/?[^>]*>/g, '')}); + props.form.setFieldsValue({'comment': _html}); + } catch (error) { + console.log(error); + } + } + // 发送 + const handleSubmit = (e) => { + e.preventDefault(); + props.form.validateFields((err, values) => { + if (!err) { + setShowQuill(false); + const content = ctx; + props.form.setFieldsValue({'comment': ''}); + setCtx(''); + console.log(content); + onSubmit && onSubmit(content); + } + }); + } + return ( + + + { + getFieldDecorator('comment', { + rules: [ + { required: true, message: '评论内容不能为空'} + ], + })( + + ) + } + + + + + + + + + ); +} + +export default Form.create()(CommentForm); diff --git a/public/react/src/common/components/comment/CommentIcon.js b/public/react/src/common/components/comment/CommentIcon.js new file mode 100644 index 000000000..5440e2579 --- /dev/null +++ b/public/react/src/common/components/comment/CommentIcon.js @@ -0,0 +1,32 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-18 10:49:46 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 11:39:23 + */ +import './index.scss'; +import React from 'react'; +import { Icon } from 'antd'; +function CommentIcon ({ + type, // 图标类型 + count, // 评论数 + iconClick, + ...props +}) { + + // 点击图标 + const handleSpanClick = () => { + iconClick && iconClick(); + } + + return ( + + + { count } + + ) +} + +export default CommentIcon; diff --git a/public/react/src/common/components/comment/CommentItem.js b/public/react/src/common/components/comment/CommentItem.js new file mode 100644 index 000000000..19da645f5 --- /dev/null +++ b/public/react/src/common/components/comment/CommentItem.js @@ -0,0 +1,165 @@ +/* + * @Description: 评论单列 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:35:17 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-19 18:02:28 + */ +import './index.scss'; +import React, { useState } from 'react'; +import CommentIcon from './CommentIcon'; +import { getImageUrl, CNotificationHOC } from 'educoder' +import { Icon } from 'antd'; +import moment from 'moment'; +// import QuillForEditor from '../../quillForEditor'; +import CommentForm from './CommentForm'; + +// import {ModalConfirm} from '../ModalConfirm'; +function CommentItem ({ + options, + confirm +}) { + // 显示评论输入框 + const [showQuill, setShowQuill] = useState(false); + // 加载更多评论内容 + const [showMore, setShowMore] = useState(false); + // 箭头方向 + const [arrow, setArrow] = useState(false); + // 删除评论 + const deleteComment = () => { + console.log('删除评论...'); + confirm({ + title: '提示', + content: (

    确定要删除该条回复吗?

    ), + onOk () { + console.log('点击了删除'); + } + }); + // ModalConfirm('提示', (

    确定要删除该条回复吗?

    ), () => { + // console.log('点击了删除'); + // }); + } + + // 评论头像 + const commentAvatar = (url) => ( + + ); + + // 评论信息 + const commentInfo = () => ( +

    + 用户名 + {moment(new Date(), 'YYYYMMDD HHmmss').fromNow()} + +

    + ); + + // 评论内容 + const commentCtx = (ctx) => ( +

    + 这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容这是评论内容 +

    + ); + + // 加载更多 + const handleOnLoadMore = () => { + if (!arrow) { + // 展开所有 + } else { + // 收起 + } + setArrow(!arrow); + }; + + // 评论追加内容 + const commentAppend = () => { + + return ( +
      +
    • + {commentAvatar()} +
      + {commentInfo()} + {commentCtx()} +
      +
    • +
    • + {commentAvatar()} +
      + {commentInfo()} + {commentCtx()} +
      +
    • +
    • + {commentAvatar()} +
      + {commentInfo()} + {commentCtx()} +
      +
    • + +
    • +

      展开其余23条评论

      +

      + +

      +
    • +
    + ); + }; + // 点击图标 + const handleIconClick = () => {} + + // 点击评论icon + const handleClickMessage = () => { + setShowQuill(true); + } + + // 点击取消 + const handleClickCancel = () => { + setShowQuill(false); + } + + // 点击保存 + const handleClickSubmit = (content) => { + // 保存并关闭 + setShowQuill(false); + console.log('获取保存内容', content); + } + + return ( +
  • + {commentAvatar()} +
    + {commentInfo()} + {commentCtx()} + + {commentAppend()} + +
    + + {/* 回复 */} + + {/* 点赞 */} + +
    + +
    + +
    +
    +
  • + ); +} + +export default CNotificationHOC() (CommentItem); diff --git a/public/react/src/common/components/comment/CommentList.js b/public/react/src/common/components/comment/CommentList.js new file mode 100644 index 000000000..9d8cde87b --- /dev/null +++ b/public/react/src/common/components/comment/CommentList.js @@ -0,0 +1,20 @@ +/* + * @Description: 评论列表页 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:34:00 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 11:48:09 + */ +import './index.scss'; +import React from 'react'; +import CommentItem from './CommentItem'; +function CommentList ({}) { + return ( +
      + +
    + ); +} + +export default CommentList; diff --git a/public/react/src/common/components/comment/index.js b/public/react/src/common/components/comment/index.js new file mode 100644 index 000000000..f0ecf3309 --- /dev/null +++ b/public/react/src/common/components/comment/index.js @@ -0,0 +1,22 @@ +/* + * @Description: 评论组件 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 17:31:33 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 11:47:39 + */ +import React from 'react'; +import CommentForm from './CommentForm'; +import CommentList from './CommentList'; +function Comment (props) { + + return ( + + + + + ); +} + +export default Comment; diff --git a/public/react/src/common/components/comment/index.scss b/public/react/src/common/components/comment/index.scss new file mode 100644 index 000000000..816e6da6c --- /dev/null +++ b/public/react/src/common/components/comment/index.scss @@ -0,0 +1,111 @@ +$bdColor: rgba(244,244,244,1); +$bgColor: rgba(250,250,250,1); +$lh14: 14px; +$lh22: 22px; +$fz14: 14px; +$fz12: 12px; +$ml: 20px; + +.comment_list_wrapper{ + box-sizing: border-box; + border-top: 1px solid $bdColor; + + .comment_item_area{ + display: flex; + padding: 20px 0; + box-sizing: border-box; + border-bottom: 1px solid $bdColor; + .flex-image{ + width: 48px; + height: 48px; + border-radius: 50%; + } + .item-desc{ + flex: 1; + margin-left: $ml; + } + .item-header{ + font-size: $fz14; + line-height: $lh14; + color: #333; + .item-time{ + font-size: $fz12; + line-height: $lh14; + margin-left: $ml; + } + .item-close{ + float: right; + cursor: pointer; + } + } + .item-ctx{ + line-height: $lh22; + font-size: $fz12; + color: #333; + margin-top: 10px; + } + .comment_icon_area{ + display: flex; + justify-content: flex-end; + margin-top: 10px; + + .comment-icon-margin{ + margin-left: 30px; + } + } + + .comment_item_quill{ + margin-top: 20px; + } + } + .comment_icon_count{ + cursor: pointer; + font-size: 12px; + line-height: 1.5; + + .comment_icon{ + color: #333; + } + .comment_count{ + color: #999999; + margin-left: 10px; + transition: color .3s; + } + + &:hover{ + .comment_icon, + .comment_count{ + color: #5091FF; + } + } + } + .comment_item_append_list{ + position: relative; + background-color: $bgColor; + border-radius: 5px; + padding: 0 15px 10px; + margin: 15px 0; + &::before { + position: absolute; + left: 15px; + bottom: 100%; + height: 0; + width: 0; + content: ''; + // border: 5px solid transparent; + border: 10px solid transparent; + border-bottom-color: $bgColor; + } + + .comment_item_loadmore{ + padding-top: 10px; + cursor: pointer; + .loadmore-txt, + .loadmore-icon{ + color: #999; + text-align: center; + font-size: $fz12; + } + } + } +} \ No newline at end of file diff --git a/public/react/src/common/quillForEditor/ImageBlot.js b/public/react/src/common/quillForEditor/ImageBlot.js new file mode 100644 index 000000000..091bd2c1f --- /dev/null +++ b/public/react/src/common/quillForEditor/ImageBlot.js @@ -0,0 +1,54 @@ +/* + * @Description: 重写图片 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-16 15:50:45 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 16:44:48 + */ +import Quill from "quill"; + +const BlockEmbed = Quill.import('blots/block/embed'); + +export default class ImageBlot extends BlockEmbed { + + static create(value) { + + const node = super.create(); + + node.setAttribute('alt', value.alt); + node.setAttribute('src', value.url); + + if (value.width) { + node.setAttribute('width', value.width); + } + if (value.height) { + node.setAttribute('height', value.height); + } + // 宽度和高度都不存在时, + if (!value.width && !value.height) { + node.setAttribute('display', 'block'); + node.setAttribute('width', '100%'); + } + // 给图片添加点击事件 + node.onclick = () => { + value.onClick && value.onClick(value.url); + } + return node; + } + + static value (node) { + + return { + alt: node.getAttribute('alt'), + url: node.getAttribute('src'), + onclick: node.onclick, + // width: node.width, + // height: node.height, + display: node.getAttribute('display') + }; + } +} + +ImageBlot.blotName = 'image'; +ImageBlot.tagName = 'img'; \ No newline at end of file diff --git a/public/react/src/common/quillForEditor/deepEqual.js b/public/react/src/common/quillForEditor/deepEqual.js new file mode 100644 index 000000000..6f2b276bf --- /dev/null +++ b/public/react/src/common/quillForEditor/deepEqual.js @@ -0,0 +1,47 @@ +function deepEqual (prev, current) { + if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined + return true; + } + + if ((!prev && current) + || (prev && !current) + || (!prev && !current) + ) { + return false; + } + + if (Array.isArray(prev)) { + if (!Array.isArray(current)) return false; + if (prev.length !== current.length) return false; + + for (let i = 0; i < prev.length; i++) { + if (!deepEqual(current[i], prev[i])) { + return false; + } + } + return true; + } + + if (typeof current === 'object') { + if (typeof prev !== 'object') return false; + const prevKeys = Object.keys(prev); + const curKeys = Object.keys(current); + + if (prevKeys.length !== curKeys.length) return false; + + prevKeys.sort(); + curKeys.sort(); + + for (let i = 0; i < prevKeys.length; i++) { + if (prevKeys[i] !== curKeys[i]) return false; + const key = prevKeys[i]; + if (!deepEqual(prev[key], current[key])) return false; + } + + return true; + } + + return false; +} + +export default deepEqual; diff --git a/public/react/src/common/quillForEditor/index.js b/public/react/src/common/quillForEditor/index.js new file mode 100644 index 000000000..6e6c01886 --- /dev/null +++ b/public/react/src/common/quillForEditor/index.js @@ -0,0 +1,166 @@ +/* + * @Description: quill 编辑器 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-18 08:49:30 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-19 16:58:50 + */ +import 'quill/dist/quill.core.css'; // 核心样式 +import 'quill/dist/quill.snow.css'; // 有工具栏 +import 'quill/dist/quill.bubble.css'; // 无工具栏 +import 'katex/dist/katex.min.css'; // katex 表达式样式 +import React, { useState, useRef, useEffect } from 'react'; +import Quill from 'quill'; +import katex from 'katex'; +import deepEqual from './deepEqual.js' +import { fetchUploadImage } from '../../services/ojService.js'; +import { getImageUrl } from 'educoder' +import ImageBlot from './ImageBlot'; + +window.Quill = Quill; +window.katex = katex; +Quill.register(ImageBlot); + +function QuillForEditor ({ + placeholder, + readOnly, + options, + value, + imgAttrs = {}, // 指定图片的宽高 + style = {}, + wrapStyle = {}, + showUploadImage, + onContentChange +}) { + // toolbar 默认值 + const defaultConfig = [ + ['bold', 'italic', 'underline'], + [{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表 + [{script: 'sub'}, {script: 'super'}], + [{ 'color': [] }, { 'background': [] }], + [{header: [1,2,3,4,5,false]}], + ['blockquote', 'code-block'], + ['link', 'image', 'video'], + ['formula'], + ['clean'] + ]; + + const editorRef = useRef(null); + // quill 实例 + const [quill, setQuill] = useState(null); + const [selection, setSelection] = useState(null); + + // 文本内容变化时 + const handleOnChange = content => { + // console.log('编辑器内容====》》》》', content); + onContentChange && onContentChange(content); + }; + + const renderOptions = options || defaultConfig; + // quill 配置信息 + const quillOption = { + modules: { + toolbar: renderOptions + }, + readOnly, + placeholder, + theme: readOnly ? 'bubble' : 'snow' + }; + + + useEffect(() => { + const _quill = new Quill(editorRef.current, quillOption); + setQuill(_quill); + + // 处理图片上传功能 + _quill.getModule('toolbar').addHandler('image', (e) => { + const input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/*'); + input.click(); + + input.onchange = async (e) => { + const file = input.files[0]; // 获取文件信息 + const formData = new FormData(); + formData.append('file', file); + + const range = _quill.getSelection(true); + let fileUrl = ''; // 保存上传成功后图片的url + // 上传文件 + const result = await fetchUploadImage(formData); + // 获取上传图片的url + if (result.data && result.data.id) { + fileUrl = getImageUrl(`api/attachments/${result.data.id}`); + } + // 根据id获取文件路径 + const { width, height } = imgAttrs; + // console.log('上传图片的url:', fileUrl); + if (fileUrl) { + _quill.insertEmbed(range.index, 'image', { + url: fileUrl, + alt: '图片信息', + onClick: showUploadImage, + width, + height + }); + } + } + }); + }, []); + + // 设置值 + useEffect(() => { + if (!quill) return + const previous = quill.getContents() + const current = value + + if (!deepEqual(previous, current)) { + setSelection(quill.getSelection()) + if (typeof value === 'string') { + quill.clipboard.dangerouslyPasteHTML(value, 'api') + } else { + quill.setContents(value) + } + } + }, [quill, value, setQuill]); + + // 清除选择区域 + useEffect(() => { + if (quill && selection) { + quill.setSelection(selection) + setSelection(null) + } + }, [quill, selection, setSelection]); + + // 设置placeholder值 + useEffect(() => { + if (!quill || !quill.root) return; + quill.root.dataset.placeholder = placeholder; + }, [quill, placeholder]); + + // 处理内容变化 + useEffect(() => { + if (!quill) return; + if (typeof handleOnChange !== 'function') return; + let handler; + quill.on( + 'text-change', + (handler = () => { + handleOnChange(quill.getContents()); // getContents: 检索编辑器内容 + }) + ); + return () => { + quill.off('text-change', handler); + } + }, [quill, handleOnChange]); + + // 返回结果 + return ( +
    +
    +
    + ); +} + +export default QuillForEditor; diff --git a/public/react/src/common/reactQuill/ImageBlot.js b/public/react/src/common/reactQuill/ImageBlot.js new file mode 100644 index 000000000..091bd2c1f --- /dev/null +++ b/public/react/src/common/reactQuill/ImageBlot.js @@ -0,0 +1,54 @@ +/* + * @Description: 重写图片 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-16 15:50:45 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 16:44:48 + */ +import Quill from "quill"; + +const BlockEmbed = Quill.import('blots/block/embed'); + +export default class ImageBlot extends BlockEmbed { + + static create(value) { + + const node = super.create(); + + node.setAttribute('alt', value.alt); + node.setAttribute('src', value.url); + + if (value.width) { + node.setAttribute('width', value.width); + } + if (value.height) { + node.setAttribute('height', value.height); + } + // 宽度和高度都不存在时, + if (!value.width && !value.height) { + node.setAttribute('display', 'block'); + node.setAttribute('width', '100%'); + } + // 给图片添加点击事件 + node.onclick = () => { + value.onClick && value.onClick(value.url); + } + return node; + } + + static value (node) { + + return { + alt: node.getAttribute('alt'), + url: node.getAttribute('src'), + onclick: node.onclick, + // width: node.width, + // height: node.height, + display: node.getAttribute('display') + }; + } +} + +ImageBlot.blotName = 'image'; +ImageBlot.tagName = 'img'; \ No newline at end of file diff --git a/public/react/src/common/reactQuill/ReactQuill.js b/public/react/src/common/reactQuill/ReactQuill.js new file mode 100644 index 000000000..1b4209409 --- /dev/null +++ b/public/react/src/common/reactQuill/ReactQuill.js @@ -0,0 +1,45 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:09:42 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-18 08:46:20 + */ +import 'quill/dist/quill.core.css'; // 核心样式 +import 'quill/dist/quill.snow.css'; // 有工具栏 +import 'quill/dist/quill.bubble.css'; // 无工具栏 +import 'katex/dist/katex.min.css'; // katex 表达式样式 +import React, { useState, useReducer, useEffect } from 'react'; +import useQuill from './useQuill'; + +function ReactQuill ({ + disallowColors, // 不可见时颜色 + placeholder, // 提示信息 + uploadImage, // 图片上传 + onChange, // 内容变化时 + options, // 配置信息 + value, // 显示的内容 + style, + showUploadImage // 显示上传图片 +}) { + + const [element, setElement] = useState(); // quill 渲染节点 + + useQuill({ + disallowColors, + placeholder, + uploadImage, + onChange, + options, + value, + showUploadImage, + element + }); + + return ( +
    + ); +} + +export default ReactQuill; diff --git a/public/react/src/common/reactQuill/deepEqual.js b/public/react/src/common/reactQuill/deepEqual.js new file mode 100644 index 000000000..6f2b276bf --- /dev/null +++ b/public/react/src/common/reactQuill/deepEqual.js @@ -0,0 +1,47 @@ +function deepEqual (prev, current) { + if (prev === current) { // 基本类型比较,值,类型都相同 或者同为 null or undefined + return true; + } + + if ((!prev && current) + || (prev && !current) + || (!prev && !current) + ) { + return false; + } + + if (Array.isArray(prev)) { + if (!Array.isArray(current)) return false; + if (prev.length !== current.length) return false; + + for (let i = 0; i < prev.length; i++) { + if (!deepEqual(current[i], prev[i])) { + return false; + } + } + return true; + } + + if (typeof current === 'object') { + if (typeof prev !== 'object') return false; + const prevKeys = Object.keys(prev); + const curKeys = Object.keys(current); + + if (prevKeys.length !== curKeys.length) return false; + + prevKeys.sort(); + curKeys.sort(); + + for (let i = 0; i < prevKeys.length; i++) { + if (prevKeys[i] !== curKeys[i]) return false; + const key = prevKeys[i]; + if (!deepEqual(prev[key], current[key])) return false; + } + + return true; + } + + return false; +} + +export default deepEqual; diff --git a/public/react/src/common/reactQuill/flatten.js b/public/react/src/common/reactQuill/flatten.js new file mode 100644 index 000000000..237cb543f --- /dev/null +++ b/public/react/src/common/reactQuill/flatten.js @@ -0,0 +1,26 @@ +/* + * @Description: 将多维数组转变成一维数组 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:35:01 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:36:22 + */ +function flatten (array) { + return flatten.rec(array, []); +} + +flatten.rec = function flatten (array, result) { + + for (let item of array) { + if (Array.isArray(item)) { + flatten(item, result); + } else { + result.push(item); + } + } + + return result; +} + +export default flatten; diff --git a/public/react/src/common/reactQuill/index.js b/public/react/src/common/reactQuill/index.js new file mode 100644 index 000000000..56a1a8d1f --- /dev/null +++ b/public/react/src/common/reactQuill/index.js @@ -0,0 +1,108 @@ +/* + * @Description: 入口文件 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-17 10:41:48 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 20:34:40 + */ +import React, { useState, useCallback, useEffect } from 'react'; +import ReactQuill from './lib'; + +function Wrapper (props) { + // 默认工具栏配置项 + const toolbarConfig = [ + ['bold', 'italic', 'underline'], + [{align: []}, {list: 'ordered'}, {list: 'bullet'}], // 列表 + [{script: 'sub'}, {script: 'super'}], + [{header: [1,2,3,4,5,false]}], + ['blockquote', 'code-block'], + ['link', 'image', 'video'], + ['formula'], + ['clean'] + ]; + + const [placeholder] = useState(props.placeholder || 'placeholder'); + const [disableBold] = useState(false); + const [value, setValue] = useState(props.value || ''); + const [toolbar, setToolbar] = useState(toolbarConfig); + const [theme, setTheme] = useState(props.theme || 'snow'); + const [readOnly] = useState(props.readOnly || false); + + const { + onContentChagne, // 当编辑器内容变化时调用该函数 + showUploadImage, // 显示上传图片, 返回url,主要用于点击图片放大 + } = props; + + // 配置信息 + const options = { + modules: { + toolbar: toolbar, + clipboard: { + matchVisual: false + } + }, + readOnly: readOnly, + theme: theme + } + // 配置信息 + useEffect (() => { + if (props.options) { + setToolbar(props.options); + } + setTheme(props.theme || 'snow'); + setValue(props.value); + }, [props]); + + // 当内容变化时 + const handleOnChange = useCallback( + contents => { + if (disableBold) { + setValue({ + ops: contents.ops.map(x => { + x = {...x}; + if (x && x.attributes && x.attributes.bold) { + x.attributes = { ...x.attributes }; + delete x.attributes.bold; + if (!Object.keys(x.attributes).length) { + delete x.attributes; + } + } + return x; + }) + }); + } else { + setValue(contents); + } + onContentChagne && onContentChagne(contents); + }, [disableBold] + ); + + // 图片上传 + const handleUploadImage = (files) => { + console.log('选择的图片信息', files); + } + + // 显示图片 + const handleShowUploadImage = (url) => { + // console.log('上传的图片url:', url); + showUploadImage && showUploadImage(url); + } + + return ( + + handleShowUploadImage(url)} + /> + + ); +} + +export default Wrapper; +// ReactDOM.render(, document.querySelector('#root')); diff --git a/public/react/src/common/reactQuill/index.scss b/public/react/src/common/reactQuill/index.scss new file mode 100644 index 000000000..b6da52bf5 --- /dev/null +++ b/public/react/src/common/reactQuill/index.scss @@ -0,0 +1,32 @@ +#quill-toolbar{ + .quill-btn{ + vertical-align: middle; + } + .quill_image{ + display: inline-block; + position: relative; + vertical-align: middle; + width: 28px; + height: 24px; + overflow: hidden; + .image_input{ + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + opacity: 0; + } + .ql-image{ + position: relative; + left: 0; + top: 0; + } + } +} + +.react_quill_area{ + .ql-toolbar:not(:last-child) { + display: none; + } +} \ No newline at end of file diff --git a/public/react/src/common/reactQuill/lib.js b/public/react/src/common/reactQuill/lib.js new file mode 100644 index 000000000..430a95bb7 --- /dev/null +++ b/public/react/src/common/reactQuill/lib.js @@ -0,0 +1,13 @@ +/* + * @Description: 导出 ReactQuill + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:08:24 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:37:13 + */ +import ReactQuill from './ReactQuill'; +import useQuill from './useQuill'; + +export default ReactQuill; +export { useQuill }; diff --git a/public/react/src/common/reactQuill/useDeepEqualMemo.js b/public/react/src/common/reactQuill/useDeepEqualMemo.js new file mode 100644 index 000000000..948e21781 --- /dev/null +++ b/public/react/src/common/reactQuill/useDeepEqualMemo.js @@ -0,0 +1,27 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-12 19:48:55 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:38:16 + */ +import { useState, useEffect } from 'react'; +import deepEqual from './deepEqual'; + +function useDeepEqual (input) { + + const [value, setValue] = useState(input); + + useEffect(() => { + + if (!deepEqual(input, value)) { + setValue(input) + } + + }, [input, value]); + + return value; +} + +export default useDeepEqual; diff --git a/public/react/src/common/reactQuill/useMountQuill.js b/public/react/src/common/reactQuill/useMountQuill.js new file mode 100644 index 000000000..c2313c480 --- /dev/null +++ b/public/react/src/common/reactQuill/useMountQuill.js @@ -0,0 +1,148 @@ +/* + * @Description: 创建 reactQuill实例 + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:31:42 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 20:42:05 + */ +import Quill from 'quill'; // 导入quill +import { useState, useEffect, useMemo } from 'react'; +import flatten from './flatten.js'; +import useDeepEqualMemo from './useDeepEqualMemo'; +import Katex from 'katex'; +import ImageBlot from './ImageBlot'; +import { fetchUploadImage } from '../../services/ojService.js'; +import { getImageUrl } from 'educoder' +window.katex = Katex; + +Quill.register(ImageBlot); + +function useMountQuill ({ + element, + options: passedOptions, + uploadImage, + showUploadImage, + imgAttrs = {} // 指定图片的宽高属性 +}) { + + // 是否引入 katex + const [katexLoaded, setKatexLoaded] = useState(Boolean(window.katex)) + const [quill, setQuill] = useState(null); + + const options = useDeepEqualMemo(passedOptions); + console.log('use mount quill: ', passedOptions); + + // 判断options中是否包含公式 + const requireKatex = useMemo(() => { + return flatten(options.modules.toolbar).includes('formula'); + }, [options]); + + // 加载katex + useEffect(() => { + if (!requireKatex) return; + if (katexLoaded) return; + + const interval = setInterval(() => { + if (window.katex) { + setKatexLoaded(true); + clearInterval(interval); + } + }); + + return () => { // 定义回调清除定时器 + clearInterval(interval); + } + + }, [ + setKatexLoaded, + katexLoaded, + requireKatex + ]); + + // 加载 quill + useEffect(() => { + if (!element) return; + if (requireKatex && !katexLoaded) { + element.innerHTML = ` +
    + Loading Katex... +
    + ` + } + // 清空内容 + element.innerHTML = ''; + console.log(element); + // 创建 quill 节点 + const quillNode = document.createElement('div'); + element.appendChild(quillNode); // 将quill节点追回到 element 元素中 + + const quill = new Quill(element, options); + setQuill(quill); + // 加载上传图片功能 + if (typeof uploadImage === 'function') { + quill.getModule('toolbar').addHandler('image', (e) => { + // 创建type类型输入框加载本地图片 + const input = document.createElement('input'); + input.setAttribute('type', 'file'); + input.setAttribute('accept', 'image/*'); + input.click(); + + input.onchange = async (e) => { + const file = input.files[0]; // 获取文件信息 + const formData = new FormData(); + formData.append('file', file); + + // const reader = new FileReader(); + // reader.readAsDataURL(file); + // console.log('文件信息===>>', reader); + // reader.onload = function (e) { + // debugger; + // console.log('文件信息===>>', e.target.result); + // const image = new Image(); + // image.src = e.target.result; + + // image.onload = function () { + // // file.width = + // console.log(image.width, image.height); + // } + // } + + const range = quill.getSelection(true); + let fileUrl = ''; // 保存上传成功后图片的url + // 上传文件 + const result = await fetchUploadImage(formData); + // 获取上传图片的url + if (result.data && result.data.id) { + fileUrl = getImageUrl(`api/attachments/${result.data.id}`); + } + // 根据id获取文件路径 + const { width, height } = imgAttrs; + // console.log('上传图片的url:', fileUrl); + if (fileUrl) { + quill.insertEmbed(range.index, 'image', { + url: fileUrl, + alt: '', + onClick: showUploadImage, + width, + height + }); + } + } + }); + } + + return () => { + element.innerHTML = ''; + } + }, [ + element, + options, + requireKatex, + katexLoaded, + ]); + + return quill; +} + +export default useMountQuill; diff --git a/public/react/src/common/reactQuill/useQuill.js b/public/react/src/common/reactQuill/useQuill.js new file mode 100644 index 000000000..b959dbc52 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuill.js @@ -0,0 +1,60 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:09:50 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-17 15:46:50 + */ +import useQuillPlaceholder from './useQuillPlaceholder'; +import useQuillValueSync from './useQuillValueSync'; +import useQuillOnChange from './useQuillOnChange'; +import useMountQuill from './useMountQuill'; +import { useEffect } from 'react'; + +function useQuill ({ + disallowColors, + placeholder, + uploadImage, + onChange, + options, + value, + element, + showUploadImage +}) { + + // 获取 quill 实例 + const quill = useMountQuill({ + element, + options, + uploadImage, + showUploadImage + }); + + useEffect(() => { + if (disallowColors && quill) { + quill.clipboard.addMatcher(Node.ELEMENT_NODE, (node, delta) => { + delta.ops = delta.ops.map(op => { + if (op.attributes && op.attributes.color) { + const { color, ...attributes } = op.attributes; + return { + ...op, + attributes + } + } + return op; + }); + return delta; + }); + } + }, [ + disallowColors, + quill + ]); + + useQuillPlaceholder(quill, placeholder); + useQuillValueSync(quill, value); + useQuillOnChange(quill, onChange); +} + +export default useQuill; diff --git a/public/react/src/common/reactQuill/useQuillOnChange.js b/public/react/src/common/reactQuill/useQuillOnChange.js new file mode 100644 index 000000000..45333a4e1 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuillOnChange.js @@ -0,0 +1,33 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-12 19:49:11 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:39:27 + */ +import { useEffect } from 'react'; + +function useQuillOnChange (quill, onChange) { + + useEffect(() => { + + if (!quill) return; + if (typeof onChange !== 'function') return; + + let handler; + + quill.on( + 'text-change', + (handler = () => { + onChange(quill.getContents()); // getContents: 检索编辑器内容 + }) + ); + + return () => { + quill.off('text-change', handler); + } + }, [quill, onChange]); +} + +export default useQuillOnChange; diff --git a/public/react/src/common/reactQuill/useQuillPlaceholder.js b/public/react/src/common/reactQuill/useQuillPlaceholder.js new file mode 100644 index 000000000..ccc341568 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuillPlaceholder.js @@ -0,0 +1,22 @@ +/* + * @Description: + * @Author: tangjiang + * @Github: + * @Date: 2019-12-09 09:28:34 + * @LastEditors: tangjiang + * @LastEditTime: 2019-12-16 11:39:48 + */ +import { useEffect } from 'react' + +function useQuillPlaceholder ( + quill, + placeholder +) { + + useEffect(() => { + if (!quill || !quill.root) return; + quill.root.dataset.placeholder = placeholder; + }, [quill, placeholder]); +} + +export default useQuillPlaceholder; diff --git a/public/react/src/common/reactQuill/useQuillValueSync.js b/public/react/src/common/reactQuill/useQuillValueSync.js new file mode 100644 index 000000000..696d88949 --- /dev/null +++ b/public/react/src/common/reactQuill/useQuillValueSync.js @@ -0,0 +1,31 @@ +import { useEffect, useState } from 'react' +import deepEqual from './deepEqual.js' + +function useQuillValueSync(quill, value) { + const [selection, setSelection] = useState(null) + + useEffect(() => { + if (!quill) return + + const previous = quill.getContents() + const current = value + + if (!deepEqual(previous, current)) { + setSelection(quill.getSelection()) + if (typeof value === 'string') { + quill.clipboard.dangerouslyPasteHTML(value, 'api') + } else { + quill.setContents(value) + } + } + }, [quill, value, setSelection]) + + useEffect(() => { + if (quill && selection) { + quill.setSelection(selection) + setSelection(null) + } + }, [quill, selection, setSelection]) +} + +export default useQuillValueSync diff --git a/public/react/src/modules/developer/DeveloperHome.js b/public/react/src/modules/developer/DeveloperHome.js index 5f787659e..73a5c37a1 100644 --- a/public/react/src/modules/developer/DeveloperHome.js +++ b/public/react/src/modules/developer/DeveloperHome.js @@ -16,7 +16,7 @@ import MultipTags from './components/multiptags'; // import { Link } from 'react-router-dom'; import CONST from '../../constants'; import { withRouter } from 'react-router'; -import { toStore } from 'educoder'; +import { toStore, CNotificationHOC } from 'educoder'; // import MyIcon from '../../common/components/MyIcon'; const {tagBackground, diffText} = CONST; @@ -249,17 +249,26 @@ class DeveloperHome extends React.PureComponent { // 删除 handleClickDelete = (record) => { const { deleteItem } = this.props; - Modal.confirm({ - title: '删除', + this.props.confirm({ + title: '提示', content: `确定要删除${record.name}吗?`, - okText: '确定', - cancelText: '取消', onOk () { // 调用删除接口 console.log(record.identifier); deleteItem(record.identifier); } }); + // Modal.confirm({ + // title: '删除', + // content: `确定要删除${record.name}吗?`, + // okText: '确定', + // cancelText: '取消', + // onOk () { + // // 调用删除接口 + // console.log(record.identifier); + // deleteItem(record.identifier); + // } + // }); } // table条件变化时 handleTableChange = (pagination, filters, sorter) => { @@ -562,5 +571,5 @@ const mapDispatchToProps = (dispatch) => ({ export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(DeveloperHome)); +)(CNotificationHOC() (DeveloperHome))); // export default DeveloperHome; diff --git a/public/react/src/modules/developer/components/controlSetting/index.js b/public/react/src/modules/developer/components/controlSetting/index.js index 587e1bee9..1d4d7834c 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.js +++ b/public/react/src/modules/developer/components/controlSetting/index.js @@ -4,10 +4,10 @@ * @Github: * @Date: 2019-11-27 16:02:36 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:32:33 + * @LastEditTime: 2019-12-19 19:47:32 */ import './index.scss'; -import React, { useState, useRef } from 'react'; +import React, { useState, useRef, useEffect } from 'react'; import { Tabs, Button, Icon } from 'antd'; import { connect } from 'react-redux'; import InitTabCtx from '../initTabCtx'; @@ -23,14 +23,15 @@ const ControlSetting = (props) => { submitLoading, identifier, excuteState, + showOrHideControl, commitRecordDetail, changeLoadingState, changeSubmitLoadingStatus, - showOrHideControl, + changeShowOrHideControl, // debuggerCode, // startDebuggerCode, // 外部存入 onDebuggerCode, - updateCode, + // updateCode, onSubmitForm } = props; const [defaultActiveKey, setDefaultActiveKey] = useState('1'); // 当前选中的tab @@ -44,10 +45,14 @@ const ControlSetting = (props) => { setDefaultActiveKey(key); } + useEffect(() => { + setShowTextResult(props.showOrHideControl); + }, [props]); + // 显示/隐藏tab const handleShowControl = () => { setShowTextResult(!showTextResult); - showOrHideControl(!showTextResult); + changeShowOrHideControl(!showTextResult); } // 调试代码 @@ -55,7 +60,7 @@ const ControlSetting = (props) => { // console.log(formRef.current.handleTestCodeFormSubmit); // 调出控制台界面 setShowTextResult(true); - showOrHideControl(true); + changeShowOrHideControl(true); formRef.current.handleTestCodeFormSubmit(() => { setDefaultActiveKey('2'); }); @@ -84,7 +89,7 @@ const ControlSetting = (props) => { @@ -131,19 +136,20 @@ const ControlSetting = (props) => { const mapStateToProps = (state) => { const {commonReducer, ojForUserReducer} = state; - const {loading, excuteState, submitLoading } = commonReducer; + const {loading, excuteState, submitLoading, showOrHideControl } = commonReducer; const { commitRecordDetail } = ojForUserReducer; return { loading, submitLoading, excuteState, + showOrHideControl, // identifier: user_program_identifier, commitRecordDetail // 提交详情 }; }; // changeSubmitLoadingStatus const mapDispatchToProps = (dispatch) => ({ - showOrHideControl: (flag) => dispatch(actions.showOrHideControl(flag)), + changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)), changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag)), changeSubmitLoadingStatus: (flag) => dispatch(actions.changeSubmitLoadingStatus(flag)), debuggerCode: (identifier, values) => dispatch(actions.debuggerCode(identifier, values)), diff --git a/public/react/src/modules/developer/components/controlSetting/index.scss b/public/react/src/modules/developer/components/controlSetting/index.scss index 97838ce5c..31beda8a5 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.scss +++ b/public/react/src/modules/developer/components/controlSetting/index.scss @@ -2,7 +2,8 @@ position: absolute; bottom: 0; width: 100%; - background:rgba(30,30,30,1); + // background: red; + // background:rgba(30,30,30,1); // height: 56px; .control_tab{ position: absolute; @@ -52,8 +53,8 @@ height: 56px; padding-right: 30px; padding-left: 10px; - // background: #000; - background:rgba(48,48,48,1); + background: rgba(18,28,36,1); + // background:rgba(48,48,48,1); } .setting_drawer{ diff --git a/public/react/src/modules/developer/components/execResult/index.js b/public/react/src/modules/developer/components/execResult/index.js index 32bbbee91..6f9341b9a 100644 --- a/public/react/src/modules/developer/components/execResult/index.js +++ b/public/react/src/modules/developer/components/execResult/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-28 08:44:54 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-10 09:24:02 + * @LastEditTime: 2019-12-19 10:44:16 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -38,6 +38,15 @@ function ExecResult (props) {
    ); + + const renderError = () => ( +
    + + 未知异常 + +
    + ) + const renderFinish = () => { const { error_line, @@ -60,6 +69,7 @@ function ExecResult (props) { ) } + // console.log('执行结果====》》》》', status); const excuteCtx = (state) => { if (state === 0) { return ( @@ -118,6 +128,8 @@ function ExecResult (props) { setRenderCtx(() => (readerLoaded)); } else if ('finish' === excuteState) { setRenderCtx(() => (renderFinish)); + } else if ('error' === excuteState) { + setRenderCtx(() => (renderError)) } }, [excuteState]); diff --git a/public/react/src/modules/developer/components/initTabCtx/index.js b/public/react/src/modules/developer/components/initTabCtx/index.js index 3834a3e11..3e707daa1 100644 --- a/public/react/src/modules/developer/components/initTabCtx/index.js +++ b/public/react/src/modules/developer/components/initTabCtx/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 19:46:14 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:38:42 + * @LastEditTime: 2019-12-19 10:47:05 */ import './index.scss'; import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react'; @@ -26,6 +26,7 @@ function InitTabCtx (props, ref) { const { inputValue, onDebuggerCode } = props; + console.log('default value', inputValue); useImperativeHandle(ref, () => ({ handleTestCodeFormSubmit: (cb) => { // console.log('父组件调用我啦~~~~~~~~~'); @@ -33,6 +34,10 @@ function InitTabCtx (props, ref) { } })); + useEffect(() => { + console.log('初始值: ========', props); + }, [props]); + // 渲染文本提示信息 const renderText = () => (请在这里添加测试用例,点击“调试代码”时将从这里读取输入来测试你的代码...); // 渲染表单信息 diff --git a/public/react/src/modules/developer/components/initTabCtx/index.scss b/public/react/src/modules/developer/components/initTabCtx/index.scss index 449db1d2a..5427aa374 100644 --- a/public/react/src/modules/developer/components/initTabCtx/index.scss +++ b/public/react/src/modules/developer/components/initTabCtx/index.scss @@ -49,7 +49,8 @@ } .input_textarea_style{ - background:rgba(30,30,30,1) !important; + // background:rgba(30,30,30,1) !important; + background:rgba(7,15,25,1) !important; color: #fff; border-color: transparent; outline: none; diff --git a/public/react/src/modules/developer/components/monacoSetting/index.js b/public/react/src/modules/developer/components/monacoSetting/index.js index a101819e0..669439577 100644 --- a/public/react/src/modules/developer/components/monacoSetting/index.js +++ b/public/react/src/modules/developer/components/monacoSetting/index.js @@ -4,10 +4,11 @@ * @Github: * @Date: 2019-11-25 17:50:33 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-06 16:51:48 + * @LastEditTime: 2019-12-19 19:32:08 */ import React, { useState } from 'react'; import { fromStore, toStore } from 'educoder'; +// import { Icon } from 'antd'; // import { Select } from 'antd'; // const { Option } = Select; const SettingDrawer = (props) => { diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.js b/public/react/src/modules/developer/components/myMonacoEditor/index.js index 60f54ee0a..948d5a4f5 100644 --- a/public/react/src/modules/developer/components/myMonacoEditor/index.js +++ b/public/react/src/modules/developer/components/myMonacoEditor/index.js @@ -4,12 +4,12 @@ * @Github: * @Date: 2019-11-27 15:02:52 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 16:16:56 + * @LastEditTime: 2019-12-19 19:36:24 */ import './index.scss'; import React, { useState, useRef, useEffect } from 'react'; -import { Drawer, Modal } from 'antd'; -import { fromStore } from 'educoder'; +import { Drawer, Modal, Icon, Badge } from 'antd'; +import { fromStore, CNotificationHOC } from 'educoder'; import { connect } from 'react-redux'; import MonacoEditor from '@monaco-editor/react'; import SettingDrawer from '../../components/monacoSetting'; @@ -19,16 +19,25 @@ import MyIcon from '../../../../common/components/MyIcon'; // import actions from '../../../../redux/actions'; const { fontSetting, opacitySetting } = CONST; +const maps = { + 'c': 'main.c', + 'c++': 'main.cc', + 'java': 'main.java', + 'pythone': 'main.py' +}; function MyMonacoEditor (props, ref) { const { + notice, language, identifier, + hadCodeUpdate, showOrHideControl, // saveUserInputCode, onCodeChange, - onRestoreInitialCode + onRestoreInitialCode, + onUpdateNotice } = props; const [showDrawer, setShowDrawer] = useState(false); // 控制配置滑框 @@ -50,7 +59,7 @@ function MyMonacoEditor (props, ref) { }, [props]); useEffect(() => { - setHeight(showOrHideControl ? 'calc(100% - 382px)' : 'calc(100% - 56px)'); + setHeight(showOrHideControl ? 'calc(100% - 378px)' : 'calc(100% - 56px)'); }, [showOrHideControl]); // 控制侧边栏设置的显示 @@ -93,28 +102,51 @@ function MyMonacoEditor (props, ref) { // 恢复初始代码 const handleRestoreCode = () => { - Modal.confirm({ + props.confirm({ + title: '提示', content: '确定要恢复代码吗?', - okText: '确定', - cancelText: '取消', onOk () { onRestoreInitialCode && onRestoreInitialCode(); } }) + // Modal.confirm({ + // content: '确定要恢复代码吗?', + // okText: '确定', + // cancelText: '取消', + // onOk () { + // onRestoreInitialCode && onRestoreInitialCode(); + // } + // }) + } + + const handleUpdateNotice = () => { + if (props.notice) { + onUpdateNotice && onUpdateNotice(); + } } const renderRestore = identifier ? ( ) : ''; + + // lex_has_save ${hadCodeUpdate} ? : '' + const _classnames = hadCodeUpdate ? `flex_strict flex_has_save` : 'flex_strict'; return (
    {/* 未保存时 ? '学员初始代码文件' : main.x */} - {identifier ? '' : '学员初始代码文件'} - {identifier ? '已保存' : ''} - {renderRestore} - {/* */} + {identifier ? language ? maps[language.toLowerCase()] : '' : '学员初始代码文件'} + {identifier ? '已保存' : ''} + + + + {renderRestore}
    @@ -161,4 +192,4 @@ const mapDispatchToProps = (dispatch) => ({ export default connect( mapStateToProps, mapDispatchToProps -)(MyMonacoEditor); +)(CNotificationHOC() (MyMonacoEditor)); diff --git a/public/react/src/modules/developer/components/myMonacoEditor/index.scss b/public/react/src/modules/developer/components/myMonacoEditor/index.scss index 7a7c4f030..61689b51e 100644 --- a/public/react/src/modules/developer/components/myMonacoEditor/index.scss +++ b/public/react/src/modules/developer/components/myMonacoEditor/index.scss @@ -1,19 +1,17 @@ .monaco_editor_area{ height: 100%; - background-color: rgba(30,30,30,1); + background-color: rgba(7,15,25,1); .code_title{ display: flex; align-items: center; - // justify-content: space-between; - // background: #000; - // background: #333333; - background-color: rgba(48,48,48,1); + background-color: rgba(18,28,36,1); color: #fff; height: 56px; padding: 0 30px; .flex_strict{ flex: 1; } + .flex_normal{ color: #E51C24; cursor: pointer; @@ -25,21 +23,21 @@ .flex_strict, .flex_normal, .code-icon{ - color: #888; + color: #666; } } } .setting_drawer{ - // .ant-drawer-body{ - // // height: calc(100vh - 120px); - // // overflow-y: auto; - // } + .ant-drawer-close{ + color: #ffffff; + } .ant-drawer-content{ top: 120px; bottom: 56px; height: calc(100vh - 176px); - background: #333333; + // background: #333333; + background: rgba(7,15,25,1); color: #fff; .setting_h2{ color: #fff; @@ -57,4 +55,17 @@ color: #fff; } } +} + +.flex_has_save{ + // animation: blink 3s line 3; + animation-name: blink; + animation-duration: .4s; + animation-iteration-count: 3; +} + +@keyframes blink{ + 50% { + color: #fff; + } } \ No newline at end of file diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js index bc905fdf7..1c451c669 100644 --- a/public/react/src/modules/developer/newOrEditTask/index.js +++ b/public/react/src/modules/developer/newOrEditTask/index.js @@ -13,11 +13,11 @@ import { Button, Modal } from 'antd'; import LeftPane from './leftpane'; import RightPane from './rightpane'; import { withRouter } from 'react-router'; -import { toStore } from 'educoder'; +import { toStore, CNotificationHOC } from 'educoder'; import UserInfo from '../components/userInfo'; // import RightPane from './rightpane/index'; import actions from '../../../redux/actions'; -import {ModalConfirm} from '../../../common/components/ModalConfirm'; +// import {ModalConfirm} from '../../../common/components/ModalConfirm'; const NewOrEditTask = (props) => { const { @@ -69,10 +69,13 @@ const NewOrEditTask = (props) => { // 模拟挑战 const imitationChallenge = () => { + // 调用 start 接口, 成功后跳转到模拟页面 + startProgramQuestion(identifier, props); } // 开始挑战 const startChallenge = () => { - // 调用 start 接口, 成功后跳转到模拟页面 + // 调用 start 接口, 成功后跳转到开启实战 + // TODO startProgramQuestion(identifier, props); } @@ -82,27 +85,38 @@ const NewOrEditTask = (props) => { props.clearOJFormStore(); // 清空描述信息 toStore('oj_description', ''); - setInterval(function () { - props.history.push('/problems'); - }, 500); + props.history.push('/problems'); } // 发布 const handleClickPublish = () => { - ModalConfirm('提示', (

    发布后即可应用到自己管理的课堂
    是否确认发布?

    ), () => { - changePublishLoadingStatus(true); - handlePublish(props, 'publish'); + // ModalConfirm('提示', (

    发布后即可应用到自己管理的课堂
    是否确认发布?

    ), () => { + // changePublishLoadingStatus(true); + // handlePublish(props, 'publish'); + // }); + props.confirm({ + title: '提示', + content: (

    发布后即可应用到自己管理的课堂
    是否确认发布?

    ), + onOk () { + changePublishLoadingStatus(true); + handlePublish(props, 'publish'); + } }); - - } // 撤销发布 const handleClickCancelPublish = () => { - ModalConfirm('提示', (

    是否确认撤销发布?

    ), () => { - changePublishLoadingStatus(true); - handleCancelPublish(props, identifier); + // ModalConfirm('提示', (

    是否确认撤销发布?

    ), () => { + // changePublishLoadingStatus(true); + // handleCancelPublish(props, identifier); + // }); + props.confirm({ + title: '提示', + content: ((

    是否确认撤销发布?

    )), + onOk () { + changePublishLoadingStatus(true); + handleCancelPublish(props, identifier); + } }); - } // 取消保存/取消按钮 @@ -125,6 +139,7 @@ const NewOrEditTask = (props) => { const renderPubOrFight = () => { const pubButton = isPublish ? ( ); - // 更新 - // const updateBtn = isPublish - // ? '' - // : ( - // - // ); - return ( - - - {pubButton} - {challengeBtn} - - ) + if (isPublish) { + return ( + + {pubButton} + + {challengeBtn} + + ); + } else { + return ( + + + {pubButton} + {challengeBtn} + + ); + } + } // 渲染退出 const renderQuit = () => { return identifier ? ( ) : '' @@ -255,4 +271,4 @@ const mapDispatchToProps = (dispatch) => ({ export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(NewOrEditTask)); +)(CNotificationHOC() (NewOrEditTask))); diff --git a/public/react/src/modules/developer/newOrEditTask/index.scss b/public/react/src/modules/developer/newOrEditTask/index.scss index ba0ed8503..ad668fcc8 100644 --- a/public/react/src/modules/developer/newOrEditTask/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/index.scss @@ -10,9 +10,23 @@ align-items: center; justify-content: center; height: 56px; - background: #333333; + // background: #333333; + background: rgba(18,28,36,1); > button{ margin-right: 20px; } } +.quite_btn{ + position: absolute; + right: 10px; + top: 15px; + margin-left: 30px; + color: #888888; + transition: all .3s; + cursor: pointer; + &:hover{ + color: #5091FF; + } +} + diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js index 4c4131fa9..8e7aa70fc 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/AddTestDemo.js @@ -4,13 +4,14 @@ * @Github: * @Date: 2019-11-21 09:19:38 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 11:58:46 + * @LastEditTime: 2019-12-19 17:54:28 */ import './index.scss'; import React, { useState } from 'react'; -import { Collapse, Icon, Input, Form, Button, Modal } from 'antd'; +import { Collapse, Icon, Input, Form, Button } from 'antd'; import { connect } from 'react-redux'; import actions from '../../../../../redux/actions'; +import { CNotificationHOC} from 'educoder'; const { Panel } = Collapse; const { TextArea } = Input; const FormItem = Form.Item; @@ -31,15 +32,22 @@ const AddTestDemo = (props) => { // console.log('点击的删除按钮') e.preventDefault(); e.stopPropagation(); - Modal.confirm({ - title: '删除', + props.confirm({ + title: '提示', content: '确定要删除当前测试用例吗?', - okText: '确定', - cancelText: '取消', onOk() { onDeleteTest(testCase); } - }) + }); + // Modal.confirm({ + // title: '删除', + // content: '确定要删除当前测试用例吗?', + // okText: '确定', + // cancelText: '取消', + // onOk() { + // onDeleteTest(testCase); + // } + // }) } // 输入框值改变时 @@ -189,4 +197,4 @@ const mapDispatchToProps = (dispatch) => ({ export default connect( mapStateToProps, mapDispatchToProps -)(Form.create()(AddTestDemo)); +)(Form.create()(CNotificationHOC()(AddTestDemo))); diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js index 762d1d3ba..da31754bd 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.js @@ -4,21 +4,20 @@ * @Github: * @Date: 2019-11-20 10:35:40 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 11:39:52 + * @LastEditTime: 2019-12-19 17:23:10 */ -import 'quill/dist/quill.core.css'; -import 'quill/dist/quill.bubble.css'; -import 'quill/dist/quill.snow.css'; import './index.scss'; // import 'katex/dist/katex.css'; import React from 'react'; import { Form, Input, Select, InputNumber, Button } from 'antd'; import { connect } from 'react-redux'; import AddTestDemo from './AddTestDemo'; -import QuillEditor from '../../../quillEditor'; +// import QuillEditor from '../../../quillEditor'; import actions from '../../../../../redux/actions'; import CONST from '../../../../../constants'; -import { fromStore, toStore } from 'educoder'; // 保存和读取store值 +import { toStore } from 'educoder'; // 保存和读取store值 +// import Wrapper from '../../../../../common/reactQuill'; +import QuillForEditor from '../../../../../common/quillForEditor'; const scrollIntoView = require('scroll-into-view'); const {jcLabel} = CONST; const FormItem = Form.Item; @@ -26,9 +25,9 @@ const { Option } = Select; const maps = { language: [ { title: 'C', key: 'C' }, - // { title: 'C++', key: 'C++' }, - // { title: 'Python', key: 'Python' }, - // { title: 'Java', key: 'Java' } + { title: 'C++', key: 'C++' }, + { title: 'Python', key: 'Python' }, + { title: 'Java', key: 'Java' } ], difficult: [ { title: '简单', key: '1' }, @@ -146,9 +145,6 @@ class EditTab extends React.Component { testCasesValidate, openTestCodeIndex = [] } = this.props; - // console.log('当前位置: ', position); - // console.log('OJForm: ', ojForm); - // console.log('当前位置: ', testCases); // 表单label const myLabel = (name, subTitle) => { if (subTitle) { @@ -185,7 +181,6 @@ class EditTab extends React.Component { }; const renderTestCase = () => { return this.props.testCases.map((item, i) => { - console.log(111); return { + console.log('描述信息为: ', content); + // 保存获取的描述信息至redux中 + this.handleChangeDescription(content); + } // 编辑器配置信息 const quillConfig = [ [{ header: [1, 2, 3, 4, 5, 6, false] }], ['bold', 'italic', 'underline', 'strike'], // 切换按钮 ['blockquote', 'code-block'], // 代码块 - [{ 'list': 'ordered' }, { 'list': 'bullet' }], // 列表 + [{align: []}, { 'list': 'ordered' }, { 'list': 'bullet' }], // 列表 [{ 'script': 'sub'}, { 'script': 'super' }], [{ 'color': [] }, { 'background': [] }], // 字体颜色与背景色 - ['formula', 'image', 'video'], // 数学公式、图片、视频 + ['image', 'formula'], // 数学公式、图片、视频 ['clean'], // 清除格式 ]; + return (
    @@ -267,7 +270,7 @@ class EditTab extends React.Component { help={ojFormValidate.timeLimit.errMsg} colon={ false } > - + - +
    + +
    +
    {/* */} + {/* 添加测试用例 */} diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss index f8fa3bd71..17f3eae34 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/editorTab/index.scss @@ -49,6 +49,11 @@ .test_demo_ctx, .editor_form{ margin: 0 30px; + + .ant-form-explain{ + margin-top: 5px; + margin-left: -10px; + } } .test_demo_title{ display: flex; diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/index.js index 8b10413a9..781b82699 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/index.js @@ -34,28 +34,6 @@ function LeftPane (props) { const [defaultActiveKey, setDefaultActiveKey] = useState('editor'); - // const tabArrs = [ - // { title: '编辑', key: 'editor', content: () }, - // { title: '预览', key: 'prev', content: () }, - // // { title: '提交记录', key: 'commit', content: () }, - // ]; - - // const tabs = tabArrs.map((tab) => { - // const Comp = tab.content; - // return ( - // - // { Comp } - // - // ) - // }); - - // tab切换时 - // const handleTabChange = (key) => { - // setDefaultActiveKey(key); - // } - - // 执行表单提交函数 - const renderComp = useMemo(() => { return Comp[defaultActiveKey]; }, [defaultActiveKey]); diff --git a/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js b/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js index c45628973..6b41d3489 100644 --- a/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js +++ b/public/react/src/modules/developer/newOrEditTask/leftpane/prevTab/index.js @@ -4,74 +4,47 @@ * @Github: * @Date: 2019-11-24 10:09:55 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-04 23:38:37 + * @LastEditTime: 2019-12-18 10:02:24 */ import './index.scss'; import React, { useEffect, useState, useRef } from 'react'; import { connect } from 'react-redux'; import {Empty} from 'antd'; -// import QuillEditor from '../../../quillEditor'; -const Quill = window.Quill; +// import Wrapper from '../../../../../common/reactQuill'; +import QuillForEditor from '../../../../../common/quillForEditor'; const PrevTab = (props) => { - const { - description - } = props; const prevRef = useRef(null); - const [desc, setDesc] = useState(''); - const [renderCtx, setRenderCtx] = useState(() => { - return function () { - return ''; - } - }); - - // 空内容 - const renderTxt = () => ( -
    - -
    - ); + // const [desc, setDesc] = useState(''); + const [renderCtx, setRenderCtx] = useState(() => ''); + // 渲染内容 - const renderQuill = () => ( -
    -
    - ); - useEffect(() => { - setDesc(description); - }, [description]); - - useEffect(() => { - if (description) { - setRenderCtx(() => renderQuill); - let count = 0; - let timer = setInterval(() => { - count++; - if (count >= 10 || prevRef.current) { - clearInterval(timer); - timer = null; - if (prevRef.current) { - const quillEditor = new Quill(prevRef.current, { - readOnly: true, - theme: 'bubble' - }); - quillEditor.container.firstChild.innerHTML = description; - } - } - }, 50); + if (props.description) { + setRenderCtx(() => ( +
    + +
    + )); } else { - setRenderCtx(() => renderTxt); + setRenderCtx(() => ( +
    + +
    + )); } - - }, [description]); + }, [props]); return (
    - {renderCtx()} + {renderCtx}
    ) diff --git a/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss b/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss index 48f5a7bb9..9c472b641 100644 --- a/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss +++ b/public/react/src/modules/developer/newOrEditTask/rightpane/index.scss @@ -1,7 +1,7 @@ .right_pane_code_wrap{ position: relative; // justify-content: center; - background-color: #222; + // background-color: #222; height: 100%; // height: calc(100vh - 178px); .code-title, @@ -11,7 +11,8 @@ align-items: center; justify-content: space-between; // padding: 0 30px; - background: #000; + // background: #000; + background: rgba(18,28,36,1); color: #fff; } .code-title, diff --git a/public/react/src/modules/developer/split_pane_resizer.scss b/public/react/src/modules/developer/split_pane_resizer.scss index 498370dd6..2898d966c 100644 --- a/public/react/src/modules/developer/split_pane_resizer.scss +++ b/public/react/src/modules/developer/split_pane_resizer.scss @@ -8,7 +8,8 @@ .record_detail_header{ height: 65px; // background:rgba(34,34,34,1); - background: #1E1E1E; + // background: #1E1E1E; + background: rgba(7,15,25,1); padding:0 30px; } @@ -123,7 +124,8 @@ .split-pane-area, .split-pane-left{ .ant-tabs-nav-wrap{ - padding: 0 30px; + // padding: 0 30px; + padding: 0 20px; } .ant-tabs-bar{ margin: 0; diff --git a/public/react/src/modules/developer/studentStudy/index.js b/public/react/src/modules/developer/studentStudy/index.js index e4b296a20..15c87e64c 100644 --- a/public/react/src/modules/developer/studentStudy/index.js +++ b/public/react/src/modules/developer/studentStudy/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-23 10:53:19 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 17:19:15 + * @LastEditTime: 2019-12-19 19:48:20 */ import './index.scss'; import React, { useEffect, useState } from 'react'; @@ -15,10 +15,10 @@ import RightPane from './rightpane'; // import { Link } from 'react-router-dom'; // import { getImageUrl } from 'educoder' // import RightPane from '../newOrEditTask/rightpane'; -import { Icon, Modal } from 'antd'; +import { Icon } from 'antd'; import UserInfo from '../components/userInfo'; import actions from '../../../redux/actions'; -import { fromStore} from 'educoder'; +import { fromStore, CNotificationHOC} from 'educoder'; import { withRouter } from 'react-router'; function StudentStudy (props) { @@ -29,7 +29,8 @@ function StudentStudy (props) { userInfo, hack_identifier, // user_program_identifier, - restoreInitialCode + restoreInitialCode, + changeShowOrHideControl } = props; const { @@ -51,32 +52,51 @@ function StudentStudy (props) { const { hack = {} } = props; if (hack.modify_code && hasUpdate) { // 代码更改,提示是否需要更新代码 setHasUpdate(false); - Modal.confirm({ - title: '提示', - content: ( -

    - 代码文件有更新啦
    - 还未提交的代码,请自行保存 -

    - ), - okText: '立即更新', - cancelText: '稍后再说', - onOk () { - restoreInitialCode(id, '更新成功'); - } - }); + handleUpdateNotice(); } }, [props, hasUpdate, setHasUpdate]); + const handleUpdateNotice = () => { + console.log(props); + props.confirm({ + title: '提示', + content: ( +

    + 代码文件有更新啦
    + 还未提交的代码,请自行保存 +

    + ), + onOk () { + restoreInitialCode(id, '更新成功'); + } + }) + // Modal.confirm({ + // title: '提示', + // content: ( + //

    + // 代码文件有更新啦
    + // 还未提交的代码,请自行保存 + //

    + // ), + // okText: '立即更新', + // cancelText: '稍后再说', + // onOk () { + // restoreInitialCode(id, '更新成功'); + // } + // }); + } const _hack_id = hack_identifier || fromStore('hack_identifier'); // 处理编辑 const handleClickEditor = () => { + changeShowOrHideControl(false); props.saveEditorCodeForDetail(); props.history.push(`/problems/${_hack_id}/edit`); } // 处理退出 const handleClickQuit = () => { + // 将控制台关闭 + changeShowOrHideControl(false); props.saveEditorCodeForDetail(); props.history.push('/problems'); } @@ -117,7 +137,9 @@ function StudentStudy (props) {
    - +
    @@ -146,11 +168,12 @@ const mapDispatchToProps = (dispatch) => ({ saveEditorCodeForDetail: (code) => dispatch(actions.saveEditorCodeForDetail(code)), // 恢复初始代码 restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)), + changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)) }); export default withRouter(connect( mapStateToProps, mapDispatchToProps -)(StudentStudy)); +)(CNotificationHOC()(StudentStudy))); diff --git a/public/react/src/modules/developer/studentStudy/index.scss b/public/react/src/modules/developer/studentStudy/index.scss index bbf66aebb..68835f2ce 100644 --- a/public/react/src/modules/developer/studentStudy/index.scss +++ b/public/react/src/modules/developer/studentStudy/index.scss @@ -5,6 +5,6 @@ .right_pane_code_wrap{ position: relative; - background-color: #222; + // background-color: #222; height: 100%; } diff --git a/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js index 329e8fba1..ca7160117 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.js @@ -4,15 +4,18 @@ * @Github: * @Date: 2019-11-27 09:49:35 * @LastEditors: tangjiang - * @LastEditTime: 2019-11-27 09:52:53 + * @LastEditTime: 2019-12-17 17:46:05 */ +import './index.scss'; import React from 'react'; - -const Comment = (props) => { +import Comment from '../../../../../common/components/comment'; +const CommentTask = (props) => { return ( -

    Comment

    +
    + +
    ) } -export default Comment; +export default CommentTask; diff --git a/public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss new file mode 100644 index 000000000..ba9c132d9 --- /dev/null +++ b/public/react/src/modules/developer/studentStudy/leftpane/comment/index.scss @@ -0,0 +1,8 @@ +.task_comment_task{ + background: #fff; + padding: 20px 30px 0; + height: calc(100vh - 177px); + box-sizing: border-box; + overflow-y: auto; + border-bottom: 1px solid rgba(244,244,244,1); +} \ No newline at end of file diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.js b/public/react/src/modules/developer/studentStudy/leftpane/index.js index 69f49b9b1..347f4b4f8 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/index.js @@ -4,11 +4,11 @@ * @Github: * @Date: 2019-11-23 11:33:41 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-09 19:57:21 + * @LastEditTime: 2019-12-19 18:03:22 // */ import './index.scss'; import React, { useState, useEffect, useMemo } from 'react'; -import { Tabs, Divider } from 'antd'; +import { Divider } from 'antd'; import { connect } from 'react-redux'; import Comment from './comment'; import CommitRecord from './commitRecord'; @@ -19,17 +19,10 @@ import actions from '../../../../redux/actions'; const LeftPane = (props) => { - const { hack, userCodeTab, changeUserCodeTab } = props; + const { hack, userCodeTab } = props; const { pass_count, submit_count } = hack; - const [defaultActiveKey, setDefaultActiveKey] = useState('task'); + const [defaultActiveKey, setDefaultActiveKey] = useState('comment'); - console.log(pass_count, submit_count); - const tabArrs = [ - { title: '任务描述', key: 'task', content: () }, - { title: '提交记录', key: 'record', content: () }, - // { title: '评论', key: 'comment', content: () }, - ]; - const navItem = [ { title: '任务描述', @@ -38,38 +31,30 @@ const LeftPane = (props) => { { title: '提交记录', key: 'record' - } + }, + // { + // title: '评论', + // key: 'comment' + // } ]; const Comp = { task: (), - record: () + record: (), + comment: () }; useEffect(() => { + console.log('====>>>>', userCodeTab); setDefaultActiveKey(userCodeTab); }, [userCodeTab]) - // const tabs = tabArrs.map((tab) => { - // const Comp = tab.content; - // return ( - // - // { Comp } - // - // ) - // }); - - // // tab切换时 - // const handleTabChange = (key) => { - // // setDefaultActiveKey(key); - // changeUserCodeTab(key); - // } - const renderComp = useMemo(() => { return Comp[defaultActiveKey]; - }, [defaultActiveKey]); + }, [defaultActiveKey, setDefaultActiveKey]); const renderNavItem = navItem.map((item) => { + const _classes = item.key === defaultActiveKey ? 'add_editor_item active' : 'add_editor_item'; return (
  • { return ( - {/* - { tabs } - -
    -
    - - - -
    -
    - - - -
    -
    */}
      { renderNavItem }
    @@ -126,11 +96,6 @@ const LeftPane = (props) => {
  • - {/*
    - - - -
    */}
    ); diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/index.scss index 9e6f019f6..1582c033f 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/index.scss +++ b/public/react/src/modules/developer/studentStudy/leftpane/index.scss @@ -13,6 +13,8 @@ bottom: 0px; height: 56px; width: 100%; + box-sizing: border-box; + border-top: 1px solid rgba(244,244,244,1); // background: pink; padding: 0 30px; // background-color: rgba(250,250,250,1); @@ -79,4 +81,9 @@ margin-right: 5px; } } +} + +.add_editor_list_area{ + box-sizing: border-box; + border-bottom: 1px solid rgba(244,244,244,1); } \ No newline at end of file diff --git a/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js b/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js index 28fe51765..981770b8c 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/taskDescription/index.js @@ -4,14 +4,15 @@ * @Github: * @Date: 2019-11-27 09:49:30 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-09 19:21:55 + * @LastEditTime: 2019-12-19 09:22:52 */ import '../index.scss'; import React from 'react'; import { Tag } from 'antd'; import { Link } from 'react-router-dom'; import { connect } from 'react-redux'; -import QuillEditor from '../../../quillEditor'; +import QuillForEditor from '../../../../../common/quillForEditor'; + import CONST from '../../../../../constants'; const {tagBackground, diffText} = CONST; @@ -36,22 +37,15 @@ const TaskDescription = (props) => {

    出题者: - {username} + {username}

    -
    - {/* */} - {/*
    */} ) } diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js index 669a8a693..af46d0aef 100644 --- a/public/react/src/modules/developer/studentStudy/rightpane/index.js +++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 14:59:51 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-13 16:50:40 + * @LastEditTime: 2019-12-19 19:13:05 */ import React, { useState, useEffect } from 'react'; import {connect} from 'react-redux'; @@ -20,8 +20,11 @@ const RightPane = (props) => { submitUserCode, input, hack, + notice, updateCode, + hadCodeUpdate, editor_code, + updateNotice, saveUserInputCode, restoreInitialCode, saveUserCodeForInterval @@ -29,6 +32,7 @@ const RightPane = (props) => { const [editorCode, setEditorCode] = useState(''); + let initFlag = true; useEffect(() => { if (editor_code) { setEditorCode(editor_code); @@ -48,7 +52,12 @@ const RightPane = (props) => { // 代码块内容变化时 const handleCodeChange = (code) => { // 保存用户提交的代码块 - console.log(code); + setEditorCode(code); + // 第一次回填代码内容时不更新; + if (initFlag) { + initFlag = false; + return; + } if (!timer) { timer = setInterval(() => { clearInterval(timer); @@ -69,13 +78,21 @@ const RightPane = (props) => { restoreInitialCode(identifier, '恢复初始代码成功'); } + // 更新代码 + const handleUpdateNotice = () => { + updateNotice && updateNotice(); + }; + return (
    { const mapStateToProps = (state) => { - const {user_program_identifier, hack, userTestInput, editor_code} = state.ojForUserReducer; + const { + user_program_identifier, + hack, + userTestInput, + editor_code, + notice, + hadCodeUpdate + } = state.ojForUserReducer; // const { language, code } = hack; return { hack, + notice, + hadCodeUpdate, editor_code, input: userTestInput, submitInput: hack.input, diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index b498c4d22..672fff455 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -58,15 +58,6 @@ class TPMBanner extends Component { } } - // star_info:[0, 0, 0, 0, 0, 0], - // star_infos:[0, 0, 0, 0, 0, 0], - // shixunsDetails:{}, - // shixunId: undefined, - // componentWillReceiveProps(newProps, newContext){ - // this.setState({ - // shixunsDetails: newProps.shixunsDetails - // }); - // } IEVersion = () => { var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串 @@ -118,31 +109,50 @@ class TPMBanner extends Component { if (prevProps != this.props) { let shixunopenprocess=window.localStorage.shixunopenprocess; let openopenpublictype=window.localStorage.openopenpublictype; - if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 0 && this.props.identity < 5){ - if(shixunopenprocess===undefined||shixunopenprocess===false){ - this.setState({ - openknow:true - }) - }else{ - this.setState({ - openknow:false - }) + if(this.props.status===0&&this.props.openknows===false){ + + if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 0 && this.props.identity < 5){ + if(shixunopenprocess===undefined||shixunopenprocess===false){ + this.setState({ + openknow:true + }) + }else{ + this.setState({ + openknow:false + }) + } } + }else{ + this.setState({ + openknow:false + }) } - if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 2 && this.props.shixunsDetails&&this.props.shixunsDetails.public===0 && this.props.identity < 5){ - if(openopenpublictype===undefined||openopenpublictype===false){ - this.setState({ - openshowpublictype:true - }) - }else{ - this.setState({ - openshowpublictype:false - }) + + + if(this.props.public===0&&this.props.status>1&&this.props.openknows===false){ + if(this.props.shixunsDetails&&this.props.shixunsDetails.shixun_status === 2 && this.props.shixunsDetails&&this.props.shixunsDetails.public===0 && this.props.identity < 5){ + if(openopenpublictype===undefined||openopenpublictype===false){ + this.setState({ + openshowpublictype:true + }) + }else{ + this.setState({ + openshowpublictype:false + }) + } } + }else{ + this.setState({ + openshowpublictype:false + }) } + + } } + + componentDidMount() { let thiisie = this.IEVersion(); @@ -155,6 +165,7 @@ class TPMBanner extends Component { isIE: false }) } + } /* @@ -784,7 +795,8 @@ class TPMBanner extends Component { }; // // console.log(this.props.shixunsDetails&&this.props.shixunsDetails.is_jupyter) - + // console.log(this.props) + // console.log(this.state) return ( shixunsDetails === undefined ? "" : @@ -796,6 +808,9 @@ class TPMBanner extends Component { height: 180px !important; padding-top:35px !important; } + .ant-popover{ + z-index:1000 !important; + } ` } diff --git a/public/react/src/modules/tpm/TPMIndex.js b/public/react/src/modules/tpm/TPMIndex.js index d79bae95b..c44d8ce51 100644 --- a/public/react/src/modules/tpm/TPMIndex.js +++ b/public/react/src/modules/tpm/TPMIndex.js @@ -207,6 +207,7 @@ class TPMIndex extends Component { propaedeutics:response.data.propaedeutics, status: response.data.shixun_status, secret_repository: response.data.secret_repository, + public:response.data.public, is_jupyter:response.data.is_jupyter=== undefined||response.data.is_jupyter===null?false:response.data.is_jupyter, }); @@ -295,10 +296,6 @@ class TPMIndex extends Component { // this.getnavdatas() } - // componentDidUpdate=()=>{ - // this.getnavdatas() - // } - setLoadingContent = (isLoadingContent) => { this.setState({ loadingContent: isLoadingContent }) } @@ -307,9 +304,6 @@ class TPMIndex extends Component { getnavdatas=()=>{ let selectedKeys; const {location} = this.props; - - console.log(location.pathname) - if(location.pathname.indexOf('/challenges')!=-1){ selectedKeys="1" }else if(location.pathname.indexOf('/propaedeutics')!=-1){ @@ -385,6 +379,9 @@ class TPMIndex extends Component { margin:0 40px 0 0; padding:0px; } + .ant-popover{ + z-index:1000 !important; + } ` } diff --git a/public/react/src/modules/tpm/TPMsettings/LearningSettings.js b/public/react/src/modules/tpm/TPMsettings/LearningSettings.js index 681cbc956..a98f68223 100644 --- a/public/react/src/modules/tpm/TPMsettings/LearningSettings.js +++ b/public/react/src/modules/tpm/TPMsettings/LearningSettings.js @@ -215,9 +215,9 @@ export default class Shixuninformation extends Component { multi_webssh: false }) } else { - this.setState({ - multi_webssh: true - }) + // this.setState({ + // multi_webssh: true + // }) } this.setState({ opensshRadio: e.target.value diff --git a/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js b/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js index 200880019..66e1da8dd 100644 --- a/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js +++ b/public/react/src/modules/tpm/TPMsettings/Shixuninformation.js @@ -50,6 +50,14 @@ class Shixuninformation extends Component { } componentDidMount() { + let query=this.props.location.search + const types = query.split('?edit=') + if(types[1]==="1"){ + let anchorElement = document.getElementById("newcourseContentMD"); + if(anchorElement){ + this.scrollToAnchor("newcourseContentMD"); + } + } } @@ -113,6 +121,7 @@ class Shixuninformation extends Component { selectright: this.props.data && this.props.data.shixun.choice_small_type, }) this.contentMdRef.current.setValue(this.props.data && this.props.data.shixun.description); + } } } @@ -807,16 +816,20 @@ class Shixuninformation extends Component { )} + + + diff --git a/public/react/src/modules/tpm/challengesnew/TPManswer.js b/public/react/src/modules/tpm/challengesnew/TPManswer.js index 9c9a23a12..9187e09b0 100644 --- a/public/react/src/modules/tpm/challengesnew/TPManswer.js +++ b/public/react/src/modules/tpm/challengesnew/TPManswer.js @@ -302,11 +302,11 @@ export default class TPManswer extends Component { className="color-grey-6 fr font-15 mt3">返回 {prev_challenge === undefined ? "" : - 上一关 + 上一关 } {next_challenge === undefined ? "" : - 下一关 + 下一关 } 返回 {prev_challenge === undefined ? "" : - 上一关 + 上一关 } {next_challenge === undefined ? "" : - 下一关 + 下一关 } 返回 { next_challenge===undefined?"": - 下一关 + 下一关 } { prev_challenge===undefined?"": - 上一关 + 上一关 } diff --git a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js index d70f22a0a..34eb1a075 100644 --- a/public/react/src/modules/tpm/challengesnew/TPMevaluation.js +++ b/public/react/src/modules/tpm/challengesnew/TPMevaluation.js @@ -824,11 +824,11 @@ export default class TPMevaluation extends Component { className="color-grey-6 fr font-15 mt3">返回 {prev_challenge === undefined ? "" : - 上一关 + 上一关 } {next_challenge === undefined ? "" : - 下一关 + 下一关 } 返回 { prev_challenge===undefined?"": - 上一关 + 上一关 } { next_challenge===undefined?"": - 下一关 + 下一关 } { @@ -97,11 +99,11 @@ class TPMRightSection extends Component {
    - {TPMRightSectionData&&TPMRightSectionData.complete_count!=null?
    + {this.props&&this.props.status>1?
    学习统计 - 已完成 {TPMRightSectionData&&TPMRightSectionData.complete_count} 个 / 共 {TPMRightSectionData&&TPMRightSectionData.challenge_count} 关 + 已完成 {TPMRightSectionData&&TPMRightSectionData.complete_count===null?0:TPMRightSectionData&&TPMRightSectionData.complete_count} 个 / 共 {TPMRightSectionData&&TPMRightSectionData.challenge_count} 关
    diff --git a/public/react/src/modules/tpm/component/TPMright.css b/public/react/src/modules/tpm/component/TPMright.css index a75160bf5..0d6b306fd 100644 --- a/public/react/src/modules/tpm/component/TPMright.css +++ b/public/react/src/modules/tpm/component/TPMright.css @@ -119,9 +119,14 @@ .padd252020px{ padding: 25px 20px 15px; } + .rightjinengs{ height: 35px; margin-top: 20px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; } .borderbottomf4{ diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js index 307823ee8..548e7224a 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js @@ -34,7 +34,8 @@ class Challenges extends Component { operationstrue:false, isSpin:false, boxoffsetHeigh:0, - opentitletype:true + opentitletype:true, + isopentitletype:"Less", } } @@ -52,6 +53,13 @@ class Challenges extends Component { ChallengesDataList: response.data, sumidtype: false, }); + + if(response.data.description=== ""||response.data.description===null||response.data.description===undefined){ + this.setState({ + isopentitletype:"Less", + }) + } + } } }).catch((error) => { @@ -71,17 +79,19 @@ class Challenges extends Component { let box=document.getElementById("shixunchallengesid"); if(box){ boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh<260){ + if(boxoffsetHeigh<300){ this.setState({ - opentitletype:false, + isopentitletype:"Less", boxoffsetHeigh:boxoffsetHeigh }) }else{ this.setState({ + opentitletype:true, + isopentitletype:"greater", boxoffsetHeigh:boxoffsetHeigh }) } - + console.log(boxoffsetHeigh) } } @@ -322,7 +332,8 @@ class Challenges extends Component { opentitle=()=>{ this.setState({ - opentitletype:!this.state.opentitletype + opentitletype:!this.state.opentitletype, + }) } @@ -334,6 +345,7 @@ class Challenges extends Component { } let id = this.props.match.params.shixunId; const antIcon = ; + return ( {AccountProfiletype===true?简介 {this.props.identity < 5 && ChallengesDataList&&ChallengesDataList.shixun_status < 3 ? - +
    {/**/} 编辑 - :""} + :""} {this.props.user && this.props.user.main_site === true ? this.props.identity < 5?实训制作指南 : "":""} @@ -407,7 +419,7 @@ class Challenges extends Component { { ` #shixunchallengesid{ - max-height: 260px; + max-height: 300px; overflow: hidden; } ` @@ -427,14 +439,22 @@ class Challenges extends Component {
    -

    + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined? +

    + {this.props.identity < 5?:} +

    暂时还没有相关数据哦!

    +
    + :

    {ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":

    } -

    +

    }
    - {this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> + + {this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 阅读全文 :this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 收起全文 diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index fcdbed408..e04ad17c9 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { Link } from "react-router-dom"; -import { markdownToHTML, configShareForCustom} from 'educoder' +import { markdownToHTML, configShareForCustom,getImageUrl} from 'educoder' import { Divider, Tooltip } from 'antd'; import LoadingSpin from '../../../../common/LoadingSpin'; import 'antd/lib/pagination/style/index.css'; @@ -23,7 +23,8 @@ class Challengesjupyter extends Component { booljupyterurls:false, loading:false, boxoffsetHeigh:0, - opentitletype:true + opentitletype:true, + isopentitletype:"Less", } } @@ -41,6 +42,11 @@ class Challengesjupyter extends Component { ChallengesDataList: response.data, sumidtype: false, }); + if(response.data.description=== ""||response.data.description===null||response.data.description===undefined){ + this.setState({ + isopentitletype:"Less", + }) + } } } }).catch((error) => { @@ -55,13 +61,15 @@ class Challengesjupyter extends Component { let box=document.getElementById("shixunchallengesid"); if(box){ boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh<260){ + if(boxoffsetHeigh<300){ this.setState({ - opentitletype:false, + isopentitletype:"Less", boxoffsetHeigh:boxoffsetHeigh }) }else{ this.setState({ + isopentitletype:"greater", + opentitletype:true, boxoffsetHeigh:boxoffsetHeigh }) } @@ -219,17 +227,17 @@ class Challengesjupyter extends Component {
    简介 - + 编辑 - +
    {this.state.opentitletype===true?:""} + :"":}
    :""} +
    + + + + {this.state.isopentitletype==="greater"&&this.state.opentitletype===true? + :""} + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""}
    diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index e04ad17c9..6ed139bc4 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -53,27 +53,47 @@ class Challengesjupyter extends Component { //console.log(error) }); } + + + getjianjiesize=()=>{ + let {ChallengesDataList}=this.state; + let boxoffsetHeigh; + let box=document.getElementById("shixunchallengesid"); + + if(box){ + boxoffsetHeigh=box.offsetHeight + if(ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined){ + + }else{ + if(this.state.isopentitletype==="greater"){ + + }else{ + if(boxoffsetHeigh>=300){ + this.setState({ + opentitletype:true, + isopentitletype:"greater", + boxoffsetHeigh:boxoffsetHeigh + }) + }else{ + this.setState({ + isopentitletype:"Less", + boxoffsetHeigh:boxoffsetHeigh + }) + } + } + + } + + } + } componentDidUpdate = (prevProps,prevState) => { //防止陷入无限循环 if(prevState.ChallengesDataList!=this.state.ChallengesDataList){ - let boxoffsetHeigh; - let box=document.getElementById("shixunchallengesid"); - if(box){ - boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh<300){ - this.setState({ - isopentitletype:"Less", - boxoffsetHeigh:boxoffsetHeigh - }) - }else{ - this.setState({ - isopentitletype:"greater", - opentitletype:true, - boxoffsetHeigh:boxoffsetHeigh - }) - } + if(this.state.isopentitletype==="greater"){ + }else{ + this.getjianjiesize() } } @@ -122,6 +142,8 @@ class Challengesjupyter extends Component { }, 600) }); + + this.getjianjiesize() } updatamakedowns = () => { @@ -233,18 +255,30 @@ class Challengesjupyter extends Component {
    - {this.state.opentitletype===true?:""} + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} -
    - + } + :""}

    {/*{ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":*/} From 841a9fea0b0bf2e4118500934dc08cfce146dd5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Fri, 20 Dec 2019 11:31:22 +0800 Subject: [PATCH 43/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tpm/shixunchild/Challenges/Challenges.js | 24 +++++++------ .../Challenges/Challengesjupyter.js | 35 ++++++++++++------- 2 files changed, 36 insertions(+), 23 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js index b1340c0de..239b46fd8 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js @@ -459,8 +459,19 @@ class Challenges extends Component { } + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} + - {this.state.isopentitletype==="greater"&&this.state.opentitletype===true? + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?"":this.state.isopentitletype==="greater"&&this.state.opentitletype===true? :""} - {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} +

    diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index 6ed139bc4..ca1e9d2ff 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -47,6 +47,7 @@ class Challengesjupyter extends Component { isopentitletype:"Less", }) } + this.getjianjiesize() } } }).catch((error) => { @@ -142,8 +143,8 @@ class Challengesjupyter extends Component { }, 600) }); + setTimeout(this.getjianjiesize(), 1000); - this.getjianjiesize() } updatamakedowns = () => { @@ -257,18 +258,16 @@ class Challengesjupyter extends Component {
    + - {this.state.isopentitletype==="greater"&&this.state.opentitletype===true? - :""} {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?"":this.state.isopentitletype==="greater"&&this.state.opentitletype===true? + :""} +

    {/*{ChallengesDataList === undefined ? "" :ChallengesDataList&&ChallengesDataList.description===null?"":*/} From 981a5b97a68f996d49718eac485ce14718f14a2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Fri, 20 Dec 2019 11:40:07 +0800 Subject: [PATCH 44/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/TPMBanner.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index da48a5b19..cde68f0b6 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -1016,8 +1016,8 @@ class TPMBanner extends Component { -

    您编辑完成后,可以马上使用到自
    -
    己的课堂和实训课程哦
    +
    点击发布后,可以马上应用到自
    +
    己的课堂和课程
    } From 45b63bdb793f9a9056bbe02a40522a1391b61b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Fri, 20 Dec 2019 11:57:39 +0800 Subject: [PATCH 45/61] =?UTF-8?q?=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../users/get_navigation_info.json.jbuilder | 4 +- public/react/src/college/College.js | 6 +- .../modules/developer/recordDetail/index.js | 5 +- public/react/src/modules/tpm/NewHeader.js | 2 +- public/react/src/modules/tpm/TPMBanner.js | 10 +- public/react/src/modules/tpm/TPMDataset.js | 2 +- .../tpm/shixunchild/Challenges/Challenges.js | 104 ++++++---- .../Challenges/Challengesjupyter.js | 98 ++++++--- public/react/src/redux/actions/ojForUser.js | 193 +++++++++--------- public/react/src/services/ojService.js | 5 +- 10 files changed, 254 insertions(+), 175 deletions(-) diff --git a/app/views/users/get_navigation_info.json.jbuilder b/app/views/users/get_navigation_info.json.jbuilder index c507f7ef8..a0f10677c 100644 --- a/app/views/users/get_navigation_info.json.jbuilder +++ b/app/views/users/get_navigation_info.json.jbuilder @@ -41,7 +41,9 @@ json.top do json.old_url @old_domain # 云上实验室管理权限 - json.laboratory_user current_laboratory.laboratory_users.exists?(user_id: @user&.id) || @user&.admin_or_business? + laboratory_user = current_laboratory.laboratory_users.exists?(user_id: @user&.id) || @user&.admin_or_business? + json.laboratory_user laboratory_user + json.laboratory_admin_url laboratory_user ? "/cooperative" : nil end json.down do diff --git a/public/react/src/college/College.js b/public/react/src/college/College.js index bc43252b7..fb116429d 100644 --- a/public/react/src/college/College.js +++ b/public/react/src/college/College.js @@ -45,11 +45,13 @@ class College extends Component { align: 'center', className: "edu-txt-center font-14 maxnamewidth340", render: (text, record) => ( - + { record.teachers } - + ) }, { diff --git a/public/react/src/modules/developer/recordDetail/index.js b/public/react/src/modules/developer/recordDetail/index.js index 1951b7712..7a3fc13e1 100644 --- a/public/react/src/modules/developer/recordDetail/index.js +++ b/public/react/src/modules/developer/recordDetail/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-12-04 08:36:21 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-10 18:55:02 + * @LastEditTime: 2019-12-20 10:38:00 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -79,7 +79,7 @@ function RecordDetail (props) {
    - 状态: {reviewResult[detail.status]} + 状态: {reviewResult[detail.status]} 提交时间: @@ -89,6 +89,7 @@ function RecordDetail (props) { 语言: C + {/* */}
    diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js index 06369d3d2..84354369c 100644 --- a/public/react/src/modules/tpm/NewHeader.js +++ b/public/react/src/modules/tpm/NewHeader.js @@ -1218,7 +1218,7 @@ submittojoinclass=(value)=>{ } { this.props.Headertop && this.props.Headertop.laboratory_user && -
  • 后台管理
  • +
  • 后台管理
  • }
  • 账号管理
  • diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index 672fff455..579e0a84a 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -148,7 +148,7 @@ class TPMBanner extends Component { }) } - + } } @@ -866,6 +866,8 @@ class TPMBanner extends Component { + { + this.props.is_jupyter===true?"": @@ -930,7 +932,7 @@ class TPMBanner extends Component {
    - + } { @@ -1014,8 +1016,8 @@ class TPMBanner extends Component { -
    您编辑完成后,可以马上使用到自
    -
    己的课堂和实训课程哦
    +
    点击发布后,可以马上应用到自
    +
    己的课堂和课程
    } diff --git a/public/react/src/modules/tpm/TPMDataset.js b/public/react/src/modules/tpm/TPMDataset.js index 85ce2006e..55cd8c746 100644 --- a/public/react/src/modules/tpm/TPMDataset.js +++ b/public/react/src/modules/tpm/TPMDataset.js @@ -461,7 +461,7 @@ class TPMDataset extends Component { const uploadProps = { width: 600, fileList, - multiple: false, + multiple: true, //multiple 是否支持多选 查重的时候不能多选 不然弹许多框出来 // https://github.com/ant-design/ant-design/issues/15505 // showUploadList={false},然后外部拿到 fileList 数组自行渲染列表。 diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js index 772cd089a..d84817fe8 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challenges.js @@ -10,8 +10,6 @@ import { Modal, Spin, Tooltip ,message,Icon,Button,Divider} from 'antd'; import axios from 'axios'; -import 'antd/lib/pagination/style/index.css'; - import '../shixunchildCss/Challenges.css'; import AccountProfile from"../../../user/AccountProfile"; @@ -74,33 +72,48 @@ class Challenges extends Component { if(box){ boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh=300){ + this.setState({ + opentitletype:true, + isopentitletype:"greater", + boxoffsetHeigh:boxoffsetHeigh + }) + }else{ + this.setState({ + isopentitletype:"Less", + boxoffsetHeigh:boxoffsetHeigh + }) + } + } + } - console.log(boxoffsetHeigh) + } } componentDidMount() { - this.ChallengesList() + if(this.state.isopentitletype==="greater"){ + + }else { + this.ChallengesList() + } } componentDidUpdate = (prevProps,prevState) => { //防止陷入无限循环 if(prevState.ChallengesDataList!=this.state.ChallengesDataList){ - this.getjianjiesize() + if(this.state.isopentitletype==="greater"){ + + }else{ + this.getjianjiesize() + } } } @@ -341,7 +354,6 @@ class Challenges extends Component { opentitle=()=>{ this.setState({ opentitletype:!this.state.opentitletype, - isopentitletype:!this.state.opentitletype===false?"Less":"greater" }) } @@ -423,25 +435,7 @@ class Challenges extends Component { this.props.identity < 5?实训制作指南 : "":""}
    - {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?this.state.opentitletype===true?:"":} +
    + + + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} + + + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?"":this.state.isopentitletype==="greater"&&this.state.opentitletype===true? + :""} +
    @@ -471,7 +499,7 @@ class Challenges extends Component {
    - {this.state.isopentitletype==="Less"&&this.state.opentitletype===false?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> + {this.state.isopentitletype==="Less"?"":this.state.opentitletype===true?this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 阅读全文 :this.opentitle()} className={"pointer Breadcrumbfont color-grey-9 "}> 收起全文 diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index c68493163..d2376d616 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -48,33 +48,54 @@ class Challengesjupyter extends Component { isopentitletype:"Less", }) } + this.getjianjiesize() } } }).catch((error) => { //console.log(error) }); } + + + getjianjiesize=()=>{ + let {ChallengesDataList}=this.state; + let boxoffsetHeigh; + let box=document.getElementById("shixunchallengesid"); + + if(box){ + boxoffsetHeigh=box.offsetHeight + if(ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined){ + + }else{ + if(this.state.isopentitletype==="greater"){ + + }else{ + if(boxoffsetHeigh>=300){ + this.setState({ + opentitletype:true, + isopentitletype:"greater", + boxoffsetHeigh:boxoffsetHeigh + }) + }else{ + this.setState({ + isopentitletype:"Less", + boxoffsetHeigh:boxoffsetHeigh + }) + } + } + + } + + } + } componentDidUpdate = (prevProps,prevState) => { //防止陷入无限循环 if(prevState.ChallengesDataList!=this.state.ChallengesDataList){ - let boxoffsetHeigh; - let box=document.getElementById("shixunchallengesid"); - if(box){ - boxoffsetHeigh=box.offsetHeight - if(boxoffsetHeigh<300){ - this.setState({ - isopentitletype:"Less", - boxoffsetHeigh:boxoffsetHeigh - }) - }else{ - this.setState({ - isopentitletype:"greater", - opentitletype:true, - boxoffsetHeigh:boxoffsetHeigh - }) - } + if(this.state.isopentitletype==="greater"){ + }else{ + this.getjianjiesize() } } @@ -132,6 +153,8 @@ class Challengesjupyter extends Component { console.log("触发了jupytermessage"); that.modifyjupyter(); }); + setTimeout(this.getjianjiesize(), 1000); + } updatamakedowns = () => { @@ -220,6 +243,7 @@ class Challengesjupyter extends Component { } + render() { let{ChallengesDataList,booljupyterurls,enlarge}=this.state; let id = this.props.match.params.shixunId; @@ -252,17 +276,39 @@ class Challengesjupyter extends Component {
    - {this.state.opentitletype===true? + + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} -
    + } + :""} + {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?"":this.state.isopentitletype==="greater"&&this.state.opentitletype===true? + :""}

    @@ -341,11 +387,7 @@ class Challengesjupyter extends Component { : ( admin===true||business===true||mysidentity===true? -

    - -
    +

    任务详情

    (请将实训题目写在下方并保存)

    @@ -402,7 +444,7 @@ class Challengesjupyter extends Component { { admin===true||business===true||mysidentity===true?
    -
    +
    { this.state.jupyter_url===null || this.state.jupyter_url===undefined? ( diff --git a/public/react/src/redux/actions/ojForUser.js b/public/react/src/redux/actions/ojForUser.js index 9cb814d80..5484b6eec 100644 --- a/public/react/src/redux/actions/ojForUser.js +++ b/public/react/src/redux/actions/ojForUser.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:42:11 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 15:11:56 + * @LastEditTime: 2019-12-20 10:25:42 */ import types from "./actionTypes"; import { Base64 } from 'js-base64'; @@ -87,7 +87,7 @@ export const getUserProgramDetail = (identifier, type) => { type: types.SAVE_USE_TEST_CASE_VALUE, payload: data.test_case || {} }); - // 代码是否更新 + // 代码是否更新 let _modify_code = false; if (data.hack) { _modify_code = data.hack.modify_code; @@ -171,15 +171,103 @@ export const updateCode = (identifier, inputValue, type) => { } } +// 代码评测 +export const codeEvaluate = (dispatch, identifier, type, time_limit) => { + // 调试代码成功后,调用轮循接口, 注意: 代码执行的时间要小于设置的时间限制 + const intervalTime = 500; + let count = 1; + /** + * @param {*} excuteTime 执行时间 + * @param {*} finalTime 总时间 + * @param {*} count 执行次数 + * @param {*} timer 定时器 + */ + function getCodeSubmit (intervalTime, finalTime, count, timer){ + const excuteTime = (count++) * intervalTime; // 当前执行时间 + fetchCodeSubmit(identifier, { mode: type }).then(res => { + const { status } = res.data; // 评测返回结果 + // 清除定时器条件: 评测通过或者评测时间大于指定时间 + if (+status === 0 || (excuteTime / 1000) > (finalTime + 1)) { + clearInterval(timer); // 清除定时器 + timer = null; + let returnData = null; + if (status === 1) { // 结果没有返回 + returnData = { + error_line: -1, + error_msg: '', + execute_memory: '', + execute_time: finalTime, + input: '', + output: '', + status: 2, + expected_output: '' + }; + } else { // 成功返回结果 + returnData = res.data.data; + } + // 返回评测结果 + dispatch({ + type: types.COMMIT_RECORD_DETAIL, + payload: returnData + }); + if (!type || type === 'debug') { + dispatch({ // 改变 loading 值 + type: types.LOADING_STATUS, + payload: false + }); + // 保存执行状态 + dispatch({ + type: types.TEST_CODE_STATUS, + payload: 'finish' + }); + } else { + // 回滚提交按钮状态 + dispatch({ + type: types.SUBMIT_LOADING_STATUS, + payload: false + }); + // 改变tab值至提交记录(只在提交时才跳转,测评时,切换到代码执行结果就可以了) + dispatch({ + type: types.CHANGE_USER_CODE_TAB, + payload: 'record' + }); + // 重新调用一下提交记录接口 + dispatch(getUserCommitRecord(identifier)); + } + } + }).catch(err => { // 评测异常时 + // 清除定时器 + clearInterval(timer); + timer = null; + // 回滚按钮状态 + if (!type || type === 'debug') { + dispatch({ // 改变 loading 值 + type: types.LOADING_STATUS, + payload: false + }); + } else { // 回滚提交按钮状态 + dispatch({ + type: types.SUBMIT_LOADING_STATUS, + payload: false + }); + } + }); + } + // 开启定时器,调用监听接口 + let timer = setInterval(() => { + getCodeSubmit(intervalTime, time_limit, count++, timer); + }, intervalTime); +} + /** * @description 调试代码 - * @param {*} identifier + * @param {*} identifier * @param {*} inputValue 输入值: 自定义 | 系统返回的 * @param {*} type 测评类型 debug | submit */ export const debuggerCode = (identifier,value, type) => { return (dispatch, getState) => { - // 调用之前 先保存 code + // 调用之前 先保存 code // TODO // console.log(identifier, value); const {hack: {time_limit = 0}} = getState().ojForUserReducer; @@ -194,15 +282,6 @@ export const debuggerCode = (identifier,value, type) => { // console.log('调用调试代码成功并返回结果: ', res); const { status } = res; if (status === 200) { - // 调试代码成功后,调用轮循接口, 注意: 代码执行的时间要小于设置的时间限制 - const intervalTime = 500; - let count = 1; - /** - * @param {*} excuteTime 执行时间 - * @param {*} finalTime 总时间 - * @param {*} count 执行次数 - * @param {*} timer 定时器 - */ if (res.data.status === 401) { dispatch({ // 改变 loading 值 type: types.LOADING_STATUS, @@ -210,81 +289,8 @@ export const debuggerCode = (identifier,value, type) => { }); return; }; - function getCodeSubmit (intervalTime, finalTime, count, timer){ - const excuteTime = (count++) * intervalTime; // 当前执行时间 - fetchCodeSubmit(identifier, { mode: type }).then(res => { - const { status } = res.data; // 评测返回结果 - // 清除定时器条件: 评测通过或者评测时间大于指定时间 - if (+status === 0 || (excuteTime / 1000) > (finalTime + 1)) { - clearInterval(timer); // 清除定时器 - timer = null; - let returnData = null; - if (status === 1) { // 结果没有返回 - returnData = { - error_line: -1, - error_msg: '', - execute_memory: '', - execute_time: finalTime, - input: '', - output: '', - status: 2, - expected_output: '' - }; - } else { // 成功返回结果 - returnData = res.data.data; - } - // 返回评测结果 - dispatch({ - type: types.COMMIT_RECORD_DETAIL, - payload: returnData - }); - if (!type || type === 'debug') { - dispatch({ // 改变 loading 值 - type: types.LOADING_STATUS, - payload: false - }); - // 保存执行状态 - dispatch({ - type: types.TEST_CODE_STATUS, - payload: 'finish' - }); - } else { - // 回滚提交按钮状态 - dispatch({ - type: types.SUBMIT_LOADING_STATUS, - payload: false - }); - // 改变tab值至提交记录(只在提交时才跳转,测评时,切换到代码执行结果就可以了) - dispatch({ - type: types.CHANGE_USER_CODE_TAB, - payload: 'record' - }); - // 重新调用一下提交记录接口 - dispatch(getUserCommitRecord(identifier)); - } - } - }).catch(err => { // 评测异常时 - // 清除定时器 - clearInterval(timer); - timer = null; - // 回滚按钮状态 - if (!type || type === 'debug') { - dispatch({ // 改变 loading 值 - type: types.LOADING_STATUS, - payload: false - }); - } else { // 回滚提交按钮状态 - dispatch({ - type: types.SUBMIT_LOADING_STATUS, - payload: false - }); - } - }); - } - // 开启定时器,调用监听接口 - let timer = setInterval(() => { - getCodeSubmit(intervalTime, time_limit, count++, timer); - }, intervalTime); + // 测评 + codeEvaluate(dispatch, identifier, type, time_limit); } }).catch(() => { dispatch({ @@ -362,7 +368,8 @@ export const changeUserCodeTab = (key) => { */ export const submitUserCode = (identifier, inputValue, type) => { return (dispatch, getState) => { - const { userCode, isUpdateCode } = getState().ojForUserReducer; + const { userCode, isUpdateCode, hack: {time_limit = 0} } = getState().ojForUserReducer; + function userCodeSubmit () { fetchUserCodeSubmit(identifier).then(res => { // console.log('用户提交代码成功======》》》》》', res); @@ -374,12 +381,8 @@ export const submitUserCode = (identifier, inputValue, type) => { }); return; }; - // 将编辑代码清空 - dispatch({ - type: types.SAVE_EDITOR_CODE, - payload: '' - }); - dispatch(debuggerCode(identifier, inputValue, type || 'submit')); + // 测评 + codeEvaluate(dispatch, identifier, type, time_limit); } }).catch(() => { dispatch({ diff --git a/public/react/src/services/ojService.js b/public/react/src/services/ojService.js index 373805b73..e552c1211 100644 --- a/public/react/src/services/ojService.js +++ b/public/react/src/services/ojService.js @@ -4,11 +4,10 @@ * @Github: * @Date: 2019-11-20 10:55:38 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-17 14:10:37 + * @LastEditTime: 2019-12-20 10:10:53 */ import axios from 'axios'; -import { func } from 'prop-types'; export async function fetchOJList (params) { console.log('传递的参数: ', params); @@ -137,4 +136,4 @@ export async function fetchUploadImage (file) { export async function fetchUploadImageUrl (id) { const url = `/attachments/${id}`; return axios.get(url); -} +} From b7abe189bff2d22c6017d74d577aa7567b2331e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 13:02:54 +0800 Subject: [PATCH 46/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tpm/shixunchild/Challenges/Challengesjupyter.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index c68493163..8e03f75e9 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -125,13 +125,13 @@ class Challengesjupyter extends Component { }); - - - window.addEventListener('jupytermessage', (e) => { + let self = this; //为了避免作用域及缓存 + window.receiveMessageFromIndex = function ( event ) { console.log("触发了jupytermessage"); console.log("触发了jupytermessage"); - that.modifyjupyter(); - }); + } + //监听message事件 + window.addEventListener("message", receiveMessageFromIndex, false); } updatamakedowns = () => { From 1954a2467c0228376eab88349f2cdc925ae18439 Mon Sep 17 00:00:00 2001 From: tangjiang <465264938@qq.com> Date: Fri, 20 Dec 2019 13:03:55 +0800 Subject: [PATCH 47/61] update style --- .../modules/developer/recordDetail/index.js | 8 +++-- .../leftpane/commitRecord/index.js | 32 ++++++++++++------- .../leftpane/commitRecord/index.scss | 2 ++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/public/react/src/modules/developer/recordDetail/index.js b/public/react/src/modules/developer/recordDetail/index.js index 7a3fc13e1..e4002004a 100644 --- a/public/react/src/modules/developer/recordDetail/index.js +++ b/public/react/src/modules/developer/recordDetail/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-12-04 08:36:21 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-20 10:38:00 + * @LastEditTime: 2019-12-20 10:52:36 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -87,9 +87,11 @@ function RecordDetail (props) { - 语言: C + 语言: {detail.language} + + + 执行用时: {`${detail.execute_time && (+detail.execute_time * 1000)}ms`} - {/* */}
    diff --git a/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js b/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js index 7fc061765..7b6cce9f8 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 09:49:33 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-20 09:35:00 + * @LastEditTime: 2019-12-20 11:44:22 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -149,19 +149,27 @@ const CommitRecord = (props) => { setRenderCtx(() => (renderRecordDetail)) }, [commitRecordDetail]); // 复制功能 - + let count = 0; useEffect(() => { - if (!clipboard) { - clipboard = new ClipboardJS('.copy_error'); - } - if (commitRecordDetail.status !== 0) { - clipboard.on('success', (e) => { - message.success('复制成功'); - e.clearSelection(); - }); - } - }, [commitRecordDetail.status]); + clipboard = new ClipboardJS('.copy_error'); + clipboard.on('success', (e) => { + e.clearSelection(); + if (count > 0) return; + count++; + message.success('复制成功'); + setTimeout(() => { + message.destroy(); + }, 300); + }); + }, []); + // if (commitRecordDetail.status !== 0) { + // clipboard.on('success', (e) => { + // console.log('成功=====》》》》》'); + // message.success('复制成功'); + // e.clearSelection(); + // }); + // } // const handleTableChange = (pagination) => { setPagination(Object.assign({}, pagination)); diff --git a/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.scss index 283617445..fb099445e 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.scss +++ b/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.scss @@ -1,6 +1,8 @@ .commit_record_area{ // padding: 20px 30px; padding: 0 20px; + overflow-y: auto; + height: calc(100vh - 177px); .record_header{ display: flex; // justify-content: space-between; From baa5ec685d301249820dd75cf54bf25a928758ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 13:41:36 +0800 Subject: [PATCH 48/61] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/tpm/shixunchild/Challenges/Challengesjupyter.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index 0e243e6d8..ee3f9a0e9 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -152,8 +152,8 @@ class Challengesjupyter extends Component { window.addEventListener('message', (e) => { console.log("触发了jupytermessage"); - console.log("触发了jupytermessage"); - that.modifyjupyter(); + console.log(e); + // that.modifyjupyter(); }); setTimeout(this.getjianjiesize(), 1000); @@ -410,8 +410,6 @@ class Challengesjupyter extends Component {
    -
    - : "" ) From 8250d5fccb73a6fed9a2dffa5d13a488419501e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 13:48:39 +0800 Subject: [PATCH 49/61] =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=80=E4=B8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tpm/shixunchild/Challenges/Challengesjupyter.js | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index ee3f9a0e9..d03a0ea89 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -153,7 +153,15 @@ class Challengesjupyter extends Component { window.addEventListener('message', (e) => { console.log("触发了jupytermessage"); console.log(e); - // that.modifyjupyter(); + if(e){ + if(e.data){ + if(e.data==="jupytermessage"){ + that.modifyjupyter(); + } + } + + } + }); setTimeout(this.getjianjiesize(), 1000); From 1e078211b0ba325957c4a60042ec4f929ca8eebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 13:57:50 +0800 Subject: [PATCH 50/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/tpm/shixunchild/Challenges/Challengesjupyter.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index 861b93c88..e9674b2ac 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -413,9 +413,9 @@ class Challengesjupyter extends Component { marginLeft: '30px', }} onClick={()=>this.onclki(true)}> } -

    导入

    -
    + {/*
    导入

    */} + {/*
    */}
    : From a44e06b50671c91368329715440028b3595e79d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 14:12:00 +0800 Subject: [PATCH 51/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Challenges/Challengesjupyter.js | 234 +++++++----------- 1 file changed, 91 insertions(+), 143 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index e9674b2ac..d3aa910b8 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -8,7 +8,7 @@ import '../shixunchildCss/Challenges.css'; import axios from 'axios'; const $ = window.$; - +//12.20,14:11 class Challengesjupyter extends Component { constructor(props) { super(props) @@ -48,54 +48,33 @@ class Challengesjupyter extends Component { isopentitletype:"Less", }) } - this.getjianjiesize() } } }).catch((error) => { //console.log(error) }); } - - - getjianjiesize=()=>{ - let {ChallengesDataList}=this.state; - let boxoffsetHeigh; - let box=document.getElementById("shixunchallengesid"); - - if(box){ - boxoffsetHeigh=box.offsetHeight - if(ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined){ - - }else{ - if(this.state.isopentitletype==="greater"){ - - }else{ - if(boxoffsetHeigh>=300){ - this.setState({ - opentitletype:true, - isopentitletype:"greater", - boxoffsetHeigh:boxoffsetHeigh - }) - }else{ - this.setState({ - isopentitletype:"Less", - boxoffsetHeigh:boxoffsetHeigh - }) - } - } - - } - - } - } componentDidUpdate = (prevProps,prevState) => { //防止陷入无限循环 if(prevState.ChallengesDataList!=this.state.ChallengesDataList){ - if(this.state.isopentitletype==="greater"){ + let boxoffsetHeigh; + let box=document.getElementById("shixunchallengesid"); + if(box){ + boxoffsetHeigh=box.offsetHeight + if(boxoffsetHeigh<300){ + this.setState({ + isopentitletype:"Less", + boxoffsetHeigh:boxoffsetHeigh + }) + }else{ + this.setState({ + isopentitletype:"greater", + opentitletype:true, + boxoffsetHeigh:boxoffsetHeigh + }) + } - }else{ - this.getjianjiesize() } } @@ -105,9 +84,9 @@ class Challengesjupyter extends Component { setTimeout(this.ChallengesList(), 1000); let id = this.props.match.params.shixunId; let ChallengesURL = `/jupyters/get_info_with_tpm.json`; - let datas={ - identifier:id, - } + let datas={ + identifier:id, + } axios.get(ChallengesURL, {params: datas}).then((response) => { if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { setTimeout(() => { @@ -115,26 +94,26 @@ class Challengesjupyter extends Component { booljupyterurls:true, }) }, 600) + }else{ + if(response.data.status===0){ + + setTimeout(() => { + this.setState({ + jupyter_url:response.data.url, + jupyter_port:response.data.port, + booljupyterurls:true, + }) + }, 800) + }else{ - if(response.data.status===0){ - - setTimeout(() => { - this.setState({ - jupyter_url:response.data.url, - jupyter_port:response.data.port, - booljupyterurls:true, - }) - }, 800) - - }else{ - setTimeout(() => { - this.setState({ - booljupyterurls:true, - }) - }, 600) + setTimeout(() => { + this.setState({ + booljupyterurls:true, + }) + }, 600) - } } + } }).catch((error) => { @@ -145,10 +124,6 @@ class Challengesjupyter extends Component { }, 600) }); - setTimeout(this.getjianjiesize(), 1000); - - - window.addEventListener('message', (e) => { console.log("触发了jupytermessage"); @@ -163,8 +138,6 @@ class Challengesjupyter extends Component { } }); - setTimeout(this.getjianjiesize(), 1000); - } updatamakedowns = () => { @@ -218,13 +191,13 @@ class Challengesjupyter extends Component { modifyjupyter=()=>{ let id=this.props.match.params.shixunId; - var jupyter_port=""; - try{ - jupyter_port= parseInt(this.state.jupyter_port); - }catch (e) { - jupyter_port=this.state.jupyter_port; + var jupyter_port=""; + try{ + jupyter_port= parseInt(this.state.jupyter_port); + }catch (e) { + jupyter_port=this.state.jupyter_port; - } + } const url=`/jupyters/save_with_tpm.json`; const data={ identifier:id, @@ -234,7 +207,6 @@ class Challengesjupyter extends Component { .then((result) => { if (result.data.status === 0) { this.props.showNotification(`应用成功`); - console.log("触发了jupytermessage调用了应用成功"); } }).catch((error) => { }) @@ -245,15 +217,12 @@ class Challengesjupyter extends Component { opentitletype:!this.state.opentitletype }) } - onclki=(bool)=>{ this.setState({ enlarge:bool }) } - - render() { let{ChallengesDataList,booljupyterurls,enlarge}=this.state; let id = this.props.match.params.shixunId; @@ -263,8 +232,6 @@ class Challengesjupyter extends Component { const business = this.props&&this.props.current_user&&this.props.current_user.business?this.props.current_user.business:false; //管理员 const admin = this.props&&this.props.current_user&&this.props.current_user.admin?this.props.current_user.admin:false; - //用户 - const login = this.props&&this.props.current_user&&this.props.current_user.login?this.props.current_user.login:""; let mysidentity =false; try { @@ -286,39 +253,17 @@ class Challengesjupyter extends Component {
    - -
    - - - {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?:""} - {ChallengesDataList === undefined || ChallengesDataList&&ChallengesDataList.description=== ""||ChallengesDataList&&ChallengesDataList.description===null||ChallengesDataList&&ChallengesDataList.description===undefined?"":this.state.isopentitletype==="greater"&&this.state.opentitletype===true? - :""} + } + :""} +

    @@ -385,9 +330,8 @@ class Challengesjupyter extends Component { display: flex; flex-direction:row-reverse; } - ; - } + } ` } @@ -396,29 +340,33 @@ class Challengesjupyter extends Component { "" : ( - admin===true||business===true||mysidentity===true? -

    -
    -

    任务详情

    -

    (请将实训题目写在下方并保存)

    -
    -
    - { - enlarge===true? - this.onclki(false)}> - : - this.onclki(true)}> - } - {/*
    导入

    */} - {/*
    */} + admin===true||business===true||mysidentity===true? +
    + +
    +
    +

    任务详情

    +

    (请将实训题目写在下方并保存)

    +
    +
    + { + enlarge===true? + this.onclki(false)}> + : + this.onclki(true)}> + } + {/*
    this.modifyjupyter(this.state)}>导入

    */} + {/*
    */} +
    - : + + : "" ) @@ -450,25 +398,25 @@ class Challengesjupyter extends Component { } { - admin===true||business===true||mysidentity===true? -
    -
    - { - this.state.jupyter_url===null || this.state.jupyter_url===undefined? - ( - booljupyterurls===false? - - :"" - ) - : + admin===true||business===true||mysidentity===true? +
    +
    + { + this.state.jupyter_url===null || this.state.jupyter_url===undefined? + ( + booljupyterurls===false? + + :"" + ) + : - } -
    + }
    - :"" +
    + :"" }
    From 9bcc7c810630902274b7afc2837950969caffbe3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 14:15:45 +0800 Subject: [PATCH 52/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tpm/shixunchild/Challenges/Challengesjupyter.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index d3aa910b8..804c485b5 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -341,9 +341,11 @@ class Challengesjupyter extends Component { : ( admin===true||business===true||mysidentity===true? -
    +
    -
    +

    任务详情

    (请将实训题目写在下方并保存)

    @@ -359,7 +361,7 @@ class Challengesjupyter extends Component { marginLeft: '30px', }} onClick={()=>this.onclki(true)}> } - {/*
    this.modifyjupyter(this.state)}>导入

    */} {/*
    */}
    From 71551ec21d421b82b2c9001576d9ca4c9672791f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 14:43:25 +0800 Subject: [PATCH 53/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/tpm/shixunchild/Challenges/Challengesjupyter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index 804c485b5..5e26ac86e 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -206,7 +206,8 @@ class Challengesjupyter extends Component { axios.get(url, {params: data}) .then((result) => { if (result.data.status === 0) { - this.props.showNotification(`应用成功`); + // this.props.showNotification(`应用成功`); + console.log("应用成功了"); } }).catch((error) => { }) From 6912f31c767f254ed6c6a8e99105a58a0d679e95 Mon Sep 17 00:00:00 2001 From: tangjiang <465264938@qq.com> Date: Fri, 20 Dec 2019 14:56:07 +0800 Subject: [PATCH 54/61] update code --- .../components/controlSetting/index.js | 10 ++--- .../modules/developer/newOrEditTask/index.js | 4 +- .../modules/developer/studentStudy/index.js | 14 ++++-- .../leftpane/commitRecord/index.js | 15 ++++--- .../developer/studentStudy/rightpane/index.js | 6 ++- public/react/src/redux/actions/actionTypes.js | 2 + public/react/src/redux/actions/index.js | 4 ++ public/react/src/redux/actions/ojForUser.js | 23 +++++++++- .../src/redux/reducers/ojForUserReducer.js | 45 ++++++++++++++++--- 9 files changed, 100 insertions(+), 23 deletions(-) diff --git a/public/react/src/modules/developer/components/controlSetting/index.js b/public/react/src/modules/developer/components/controlSetting/index.js index 1d4d7834c..502f3ae09 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.js +++ b/public/react/src/modules/developer/components/controlSetting/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 16:02:36 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 19:47:32 + * @LastEditTime: 2019-12-20 14:37:39 */ import './index.scss'; import React, { useState, useRef, useEffect } from 'react'; @@ -24,7 +24,7 @@ const ControlSetting = (props) => { identifier, excuteState, showOrHideControl, - commitRecordDetail, + commitTestRecordDetail, changeLoadingState, changeSubmitLoadingStatus, changeShowOrHideControl, @@ -102,7 +102,7 @@ const ControlSetting = (props) => { @@ -137,14 +137,14 @@ const ControlSetting = (props) => { const mapStateToProps = (state) => { const {commonReducer, ojForUserReducer} = state; const {loading, excuteState, submitLoading, showOrHideControl } = commonReducer; - const { commitRecordDetail } = ojForUserReducer; + const { commitTestRecordDetail } = ojForUserReducer; return { loading, submitLoading, excuteState, showOrHideControl, // identifier: user_program_identifier, - commitRecordDetail // 提交详情 + commitTestRecordDetail // 提交详情 }; }; // changeSubmitLoadingStatus diff --git a/public/react/src/modules/developer/newOrEditTask/index.js b/public/react/src/modules/developer/newOrEditTask/index.js index 1c451c669..b498abe0d 100644 --- a/public/react/src/modules/developer/newOrEditTask/index.js +++ b/public/react/src/modules/developer/newOrEditTask/index.js @@ -70,13 +70,13 @@ const NewOrEditTask = (props) => { // 模拟挑战 const imitationChallenge = () => { // 调用 start 接口, 成功后跳转到模拟页面 - startProgramQuestion(identifier, props); + identifier && startProgramQuestion(identifier, props); } // 开始挑战 const startChallenge = () => { // 调用 start 接口, 成功后跳转到开启实战 // TODO - startProgramQuestion(identifier, props); + identifier && startProgramQuestion(identifier, props); } // 取消 diff --git a/public/react/src/modules/developer/studentStudy/index.js b/public/react/src/modules/developer/studentStudy/index.js index 15c87e64c..9039bf3ac 100644 --- a/public/react/src/modules/developer/studentStudy/index.js +++ b/public/react/src/modules/developer/studentStudy/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-23 10:53:19 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 19:48:20 + * @LastEditTime: 2019-12-20 14:54:39 */ import './index.scss'; import React, { useEffect, useState } from 'react'; @@ -92,9 +92,12 @@ function StudentStudy (props) { changeShowOrHideControl(false); props.saveEditorCodeForDetail(); props.history.push(`/problems/${_hack_id}/edit`); + props.clearOjForUserReducer(); } // 处理退出 const handleClickQuit = () => { + // 退出时,清空内容 + props.clearOjForUserReducer(); // 将控制台关闭 changeShowOrHideControl(false); props.saveEditorCodeForDetail(); @@ -116,7 +119,11 @@ function StudentStudy (props) {
    {/* to={`/problems/${_hack_id}/edit`} */} - + 编辑 {/* to="/problems" */} @@ -168,7 +175,8 @@ const mapDispatchToProps = (dispatch) => ({ saveEditorCodeForDetail: (code) => dispatch(actions.saveEditorCodeForDetail(code)), // 恢复初始代码 restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)), - changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)) + changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)), + clearOjForUserReducer: () => dispatch(actions.clearOjForUserReducer()) }); export default withRouter(connect( diff --git a/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js b/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js index 7b6cce9f8..90c486cca 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js +++ b/public/react/src/modules/developer/studentStudy/leftpane/commitRecord/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 09:49:33 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-20 11:44:22 + * @LastEditTime: 2019-12-20 13:55:07 */ import './index.scss'; import React, { useState, useEffect } from 'react'; @@ -73,6 +73,7 @@ const CommitRecord = (props) => { commitRecord, // excuteState, language, + operateType, commitRecordDetail, getUserCommitRecord } = props; @@ -146,8 +147,10 @@ const CommitRecord = (props) => { // 提交详情变化时,显示当前提交信息 useEffect(() => { // setRecordDetail(commitRecordDetail); - setRenderCtx(() => (renderRecordDetail)) - }, [commitRecordDetail]); + if (operateType === 'submit') { + setRenderCtx(() => (renderRecordDetail)) + } + }, [commitRecordDetail, operateType]); // 复制功能 let count = 0; useEffect(() => { @@ -198,7 +201,8 @@ const mapStateToProps = (state) => { user_program_identifier, commitRecordDetail, commitRecord, - hack + hack, + operateType } = ojForUserReducer; const { excuteState } = commonReducer; return { @@ -206,7 +210,8 @@ const mapStateToProps = (state) => { commitRecordDetail, commitRecord, // 提交记录 excuteState, // 代码执行状态 - language: hack.language + language: hack.language, + operateType } } const mapDispatchToProps = (dispatch) => ({ diff --git a/public/react/src/modules/developer/studentStudy/rightpane/index.js b/public/react/src/modules/developer/studentStudy/rightpane/index.js index af46d0aef..054997359 100644 --- a/public/react/src/modules/developer/studentStudy/rightpane/index.js +++ b/public/react/src/modules/developer/studentStudy/rightpane/index.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 14:59:51 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 19:13:05 + * @LastEditTime: 2019-12-20 14:01:57 */ import React, { useState, useEffect } from 'react'; import {connect} from 'react-redux'; @@ -27,6 +27,7 @@ const RightPane = (props) => { updateNotice, saveUserInputCode, restoreInitialCode, + saveOpacityType, saveUserCodeForInterval } = props; @@ -43,6 +44,7 @@ const RightPane = (props) => { const handleSubmitForm = () => { // 提交时, 先调用提交接口,提交成功后,循环调用测评接口 + // saveOpacityType('submit'); submitUserCode(identifier, submitInput, 'submit'); // // 提交时,先调用评测接口, 评测通过后才调用保存接口 // updateCode(identifier, submitInput, 'submit'); @@ -71,6 +73,7 @@ const RightPane = (props) => { // 代码调试 const handleDebuggerCode = (value) => { // 调用保存代码块接口,成功后,调用调试接口 + // saveOpacityType('debug'); updateCode(identifier, value, 'debug'); } // 恢复初始代码 @@ -137,6 +140,7 @@ const mapDispatchToProps = (dispatch) => ({ saveUserCodeForInterval: (identifier, code) => dispatch(actions.saveUserCodeForInterval(identifier, code)), // 恢复初始代码 restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)), + // saveOpacityType: (type) => dispatch(actions.saveOpacityType(type)) }); export default connect( diff --git a/public/react/src/redux/actions/actionTypes.js b/public/react/src/redux/actions/actionTypes.js index 1129a3235..144558c1d 100644 --- a/public/react/src/redux/actions/actionTypes.js +++ b/public/react/src/redux/actions/actionTypes.js @@ -51,6 +51,8 @@ const types = { SAVE_USER_INFO: 'SAVE_USER_INFO', // 只在用户信息 SAVE_HACK_IDENTIFIER: 'SAVE_HACK_IDENTIFIER', // 用户界面跑到编辑界面需要用的id值 SAVE_EDITOR_CODE: 'SAVE_EDITOR_CODE', // 保存详情页面中编辑时的代码 + CLICK_OPERATE_TYPE: 'CLICK_OPERATE_TYPE', // 点击类型 + CLEAR_OJ_FOR_USER_REDUCER: 'CLEAR_OJ_FOR_USER_REDUCER', // 退出时清空 ojForUserReducer保存内容 /*** jupyter */ GET_JUPYTER_DATA_SETS: 'GET_JUPYTER_DATA_SETS', // jupyter 数据集 GET_JUPYTER_TPI_URL: 'GET_JUPYTER_TPI_URL', // 获取 jupyter url diff --git a/public/react/src/redux/actions/index.js b/public/react/src/redux/actions/index.js index b42c4c2b6..93a0788cf 100644 --- a/public/react/src/redux/actions/index.js +++ b/public/react/src/redux/actions/index.js @@ -48,6 +48,8 @@ import { restoreInitialCode, saveUserCodeForInterval, saveEditorCodeForDetail, + saveOpacityType, + clearOjForUserReducer // isUpdateCodeCtx } from './ojForUser'; @@ -116,6 +118,8 @@ export default { getUserInfoForNew, saveUserCodeForInterval, saveEditorCodeForDetail, + saveOpacityType, + clearOjForUserReducer, // jupyter getJupyterTpiDataSet, getJupyterTpiUrl, diff --git a/public/react/src/redux/actions/ojForUser.js b/public/react/src/redux/actions/ojForUser.js index 994830280..89d826e69 100644 --- a/public/react/src/redux/actions/ojForUser.js +++ b/public/react/src/redux/actions/ojForUser.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:42:11 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-20 10:25:42 + * @LastEditTime: 2019-12-20 14:47:26 */ import types from "./actionTypes"; import { Base64 } from 'js-base64'; @@ -208,7 +208,10 @@ export const codeEvaluate = (dispatch, identifier, type, time_limit) => { // 返回评测结果 dispatch({ type: types.COMMIT_RECORD_DETAIL, - payload: returnData + payload: { + type, + data: returnData + } }); if (!type || type === 'debug') { dispatch({ // 改变 loading 值 @@ -233,6 +236,7 @@ export const codeEvaluate = (dispatch, identifier, type, time_limit) => { }); // 重新调用一下提交记录接口 dispatch(getUserCommitRecord(identifier)); + dispatch(saveOpacityType(type)); } } }).catch(err => { // 评测异常时 @@ -454,5 +458,20 @@ export const saveEditorCodeForDetail = (code) => { } } +// 保存操作类型: 提交或调试 +export const saveOpacityType = (type) => { + return { + type: types.CLICK_OPERATE_TYPE, + payload: type + } +} + + +export const clearOjForUserReducer = () => { + return { + type: types.CLEAR_OJ_FOR_USER_REDUCER + }; +} + // 更新通知状态 diff --git a/public/react/src/redux/reducers/ojForUserReducer.js b/public/react/src/redux/reducers/ojForUserReducer.js index 0c7594dd2..7e3740c19 100644 --- a/public/react/src/redux/reducers/ojForUserReducer.js +++ b/public/react/src/redux/reducers/ojForUserReducer.js @@ -4,7 +4,7 @@ * @Github: * @Date: 2019-11-27 13:41:48 * @LastEditors: tangjiang - * @LastEditTime: 2019-12-19 20:10:39 + * @LastEditTime: 2019-12-20 14:46:07 */ import types from "../actions/actionTypes"; import { Base64 } from 'js-base64'; @@ -13,6 +13,7 @@ const initialState = { user_program_identifier: '', // 开启OJ题的唯一标题 hack: {}, // 编程题主要内容 test_case: {}, // 测试用例 + commitTestRecordDetail: {}, // 调试代码执行结果 commitRecordDetail: {}, // 提交成功后记录提交的详情 commitRecord: [], // 提交记录 userCode: '', // 保存当前用户输入的代码 @@ -24,6 +25,7 @@ const initialState = { editor_code: '', // 保存编辑代码 notice: false, // 通知 hadCodeUpdate: false, // 更新代码 + operateType: '', // 点击类型: 调度或提交 }; const ojForUserReducer = (state = initialState, action) => { @@ -51,7 +53,7 @@ const ojForUserReducer = (state = initialState, action) => { test_case: Object.assign({}, test_case) } case types.COMMIT_RECORD_DETAIL: - let result = action.payload; + let result = action.payload.data; if (result['expected_output']) { result['expected_output'] = Base64.decode(result['expected_output']) } @@ -63,10 +65,18 @@ const ojForUserReducer = (state = initialState, action) => { } catch (e) { console.log('错误信息:', e); } - return { - ...state, - commitRecordDetail: Object.assign({}, result) + if (action.payload.type === 'submit') { + return { + ...state, + commitRecordDetail: Object.assign({}, result) + } + } else { + return { + ...state, + commitTestRecordDetail: Object.assign({}, result) + } } + case types.COMMIT_RECORD: return { ...state, @@ -144,6 +154,31 @@ const ojForUserReducer = (state = initialState, action) => { ...state, hadCodeUpdate: action.payload }; + case types.CLICK_OPERATE_TYPE: + return { + ...state, + operateType: action.payload + } + case types.CLEAR_OJ_FOR_USER_REDUCER: + return { + ...state, + user_program_identifier: '', // 开启OJ题的唯一标题 + hack: {}, // 编程题主要内容 + test_case: {}, // 测试用例 + commitTestRecordDetail: {}, // 调试代码执行结果 + commitRecordDetail: {}, // 提交成功后记录提交的详情 + commitRecord: [], // 提交记录 + userCode: '', // 保存当前用户输入的代码 + isUpdateCode: false, // 是否更新了代码内容 + userCodeTab: 'task', // 学员测评tab位置: task | record | comment + userTestInput: '', // 用户自定义输入值 + recordDetail: {}, // 根据id号获取的记录详情 + hack_identifier: '', // 用户界面编辑时 + editor_code: '', // 保存编辑代码 + notice: false, // 通知 + hadCodeUpdate: false, // 更新代码 + operateType: '', // 点击类型: 调度或提交 + }; default: return state; } From 8fcb7b9e259c2f9fbc6ec15624ceb9cf0d400470 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 14:56:09 +0800 Subject: [PATCH 55/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/TPMBanner.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index c122289bb..bb07df5df 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -868,8 +868,8 @@ class TPMBanner extends Component { - { - this.props.is_jupyter===true?"": + {/*{*/} + {/* this.props.is_jupyter===true?"":*/} @@ -934,7 +934,7 @@ class TPMBanner extends Component {
    - } + // } { From 5cf64eb4c12e07235edf223ce0283a5c1fd8af5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 14:57:52 +0800 Subject: [PATCH 56/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/tpm/shixunchild/Challenges/Challengesjupyter.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index 5e26ac86e..e137dc883 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -354,11 +354,11 @@ class Challengesjupyter extends Component {
    { enlarge===true? - this.onclki(false)}> : - this.onclki(true)}> } From de957b68d753287027e6b5e00e85bb7a936d5b40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 14:59:49 +0800 Subject: [PATCH 57/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/tpm/shixunchild/shixunchildCss/Challenges.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css b/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css index d18370a51..1e1945f89 100644 --- a/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css +++ b/public/react/src/modules/tpm/shixunchild/shixunchildCss/Challenges.css @@ -187,7 +187,7 @@ } .ysliconfont{ text-align: center; - line-height: 30px; + line-height: 29px; } .fangdaone{ From f33bc9e22dc2b95407de906068c31e34e25c3082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 15:07:03 +0800 Subject: [PATCH 58/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/src/modules/tpm/TPMBanner.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/src/modules/tpm/TPMBanner.js b/public/react/src/modules/tpm/TPMBanner.js index bb07df5df..0a123e73a 100644 --- a/public/react/src/modules/tpm/TPMBanner.js +++ b/public/react/src/modules/tpm/TPMBanner.js @@ -934,7 +934,7 @@ class TPMBanner extends Component {
    - // } + {/*// }*/} { From 674e30e2a364fa9d18e9a2d97f616f0b7e3de775 Mon Sep 17 00:00:00 2001 From: tangjiang <465264938@qq.com> Date: Fri, 20 Dec 2019 15:15:46 +0800 Subject: [PATCH 59/61] update style --- .../src/modules/developer/components/controlSetting/index.scss | 2 +- .../react/src/modules/developer/components/userInfo/index.scss | 1 + .../src/modules/developer/studentStudy/leftpane/index.scss | 2 +- public/react/src/modules/tpm/jupyter/rightPane/index.scss | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/public/react/src/modules/developer/components/controlSetting/index.scss b/public/react/src/modules/developer/components/controlSetting/index.scss index 31beda8a5..231358ea0 100644 --- a/public/react/src/modules/developer/components/controlSetting/index.scss +++ b/public/react/src/modules/developer/components/controlSetting/index.scss @@ -51,7 +51,7 @@ align-items: center; z-index: 20; height: 56px; - padding-right: 30px; + padding-right: 20px; padding-left: 10px; background: rgba(18,28,36,1); // background:rgba(48,48,48,1); diff --git a/public/react/src/modules/developer/components/userInfo/index.scss b/public/react/src/modules/developer/components/userInfo/index.scss index f9ea713f8..25c85d0e3 100644 --- a/public/react/src/modules/developer/components/userInfo/index.scss +++ b/public/react/src/modules/developer/components/userInfo/index.scss @@ -3,6 +3,7 @@ position: absolute; color: #fff; line-height: 65px; + left: 20px; // height: 65px; .student_img, .student_nicker{ diff --git a/public/react/src/modules/developer/studentStudy/leftpane/index.scss b/public/react/src/modules/developer/studentStudy/leftpane/index.scss index a48d021f9..b5362429f 100644 --- a/public/react/src/modules/developer/studentStudy/leftpane/index.scss +++ b/public/react/src/modules/developer/studentStudy/leftpane/index.scss @@ -65,7 +65,7 @@ .student_study_header{ .study_quit{ position: absolute; - right: 30px; + right: 20px; } .quit-btn{ cursor: pointer; diff --git a/public/react/src/modules/tpm/jupyter/rightPane/index.scss b/public/react/src/modules/tpm/jupyter/rightPane/index.scss index 4facded6b..fe2d52456 100644 --- a/public/react/src/modules/tpm/jupyter/rightPane/index.scss +++ b/public/react/src/modules/tpm/jupyter/rightPane/index.scss @@ -68,7 +68,7 @@ align-items: center; height: 56px; justify-content: flex-end; - padding-right: 30px; + padding-right: 20px; } } } \ No newline at end of file From 76a67e76711d7752ec3abce64ec0388715ec36f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Fri, 20 Dec 2019 16:10:33 +0800 Subject: [PATCH 60/61] =?UTF-8?q?=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../modules/tpm/shixunchild/Challenges/Challengesjupyter.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index e137dc883..bf98054d7 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -98,8 +98,11 @@ class Challengesjupyter extends Component { if(response.data.status===0){ setTimeout(() => { + + var url=response.data.url; + var url2=url.replace("http://","https://"); this.setState({ - jupyter_url:response.data.url, + jupyter_url:url2, jupyter_port:response.data.port, booljupyterurls:true, }) From a5077c3011fd657f1ade30cc8de7362275cf73dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Fri, 20 Dec 2019 16:23:43 +0800 Subject: [PATCH 61/61] =?UTF-8?q?jupytertpi=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/public/js/jupyter.js | 17 +++- public/react/src/modules/page/VNC.css | 2 +- public/react/src/modules/tpm/jupyter/index.js | 93 +++++++++++++++++-- .../react/src/modules/tpm/jupyter/index.scss | 57 +++++++++++- .../modules/tpm/jupyter/leftPane/index.scss | 11 ++- .../Challenges/Challengesjupyter.js | 2 - 6 files changed, 162 insertions(+), 20 deletions(-) diff --git a/public/react/public/js/jupyter.js b/public/react/public/js/jupyter.js index 97a0face2..361287317 100644 --- a/public/react/public/js/jupyter.js +++ b/public/react/public/js/jupyter.js @@ -1,9 +1,16 @@ +/* + * @Author: your name + * @Date: 2019-12-20 11:40:56 + * @LastEditTime : 2019-12-20 13:38:49 + * @LastEditors : Please set LastEditors + * @Description: In User Settings Edit + * @FilePath: /notebook/Users/yangshuming/Desktop/new__educode/educoder/public/react/public/js/jupyter.js + */ window.onload=function(){ - // require(["base/js/namespace"],function(Jupyter) { - // Jupyter.notebook.save_checkpoint(); - // }); - $('.navbar-nav').children().eq(7).css({'display':'none'}) - console.log($('.navbar-nav').children().eq(7)) + require(["base/js/namespace"],function(Jupyter) { + Jupyter.notebook.save_checkpoint(); + }); + } diff --git a/public/react/src/modules/page/VNC.css b/public/react/src/modules/page/VNC.css index e29335242..d59d91121 100644 --- a/public/react/src/modules/page/VNC.css +++ b/public/react/src/modules/page/VNC.css @@ -38,5 +38,5 @@ } .newjupyter_float_button{ - right: 257px; + right: 330px; } \ No newline at end of file diff --git a/public/react/src/modules/tpm/jupyter/index.js b/public/react/src/modules/tpm/jupyter/index.js index 7425a4732..617ef0936 100644 --- a/public/react/src/modules/tpm/jupyter/index.js +++ b/public/react/src/modules/tpm/jupyter/index.js @@ -9,7 +9,7 @@ import './index.scss'; import React, { useEffect, useState } from 'react'; import SplitPane from 'react-split-pane'; -import { Button, Modal,Drawer } from 'antd'; +import { Button, Modal,Drawer ,Pagination,Empty,Tooltip,Icon,message} from 'antd'; import { connect } from 'react-redux'; @@ -18,6 +18,25 @@ import UserInfo from '../../developer/components/userInfo'; import actions from '../../../redux/actions'; import LeftPane from './leftPane'; import RightPane from './rightPane'; +import MyIcon from "../../../common/components/MyIcon"; +function jsCopy(s) { + var copyEle = document.getElementById(s); + const range = document.createRange(); // 创造range + window.getSelection().removeAllRanges(); //清除页面中已有的selection + range.selectNode(copyEle); // 选中需要复制的节点 + window.getSelection().addRange(range); // 执行选中元素 + const copyStatus = document.execCommand("Copy"); // 执行copy操作 + // 对成功与否定进行提示 + copyStatuss(copyStatus) +} + +function copyStatuss(copyStatus){ + if (copyStatus) { + message.success('复制成功'); + } else { + message.error('复制失败'); + } +} function JupyterTPI (props) { // 获取 identifier 值 @@ -45,11 +64,17 @@ function JupyterTPI (props) { drawervisible, } = props; + const emptyCtx = ( +
    + +
    + ); const {identifier} = params; const [userInfo, setUserInfo] = useState({}); const [jupyterInfo, setJupyterInfo] = useState({}); const [updateTip, setUpdateTip] = useState(true); const [myIdentifier, setMyIdentifier] = useState(''); + const [renderCtx, setRenderCtx] = useState(() => (emptyCtx)); useEffect(() => { /* 先调用 jupyter的 TPI 接口, * 获取 用户信息, @@ -170,6 +195,45 @@ function JupyterTPI (props) { const firstDrawerWidth = ()=>{ return 260 }; + + // 分页处理 + const handleChangePage = (page) => { + // console.log(page, pageSize); + handlePageChange(page); + } + // const listCtx = ; + useEffect(() => { + if (dataSets.length > 0) { + console.log('数据集的个数: ', dataSets.length); + const oList = dataSets.map((item, i) => { + return ( +
  • + + + {item.title} + { + jsCopy("file_path"+i) + }}>复制地址 + + +
  • + ); + }); + + const oUl = ( +
      + { oList } +
    + ); + + setRenderCtx(oUl); + } + }, [props]); return (
    @@ -206,8 +270,8 @@ function JupyterTPI (props) {
    {/*
    */} - {/* -

    Some contents...

    -

    Some contents...

    -

    Some contents...

    +

    +
    +

    + {/**/} + 数据集 + {/* 数据集 */} +

    + { renderCtx } +
    + {total<20?"":} +
    + +
    diff --git a/public/react/src/modules/tpm/jupyter/index.scss b/public/react/src/modules/tpm/jupyter/index.scss index 5fdfcb02c..76c8bedd1 100644 --- a/public/react/src/modules/tpm/jupyter/index.scss +++ b/public/react/src/modules/tpm/jupyter/index.scss @@ -103,4 +103,59 @@ font-size: 14px; } } -} \ No newline at end of file +} + +.RightPaneDrawer{ + .RightPaneDrawertop{ + width:330px; + height:29px; + background:rgba(17,28,36,1); + } + + .ant-drawer-content-wrapper{ + width:330px !important; + box-shadow: -2px 0 8px #070F1A !important; + } + .ant-drawer-body{ + padding: 0px; + } + .ant-drawer-wrapper-body{ + padding-top: 60px; + background: #070F1A; + overflow: hidden !important; + } + + .ant-pagination{ + color:#fff !important; + } + +} + +.newjupyter_data_sets_area{ + background:#070F1A !important; + .jupyter_h2_title { + height:49px; + line-height: 49px; + background: #070F1A !important; + border-bottom: 1px solid #17212F !important; + color:#FFFFFF !important; + border-top: 1px solid #17212F !important; + } + .iconfont{ + color:#28b887!important; + font-size: 30px !important; + margin-right: 20px; + } + .jupyter_pagination{ + border-top: 1px solid #070F1A !important; + } + + .jupyter_name{ + color:#FFFFFF !important; + } + .file_path_input{ + position: absolute; + right: -50%; + } +} + diff --git a/public/react/src/modules/tpm/jupyter/leftPane/index.scss b/public/react/src/modules/tpm/jupyter/leftPane/index.scss index 352e1c9ab..495e21f20 100644 --- a/public/react/src/modules/tpm/jupyter/leftPane/index.scss +++ b/public/react/src/modules/tpm/jupyter/leftPane/index.scss @@ -2,15 +2,15 @@ height: 100%; background: #fff; .jupyter_h2_title{ - height: 44px; - line-height: 44px; + //height: 44px; + //line-height: 44px; // background-color: #EEEEEE; background: #fff; padding: 0 20px; font-size: 16px; // box-size: border-box; box-sizing: border-box; - border-bottom: 1px solid rgba(238,238,238,1); + //border-bottom: 1px solid rgba(238,238,238,1); .jupyter_data_icon{ // color: #7286ff; color: #1890ff; @@ -24,14 +24,15 @@ .jupyter_data_list, .jupyter_empty{ - height: calc(100vh - 160px); + //height: calc(100vh - 160px); + min-height: 350px; overflow-y: auto; } .jupyter_data_list{ .jupyter_item{ line-height:45px; - border-bottom: 1px solid rgba(238,238,238, 1); + //border-bottom: 1px solid rgba(238,238,238, 1); padding: 0 30px 0 60px; overflow: hidden; text-overflow:ellipsis; diff --git a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js index f11f03b6b..995753dff 100644 --- a/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js +++ b/public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js @@ -410,8 +410,6 @@ class Challengesjupyter extends Component {
    -
    - : "" )