diff --git a/README.md b/README.md index 8dcb6d131..90f519de4 100644 --- a/README.md +++ b/README.md @@ -1,69 +1,70 @@ -# README - -This README would normally document whatever steps are necessary to get the -application up and running. - -Things you may want to cover: - -* Ruby version - -* System dependencies - -* Configuration - -* Database creation - -* Database initialization - -* How to run the test suite - -* Services (job queues, cache servers, search engines, etc.) - -* Deployment instructions - -* ... -#### Jbuilder介绍 -Jbuilder: https://github.com/rails/jbuilder - -#### Rails5 介绍 -rails guide: https://ruby-china.github.io/rails-guides/v5.0/ - -#### API设计文档 -doc for api: https://www.showdoc.cc/web/#/127895880302646?page_id=729221359592009 -user:Hjqreturn PW:12345678 - -#### 测试版访问地址:https://testeduplus2.educoder.net - -#### 实训平台繁忙 - 仓库异常:繁忙等级(81) - -#### 新版域名跳转规则 -新版域名要求总结:testeduplus2.educoder.net/(主要提供实训、实训课堂等业务) -目前有两个域名testbdweb.educoder.net(老版:主要提供课堂、项目、个人主页、后台等服务) - -要求: -1、两服务域名都应该启动‘提供服务 - -2、如果请求链接包含以下的形式,则域名跳至testeduplus2.educoder.net -testeduplus2.educoder.net/shixuns -testeduplus2.educoder.net/shixuns/* -testeduplus2.educoder.net/paths -testeduplus2.educoder.net/paths/* -testeduplus2.educoder.net/myshixuns/ -testeduplus2.educoder.net/tasks/* -testeduplus2.educoder.net/games/* - -如果不满足上述需求的,域名全部跳转至testbdweb.educoder.net -比如:门户首页,如果访问:testeduplus2.educoder.net 应为没包含上述链接。则调制testbdweb.educoder.net -在比如:testeduplus2.educoder.net /users/Hjqreturn没包含上述规则,则跳转到testbdweb.educoder.net/users/Hjqreturn - - -# 需要重构user_extensions 相关sql语句的地方标记 REDO:Extention - -# 文件上传:ActiveStorage -# 新能:bootsnap - -# 注意事项: -# 第一次部署需要执行一些rake任务 -# 配置redis地址 +# README +https://www.trustie.net/issues/24719 +[云上实验室] Logo、导航、底部备案信息定制化 +This README would normally document whatever steps are necessary to get the +application up and running. + +Things you may want to cover: + +* Ruby version + +* System dependencies + +* Configuration + +* Database creation + +* Database initialization + +* How to run the test suite + +* Services (job queues, cache servers, search engines, etc.) + +* Deployment instructions + +* ... +#### Jbuilder介绍 +Jbuilder: https://github.com/rails/jbuilder + +#### Rails5 介绍 +rails guide: https://ruby-china.github.io/rails-guides/v5.0/ + +#### API设计文档 +doc for api: https://www.showdoc.cc/web/#/127895880302646?page_id=729221359592009 +user:Hjqreturn PW:12345678 + +#### 测试版访问地址:https://testeduplus2.educoder.net + +#### 实训平台繁忙 + 仓库异常:繁忙等级(81) + +#### 新版域名跳转规则 +新版域名要求总结:testeduplus2.educoder.net/(主要提供实训、实训课堂等业务) +目前有两个域名testbdweb.educoder.net(老版:主要提供课堂、项目、个人主页、后台等服务) + +要求: +1、两服务域名都应该启动‘提供服务 + +2、如果请求链接包含以下的形式,则域名跳至testeduplus2.educoder.net +testeduplus2.educoder.net/shixuns +testeduplus2.educoder.net/shixuns/* +testeduplus2.educoder.net/paths +testeduplus2.educoder.net/paths/* +testeduplus2.educoder.net/myshixuns/ +testeduplus2.educoder.net/tasks/* +testeduplus2.educoder.net/games/* + +如果不满足上述需求的,域名全部跳转至testbdweb.educoder.net +比如:门户首页,如果访问:testeduplus2.educoder.net 应为没包含上述链接。则调制testbdweb.educoder.net +在比如:testeduplus2.educoder.net /users/Hjqreturn没包含上述规则,则跳转到testbdweb.educoder.net/users/Hjqreturn + + +# 需要重构user_extensions 相关sql语句的地方标记 REDO:Extention + +# 文件上传:ActiveStorage +# 新能:bootsnap + +# 注意事项: +# 第一次部署需要执行一些rake任务 +# 配置redis地址 # 配置gitlab/intializers/gitlab_config.yml \ No newline at end of file diff --git a/app/controllers/admins/competitions_controller.rb b/app/controllers/admins/competitions_controller.rb new file mode 100644 index 000000000..3d6bef819 --- /dev/null +++ b/app/controllers/admins/competitions_controller.rb @@ -0,0 +1,15 @@ +class Admins::CompetitionsController < Admins::BaseController + + def index + params[:sort_by] = params[:sort_by].presence || 'created_on' + params[:sort_direction] = params[:sort_direction].presence || 'desc' + @competitions = custom_sort Competition.all, params[:sort_by], params[:sort_direction] + @params_page = params[:page] || 1 + @competitions = paginate @competitions + + respond_to do |format| + format.js + format.html + end + end +end \ No newline at end of file diff --git a/app/controllers/boards_controller.rb b/app/controllers/boards_controller.rb index 1081a82ce..2bcc8d8f6 100644 --- a/app/controllers/boards_controller.rb +++ b/app/controllers/boards_controller.rb @@ -2,7 +2,7 @@ class BoardsController < ApplicationController before_action :require_login, :check_auth before_action :find_course, only: [:create] before_action :set_board, except: [:create] - before_action :teacher_or_admin_allowed + before_action :teacher_allowed def index @boards = @course.boards.includes(messages: [:last_reply, :author]) diff --git a/app/controllers/course_groups_controller.rb b/app/controllers/course_groups_controller.rb index 0e16d1bac..bfdb959b4 100644 --- a/app/controllers/course_groups_controller.rb +++ b/app/controllers/course_groups_controller.rb @@ -2,7 +2,7 @@ class CourseGroupsController < ApplicationController before_action :require_login, :check_auth before_action :set_group, except: [:create] before_action :find_course, only: [:create] - before_action :teacher_or_admin_allowed + before_action :teacher_allowed def create tip_exception("分班名称不能为空") if params[:name].blank? diff --git a/app/controllers/course_modules_controller.rb b/app/controllers/course_modules_controller.rb index fccc28f6d..0bef519fd 100644 --- a/app/controllers/course_modules_controller.rb +++ b/app/controllers/course_modules_controller.rb @@ -2,7 +2,8 @@ class CourseModulesController < ApplicationController before_action :require_login, :check_auth before_action :set_module, except: [:unhidden_modules] before_action :find_course, only: [:unhidden_modules] - before_action :teacher_or_admin_allowed + before_action :teacher_or_admin_allowed, except: [:add_second_category] + before_action :teacher_allowed, only: [:add_second_category] # 模块置顶 def sticky_module diff --git a/app/controllers/course_second_categories_controller.rb b/app/controllers/course_second_categories_controller.rb index e5c3366cd..2de1637f2 100644 --- a/app/controllers/course_second_categories_controller.rb +++ b/app/controllers/course_second_categories_controller.rb @@ -1,7 +1,7 @@ class CourseSecondCategoriesController < ApplicationController before_action :require_login, :check_auth before_action :set_category - before_action :teacher_or_admin_allowed + before_action :teacher_allowed # 目录重命名 def rename_category diff --git a/app/models/attachment.rb b/app/models/attachment.rb index 9c60317bd..8b7034ab9 100644 --- a/app/models/attachment.rb +++ b/app/models/attachment.rb @@ -98,7 +98,7 @@ class Attachment < ApplicationRecord def become_history history = self.attachment_histories.first - new_attachment_history = AttachmentHistory.new(self.attributes.except("id", "resource_bank_id", "unified_setting", "course_second_category_id").merge( + new_attachment_history = AttachmentHistory.new(self.attributes.except("id", "resource_bank_id", "unified_setting", "course_second_category_id", "delay_publish").merge( attachment_id: self.id, version: history.nil? ? 1 : history.version + 1, )) @@ -106,7 +106,7 @@ class Attachment < ApplicationRecord end def copy_attributes_from_new_attachment(new_attachment) - self.attributes = new_attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes",'is_publish','publish_time') + self.attributes = new_attachment.attributes.dup.except("id","container_id","container_type","is_public","downloads", "quotes",'is_publish','publish_time', "delay_publish") end def set_public(is_public) diff --git a/app/models/competition_mode_setting.rb b/app/models/competition_mode_setting.rb new file mode 100644 index 000000000..b6bafa7c3 --- /dev/null +++ b/app/models/competition_mode_setting.rb @@ -0,0 +1,3 @@ +class CompetitionModeSetting < ApplicationRecord + belongs_to :course +end diff --git a/app/views/admins/competitions/index.html.erb b/app/views/admins/competitions/index.html.erb new file mode 100644 index 000000000..8fa238181 --- /dev/null +++ b/app/views/admins/competitions/index.html.erb @@ -0,0 +1,7 @@ +<% define_admin_breadcrumbs do %> + <% add_admin_breadcrumb('竞赛列表', admins_competitions_path) %> +<% end %> + +
+ <%= render partial: 'admins/shixuns/shared/list', locals: { shixuns: @shixuns } %> +
diff --git a/app/views/admins/shared/_sidebar.html.erb b/app/views/admins/shared/_sidebar.html.erb index 145910928..ca6fb2a46 100644 --- a/app/views/admins/shared/_sidebar.html.erb +++ b/app/views/admins/shared/_sidebar.html.erb @@ -66,6 +66,8 @@ <% end %> +
  • <%= sidebar_item(admins_competitions_path, '竞赛', icon: 'trophy', controller: 'admins-competitions') %>
  • +
  • <%= sidebar_item_group('#setting-submenu', '网站建设', icon: 'cogs') do %>
  • <%= sidebar_item(admins_carousels_path, '轮播图', icon: 'image', controller: 'admins-carousels') %>
  • diff --git a/app/views/competitions/competitions/index.json.jbuilder b/app/views/competitions/competitions/index.json.jbuilder index f0d70f69e..400f17379 100644 --- a/app/views/competitions/competitions/index.json.jbuilder +++ b/app/views/competitions/competitions/index.json.jbuilder @@ -20,7 +20,7 @@ json.competitions do if section json.current_stage do - json.name = section.competition_stage.name + json.name section.competition_stage.name json.start_time section.display_start_time json.end_time section.display_end_time end diff --git a/app/views/courses/mine.json.jbuilder b/app/views/courses/mine.json.jbuilder index 41368d883..fc6a5becc 100644 --- a/app/views/courses/mine.json.jbuilder +++ b/app/views/courses/mine.json.jbuilder @@ -1,5 +1,6 @@ json.partial! "commons/success" -json.data do - json.array! @courses, :id, :name, :updated_at, :created_at, :end_date +json.data @courses do |course| + json.(course, :id, :name, :updated_at, :end_date) + json.created_at course.created_at.strftime("%Y-%m-%d") end diff --git a/config/routes.rb b/config/routes.rb index 32725e8e9..f6f8db066 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -980,6 +980,8 @@ Rails.application.routes.draw do resource :laboratory_setting, only: [:show, :update] resource :laboratory_user, only: [:create, :destroy] end + + resources :competitions, only: [:index, :destroy] end resources :colleges, only: [] do diff --git a/db/migrate/20191015013924_add_new_column_to_competitions.rb b/db/migrate/20191015013924_add_new_column_to_competitions.rb new file mode 100644 index 000000000..616a46059 --- /dev/null +++ b/db/migrate/20191015013924_add_new_column_to_competitions.rb @@ -0,0 +1,6 @@ +class AddNewColumnToCompetitions < ActiveRecord::Migration[5.2] + def change + add_column :competitions, :bonus, :integer, default: 0 + add_column :competitions, :mode, :integer, default: 0 + end +end diff --git a/db/migrate/20191015015723_create_competition_mode_settings.rb b/db/migrate/20191015015723_create_competition_mode_settings.rb new file mode 100644 index 000000000..5d170eeab --- /dev/null +++ b/db/migrate/20191015015723_create_competition_mode_settings.rb @@ -0,0 +1,11 @@ +class CreateCompetitionModeSettings < ActiveRecord::Migration[5.2] + def change + create_table :competition_mode_settings do |t| + t.references :course + t.datetime :start_time + t.datetime :end_time + + t.timestamps + end + end +end diff --git a/public/react/public/index.html b/public/react/public/index.html index f6eef196a..9b757d2c4 100755 --- a/public/react/public/index.html +++ b/public/react/public/index.html @@ -13,7 +13,7 @@ - + - EduCoder + + diff --git a/public/react/src/App.js b/public/react/src/App.js index 34b5d1a4f..fd945914a 100644 --- a/public/react/src/App.js +++ b/public/react/src/App.js @@ -9,7 +9,7 @@ import { Route, Switch } from 'react-router-dom'; - +import axios from 'axios'; import '@icedesign/base/dist/ICEDesignBase.css'; import '@icedesign/base/index.scss'; @@ -287,6 +287,7 @@ class App extends Component { Addcoursestypes:false, mydisplay:false, occupation:0, + mygetHelmetapi:undefined, } } @@ -327,7 +328,6 @@ class App extends Component { } componentDidMount() { this.disableVideoContextMenu(); - // force an update if the URL changes history.listen(() => { this.forceUpdate() @@ -336,7 +336,8 @@ class App extends Component { $("html").animate({ scrollTop: $('html').scrollTop() - 0 }) }); - initAxiosInterceptors(this.props) + initAxiosInterceptors(this.props); + this.getAppdata(); // // axios.interceptors.response.use((response) => { // // console.log("response"+response); @@ -362,15 +363,78 @@ class App extends Component { this.setState({ isRender:false, }) - } - - render() { + }; + //获取当前定制信息 + getAppdata=()=>{ + let url = "/setting.json"; + axios.get(url).then((response) => { + // console.log("app.js开始请求/setting.json"); + // console.log("获取当前定制信息"); + if(response){ + if(response.data){ + this.setState({ + mygetHelmetapi:response.data.setting + }); + document.title = response.data.setting.name; + var link = document.createElement('link'), + oldLink = document.getElementById('dynamic-favicon'); + link.id = 'dynamic-favicon'; + link.rel = 'shortcut icon'; + link.href = '/'+response.data.setting.tab_logo_url; + if (oldLink) { + document.head.removeChild(oldLink); + } + document.head.appendChild(link); + }else { + document.title = "EduCoder"; + var link = document.createElement('link'), + oldLink = document.getElementById('dynamic-favicon'); + link.id = 'dynamic-favicon'; + link.rel = 'shortcut icon'; + link.href = "/react/build/./favicon.ico"; + if (oldLink) { + document.head.removeChild(oldLink); + } + document.head.appendChild(link); + } + + }else{ + document.title = "EduCoder"; + var link = document.createElement('link'), + oldLink = document.getElementById('dynamic-favicon'); + link.id = 'dynamic-favicon'; + link.rel = 'shortcut icon'; + link.href = "/react/build/./favicon.ico"; + if (oldLink) { + document.head.removeChild(oldLink); + } + document.head.appendChild(link); + } + }).catch((error) => { + document.title = "EduCoder"; + var link = document.createElement('link'), + oldLink = document.getElementById('dynamic-favicon'); + link.id = 'dynamic-favicon'; + link.rel = 'shortcut icon'; + link.href = "/react/build/./favicon.ico"; + if (oldLink) { + document.head.removeChild(oldLink); + } + document.head.appendChild(link); + }); + }; + render() { + let{mygetHelmetapi}=this.state; + // console.log("appappapp"); + // console.log(mygetHelmetapi); return ( + + this.Modifyloginvalue()}> @@ -413,10 +477,22 @@ class App extends Component { { + + return () + } + } /> { + + return () + } + } /> { + + return () + } + } /> {/*课堂*/} - + {/* */} @@ -502,7 +584,12 @@ class App extends Component { render={ (props)=>() }/> - + () + } + /> @@ -625,4 +712,4 @@ moment.defineLocale('zh-cn', { doy: 4 // The week that contains Jan 4th is the first week of the year. } }); -export default SnackbarHOC()(App); \ No newline at end of file +export default SnackbarHOC()(App) ; \ No newline at end of file diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index e1d5da561..9cf68503d 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -94,9 +94,15 @@ export function initAxiosInterceptors(props) { } } - if (requestMap[config.url] === true) { // 避免重复的请求 + if (config.method === "post") { + if (requestMap[config.url] === true) { // 避免重复的请求 导致页面f5刷新 也会被阻止 显示这个方法会影响到定制信息定制信息是get 请求 + // console.log(config); + // console.log(JSON.parse(config)); + // console.log(config.url); + // console.log("被阻止了是重复请求================================="); return false; } + } // 非file_update请求 if (config.url.indexOf('update_file') === -1) { requestMap[config.url] = true; diff --git a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js index 438c07aeb..e1a1f17f9 100644 --- a/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js +++ b/public/react/src/modules/courses/exercise/Studentshavecompletedthelist.js @@ -2663,6 +2663,9 @@ class Studentshavecompletedthelist extends Component { .ant-spin-nested-loading > div > .ant-spin .ant-spin-dot { top: 72%;} } + .ysltableows2 .ant-table-thead > tr > th, .ant-table-tbody > tr > td { + padding: 9px; + } `}
    {data === undefined ? "" : div > .ant-spin .ant-spin-dot { top: 72%;} } + .ysltableows2 .ant-table-thead > tr > th, .ant-table-tbody > tr > td { + padding: 9px; + } `} -
    +
    {datas === undefined ? "" :
    { - // console.log("Commonheadofthetestpaper"); + console.log("Commonheadofthetestpaper 试卷公用头部"); var exercise_id = this.props.match.params.Id; var url = `/exercises/${exercise_id}/common_header.json`; axios.get(url).then((response) => { @@ -249,6 +249,19 @@ class Testpapersettinghomepage extends Component{ // DownloadMessageval:undefined // }) // } + getsetdata =()=>{ + // console.log("Testpapersettinghomepage"); + // console.log("getsetdatassssss"); + let{tab}=this.state; + try { + if(tab[0]==="0"){ + this.child.Teacherliststudentlist(); + } + }catch (e) { + + } + + } bindRef = ref => { this.child = ref }; goback=()=>{ // let {datalist}=this.state; @@ -410,6 +423,7 @@ class Testpapersettinghomepage extends Component{ Exercisetype={"exercise"} action={this.Commonheadofthetestpaper} single={true} + getsetdata={this.getsetdata} > :"":""} {isAdmin === true? 编辑试卷:""} diff --git a/public/react/src/modules/courses/members/ChangeRolePop.js b/public/react/src/modules/courses/members/ChangeRolePop.js index 455e851ee..adc4fa26a 100644 --- a/public/react/src/modules/courses/members/ChangeRolePop.js +++ b/public/react/src/modules/courses/members/ChangeRolePop.js @@ -6,7 +6,7 @@ import axios from 'axios' /** 角色数组, CREATOR: 创建者, PROFESSOR: 教师, ASSISTANT_PROFESSOR: 助教, STUDENT: 学生 */ -function ChangeRolePop({ member_roles = [], record, courseId, onChangeRoleSuccess, showNotification, getUserId, fetchUser }) { +function ChangeRolePop({ member_roles = [], record, courseId, onChangeRoleSuccess, showNotification, getUserId, fetchUser, style }) { const [checkBoxRoles, setCheckBoxRoles] = useState(member_roles) // useEffect(() => { // if (checkBoxRoles.length != member_roles.length) { // 死循环 @@ -75,7 +75,7 @@ function ChangeRolePop({ member_roles = [], record, courseId, onChangeRoleSucces } > - 修改角色 + 修改角色 ) } diff --git a/public/react/src/modules/courses/members/studentsList.js b/public/react/src/modules/courses/members/studentsList.js index 1f6bf9096..a63509c59 100644 --- a/public/react/src/modules/courses/members/studentsList.js +++ b/public/react/src/modules/courses/members/studentsList.js @@ -320,6 +320,9 @@ class studentsList extends Component{ isAdmin && on('updateNavSuccess', this.updateNavSuccess) } componentWillUnmount() { + if (this.clipboard) { + this.clipboard.destroy() + } const isAdmin = this.props.isAdmin() if (isAdmin) { off('addStudentSuccess', this.addStudentSuccessListener) @@ -420,12 +423,14 @@ class studentsList extends Component{ invite_code: result.data.invite_code, isSpin:false }, () => { - if (!this.clipboard) { - const clipboard = new ClipboardJS('.copybtn'); - clipboard.on('success', (e) => { - this.props.showNotification('复制成功') - }); - this.clipboard = clipboard + if (course_group_id) { + if (!this.clipboard) { + const clipboard = new ClipboardJS('.copybtn'); + clipboard.on('success', (e) => { + this.props.showNotification('复制成功') + }); + this.clipboard = clipboard + } } }) } @@ -598,7 +603,7 @@ class studentsList extends Component{ .then((response) => { if (response.data.status == 0) { this.props.showNotification('删除成功') - this.props.history.push(`/courses/${coursesId}/course_groups`) + this.props.history.push(`/courses/${courseId}/course_groups`) } }) .catch(function (error) { @@ -706,7 +711,7 @@ class studentsList extends Component{ - { this.props.history.push(`/courses/${coursesids}/course_groups`)}} + { this.props.history.push(`/courses/${courseId}/course_groups`)}} style={{color: '#212121', verticalAlign: 'initial', marginRight: '14px' }} > {course_group_name || '未分班'} @@ -751,7 +756,7 @@ class studentsList extends Component{ !isStudentPage && !isCourseEnd && isAdmin && this.addDir()}>新建分班 } { - !isStudentPage && isStudent && !isParent && course_group_id != 0 && this.addToDir()}>加入分班 } + !isStudentPage && isStudent && !isParent && course_group_id != 0 && this.addToDir()}>加入分班 } -
    - {/*<%= link_to image_tag("/images/educoder/logo.png", alt:"高校智能化教学与实训平台", className:"logoimg"), home_path %>*/} + { + mygetHelmetapi2!==undefined&&mygetHelmetapi2.navbar!==null&&mygetHelmetapi2.navbar!==undefined&&mygetHelmetapi2.navbar.length>0? +
    +
      + {/*
    • 首页
    • */} + {/*
    • 实训路径
    • */} + { + mygetHelmetapi2.navbar && mygetHelmetapi2.navbar.map((item,key)=>{ + // console.log("headtypes"); + // console.log(headtypes);hidden + var str=new RegExp("http"); + var strbool=false; + //test方法返回值为(true或者false) + if(item.link){ + if(str.test(item.link)===true){ + strbool=true + }else{ + strbool=false + } + } + console.log(item.hidden); + return( +
    • this.headtypesonClick(item.link,true)} className={`${headtypes===undefined?'pr':headtypes===item.link?'pr active':'pr'}`} style={item.hidden==false?{display: 'block'}:{display: 'none'}}> + { + strbool===true? + {item.name} + : + {item.name} + } +
    • + ) + }) + } + {/*
    • */} + {/* 实践课程*/} + {/*
    • */} + + {/*
    • 课堂
    • */} + {/*
    • */} + {/* /!*课堂*!/*/} + {/* 翻转课堂*/} + {/*
    • */} + + {/*
    • */} + {/* 实训项目*/} + {/* */} + {/* */} + {/*
    • */} + + + {/*
    • 教学案例
    • */} + {/*
    • */} + {/* 在线竞赛*/} + {/* */} + {/*
    • */} + {/*
    • 教学案例
    • */} + {/*
    • */} + {/*众包创新*/} + {/*
    • */} + {/*
    • 交流问答
    • */} + {/*工程认证*/} + + + + +
    • 0 ? 'block' : 'none'}}> + 职业路径 +
      0 ? 'block' : 'none'}}> +
        + {this.props.Headertop === undefined ? "" : this.props.Headertop.career_url.map((item, key) => { + return( +
      • {item.name}
      • + ) + }) + } +
      +
      +
    • +
    +
    + // :mygetHelmetapi2===undefined||mygetHelmetapi2.navbar===null||mygetHelmetapi2.navbar===undefined||mygetHelmetapi2.navbar.length===0? + //
    + // + //
      + // {/*
    • 首页
    • */} + // + // {/*
    • 实训路径
    • */} + //
    • + // 实践课程 + //
    • + // + // {/*
    • 课堂
    • */} + //
    • + // {/*课堂*/} + // 翻转课堂 + //
    • + // + //
    • + // 实训项目 + // {/**/} + // {/**/} + //
    • + // + //
    • 0 ? 'block' : 'none'}}> + // 职业路径 + //
      0 ? 'block' : 'none'}}> + //
        + // {this.props.Headertop === undefined ? "" : this.props.Headertop.career_url.map((item, key) => { + // return( + //
      • {item.name}
      • + // ) + // }) + // } + //
      + //
      + //
    • + // + // {/*
    • 教学案例
    • */} + //
    • + // 在线竞赛 + // {/**/} + //
    • + //
    • 教学案例
    • + // {/*
    • */} + // {/*众包创新*/} + // {/*
    • */} + //
    • 交流问答
    • + //
    • 工程认证
    • + //
    + //
    + : +
    + +
      + {/*
    • 首页
    • */} + + {/*
    • 实训路径
    • */} +
    • + 实践课程 +
    • + + {/*
    • 课堂
    • */} +
    • + {/*课堂*/} + 翻转课堂 +
    • + +
    • + 实训项目 + {/**/} + {/**/} +
    • + +
    • 0 ? 'block' : 'none'}}> + 职业路径 +
      0 ? 'block' : 'none'}}> +
        + {this.props.Headertop === undefined ? "" : this.props.Headertop.career_url.map((item, key) => { + return( +
      • {item.name}
      • + ) + }) + } +
      +
      +
    • + + {/*
    • 教学案例
    • */} +
    • + 在线竞赛 + {/**/} +
    • +
    • 教学案例
    • + {/*
    • */} + {/*众包创新*/} + {/*
    • */} +
    • 交流问答
    • +
    • 工程认证
    • +
    +
    + } -
    -
      - {/*
    • 首页
    • */} - {/*
    • 实训路径
    • */} -
    • - 实践课程 -
    • - {/*
    • 课堂
    • */} -
    • - {/*课堂*/} - 翻转课堂 -
    • -
    • - 实训项目 - - -
    • - -
    • 0 ? 'block' : 'none'}}> - 职业路径 -
      0 ? 'block' : 'none'}}> -
        - {this.props.Headertop === undefined ? "" : this.props.Headertop.career_url.map((item, key) => { - return( -
      • {item.name}
      • - ) - }) - } -
      -
      -
    • - - {/*
    • 教学案例
    • */} -
    • - 在线竞赛 - -
    • -
    • 教学案例
    • - {/*
    • */} - {/*众包创新*/} - {/*
    • */} -
    • 交流问答
    • -
    • 工程认证
    • -
    - - -
    -