diff --git a/app/controllers/ecs/reach_evaluations_controller.rb b/app/controllers/ecs/reach_evaluations_controller.rb index 97576447c..25ac24656 100644 --- a/app/controllers/ecs/reach_evaluations_controller.rb +++ b/app/controllers/ecs/reach_evaluations_controller.rb @@ -14,5 +14,13 @@ class Ecs::ReachEvaluationsController < Ecs::BaseController end def create + relations = current_year.ec_graduation_requirements.joins(ec_graduation_subitems: :ec_course_support) + ec_course_ids = relations.pluck('ec_course_supports.ec_course_id').uniq + + EcCourse.where(id: ec_course_ids).each do |ec_course| + Ecs::CalculateCourseEvaluationService.call(ec_course) + end + + render_ok end end diff --git a/app/models/ec_course_support.rb b/app/models/ec_course_support.rb index c7865f73c..518fc1385 100644 --- a/app/models/ec_course_support.rb +++ b/app/models/ec_course_support.rb @@ -1,6 +1,8 @@ class EcCourseSupport < ApplicationRecord default_scope { order(position: :asc) } + alias_attribute :weights, :weigths + belongs_to :ec_course belongs_to :ec_graduation_subitem diff --git a/app/models/ec_course_target.rb b/app/models/ec_course_target.rb index 9b93cb73c..b13c81059 100644 --- a/app/models/ec_course_target.rb +++ b/app/models/ec_course_target.rb @@ -1,4 +1,3 @@ -# TODO:: change table column :weigths => :weight class EcCourseTarget < ApplicationRecord belongs_to :ec_course @@ -8,6 +7,8 @@ class EcCourseTarget < ApplicationRecord has_many :ec_course_achievement_methods, dependent: :destroy has_many :ec_achievement_evaluation_relates, dependent: :destroy + alias_attribute :weight, :weigths + validates :content, presence: true validates :standard_grade, numericality: { only_integer: true, greater_than: 0 } validates :weight, presence: true, numericality: { less_than_or_equal_to: 1, greater_than_or_equal_to: 0 } diff --git a/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder b/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder index 1ffe12ec4..aee77c5b7 100644 --- a/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder +++ b/app/views/ecs/graduation_course_supports/shared/_ec_graduation_subitem.json.jbuilder @@ -3,3 +3,4 @@ json.extract! ec_graduation_subitem, :id, :position, :content, :ec_graduation_re json.graduation_requirement_position ec_graduation_subitem.ec_graduation_requirement.position json.course_supports ec_graduation_subitem.ec_course_supports, partial: 'ec_course_support', as: :ec_course_support +json.weights_total ec_graduation_subitem.ec_course_supports.to_a.sum(&:weights) diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 20d34e841..5f30a26a8 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -10,7 +10,7 @@ broadcastChannelOnmessage('refreshPage', () => { }) function locationurl(list){ - + debugger if (window.location.port === "3007") { } else { @@ -38,18 +38,14 @@ export function initAxiosInterceptors(props) { // https://github.com/axios/axios/issues/1497 // TODO 读取到package.json中的配置? - var proxy = "http://localhost:3000"; - // proxy = "http://testbdweb.trustie.net" - // proxy = "http://testbdweb.educoder.net" - // proxy = "https://testeduplus2.educoder.net" - proxy="http://47.96.87.25:48080"; - // wy - proxy="https://pre-newweb.educoder.net"; - proxy="https://test-newweb.educoder.net"; - proxy="http://192.168.2.63:3001"; + var proxy = "http://localhost:3000" + + // proxy="https://pre-newweb.educoder.net" + // proxy="https://test-newweb.educoder.net" + proxy="http://192.168.2.63:3001"; // wy - // proxy="http://192.168.2.63:3001" + proxy="http://192.168.2.63:3001" // 在这里使用requestMap控制,避免用户通过双击等操作发出重复的请求; // 如果需要支持重复的请求,考虑config里面自定义一个allowRepeat参考来控制 diff --git a/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css b/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css new file mode 100644 index 000000000..3f1dc000a --- /dev/null +++ b/public/react/src/modules/ecs/EcSetting/CourseSupports/ecCourseSupports.css @@ -0,0 +1,352 @@ +.eaSystemp a{ + color:#05101a; +} +.eaSystemp span{ + color: #05101a !important; +} +.eacourse p{ + height:84px; + margin-bottom:0px !important; +} +.eacourse #training_objective_contents{ + height:81px; +} +.courseSystem{ +font-size:18px; +font-family:MicrosoftYaHei; +font-weight:400; +line-height:45px; +color:rgba(5,16,26,1); +} +.SystemParameters{ + font-size:14px; + font-family:MicrosoftYaHei; + font-weight:400; + line-height:45px; + color:rgba(50,50,50,1); +} +.Systemnum{ + font-size:14px; + font-family:MicrosoftYaHei; + font-weight:400; + color:#FF6800; +} +.newSystem{ + width:1200px; + overflow:auto; + background: #FFF; +} +.newSystem .clearfix .column-1{ + width: 113px !important; + text-align: center; +} +.operationColumn{ + margin: 0px 10%; + width:100%; + height:100%; +} +.operationalter{ + margin: 20px 16px; +} +.SystemModifythelist .column-1{ + width: 120px !important; + text-align: center; +} + +.SystemModifythelist .column-3{ + padding-left: 96px; + margin-right: 23px; +} +.operationright{ + float:right !important; +} + +.newSystem p{ + /*padding: 10px 33px !important;*/ + margin-bottom: 0em; +} +.newSystem li{ + margin:0 !important; +} +.SystemModifythelist{ + background:#FFF !important; +} + +.SystemModifythelist .column-1:nth-child(1){ + margin-left: 7px; +} + +.Systempoint{ + font-size:12px; + font-family:MicrosoftYaHei; + font-weight:400; + color:rgba(152,152,152,1); +} +.editorModify{ + background:#FFF !important; +} +.newSystem .editorModify .column-1{ + width: 194px !important; + text-align: left; + margin-left: 30px; +} +.newSystem .editorModify .column-1:nth-child(1){ + margin-right: 510px; +} +.editorModify .ant-select{ + width: 556px !important; + margin-left: 36px; +} +.editorModify .ant-select .ant-select-selection{ + height: 30px !important; +} +.editorModify .ant-select .ant-select-selection .ant-select-selection__rendered{ + height: 30px !important; +} +.editorModify .ant-select .ant-select-selection .ant-select-selection__rendered .ant-select-selection-selected-value{ + line-height: 30px !important; +} +.inputWeight{ + width: 20%; + font-size:14px; + height:30px; + margin-left: 20px; + background-color: #F5F5F5; +} +.SetTheAssociated{ + width: 314px; + height: 30px; + float: right; + margin-right: -3.5%; +} +.SetTheAssociatedchild{ + width: 120px; + height: 30px; + background: rgba(255,255,255,1); + border: 1px solid rgba(234,234,234,1); + border-radius: 4px; + float: left; + margin-right: 10px; + text-align: center; + line-height: 30px; + /*margin-left: 34px;*/ +} +.operatebutton{ + margin-left: 20px; + /* margin-top: 16px; */ +} +.editbulebutton{ + width:120px; + height:30px; + background:rgba(76,172,255,1); + border-radius:2px; + color:#FFF; + text-align: center; + line-height: 30px; +} +.editglybutton{ + width:120px; + height:30px; + border:1px solid rgba(205,205,205,1); + border-radius:2px; + color:#999; + text-align: center; + line-height: 30px; +} + +.editglybuttonbox{ + width: 275px; + margin-bottom: 30px; + margin-right: 20px; + margin-right:7%; +} +.editglybuttonboxs{ + width: 275px; + margin-bottom: 30px; + margin-right: 20px; + margin-right:3%; +} +.defalutCancelbtn:hover { + border: 1px solid #B2B2B2; + color: #B2B2B2!important; +} + +.gouxuanbule{ + color:#4CACFF; +} +.gouxuanwhite{ + color:#FFF; +} +.icon-gouxuan{ + cursor: pointer; +} +/* 谷歌 */ +input::-webkit-outer-spin-button, +input::-webkit-inner-spin-button { + -webkit-appearance: none; + appearance: none; + margin: 0; +} +/* 火狐 */ +input{ + -moz-appearance:textfield; +} +.inputWeight{ + text-indent:0.625rem; +} + +.columnlocation{ + height: 40px; + line-height: 40px; +} +.paddingLF{ + padding:0 33px; +} +.width20{ + width: 20px; + height: 20px; + text-align: center; +} +.defalutSubmitbtn,.defalutCancelbtn{ + cursor: pointer; +} +.mb290{ + margin-bottom:290px; +} +.Spinlarge{ + text-align: center; + width: 100%; + margin-top: 25px; + margin-bottom: 25px; +} +.DDred{ + color:#DD1717; +} +.color-666{ + color:#666666 !important; +} +.color-05101A{ + color:#05101A !important; +} +.ec_graduation_name{ + margin-right:20px !important; +} +.column-width575{ + color: transparent !important; +} +.column-width130{ + width: 130px !important; + height: 40px; +} + + +.ListTableLine li>span { + max-width: 550px !important; +} + +.graduateRequirement .clearfix .column-1 { + width: 76px!important; +} + +.newrightcalculatebutton{ + width: 50px; + height: 25px; + border: 1px solid rgba(76,172,255,1); + border-radius: 1px; + line-height: 25px; + text-align: center; + margin-top: 7px; + cursor: pointer; + color: rgba(76,172,255,1); +} +.columnbox{ + height: 53px; + overflow: hidden; +} + +.ant-modal-mask { + background-color: rgba(5,16,26,0.4); +} +.ecmodeldelet{ + top:300px; +} +.ecmodeldelet .ant-modal-header{ + padding: 0px 24px; +} +.ecmodeldelet .ant-modal-title{ + padding: 0px 15px; + text-align: center; + box-sizing: border-box; + line-height: 70px; + height: 70px; + border-radius: 10px 10px 0px 0px; + font-size: 16px; + font-weight: bold; +} +.bor-red { + border: 1px solid #db0505 !important; +} + +.ml93{ + margin-left:93px; +} +.ml26{ + margin-left: 26px; +} +.finishtarget{ + width: 69px; + /* height: 48px; */ + line-height: 20px; + text-align: center; + margin-right: 48px; +} + +.bordereaeaea{ + border-bottom: 1px solid transparent !important; +} + +.heightimportant{ + height: 30px !important; + background-color: #F5F5F5; +} +.heightimportant:focus { + background-color: #fff; +} +.inputWeight:focus { + background-color: #fff; + } +.heightlineimportant{ + line-height: 30px !important; +} + +.ant-select-selection:hover{ + border-color: #d9d9d9 !important; +} +.ant-input:focus { + outline: 0; + -webkit-box-shadow: 0 0 0 2px transparent !important; + box-shadow: 0 0 0 2px transparent !important; + } + .ant-input{ + border-color: #d9d9d9 !important; + } + .ant-select-selection:focus{ + -webkit-box-shadow: 0 0 0 2px transparent !important; + box-shadow: 0 0 0 2px transparent !important; + } + .ant-select-selection:active{ + -webkit-box-shadow: 0 0 0 2px transparent !important; + box-shadow: 0 0 0 2px transparent !important; + } + + .ant-select-selection:focus{ + border-color: #d9d9d9 !important; + } + .ant-select-selection{ + -webkit-box-shadow: 0 0 0 2px transparent !important; + box-shadow: 0 0 0 2px transparent !important; + } + +.mt60{ + margin-top:60px; +} \ No newline at end of file diff --git a/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js b/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js new file mode 100644 index 000000000..60c573445 --- /dev/null +++ b/public/react/src/modules/ecs/EcSetting/CourseSupports/index.js @@ -0,0 +1,638 @@ +import React, { Component } from 'react'; + +import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom"; + +import axios from 'axios'; + +import { Select,message,Modal,Input,Spin,Icon,Tooltip } from 'antd'; + +import './ecCourseSupports.css'; + +const $ = window.$; +class CourseSupports extends Component { + constructor(props) { + super(props) + this.state={ + data:'', + ec_courses_list:[], + editcourse:[{"weigths": 0, + "ec_course_name":'', + "top_relation": false, + "ec_course_id":'' + }], + editnum:0, + index:0, + ec_graduation_subitem_id:0, + ec_year_id:0, + schooldata:{}, + spinning:true, + ecComponentState:'ecCourseSupports', + supportid:null, + Editkey:null, + titlemessage:"提示", + Supportstype:false, + Supportslist:'', + Supportssum:false, + Supportsclass:false + } + } + + componentWillMount(){ + this.setState({ + ec_year_id:this.props.match.params.ec_year_id, + major_school_id:this.props.match.params.major_school_id + }) + window.document.title = '课程体系 vs 毕业要求'; + } + + UpdateClassData=()=>{ + + let ec_year_id=this.props.match.params.ec_year_id; + + this.setState({ + ec_year_id:ec_year_id + }) + // const jol =`/ec_major_schools/get_navigation_data?ec_year_id=`+ec_year_id; + // axios.get(jol, { + // withCredentials: true, + // }) + // .then((response) => { + // if(response.status===200){ + // // if(response.data.allow_visit===false){ + // // window.location.href="/403" + // // } + // this.setState({ + // schooldata:response.data + // }) + // } + // }) + // .catch(function (error) { + // console.log(error); + // }); + + + const url = `/ec_years/${ec_year_id}/graduation_course_supports.json`; + axios.get(url) + .then((response) => { + if(response.status===200){ + this.setState({ + data:response.data + }) + } + if(response.data.graduation_subitems.length===0){ + this.setState({ + Supportstype:true, + Supportslist:'数据为空,请去毕业要求——>毕业要求指标点分解列表配置数据' + }) + } + }) + .catch(function (error) { + console.log(error); + }); + + // this.setState({ + // data:{course_count: 14, + // course_support_data: [ + // {course_data: [{ + // name: "军事课堂", + // top_relation: true, + // weigths: 0.1 + // }, { + // name: "大学生心理健康教育", + // top_relation: true, + // weigths: 0.2 + // }], + // ec_graduation_subitem_id: 2, + // num_total: 2, + // sequence_num: "1-1", + // weights_total: 0.30000000000000004, + // }, + // ], + // course_url: "/ec_major_schools/1/academic_years/1/ec_course_setting", + // ec_year_id: 1, + // max_support_count: 12, + // subitems_count: 7, + // subitems_url: "/ec_major_schools/1/academic_years/1/graduation_requirement" + // } + // }) + + } + componentDidMount(){ + this.setState({ + ec_year_id:this.props.match.params.ec_year_id, + major_school_id:this.props.match.params.major_school_id + }) + this.UpdateClassData(); + + } + EditSupportCourse=(key,e)=>{ + $('#school_major_list').scrollLeft(0); + let id=e.target.id; + id=parseInt(id); + + let subindex =e.target.getAttribute("subindex"); + const url = `/ec_course_supports/edit_require_vs_course?subitem_id=`+id + axios.get(url) + .then((response) => { + + if(response.status===200){ + var support_data; + if(response.data.edit_support_data.length>0){ + support_data=response.data.edit_support_data; + }else if(response.data.edit_support_data.length===0){ + support_data=[{weights: 0,top_relation: false,ec_course_name:'',ec_course_id:''}]; + } + + this.setState({ + ec_courses_list:response.data.ec_courses_list, + editcourse:support_data, + index:subindex, + ec_graduation_subitem_id:id, + Supportssum:false, + Supportsclass:false, + }) + + let {editcourse} =this.state; + let neweditcourse=editcourse; + let newnum=0; + for(var j=0;j{ + let {editcourse} =this.state; + let neweditcourse=editcourse; + let newadd = {weigths: 0,top_relation: false,ec_course_name:'',ec_course_id:''}; + neweditcourse.push(newadd); + this.setState({ + editcourse:neweditcourse + }) + } + editcourse=(neweditcourse)=>{ + this.setState({ + editcourse:neweditcourse + }) + + } + + Deletcourse=(e)=>{ + // 删除 + // let id =e.target.getAttribute("index"); + let {editcourse} = this.state; + let neweditcourse=editcourse; + neweditcourse.splice(e,1); + let newnum=0; + for(var j=0;j{ + let {editcourse} = this.state; + let neweditcourse=editcourse; + var id=e.target.id; + var value=parseFloat(e.target.value); + if(isNaN(value)){ + value="" + } + var x = String(value).indexOf('.') + 1; + var y = String(value).length - x; + if(y > 2){ + this.setState({ + // Supportstype:true, + Supportslist:'请精确到2位数', + Supportssum:true + }) + return + } + + + const person = new Object (); + person.weigths=value; + person.ec_course_id= neweditcourse[id].ec_course_id; + person.ec_course_name=neweditcourse[id].ec_course_name; + person.top_relation=neweditcourse[id].top_relation; + + + neweditcourse[id]=person; + + let newnum=0; + for(var j=0;j1){ + this.setState({ + // Supportstype:true, + Supportslist:'权重之和不能大于1', + Supportssum:true + }) + } + + } + handleChange=(e)=> { + + let {editcourse} = this.state; + let value=`${e[0]}`; + value=parseInt(value) + let neweditcourse=editcourse; + let num=`${e[1]}`; + num=parseInt(num) + + for(var z=0;z{ + + let {editcourse} = this.state; + let neweditcourse=editcourse; + let id =e.target.getAttribute("itindex"); + for(var i=0;i<1;i++){ + neweditcourse[id].top_relation=false; + } + + this.editcourse(neweditcourse); + } + + relevancebottom=(e)=>{ + + let {editcourse} = this.state; + let neweditcourse=editcourse; + let id =e.target.getAttribute("itindex"); + for(var i=0;i<1;i++){ + neweditcourse[id].top_relation=true; + } + + this.editcourse(neweditcourse); + } + focus() { + this.inputNumberRef.focus(); + } + + blur() { + this.inputNumberRef.blur(); + } + CancelSupports=()=>{ + this.setState({ + Editkey:null, + Supportssum:false, + Supportsclass:false, + }) + } + SubmitClassData=()=>{ + let {editcourse,editnum,ec_graduation_subitem_id,ec_year_id} = this.state; + if(editcourse.length===0){ + this.setState({ + // Supportstype:true, + Supportslist:'保存失败,至少保留一个课程', + Supportssum:true + }) + return + } + if(editnum>1||editnum===0){ + this.setState({ + // Supportstype:true, + Supportslist:'保存失败,权重大于1或为空', + Supportssum:true + }) + return + } + for(var p=0; p { + + if(response.data.status===0){ + this.setState({ + Editkey:null, + Supportslist:response.data.messsage, + Supportstype:true, + Supportssum:false, + Supportsclass:false, + }) + this.UpdateClassData(); + }else if(response.data.status===-1){ + this.setState({ + Supportslist:"参数错误", + Supportstype:true, + Supportssum:false, + Supportsclass:false, + }) + } + }).catch((error) => { + console.log(error) + }) + } + Deletcourses=(key)=>{ + this.setState({ + supportid:key, + Supportslist:"您确定要删除吗?", + Supportstype:true + }) + } + hideSupports=()=>{ + this.setState({ + Supportstype:false, + supportid:null, + Supportslist:"", + }) + } + render() { + const Option = Select.Option; + let {data,ec_courses_list,editcourse,editnum,index,ec_year_id,schooldata,ecComponentState,hidesupport,supportid,Editkey,titlemessage,Supportstype,Supportslist,Supportssum,Supportsclass,major_school_id} = this.state; + var list = (length) => { + var res = []; + for(var i = 0; i < length; i++) { + res.push( +
支撑课程 +
(权值) +
+
) + } + return res + } + + return ( +
+ +
+
{Supportslist}
+
+ +
+ + +
+ + + +
+ +
+ 课程体系对毕业要求的支撑 + {/* 导出培养目标 */} + + 导出课程体系支撑矩阵 + +
用矩阵图的形式说明本专业课程体系对毕业要求的支撑关系 window.elasticLayer(3534)} >查看详情
+ +
+
+ 毕业要求指标点({data.subitems_count} + 课程体系({data.course_count} +
+ +
+ +
+ +

1200? 140*data.max_support_count : 1200+"px"}}> + 毕业要求指标点 + {list(data.max_support_count<5||data.max_support_count===undefined?5:data.max_support_count)} + 合计 +

+
+ { + data.graduation_subitems===undefined? }/>:data.graduation_subitems.map((item,key)=>{ + + return ( +
  • 1134 ? 136*data.max_support_count : 1134+"px",margin: '0px 0px'}}> + + {item.sequence_num} + + + + { + item.course_supports.map((t,kes)=>{ + return( + +
    {t.name.length>12?t.name.substring(0, 10)+"...":t.name}
    +
    ({t.weigths})
    +
    + ) + + }) + } + + +
    +
    +
    {item.course_supports.length}
    +
    {Math.round(item.weights_total*100)/100===0?" ":(Math.round(item.weights_total*100)/100)}
    +
    +
    + {data.is_manager===false?"": + + } +
    +
    + +
    + +

    + +

    + 指标点 {index} + 支撑课程 + + 权重(∑=1) + (精确到两位小数) + + 关联度最高 +

    + +
    + + { + editcourse.map((it,key)=>{ + + return( +
    + + + + +
    + +
    + + + + +
    + + + +
    + +
    + ) + }) + } + +
    + {Supportslist} +
    + 合计: {editcourse.length} + 合计: {editnum} +
    + +
    +
    保存
    +
    取消
    +
    + +

    + + +
  • + ) + }) + } +
    +
    + +
    +
    + ); + } +} + +export default CourseSupports ; + diff --git a/public/react/src/modules/ecs/EcSetting/index.js b/public/react/src/modules/ecs/EcSetting/index.js index 1a887aa1b..4dd6318bf 100644 --- a/public/react/src/modules/ecs/EcSetting/index.js +++ b/public/react/src/modules/ecs/EcSetting/index.js @@ -11,6 +11,8 @@ const { Step } = Steps; const TrainingObjective = CustomLoadable(() => import('./TrainingObjective/index')) const GraduationRequirement = CustomLoadable(() => import('./GraduationRequirement/index')) +const CourseSupports = CustomLoadable(() => import('./CourseSupports/index')) + const steps = ["培养目标", "毕业要求", "培养目标VS毕业要求", "毕业要求VS通用标准", "学生", "课程体系", "课程体系VS毕业要求", "达成度评价结果"]; const stepTypes = ["training_objectives", "graduation_requirement", "requirement_vs_objective", "requirement_vs_standard", "students", "courses", "requirement_vs_courses", "reach_calculation_info"]; @@ -107,6 +109,10 @@ class EcSetting extends React.Component { render={ (props) => () }> () }> + + + () }> ) } diff --git a/public/react/src/modules/ecs/EcSetting/index.scss b/public/react/src/modules/ecs/EcSetting/index.scss index 8c8d7cbd3..7fcd80880 100644 --- a/public/react/src/modules/ecs/EcSetting/index.scss +++ b/public/react/src/modules/ecs/EcSetting/index.scss @@ -15,7 +15,7 @@ background: #fff; .ant-steps-item { - flex: unset; + flex: unset !important; &-container { margin-left: 0;