From e44dc226c7b33de75ea4f8b86c559d3c77a27430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Wed, 30 Oct 2019 16:48:05 +0800 Subject: [PATCH 1/7] =?UTF-8?q?=E8=AF=BE=E5=A0=82=E7=BB=9F=E8=AE=A1?= =?UTF-8?q?=E6=A8=A1=E5=9D=97end?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/react/package.json | 1 + .../modules/courses/statistics/Dropdownbox.js | 123 +++++++ .../modules/courses/statistics/Dynamiclist.js | 90 +++++ .../modules/courses/statistics/Statistics.css | 62 +++- .../modules/courses/statistics/Statistics.js | 333 ++++++++++++++---- 5 files changed, 544 insertions(+), 65 deletions(-) create mode 100644 public/react/src/modules/courses/statistics/Dropdownbox.js create mode 100644 public/react/src/modules/courses/statistics/Dynamiclist.js diff --git a/public/react/package.json b/public/react/package.json index ac239dd0f..5bc10f627 100644 --- a/public/react/package.json +++ b/public/react/package.json @@ -16,6 +16,7 @@ "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-preset-react-app": "^3.1.1", "babel-runtime": "6.26.0", + "bizcharts": "^3.5.5", "bundle-loader": "^0.5.6", "case-sensitive-paths-webpack-plugin": "2.1.1", "chalk": "1.1.3", diff --git a/public/react/src/modules/courses/statistics/Dropdownbox.js b/public/react/src/modules/courses/statistics/Dropdownbox.js new file mode 100644 index 000000000..548715993 --- /dev/null +++ b/public/react/src/modules/courses/statistics/Dropdownbox.js @@ -0,0 +1,123 @@ +import React,{ Component } from "react"; +import {Menu, Dropdown, Icon,Input,Checkbox} from "antd"; +import {getImageUrl} from 'educoder'; +const { Search } = Input; +class Dropdownbox extends Component{ + constructor(props){ + super(props); + this.state={ + activeKey:'1', + visible: false, + onSearchvalue:undefined, + checkedValues:[] + } + } + + componentDidMount() { + let {group_ids}=this.props; + if(group_ids){ + this.setState({ + checkedValues:group_ids + }) + } + } + componentDidUpdate=(prevProps)=>{ + if(prevProps!=this.props){ + let {group_ids}=this.props; + if(group_ids){ + this.setState({ + checkedValues:group_ids + }) + } + } + } + SaveChange=()=>{ + this.props.postwork_scoredata(this.state.checkedValues) + } + + + handleVisibleChange=flag=>{ + this.setState({ visible: flag }); + }; + + CheckboxonChange=(checkedValues)=>{ + this.setState({ + checkedValues:checkedValues + }) + } + + unCheckboxonChange=()=>{ + this.setState({ + checkedValues:[], + onSearchvalue:undefined + }) + } + + onSearch=(value)=>{ + this.setState({ + onSearchvalue:value + }) + } + + onSearchonChange=(e)=>{ + this.setState({ + onSearchvalue:e.target.value + }) + } + + render(){ + let {course_groups}=this.props; + + const menu = ( + this.CheckboxonChange(checkedValues)}> + +
  • + {course_groups&&course_groups.length>10?this.onSearch(value)} + onChange={(e)=>this.onSearchonChange(e)} + value={this.state.onSearchvalue} + style={{ width: 200 }} + />:""} +
  • + {course_groups&&course_groups.map((item,key)=>{ + if(this.state.onSearchvalue){ + if(item.name.indexOf(this.state.onSearchvalue) != -1){ + return( + + {item.name} + + ) + } + }else{ + return( + + {item.name} + + ) + } + })} + +
  • + this.SaveChange()} className={"ant-btn-link"}>确定 + this.unCheckboxonChange()}>重置 +
  • +
    +
    + ); + + return( + + + + 分班 + + + + ) + } +} +export default Dropdownbox; diff --git a/public/react/src/modules/courses/statistics/Dynamiclist.js b/public/react/src/modules/courses/statistics/Dynamiclist.js new file mode 100644 index 000000000..0ea6eac1b --- /dev/null +++ b/public/react/src/modules/courses/statistics/Dynamiclist.js @@ -0,0 +1,90 @@ +import React,{ Component } from "react"; +import {Row, Col,Popover,Button,Icon} from "antd"; +import { + G2, + Chart, + Geom, + Axis, + Tooltip, + Coord, + Label, + Legend, + View, + Guide, + Shape, + Facet, + Util +} from "bizcharts"; + +class Dynamiclist extends Component{ + constructor(props){ + super(props); + this.state={ + + } + } + + + render(){ + const data = [] + let {course_members}=this.props; + if(course_members){ + if(course_members.length>0){ + course_members.map((item,key)=>{ + data.push({'name':item.user_name,'活跃度':item.total_score}) + }) + } + } + + const content = ( +
    +

    + 作业完成数(*10) +

    +

    + 试卷完成数(*10) +

    +

    + 问卷完成数(*7) +

    +

    + 资源发布数(*5) +

    +

    + 帖子发布数(*2) +

    +

    + 帖子回复数(*1) +

    +

    + 作业回复数(*1) +

    +
    + ); + return( + + + Top 10 + + 计算规则 + + + + + + {/*scale={cols}*/} + + + + + + + + ) + } +} +export default Dynamiclist; diff --git a/public/react/src/modules/courses/statistics/Statistics.css b/public/react/src/modules/courses/statistics/Statistics.css index 686abd52e..cfae65597 100644 --- a/public/react/src/modules/courses/statistics/Statistics.css +++ b/public/react/src/modules/courses/statistics/Statistics.css @@ -63,5 +63,65 @@ text-align: center; line-height: 61px; font-size: 16px; - color: rgba(80,145,255,1); +} + +.Statisticsli{ + clear: both; + margin: 0; + padding: 5px 12px; + color: rgba(0, 0, 0, 0.65); + font-weight: normal; + font-size: 14px; + line-height: 22px; + white-space: nowrap; + cursor: pointer; + -webkit-transition: all 0.3s; + -o-transition: all 0.3s; + transition: all 0.3s; +} + +.StatisticsMenubox{ + position: relative; + margin: 0; + padding: 4px 0; + text-align: left; + list-style-type: none; + background-color: #fff; + background-clip: padding-box; + border-radius: 4px; + outline: none; + -webkit-box-shadow: 0 2px 8px rgba(0,0,0,0.15); + box-shadow: 0 2px 8px rgba(0,0,0,0.15); + -webkit-transform: translate3d(0, 0, 0); +} + +.Statisticslibox li label{ + width: 200px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} +.Statisticslibox .ant-menu-item{ + height: 20px; + line-height: 20px; + text-overflow: clip; +} + +.top10s{ + font-size: 16px; + font-weight: bold; + color: rgba(51,51,51,1); +} + +.Statisticsliboxjsgz{ + font-size:12px; + color:rgba(51,51,51,1); + text-align: right; +} + +.Statisticscircle p{ + height: 30px; + font-size: 12px; + color: rgba(153,153,153,1); + line-height: 30px; } \ No newline at end of file diff --git a/public/react/src/modules/courses/statistics/Statistics.js b/public/react/src/modules/courses/statistics/Statistics.js index c4d5ddfa6..cb5cf9574 100644 --- a/public/react/src/modules/courses/statistics/Statistics.js +++ b/public/react/src/modules/courses/statistics/Statistics.js @@ -1,8 +1,9 @@ import React,{ Component } from "react"; -import {Table, Pagination,Tooltip,Spin, Row, Col ,Tabs} from "antd"; -import { WordsBtn,on, off, trigger ,getImageUrl} from 'educoder'; -import {BrowserRouter as Router,Route,Switch,Link} from 'react-router-dom'; +import {Table, Pagination,Tooltip,Spin, Row, Col ,Checkbox,Tabs,Menu, Dropdown, Icon,Input} from "antd"; +import { WordsBtn,on, off, trigger ,getImageUrl,sortDirections} from 'educoder'; import axios from'axios'; +import Dropdownbox from './Dropdownbox'; +import Dynamiclist from './Dynamiclist'; import './Statistics.css'; const { TabPane } = Tabs; class Statistics extends Component{ @@ -18,20 +19,29 @@ class Statistics extends Component{ bomisSpin:true, sort:'desc', course_groups:[], - page:1 + page:1, + all_count:null, + activeKey:'1', + visible: false, + group_ids:[], + course_members:[] } } componentDidMount() { - let {page,group_ids,sort}=this.state; + this.getdatas() + } + + getdatas=()=>{ + let {page,group_ids,sort}=this.state; let courseId=this.props.match.params.coursesId; let url=`/courses/${courseId}/statistics.json`; axios.get(url).then((result) => { if (result) { - this.setState({ - data:result.data.top_scores, - topisSpin:false - }) + this.setState({ + data:result.data.top_scores, + topisSpin:false + }) } }).catch((error) => { console.log(error); @@ -39,8 +49,6 @@ class Statistics extends Component{ topisSpin:false, }) }) - - let courseurl=`/courses/${courseId}/all_course_groups.json`; axios.get(courseurl).then((result) => { if (result) { @@ -57,11 +65,43 @@ class Statistics extends Component{ } }).catch((error) => { console.log(error); + }) + } + + getDynamiclistdatas=(group_ids)=>{ + let courseId=this.props.match.params.coursesId; + let url=`/courses/${courseId}/act_score.json`; + let data={ + group_ids:group_ids, + } + axios.get(url,{params: + data + }).then((result) => { + if (result) { + this.setState({ + course_members:result.data.course_members, + bomisSpin:false + }) + } + }).catch((error) => { + console.log(error); + this.setState({ + bomisSpin:false, + }) }) } getwork_scoredata=(page,group_ids,sort)=>{ + let {activeKey}=this.state; + this.setState({ + page:page, + sort:sort, + group_ids:group_ids, + bomisSpin:true, + }) + + if(activeKey==='1'){ let courseId=this.props.match.params.coursesId; let url=`/courses/${courseId}/work_score.json`; let data={ @@ -76,6 +116,7 @@ class Statistics extends Component{ if (result) { this.setState({ bomdata:result.data.course_members, + all_count:result.data.all_count, bomisSpin:false }) } @@ -85,63 +126,196 @@ class Statistics extends Component{ bomisSpin:false, }) }) + }else{ + this.getDynamiclistdatas(group_ids) + } + } - callback=(key)=>{ - console.log(key); + activeKey=(key)=>{ + if(key==="1"){ + this.getdatas() + }else{ + let{group_ids}=this.state; + this.getDynamiclistdatas(group_ids) + } + this.setState({ + activeKey:key + }) } + + PaginationCourse=(pageNumber)=>{ + let {group_ids,sort}=this.state; + + this.getwork_scoredata(pageNumber,group_ids,sort); + } + + derivefun=(url)=>{ + let{group_ids}=this.state; + let data={ + group_id:group_ids + } + axios.get(url,{params: + data + }).then((response)=>{ + if(response === undefined){ + return + } + if(response.data.status&&response.data.status===-1){ + this.props.showNotification(response.data.message); + }else if(response.data.status&&response.data.status===-2){ + // if(response.data.message === "100"){ + // // 已超出文件导出的上限数量(100 ),建议: + // + // this.setState({ + // DownloadType:true, + // DownloadMessageval:100 + // }) + // }else { + // //因附件资料超过500M + // this.setState({ + // DownloadType:true, + // DownloadMessageval:500 + // }) + // } + this.props.showNotification(response.data.message); + }else { + // this.props.showNotification(`正在下载中`); + // window.open("/api"+url, '_blank'); + this.props.slowDownload(url); + } + }).catch((error) => { + console.log(error) + }); + } + + + // 筛选 + handleTableChange =(pagination, filters, data)=>{ + let order=data.order; + let {page,group_ids}=this.state; + if(order==="descend"){ + this.getwork_scoredata(page,group_ids,'desc') + }else{ + this.getwork_scoredata(page,group_ids,'asc') + } + + } + render(){ - let {nd1,nd2,nd3,data,bomdata,course_groups}=this.state; - let course_grouptype=false - if(this.props&&this.props.course_modules!=undefined){ + let {nd1,nd2,nd3,data,bomdata}=this.state; + + const columns = [ + { + title: this.props.isAdmin()===true?'序号':'排名', + dataIndex: 'index', + render: (text, record,index) => { + return this.props.isAdmin()===true?(this.state.page - 1) * 20 + index + 1:record.rank + } + }, + { + title: '姓名', + dataIndex:'user_name', + render: (text, record) => ( + {record.user_name} + ) + }, + { + title: '分班', + dataIndex: 'course_group', + render: (text, record) => ( + {record.course_group} + ) + }, + { + title: '实训作业', + dataIndex: 'practice_score', + render: (text, record) => ( + {record.practice_score.toFixed(2)} + ) + }, + { + title: '普通作业', + dataIndex: 'common_score', + render: (text, record) => ( + {record.common_score.toFixed(2)} + ) + }, + { + title: '分组作业', + dataIndex: 'group_score', + render: (text, record) => ( + {record.group_score.toFixed(2)} + ) + }, + { + title: '毕设任务', + dataIndex: 'graduation_score', + render: (text, record) => ( + {record.graduation_score.toFixed(2)} + ) + }, + { + title: '试卷', + dataIndex: 'exercise_score', + render: (text, record) => ( + {record.exercise_score} + ) + }, + { + title: '总成绩', + dataIndex: 'total_score', + sorter: this.props.isAdmin()===true?true:false, + defaultSortOrder: 'descend', + sortDirections: sortDirections, + render: (text, record) => ( + {record.total_score.toFixed(2)} + ) + }, + ]; + + let course_grouptype=false; + if(this.props&&this.props.course_modules!=undefined){ {this.props&&this.props.course_modules.map((item,key)=>{ if(item.type==="course_group"){ course_grouptype=true } })} } - - // const columns = [ - // { - // title: 'Name', - // dataIndex: 'name', - // sorter: true, - // render: name => `${name.first} ${name.last}`, - // width: '20%', - // }, - // { - // title: 'Gender', - // dataIndex: 'gender', - // filters: course_groups, - // width: '20%', - // }, - // { - // title: 'Email', - // dataIndex: 'email', - // }, - // ]; - - - // console.log(bomdata) - - - //common_score: 0 - // course_group: "威风威风急急急" - // exercise_score: "0.0" - // graduation_score: 0 - // group_score: 0 - // practice_score: 3232 - // total_score: 3232 - // user_login: "p40793521" - // user_name: "李明霞" - - + if(course_grouptype===false){ + columns.some((item,key)=> { + if (item.title === "分班") { + columns.splice(key, 1) + return true + } + } + ) + } + // console.log(this.props.isAdmin) + + + // "user_login": "p94602358", + // "user_name": "卿前程", + // "course_group": "电气工程1805", // 分班 + // "common_score": 0.0, // 普通作业 + // "group_score": 0.0, // 分组作业 + // "practice_score": 747.1000061035156, // 实训作业 + // "exercise_score": 0.0, // 试卷成绩 + // "graduation_score": 0.0, // 毕设成绩 + // "total_score": 747.1000061035156, // 总成绩 + // "rank": 1 // 排名,学生身份才传 + const operations = + this.getwork_scoredata(1,group_idss,'desc')} + /> + this.derivefun(`/courses/${this.props.match.params.coursesId}/export_member_scores_excel.xlsx`)}>导出 + ; return( - -
    - +

    @@ -301,22 +475,53 @@ class Statistics extends Component{

    - - - {/**/} + + + + - Content of Tab Pane 2 + - + {this.state.all_count===undefined||this.state.all_count===null||this.state.activeKey==="2"?'':this.state.all_count >20&&this.props.isAdmin()===true?
    + + + +
    :""} + ) } From 7483e8c13f41b21f18e90e13b3607fb9b3c41618 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Wed, 30 Oct 2019 17:12:21 +0800 Subject: [PATCH 2/7] =?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/courses/statistics/Statistics.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/public/react/src/modules/courses/statistics/Statistics.js b/public/react/src/modules/courses/statistics/Statistics.js index cb5cf9574..86feed447 100644 --- a/public/react/src/modules/courses/statistics/Statistics.js +++ b/public/react/src/modules/courses/statistics/Statistics.js @@ -135,7 +135,9 @@ class Statistics extends Component{ activeKey=(key)=>{ if(key==="1"){ - this.getdatas() + let {page,group_ids,sort}=this.state; + // this.getdatas() + this.getwork_scoredata(page,group_ids,sort) }else{ let{group_ids}=this.state; this.getDynamiclistdatas(group_ids) From 18fc207c354792aa9cf222a60efd718336038ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Wed, 30 Oct 2019 17:18:20 +0800 Subject: [PATCH 3/7] =?UTF-8?q?=E8=B0=83=E6=95=B4=E8=AF=95=E5=8D=B7?= =?UTF-8?q?=E7=BB=9F=E8=AE=A1=E8=B0=83=E5=88=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../courses/exercise/Exercisestatisticalresult.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js b/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js index e6bd595c5..64f1b3cb6 100644 --- a/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js +++ b/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js @@ -96,10 +96,17 @@ class Exercisestatisticalresult extends Component { exercise_group_id:checkedValues }) } - - this.updatefun(sort,checkedValues,page,limit) } + + alldatalist=()=>{ + + let{sort,page,limit}=this.state; + this.setState({ + exercise_group_id:[] + }) + this.updatefun(sort,[],page,limit) + } PaginationCourse=(pageNumber)=>{ let{sort,exercise_group_id,limit}=this.state; @@ -136,7 +143,7 @@ class Exercisestatisticalresult extends Component {
  • 分班情况: - 不限 + this.alldatalist()}>不限 this.funtaskstatustwo(e,data&&data.course_groups)} value={this.state.exercise_group_id} style={{width:'87%',paddingTop: '4px'}}> { data&&data.course_groups.map((item, key) => { From f868cac39078f32697b07db0f78eb44302963576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Wed, 30 Oct 2019 17:18:51 +0800 Subject: [PATCH 4/7] =?UTF-8?q?=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/modules/courses/exercise/Exercisestatisticalresult.js | 1 - 1 file changed, 1 deletion(-) diff --git a/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js b/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js index 64f1b3cb6..1dcab1476 100644 --- a/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js +++ b/public/react/src/modules/courses/exercise/Exercisestatisticalresult.js @@ -100,7 +100,6 @@ class Exercisestatisticalresult extends Component { } alldatalist=()=>{ - let{sort,page,limit}=this.state; this.setState({ exercise_group_id:[] From af8ab8114656d81c5a42ca055de25b9271495458 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=98=8E?= <775174143@qq.com> Date: Wed, 30 Oct 2019 17:32:43 +0800 Subject: [PATCH 5/7] =?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/config/webpack.config.dev.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/react/config/webpack.config.dev.js b/public/react/config/webpack.config.dev.js index e96f22663..63324c35f 100644 --- a/public/react/config/webpack.config.dev.js +++ b/public/react/config/webpack.config.dev.js @@ -32,7 +32,7 @@ module.exports = { // See the discussion in https://github.com/facebookincubator/create-react-app/issues/343.s // devtool: "cheap-module-eval-source-map", // 开启调试 - devtool: "source-map", // 开启调试 + //devtool: "source-map", // 开启调试 // These are the "entry points" to our application. // This means they will be the "root" imports that are included in JS bundle. // The first two entry points enable "hot" CSS and auto-refreshes for JS. From 68c9a83308f0cb3a37214d32ee42c029125db095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E6=A0=91=E6=9E=97?= <904079904@qq.com> Date: Wed, 30 Oct 2019 17:36:33 +0800 Subject: [PATCH 6/7] aliyun --- .../src/modules/courses/shixunHomework/ShixunStudentWork.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/public/react/src/modules/courses/shixunHomework/ShixunStudentWork.js b/public/react/src/modules/courses/shixunHomework/ShixunStudentWork.js index 0c0591acf..a89022ee6 100644 --- a/public/react/src/modules/courses/shixunHomework/ShixunStudentWork.js +++ b/public/react/src/modules/courses/shixunHomework/ShixunStudentWork.js @@ -704,6 +704,7 @@ class ShixunStudentWork extends Component { title: '序号', dataIndex: 'number', key: 'number', + width: '176px', render: (text, record) => ( {record.number} @@ -714,6 +715,7 @@ class ShixunStudentWork extends Component { title: '姓名', dataIndex: 'name', key: 'name', + width: '218px', render: (text, record) => ( {record.name} @@ -726,6 +728,7 @@ class ShixunStudentWork extends Component { key: 'stduynumber', sorter: true, sortDirections: sortDirections, + width: '351px', render: (text, record) => ( {record.stduynumber} @@ -739,6 +742,7 @@ class ShixunStudentWork extends Component { sorter: true, defaultSortOrder: 'descend', sortDirections: sortDirections, + width: '277', render: (text, record) => ( =90?'#FF6800':"#747A7F", "text-align": "center"}}>{isNaN(record.classroom)?"--":record.classroom}% @@ -749,6 +753,7 @@ class ShixunStudentWork extends Component { title: '操作', dataIndex: 'operating', key: 'operating', + width: '178px', render: (text, record) => ( this.Viewstudenttraininginformation("/courses/"+this.props.match.params.coursesId+"/"+this.state.shixuntypes+"/"+this.props.match.params.homeworkid+"/review_detail/"+record.operating)} >查看 From 5eff0cf1bee31351f64e821175128b450cdd92c6 Mon Sep 17 00:00:00 2001 From: p31729568 Date: Thu, 31 Oct 2019 08:51:25 +0800 Subject: [PATCH 7/7] weapp: search api add column --- app/models/searchable/shixun.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/models/searchable/shixun.rb b/app/models/searchable/shixun.rb index 41bc94b04..3229f278f 100644 --- a/app/models/searchable/shixun.rb +++ b/app/models/searchable/shixun.rb @@ -51,6 +51,8 @@ module Searchable::Shixun visits_count: visits, challenges_count: challenges_count, study_count: myshixuns_count, + star: averge_star, + level: shixun_level } end