forked from Open-CT/OpenPBL
feat: student evidence page ui
This commit is contained in:
parent
9f2ba3f934
commit
735dc1365f
|
@ -82,9 +82,47 @@ func (p *ProjectController) GetProjectTasks() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pid := p.GetString(":projectId")
|
||||||
|
tasks, err := models.GetProjectTasks(pid, "")
|
||||||
|
if err != nil {
|
||||||
|
p.Data["json"] = Response{
|
||||||
|
Code: 400,
|
||||||
|
Msg: err.Error(),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
p.Data["json"] = Response{
|
||||||
|
Code: 200,
|
||||||
|
Data: tasks,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p.ServeJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetProjectTasksAndSubmits
|
||||||
|
// @Title
|
||||||
|
// @Description get all the tasks of a section
|
||||||
|
// @Param sid path string true ""
|
||||||
|
// @Success 200 {object}
|
||||||
|
// @Failure 400
|
||||||
|
// @router /:projectId/tasks-submits [get]
|
||||||
|
func (p *ProjectController) GetProjectTasksAndSubmits() {
|
||||||
|
user := p.GetSessionUser()
|
||||||
|
if user == nil {
|
||||||
|
p.Data["json"] = TaskResponse{
|
||||||
|
Response: Response{
|
||||||
|
Code: 401,
|
||||||
|
Msg: "请先登录",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
p.ServeJSON()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
uid := ""
|
uid := ""
|
||||||
if user.Tag == "student" {
|
if user.Tag == "student" {
|
||||||
uid = user.Username
|
uid = user.Username
|
||||||
|
} else if user.Tag == "teacher" {
|
||||||
|
uid = p.GetString("StudentId")
|
||||||
}
|
}
|
||||||
|
|
||||||
pid := p.GetString(":projectId")
|
pid := p.GetString(":projectId")
|
||||||
|
|
|
@ -14,6 +14,12 @@ const TaskApi = {
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
getProjectTasksAndSubmits(pid) {
|
||||||
|
return request({
|
||||||
|
url: `/project/${pid}/tasks-submits`,
|
||||||
|
method: 'get',
|
||||||
|
})
|
||||||
|
},
|
||||||
createTask(pid, q) {
|
createTask(pid, q) {
|
||||||
return request({
|
return request({
|
||||||
url: `/project/${pid}/task`,
|
url: `/project/${pid}/task`,
|
||||||
|
|
|
@ -151,7 +151,7 @@ function OutlineEditPage(obj) {
|
||||||
sectionNumber: section.sectionNumber,
|
sectionNumber: section.sectionNumber,
|
||||||
chapterNumber: section.chapterNumber
|
chapterNumber: section.chapterNumber
|
||||||
}
|
}
|
||||||
SectionApi.updateChapterSection(s)
|
SectionApi.updateChapterSection(pid, s)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data.code === 200) {
|
if (res.data.code === 200) {
|
||||||
chapters[index].sections[subIndex] = s
|
chapters[index].sections[subIndex] = s
|
||||||
|
|
|
@ -6,13 +6,14 @@ import 'echarts/lib/component/legend';
|
||||||
import 'echarts/lib/component/markPoint';
|
import 'echarts/lib/component/markPoint';
|
||||||
import ReactEcharts from 'echarts-for-react';
|
import ReactEcharts from 'echarts-for-react';
|
||||||
import QueueAnim from 'rc-queue-anim';
|
import QueueAnim from 'rc-queue-anim';
|
||||||
import {Button, Card, Col, Divider, InputNumber, Row, Table, message, Menu, Input} from "antd";
|
import {Button, Card, Col, Divider, InputNumber, Row, Table, message, Menu, Input, List, Progress} from "antd";
|
||||||
|
|
||||||
import TaskApi from "../../../../api/TaskApi";
|
import TaskApi from "../../../../api/TaskApi";
|
||||||
import ProjectApi from "../../../../api/ProjectApi";
|
import ProjectApi from "../../../../api/ProjectApi";
|
||||||
import ChapterApi from "../../../../api/ChapterApi";
|
import ChapterApi from "../../../../api/ChapterApi";
|
||||||
import SectionApi from "../../../../api/SectionApi";
|
import SectionApi from "../../../../api/SectionApi";
|
||||||
|
|
||||||
|
import "./index.less"
|
||||||
|
|
||||||
const {SubMenu} = Menu
|
const {SubMenu} = Menu
|
||||||
|
|
||||||
|
@ -129,6 +130,8 @@ function ProjectEvaluation(obj) {
|
||||||
setEditWeight(false)
|
setEditWeight(false)
|
||||||
}
|
}
|
||||||
const changeLearnMinute = (v, index, subIndex) => {
|
const changeLearnMinute = (v, index, subIndex) => {
|
||||||
|
console.log(index, subIndex)
|
||||||
|
|
||||||
chapters[index].sections[subIndex].sectionMinute = v
|
chapters[index].sections[subIndex].sectionMinute = v
|
||||||
setChapters([...chapters])
|
setChapters([...chapters])
|
||||||
}
|
}
|
||||||
|
@ -210,8 +213,9 @@ function ProjectEvaluation(obj) {
|
||||||
<div style={{textAlign: 'left', marginBottom: '30px'}} key="1">
|
<div style={{textAlign: 'left', marginBottom: '30px'}} key="1">
|
||||||
<ReactEcharts option={getOptions()}/>
|
<ReactEcharts option={getOptions()}/>
|
||||||
<div>
|
<div>
|
||||||
<p style={{textAlign: 'center', fontWeight: 'bold', fontSize: '20px', marginTop: '20px'}}>
|
<Divider orientation="left">
|
||||||
章节学习时长</p>
|
<p className="evidence-title">章节学习时长</p>
|
||||||
|
</Divider>
|
||||||
{!published ?
|
{!published ?
|
||||||
<div style={{float: 'right'}}>
|
<div style={{float: 'right'}}>
|
||||||
{editMinute ?
|
{editMinute ?
|
||||||
|
@ -226,7 +230,44 @@ function ProjectEvaluation(obj) {
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
|
||||||
|
|
||||||
|
{chapters.map((item, index) => (
|
||||||
|
<div key={index.toString()} style={{textAlign: 'left'}}>
|
||||||
|
<p style={{fontWeight: 'bold', fontSize: '16px'}}>{item.chapterName}</p>
|
||||||
|
{(item.sections === null || item.sections === undefined) ?
|
||||||
|
null
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<List
|
||||||
|
size="large"
|
||||||
|
dataSource={item.sections}
|
||||||
|
renderItem={
|
||||||
|
(item, subIndex) => (
|
||||||
|
<List.Item>
|
||||||
|
{item.sectionName}
|
||||||
|
{editMinute ?
|
||||||
|
<div style={{float: 'right'}}>
|
||||||
|
学习时长不少于
|
||||||
|
<InputNumber value={item.sectionMinute} onChange={v=>changeLearnMinute(v, index, subIndex)} min={0}/>
|
||||||
|
分钟
|
||||||
|
</div>
|
||||||
|
:
|
||||||
|
<div style={{float: 'right'}}>
|
||||||
|
学习时长不少于 {item.sectionMinute} 分钟
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
|
||||||
|
</List.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/><br/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{/* <Menu
|
||||||
style={{width: '100%'}}
|
style={{width: '100%'}}
|
||||||
defaultSelectedKeys={['0']}
|
defaultSelectedKeys={['0']}
|
||||||
mode="inline"
|
mode="inline"
|
||||||
|
@ -252,11 +293,14 @@ function ProjectEvaluation(obj) {
|
||||||
}
|
}
|
||||||
</SubMenu>
|
</SubMenu>
|
||||||
))}
|
))}
|
||||||
</Menu>
|
</Menu>*/}
|
||||||
<div>
|
<div>
|
||||||
<p style={{textAlign: 'center', fontWeight: 'bold', fontSize: '20px', marginTop: '20px'}}>
|
|
||||||
权重占比
|
|
||||||
</p>
|
|
||||||
|
<Divider orientation="left">
|
||||||
|
<p className="evidence-title">权重占比</p>
|
||||||
|
</Divider>
|
||||||
{!published ?
|
{!published ?
|
||||||
<div style={{float: 'right'}}>
|
<div style={{float: 'right'}}>
|
||||||
{editWeight ?
|
{editWeight ?
|
||||||
|
|
|
@ -12,6 +12,9 @@ function ProjectOutline(obj) {
|
||||||
const [chapters, setChapters] = useState([])
|
const [chapters, setChapters] = useState([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
getChapters()
|
||||||
|
}, [])
|
||||||
|
const getChapters = () => {
|
||||||
ChapterApi.getProjectChapters(pid)
|
ChapterApi.getProjectChapters(pid)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (res.data.chapters === null) {
|
if (res.data.chapters === null) {
|
||||||
|
@ -21,7 +24,7 @@ function ProjectOutline(obj) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(e=>{console.log(e)})
|
.catch(e=>{console.log(e)})
|
||||||
}, [])
|
}
|
||||||
const gotoLearning = (item, subItem) => {
|
const gotoLearning = (item, subItem) => {
|
||||||
window.open(`/project/${pid}/section/${subItem.id}/preview?back=/project/${pid}/info`)
|
window.open(`/project/${pid}/section/${subItem.id}/preview?back=/project/${pid}/info`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,45 @@
|
||||||
import React, {useEffect, useState} from "react";
|
import React, {useEffect, useState} from "react";
|
||||||
import {InputNumber, Table} from "antd";
|
import {Col, Collapse, Divider, List, Progress, Row, Table} from "antd";
|
||||||
|
|
||||||
import TaskApi from "../../../../api/TaskApi";
|
import TaskApi from "../../../../api/TaskApi";
|
||||||
|
import ChapterApi from "../../../../api/ChapterApi";
|
||||||
|
|
||||||
|
|
||||||
function StudentEvidence(obj) {
|
function StudentEvidence(obj) {
|
||||||
const pid = obj.project.id
|
const pid = obj.project.id
|
||||||
const [tasks, setTasks] = useState([])
|
const [tasks, setTasks] = useState([])
|
||||||
|
const [chapters, setChapters] = useState([])
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
getChapters()
|
||||||
|
|
||||||
getTasks()
|
getTasks()
|
||||||
}, []);
|
}, []);
|
||||||
|
const getChapters = () => {
|
||||||
|
ChapterApi.getProjectChapters(pid)
|
||||||
|
.then((res) => {
|
||||||
|
if (res.data.chapters === null) {
|
||||||
|
setChapters([])
|
||||||
|
} else {
|
||||||
|
setChapters(res.data.chapters)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(e => {
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
|
}
|
||||||
const getTasks = () => {
|
const getTasks = () => {
|
||||||
TaskApi.getProjectTasks(pid)
|
TaskApi.getProjectTasksAndSubmits(pid)
|
||||||
.then(res=>{
|
.then(res => {
|
||||||
if (res.data.code === 200) {
|
if (res.data.code === 200) {
|
||||||
if (res.data.data != null) {
|
if (res.data.data != null) {
|
||||||
setTasks(res.data.data)
|
setTasks(res.data.data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(e=>{console.log(e)})
|
.catch(e => {
|
||||||
|
console.log(e)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
const getColumns = () => {
|
const getColumns = () => {
|
||||||
let c = [
|
let c = [
|
||||||
|
@ -59,7 +80,7 @@ function StudentEvidence(obj) {
|
||||||
render: (text, item, index) => (
|
render: (text, item, index) => (
|
||||||
<>
|
<>
|
||||||
{item.scored ?
|
{item.scored ?
|
||||||
<span>已打分</span>
|
<span style={{color: 'green'}}>已打分</span>
|
||||||
:
|
:
|
||||||
<span>未打分</span>
|
<span>未打分</span>
|
||||||
}
|
}
|
||||||
|
@ -74,6 +95,82 @@ function StudentEvidence(obj) {
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
<Divider orientation="left">
|
||||||
|
<p className="evidence-title">章节学习时长</p>
|
||||||
|
</Divider>
|
||||||
|
{chapters.map((item, index) => (
|
||||||
|
<div key={index.toString()} style={{textAlign: 'left'}}>
|
||||||
|
<p style={{fontWeight: 'bold', fontSize: '16px'}}>{item.chapterName}</p>
|
||||||
|
{(item.sections === null || item.sections === undefined) ?
|
||||||
|
null
|
||||||
|
:
|
||||||
|
<>
|
||||||
|
<List
|
||||||
|
size="large"
|
||||||
|
dataSource={item.sections}
|
||||||
|
renderItem={
|
||||||
|
item => (
|
||||||
|
<List.Item>
|
||||||
|
{item.sectionName}
|
||||||
|
{obj.project.learning ?
|
||||||
|
<>
|
||||||
|
<span style={{float: 'right'}}>
|
||||||
|
<Progress
|
||||||
|
trailColor="lightgray"
|
||||||
|
width={30}
|
||||||
|
strokeWidth={10}
|
||||||
|
type="circle"
|
||||||
|
percent={((item.learnMinute + item.learnSecond / 60) / item.sectionMinute * 100).toFixed(1)}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<span style={{float: 'right', marginRight: '20px'}}>
|
||||||
|
学习进度:
|
||||||
|
{item.learnMinute} : {item.learnSecond} /
|
||||||
|
{item.sectionMinute}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
: null}
|
||||||
|
</List.Item>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/><br/>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
<Divider orientation="left">
|
||||||
|
<p className="evidence-title">学生任务</p>
|
||||||
|
</Divider>
|
||||||
|
|
||||||
|
<Collapse style={{textAlign: 'left'}}>
|
||||||
|
{tasks.map((item, index) => (
|
||||||
|
<Collapse.Panel
|
||||||
|
key={index.toString()}
|
||||||
|
header={
|
||||||
|
<>
|
||||||
|
{item.taskTitle}
|
||||||
|
<span style={{float: 'right', marginRight: '20px'}}>
|
||||||
|
{item.scored ?
|
||||||
|
<span style={{color: 'green'}}>已打分</span>
|
||||||
|
:
|
||||||
|
<span>未打分</span>
|
||||||
|
}
|
||||||
|
</span>
|
||||||
|
<span style={{float: 'right', marginRight: '20px'}}>
|
||||||
|
权重:{item.taskWeight}
|
||||||
|
</span>
|
||||||
|
<span style={{float: 'right', marginRight: '20px'}}>
|
||||||
|
得分:{getScore(item.score, item.taskWeight)} / {item.taskWeight}
|
||||||
|
</span>
|
||||||
|
</>
|
||||||
|
}
|
||||||
|
>
|
||||||
|
neironog
|
||||||
|
</Collapse.Panel>
|
||||||
|
))}
|
||||||
|
</Collapse>
|
||||||
|
|
||||||
<Table
|
<Table
|
||||||
columns={getColumns()}
|
columns={getColumns()}
|
||||||
dataSource={tasks}
|
dataSource={tasks}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
.evidence-title{
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 20px;
|
||||||
|
margin-top: 20px
|
||||||
|
}
|
|
@ -279,18 +279,18 @@ func init() {
|
||||||
|
|
||||||
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "CreateSurvey",
|
Method: "GetSurveyDetailByTaskId",
|
||||||
Router: "/:projectId/task/:taskId/survey",
|
Router: "/:projectId/task/:taskId/survey",
|
||||||
AllowHTTPMethods: []string{"post"},
|
AllowHTTPMethods: []string{"get"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "GetSurveyDetailByTaskId",
|
Method: "CreateSurvey",
|
||||||
Router: "/:projectId/task/:taskId/survey",
|
Router: "/:projectId/task/:taskId/survey",
|
||||||
AllowHTTPMethods: []string{"get"},
|
AllowHTTPMethods: []string{"post"},
|
||||||
MethodParams: param.Make(),
|
MethodParams: param.Make(),
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
@ -349,6 +349,15 @@ func init() {
|
||||||
Filters: nil,
|
Filters: nil,
|
||||||
Params: nil})
|
Params: nil})
|
||||||
|
|
||||||
|
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
||||||
|
beego.ControllerComments{
|
||||||
|
Method: "GetProjectTasksAndSubmits",
|
||||||
|
Router: "/:projectId/tasks-submits",
|
||||||
|
AllowHTTPMethods: []string{"get"},
|
||||||
|
MethodParams: param.Make(),
|
||||||
|
Filters: nil,
|
||||||
|
Params: nil})
|
||||||
|
|
||||||
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"] = append(beego.GlobalControllerRouter["OpenPBL/controllers:ProjectController"],
|
||||||
beego.ControllerComments{
|
beego.ControllerComments{
|
||||||
Method: "ExchangeTask",
|
Method: "ExchangeTask",
|
||||||
|
|
Loading…
Reference in New Issue