dev_ec
杨树林 5 years ago
commit d6d2093fa6

@ -378,6 +378,7 @@ DEPENDENCIES
kaminari (~> 1.1, >= 1.1.1)
listen (>= 3.0.5, < 3.2)
mysql2 (>= 0.4.4, < 0.6.0)
newrelic_rpm
oauth2
pdfkit
puma (~> 3.11)

@ -0,0 +1,4 @@
$(document).on('turbolinks:load', function() {
if ($('body.admins-schools-index-page').length > 0) {
}
});

@ -0,0 +1,3 @@
.admins-schools-index-page {
}

@ -0,0 +1,30 @@
class Admins::SchoolsController < Admins::BaseController
def index
params[:sort_by] ||= 'created_at'
params[:sort_direction] ||= 'desc'
schools = Admins::SchoolQuery.call(params)
@schools = paginate schools
school_ids = @schools.map(&:id)
@department_count = Department.where(school_id: school_ids).group(:school_id).count
end
def destroy
users = User.joins(:user_extension).where(user_extensions: { school_id: current_school.id })
ActiveRecord::Base.transaction do
users.update_all(profile_completed: false)
current_school.destroy!
end
render_delete_success
end
private
def current_school
@_current_school ||= School.find(params[:id])
end
end

@ -14,6 +14,7 @@ class ApplicationController < ActionController::Base
#before_action :check_account
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
OPENKEY = "79e33abd4b6588941ab7622aed1e67e8"
helper_method :current_user
@ -246,6 +247,16 @@ class ApplicationController < ActionController::Base
User.current = find_current_user
uid_logger("user_setup: " + (User.current.logged? ? "#{User.current.try(:login)} (id=#{User.current.try(:id)})" : "anonymous"))
# 开放课程通过链接访问的用户
if !User.current.logged? && !params[:chinaoocTimestamp].blank? && !params[:websiteName].blank? && !params[:chinaoocKey].blank?
content = "#{OPENKEY}#{params[:websiteName]}#{params[:chinaoocTimestamp]}"
if Digest::MD5.hexdigest(content) == params[:chinaoocKey]
user = User.open_class_user
start_user_session(user) if user
User.current = user
end
end
if !User.current.logged? && Rails.env.development?
User.current = User.find 1
end

@ -3,6 +3,7 @@ class Ecs::GraduationCourseSupportsController < Ecs::BaseController
def show
@graduation_subitems = current_year.ec_graduation_subitems
.reorder('ec_graduation_requirements.position ASC, ec_graduation_subitems.position ASC')
.includes(:ec_graduation_requirement, ec_course_supports: :ec_course)
@course_count = current_year.ec_courses.count

@ -0,0 +1,6 @@
class Ecs::GraduationSubitemsController < Ecs::BaseController
def index
subitems = current_year.ec_graduation_subitems.reorder('ec_graduation_requirements.position ASC, ec_graduation_subitems.position ASC')
@graduation_subitems = subitems.includes(:ec_graduation_requirement)
end
end

@ -321,11 +321,12 @@ class StudentWorksController < ApplicationController
ActiveRecord::Base.transaction do
begin
revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last
if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}'
and score is not null").count == 0
revise_attachment.destroy
end
# 补交作业附件不覆盖之前上传的附件
# revise_attachment = @work.attachments.where(attachtype: 7).reorder("created_on desc").last
# if revise_attachment.present? && @work.student_works_scores.where("created_at > '#{revise_attachment.created_on}'
# and score is not null").count == 0
# revise_attachment.destroy
# end
Attachment.associate_container(params[:attachment_ids], @work.id, @work.class, 7)
revise_attachment = Attachment.where(attachtype: 7, container_id: @work.id, container_type: "StudentWork").last
revise_attachment.update_attributes(description: params[:description]) if revise_attachment.present?

@ -81,7 +81,7 @@ module TidingDecorator
end
def student_join_course_content
I18n.t(locale_format) % Course.find_by(id: container_id)&.name
I18n.t(locale_format) % [trigger_user.show_real_name, Course.find_by(id: container_id)&.name]
end
def teacher_join_course_content

@ -8,7 +8,7 @@ class ApplyTeacherRoleJoinCourseNotifyJob < ApplicationJob
return if user.blank? || course.blank?
attrs = %i[user_id trigger_user_id container_id container_type belong_container_id
belong_container_type tiding_type extra created_at updated_at]
belong_container_type tiding_type status extra created_at updated_at]
same_attrs = {
trigger_user_id: user.id, container_id: course.id, container_type: 'JoinCourse', status: 0,

@ -18,10 +18,18 @@ module Util::FileManage
File.exist?(disk_filename(source_type, source_id))
end
def exists?(source)
File.exist?(disk_filename(source.class, source.id))
end
def disk_file_url(source_type, source_id)
File.join('/images', relative_path, "#{source_type}", "#{source_id}")
end
def source_disk_file_url(source)
File.join('/images', relative_path, "#{source.class}", "#{source.id}")
end
def disk_auth_filename(source_type, source_id, type)
File.join(storage_path, "#{source_type}", "#{source_id}#{type}")
end

@ -32,6 +32,6 @@ class CourseMessage < ApplicationRecord
belong_container: course, extra: content.to_i == 2 ? '9' : '7', tiding_type: 'System', status: deal_status
)
# 将申请消息置为已处理
Tiding.where(trigger_user_id: user_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1)
Tiding.where(trigger_user_id: course_message_id, container_id: course_id, container_type: 'JoinCourse', status: 0).update_all(status: 1)
end
end

@ -5,7 +5,7 @@ class Department < ApplicationRecord
has_many :member_users, through: :department_members, source: :user
has_many :user_extensions, dependent: :nullify
has_many :apply_add_departments
has_many :apply_add_departments, dependent: :destroy
scope :without_deleted, -> { where(is_delete: false) }

@ -17,6 +17,7 @@ class School < ApplicationRecord
has_many :partners, dependent: :destroy
has_many :apply_add_departments, dependent: :destroy
has_many :user_extensions, dependent: :nullify
# 学校管理员
def manager?(user)

@ -21,7 +21,7 @@ class StudentGraduationTopic < ApplicationRecord
def send_tiding
self.tidings << Tiding.new(:user_id => self.graduation_topic.tea_id, :trigger_user_id => self.user_id, :parent_container_id => self.graduation_topic_id, :parent_container_type => "GraduationTopic",
:belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "GraduationTopic")
:belong_container_id => self.graduation_topic.course_id, :belong_container_type => "Course", :viewed => 0, :status => 0, :tiding_type => "Apply")
end
# 学生名称

@ -610,6 +610,29 @@ class User < ApplicationRecord
admin? || business?
end
# 149课程的评审用户数据创建包含创建课堂学生
def open_class_user
user = User.find_by(login: "OpenClassUser")
unless user
ActiveRecord::Base.transaction do
user_params = {status: 1, login: "OpenClassUser", lastname: "开放课程",
nickname: "开放课程", professional_certification: 1, certification: 1, grade: 0,
password: "12345678", phone: "11122223333", profile_completed: 1}
user = User.create!(user_params)
UserExtension.create!(user_id: user.id, gender: 0, school_id: 117, :identity => 1, :student_id => "openclassuser")
subject = Subject.find_by(id: 149)
if subject
subject.courses.each do |course|
CourseMember.create!(course_id: course.id, role: 4, user_id: user.id) if !course.course_students.exists?(user_id: user.id)
end
end
end
end
user
end
protected
def validate_password_length
# 管理员的初始密码是5位

@ -1,6 +1,6 @@
class UserExtension < ApplicationRecord
# identity 0: 教师教授 1: 学生, 2: 专业人士, 3: 开发者
enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, cnmooc: 4, unselect: -1 }
enum identity: { teacher: 0, student: 1, professional: 2, developer: 3, enterprise: 4, unselect: -1 }
belongs_to :user, touch: true
belongs_to :school, optional: true

@ -0,0 +1,23 @@
class Admins::SchoolQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :users_count, :created_at, default_by: :created_at, default_direction: :desc
def initialize(params)
@params = params
end
def call
schools = School.all
keyword = strip_param(:keyword)
schools = schools.where('schools.name LIKE ?', "%#{keyword}%") if keyword
schools = schools.joins(:user_extensions).group(:id)
schools = schools.select('schools.*, COUNT(*) AS users_count')
custom_sort schools, params[:sort_by], params[:sort_direction]
end
end

@ -0,0 +1,16 @@
<% define_admin_breadcrumbs do %>
<% add_admin_breadcrumb('单位列表') %>
<% end %>
<div class="box search-form-container school-list-form">
<%= form_tag(admins_schools_path, method: :get, class: 'form-inline search-form flex-1', remote: true) do %>
<%= text_field_tag(:keyword, params[:keyword], class: 'form-control col-sm-2 ml-3', placeholder: '部门名称检索') %>
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<% end %>
<%#= javascript_void_link '新建单位', class: 'btn btn-primary', data: { toggle: 'modal', target: '.admin-create-school-modal' } %>
</div>
<div class="box school-list-container">
<%= render partial: 'admins/schools/shared/list', locals: { schools: @schools } %>
</div>

@ -0,0 +1 @@
$('.school-list-container').html("<%= j(render partial: 'admins/schools/shared/list', locals: { schools: @schools }) %>");

@ -0,0 +1,48 @@
<table class="table table-hover text-center school-list-table">
<thead class="thead-light">
<tr>
<th width="6%">ID</th>
<th width="6%">LOGO</th>
<th width="8%">标识码</th>
<th width="14%" class="text-left">单位名称</th>
<th width="6%">地区</th>
<th width="6%">城市</th>
<th width="16%">详细地址</th>
<th width="6%"><%= sort_tag('用户数', name: 'users_count', path: admins_schools_path) %></th>
<th width="6%">部门数</th>
<th width="12%"><%= sort_tag('创建时间', name: 'created_at', path: admins_schools_path) %></th>
<th width="14%">操作</th>
</tr>
</thead>
<tbody>
<% if schools.present? %>
<% schools.each do |school| %>
<tr class="school-item-<%= school.id %>">
<td><%= school.id %></td>
<td>
<% if Util::FileManage.exists?(school) %>
<%= image_tag(Util::FileManage.source_disk_file_url(school).to_s + "?#{Time.now.to_i}", width: 40, height: 40, class: 'preview-image') %>
<% else %>
<%= content_tag(:span, '--', class: 'text-secondary') %>
<% end %>
</td>
<td><%= display_text school.identifier %></td>
<td class="text-left"><%= school.name %></td>
<td><%= school.province %></td>
<td><%= school.city %></td>
<td class="text-left"><%= school.address %></td>
<td><%= school.users_count %></td>
<td><%= @department_count.fetch(school.id, 0) %></td>
<td><%= school.created_at&.strftime('%Y-%m-%d %H:%M') %></td>
<td>
<%= delete_link '删除', admins_school_path(school, element: ".school-item-#{school.id}"), class: 'delete-school-action' %>
</td>
</tr>
<% end %>
<% else %>
<%= render 'admins/shared/no_data_for_table' %>
<% end %>
</tbody>
</table>
<%= render partial: 'admins/shared/paginate', locals: { objects: schools } %>

@ -31,6 +31,7 @@
<li>
<%= sidebar_item_group('#schools-submenu', '单位管理', icon: 'building') do %>
<li><%= sidebar_item(admins_schools_path, '单位列表', icon: 'university', controller: 'admins-schools') %></li>
<li><%= sidebar_item(admins_departments_path, '部门列表', icon: 'sitemap', controller: 'admins-departments') %></li>
<% end %>
</li>

@ -12,7 +12,7 @@
<div class="form-group mr-2">
<label for="identity">职业:</label>
<% identity_options = [['全部', '']] + UserExtension.identities.map { |k, v| [I18n.t("user.identity.#{k}"), v] } %>
<% identity_options = [['全部', ''], ['教师', 0], ['学生', 1], ['专业人士', 2]] %>
<%= select_tag(:identity, options_for_select(identity_options), class: 'form-control') %>
</div>

@ -2,5 +2,5 @@ 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.course_supports ec_graduation_subitem.ec_course_supports, partial: 'ecs/graduation_course_supports/shared/ec_course_support', as: :ec_course_support
json.weights_total ec_graduation_subitem.ec_course_supports.to_a.sum(&:weights)

@ -0,0 +1,8 @@
json.graduation_subitems do
json.array! @graduation_subitems do |graduation_subitem|
json.extract! graduation_subitem, :id, :position, :content
json.graduation_requirement_position graduation_subitem.ec_graduation_requirement.position
end
end
json.count @graduation_subitems.size

@ -18,9 +18,7 @@ json.time tiding.how_long_time
json.new_tiding tiding.unread?(@onclick_time)
# 需要系统头像
show_system_user = tiding.trigger_user_id.zero? ||
(tiding.trigger_user_id == 1 && tiding.tiding_type == 'System') ||
tiding.anonymous?
show_system_user = tiding.trigger_user_id.zero? || tiding.tiding_type == 'System' || tiding.anonymous?
json.trigger_user do
if show_system_user

@ -19,7 +19,7 @@
"9_2_end": "你提交的加入课堂申请:%s教师, 审核未通过"
"7_1_end": "你提交的加入课堂申请:%s助教, 审核已通过"
"7_2_end": "你提交的加入课堂申请:%s助教, 审核未通过"
StudentJoinCourse_end: "加入了课堂:%s学生"
StudentJoinCourse_end: "%s 加入了课堂:%s学生"
TeacherJoinCourse:
"2_end": "%s将你加入课堂%s教师"
"3_end": "%s将你加入课堂%s助教"

@ -13,7 +13,9 @@
professional: 专业人士
developer: 从业者
enterprise: 组织
unselect: 未选择
"0": 教师
"1": 学生
"2": 专业人士
"3": 专业人士
"3": 从业者
"4": 组织

@ -737,6 +737,7 @@ Rails.application.routes.draw do
resource :graduation_course_supports, only: [:show, :create]
resource :reach_evaluation, only: [:show, :create]
resource :reach_criteria, only: [:create]
resources :graduation_subitems, only: [:index]
end
resources :ec_courses, only: [] do
@ -927,6 +928,7 @@ Rails.application.routes.draw do
resources :mirror_scripts, only: [:index, :new, :create, :edit, :update, :destroy]
end
resources :choose_mirror_repositories, only: [:new, :create]
resources :schools, only: [:index, :destroy]
resources :departments, only: [:index, :create, :edit, :update, :destroy] do
resource :department_member, only: [:create, :update, :destroy]
post :merge, on: :collection

File diff suppressed because one or more lines are too long

@ -1,5 +1,5 @@
'use strict';
// extract-css-assets-webpack-plugin
const autoprefixer = require('autoprefixer');
const path = require('path');
const webpack = require('webpack');

File diff suppressed because one or more lines are too long

@ -63,7 +63,7 @@ export { default as Clappr } from './components/media/Clappr'
export { default as AliyunUploader } from './components/media/AliyunUploader'
export { default as ImageLayerHook } from './hooks/ImageLayerHook'
export { default as ImageLayer2 } from './hooks/ImageLayer2'
// 外部
export { default as CBreadcrumb } from '../modules/courses/common/CBreadcrumb'

@ -2,7 +2,7 @@ import React, { useState, useEffect, memo } from 'react';
import ImageLayer from '../../modules/page/layers/ImageLayer';
import { isImageExtension } from 'educoder';
const $ = window.$;
function ImageLayerHook(props) {
function ImageLayer2(props) {
const [showImage, setShowImage] = useState(false)
const [imageSrc, setImageSrc] = useState('')
@ -45,4 +45,4 @@ function ImageLayerHook(props) {
)
}
export default memo(ImageLayerHook)
export default memo(ImageLayer2)

@ -16,41 +16,45 @@ const urlDoneMap = {}
function requestForSignatrue (callback) {
const currentUrl = window.location.href.split('#')[0]
if (window.wx && !urlDoneMap[currentUrl]) {
const wx = window.wx
const url = '/wechats/js_sdk_signature.json'
urlDoneMap[currentUrl] = true
// window.encodeURIComponent()
axios.post(url, {
url: window.__testUrl || currentUrl,
}).then((response) => {
console.log('got res')
const data = response.data;
wx.config({
debug: false,
appId: data.appid,
timestamp: data.timestamp,
nonceStr: data.noncestr,
signature: data.signature,
jsApiList: [
'onMenuShareTimeline',//
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone'
]
});
wx.ready(function () {
callback && callback()
});
wx.error(function (res) {
console.log('wx is error')
console.log(res)
//alert(res.errMsg);//错误提示
});
}).catch((error) => {
console.log(error)
})
if (window.wx) {
if (urlDoneMap[currentUrl]) {
callback && callback()
} else {
const wx = window.wx
const url = '/wechats/js_sdk_signature.json'
urlDoneMap[currentUrl] = true
// window.encodeURIComponent()
axios.post(url, {
url: window.__testUrl || currentUrl,
}).then((response) => {
console.log('got res')
const data = response.data;
wx.config({
debug: false,
appId: data.appid,
timestamp: data.timestamp,
nonceStr: data.noncestr,
signature: data.signature,
jsApiList: [
'onMenuShareTimeline',//
'onMenuShareAppMessage',
'onMenuShareQQ',
'onMenuShareWeibo',
'onMenuShareQZone'
]
});
wx.ready(function () {
callback && callback()
});
wx.error(function (res) {
console.log('wx is error')
console.log(res)
//alert(res.errMsg);//错误提示
});
}).catch((error) => {
console.log(error)
})
}
}
}
/**
@ -115,14 +119,14 @@ export function configShareForCourses () {
}
// detail
export function configShareForCustom (title, desc, path, imgUrl) {
export function configShareForCustom (title, desc, imgUrl, path) {
requestForSignatrue(() => {
console.log('configShareForCustom', host)
const _url = window.location.href.split('#')[0];
var shareData = {
title: title,
desc: desc,
link: `${host}/${path}`,
link: path ? `${host}/${path}` : _url,
imgUrl: imgUrl || window.__testImageUrl
|| host + '/react/build/images/share_logo_icon.jpg'
};

@ -68,7 +68,7 @@ class CommentInput extends Component {
</textarea>
</div>
<div className="tips"
style={{ 'float': 'left', 'margin-top': '6px', 'font-size': '12px', 'color': '#ff6800'}}>
style={{ 'float': 'left', 'marginTop': '6px', 'fontSize': '12px', 'color': '#ff6800'}}>
请勿粘贴答案否则将造成账号禁用等后果
</div>
<div className="fr buttons" style={{ minWidth:'25px', height: '32px' }}>

@ -2,7 +2,7 @@ import React,{Component} from "React";
import { Form, Select, Input, Button,Checkbox,Upload,Icon,message,Modal, Table, Divider, Tag,DatePicker,Radio,Tooltip} from "antd";
import {Link} from 'react-router-dom';
import locale from 'antd/lib/date-picker/locale/zh_CN';
import { WordsBtn, MarkdownToHtml, markdownToHTML } from 'educoder';
import { WordsBtn, MarkdownToHtml, markdownToHTML, ImageLayer2 } from 'educoder';
import axios from 'axios';
import Modals from '../../modals/Modals';
import CoursesListType from '../coursesPublic/CoursesListType';
@ -197,6 +197,7 @@ class CommonWorkAppraise extends Component{
border-bottom: none !important;
}
`}</style>
<ImageLayer2 parentSel=".workAppraise" childSel="a.imageTarget"></ImageLayer2>
<div className={"workAppraise"}>
{(description || (attachments && attachments.length != 0)) && <div className={"stud-class-set edu-back-white padding20-30"}>
<div className={"color-grey-6 mb15 font-16"}>
@ -247,7 +248,9 @@ class CommonWorkAppraise extends Component{
</div> }
<CommonWorkAppraiseReviseAttachments {...this.state}></CommonWorkAppraiseReviseAttachments>
<CommonWorkAppraiseReviseAttachments {...this.state}
onAttachmentRemove={this.onAttachmentRemove}
></CommonWorkAppraiseReviseAttachments>
{is_evaluation != true && project_info && project_info.name && <div className={"stud-class-set bor-top-greyE edu-back-white padding20-30"}>
<div className={"color-grey-6 mb10"}>

@ -33,7 +33,7 @@ function CommonWorkAppraiseReviseAttachments(props) {
{item.title}
</a>
<span className="color656565 mt2 color-grey-6 font-12 mr8">{item.filesize}</span>
{item.delete===true?<i className="font-14 iconfont icon-guanbi " style={{display: 'none'}} id={item.id} aria-hidden="true" onClick={()=>this.onAttachmentRemove(item.id)}></i>:""}
{item.delete===true?<i className="font-14 iconfont icon-guanbi " style={{display: 'none'}} id={item.id} aria-hidden="true" onClick={()=>this.props.onAttachmentRemove(item.id)}></i>:""}
</div>
)
})}

@ -73,7 +73,6 @@ class NewWorkForm extends Component{
setTimeout(() => {
this.contentMdRef.current.setValue(data.description || '')
this.answerMdRef.current.setValue(data.reference_answer || '')
}, 2000)
this.props.form.setFieldsValue({
@ -86,8 +85,13 @@ class NewWorkForm extends Component{
} else { // new
}
this._scrollToTop()
}
_scrollToTop = () => {
setTimeout(() => {
$("html").animate({ scrollTop: 0 })
}, 1500)
}
// 输入title
changeTitle=(e)=>{
@ -289,6 +293,7 @@ class NewWorkForm extends Component{
}
componentDidMount() {
window.$('.groupSetting .ant-form-item-label > label').addClass('ant-form-item-required')
this._scrollToTop()
}
render(){

@ -141,7 +141,7 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback, initV
$("#" + _id + " [type=\"inline\"]").bind("click", function () {
_editorName.cm.replaceSelection("`$$$$`");
var __Cursor = _editorName.cm.getDoc().getCursor();
_editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
_editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
_editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -78,7 +78,7 @@ class NewShixunModel extends Component{
{item.map((list,key)=>{
return(
<Menu.Item key={key} id={list.id}>
<a target="_blank" href={`/paths/${list.id}`} className={"newshixun500"} title={list.name}>{list.name}</a>
<a target="_blank" href={`/paths/${list.id}`} className={"newshixun500"}>{list.name}</a>
</Menu.Item>
)
})}
@ -340,26 +340,45 @@ class NewShixunModel extends Component{
`body{ overflow: hidden !important; }
.ant-drawer-content{ overflow:auto !important; background: #f5f5f5; }
.yslbottomsj{position: absolute;bottom: -8px;}
.ant-drawer-close{
font-size:24px !important;
}
.ant-drawer-body {
padding:15px 24px 24px 0px;
}
`
}
</style>
<Drawer
placement="bottom"
closable={false}
closable={true}
destroyOnClose={true}
onClose={()=>this.props.hideNewShixunModelType()}
visible={this.props.NewShixunModelType}
height={'100%'}
>
<Spin spinning={this.state.isspinning}>
<div className={"clearfix educontent pr"}>
<div className={"clearfix educontent pr mb60shixun"}>
<div className={"square-list clearfix"}>
<div className="newshixunheadersear">
<div style={{height:"53px"}}></div>
<style>
{
`
.ant-input, .ant-input .ant-input-suffix{
background-color: #fff !important;
}
.packinput .ant-input{
border: 1px solid rgba(217,217,217,1) !important;
}
`
}
</style>
<Search
style={{ width: "800px"}}
style={{ width: "780px"}}
className="packinput"
placeholder="实训信息 / 院校名称 / 创建者"
value={this.state.keyword}
@ -378,8 +397,8 @@ class NewShixunModel extends Component{
<span className="fl color-grey-9 pointer mr30">
<a className={" color-grey-6"} onClick={()=>this.updatedlist(order)}>学习人数</a>
<sapn className="relativef ml5 " >
<i className={order==="desc"?"iconfont icon-sanjiaoxing-up font-12 ntopsj color-grey-9 color-blue":"iconfont icon-sanjiaoxing-up font-12 ntopsj color-grey-9"}></i>
<i className={order==="asc"?"iconfont icon-sanjiaoxing-down font-12 nyslbottomsj color-grey-9 color-blue":"iconfont icon-sanjiaoxing-down font-12 nyslbottomsj color-grey-9"}></i>
<i className={order==="asc"?"iconfont icon-sanjiaoxing-up font-12 ntopsj color-grey-9 color-blue":"iconfont icon-sanjiaoxing-up font-12 ntopsj color-grey-9"}></i>
<i className={order==="desc"?"iconfont icon-sanjiaoxing-down font-12 nyslbottomsj color-grey-9 color-blue":"iconfont icon-sanjiaoxing-down font-12 nyslbottomsj color-grey-9"}></i>
</sapn>
</span>
@ -397,8 +416,8 @@ class NewShixunModel extends Component{
</div>
<div className="font-12 alltopiscright ml25 fr">
<span className={"fr pointer color-grey-3"} onClick={()=>this.props.hideNewShixunModelType()}>返回</span>
<span className={type==="mine"?"fr mr30 topcsactive pointer color-grey-3 color-blue":"fr mr30 pointer color-grey-3"} onClick={()=>this.belongto("mine")}>我的实训</span>
{/*<span className={"fr pointer color-grey-3"} onClick={()=>this.props.hideNewShixunModelType()}>返回</span>*/}
<span className={type==="mine"?"fr topcsactive pointer color-grey-3 color-blue":"fr pointer color-grey-3"} onClick={()=>this.belongto("mine")}>我的实训</span>
<span className={type==="all"?"fr mr30 topcsactive pointer color-grey-3 color-blue":"fr mr30 pointer color-grey-3"} onClick={()=>this.belongto("all")}>全部实训</span>
</div>
@ -409,7 +428,7 @@ class NewShixunModel extends Component{
{shixun_list===undefined?"":shixun_list.length===0?"":shixun_list.map((item,key)=>{
return(
<div className="mt20 edu-back-white pd20 relativef newshixunlist" key={key}>
<div className="mt10 edu-back-white pd20 relativef newshixunlist" key={key}>
<div className="clearfix">
<div className="item-body">
<div className="clearfix ds pr contentSection">
@ -419,7 +438,7 @@ class NewShixunModel extends Component{
className="fl task-hide edu-txt-left mt3"
name="shixun_homework[]"
></Checkbox>
<a target="_blank" href={`/shixuns/${item.identifier}/challenges`} title={item.title} className="ml15 fl font-16 color-dark maxwidth1100"
<a target="_blank" href={`/shixuns/${item.identifier}/challenges`} className="ml15 fl font-16 color-dark maxwidth1100"
dangerouslySetInnerHTML={{__html: item.title}}
>
</a>
@ -439,7 +458,7 @@ class NewShixunModel extends Component{
`
}
</style>
{JSON.stringify(item.description) == "{}"?"":<div className="newshixunmodelmidfont newradioStyles" title={item.description} dangerouslySetInnerHTML={{__html: item.description}}>
{JSON.stringify(item.description) == "{}"?"":<div className="newshixunmodelmidfont newradioStyles" dangerouslySetInnerHTML={{__html: item.description}}>
</div>}
{item.challenge_names.length===0?"":<div className="newshixunmodelbotfont">
@ -511,15 +530,21 @@ class NewShixunModel extends Component{
:shixun_list.length===0? <NoneData></NoneData>:""
}
{
shixun_list===undefined?"":shixun_list.length===0?"":<div className={" edu-txt-center padding20-30"}>
<Button className={"mr20 newshixunmode"} onClick={()=>this.props.hideNewShixunModelType()}>取消</Button>
<Button className={"newshixunmode"} type="primary" onClick={()=>this.savecouseShixunModal()} loading={this.state.hometypepvisible}>确定</Button>
</div>}
</div>
</div>
<div className="clearfix bor-bottom-greyE edu-back-white orderingbox newshixunbottombtn"
>
{
shixun_list===undefined?"":shixun_list.length===0?"":<div className={" edu-txt-center padding13-30"}>
<Button className={"mr20 newshixunmode"} onClick={()=>this.props.hideNewShixunModelType()}>取消</Button>
<Button className={"newshixunmode mr40"} type="primary" onClick={()=>this.savecouseShixunModal()} loading={this.state.hometypepvisible}>确定</Button>
</div>}
</div>
</Spin>
</Drawer>
</div>

@ -195,7 +195,7 @@
width: 100px;
height: 38px;
border-radius: 3px;
border: 1px solid rgba(191,191,191,1);
/*border: 1px solid rgba(191,191,191,1);*/
}
.ntopsj {
@ -248,3 +248,22 @@
color: #4CACFF;
}
.newshixunbottombtn{
position: fixed;
z-index: 1000;
bottom: 0px;
width: 100%;
height: 63px;
background: rgba(255,255,255,1);
box-shadow: 0px -4px 4px 0px rgba(0,0,0,0.05);
}
.mb60shixun{
margin-bottom: 60px !important;
}
.padding13-30 {
padding: 13px 30px;
box-sizing: border-box;
}

@ -22,7 +22,7 @@ import 'moment/locale/zh-cn';
import './yslexercisetable.css';
import {getImageUrl, toPath} from 'educoder';
import CheckBoxGroup from "../../page/component/CheckBoxGroup";
import NoneData from '../../../modules/courses/coursesPublic/NoneData'
const Search = Input.Search;
const RadioGroup = Radio.Group;
const CheckboxGroup = Checkbox.Group;
@ -1217,6 +1217,7 @@ class Studentshavecompletedthelist extends Component {
)
},
],
exercise_status:0,
}
// console.log("Studentshavecompletedthelist");
// console.log(props.current_status);
@ -1277,6 +1278,20 @@ class Studentshavecompletedthelist extends Component {
}catch (e) {
}
try {
if(this.props.Commonheadofthetestpaper.exercise_status !== undefined){
this.setState({
exercise_status:this.props.Commonheadofthetestpaper.exercise_status,
})
}else{
this.setState({
exercise_status:0,
})
}
}catch (e) {
}
}
componentWillReceiveProps = (nextProps) => {
@ -2065,11 +2080,11 @@ class Studentshavecompletedthelist extends Component {
this.setState({
loadingstate: false,
})
console.log(response);
console.log(1997);
// console.log(response);
// console.log(1997);
this.Generatenewdatasy(response.data.exercise_users, response);
}).catch((error) => {
console.log(error)
// console.log(error)
this.setState({
loadingstate: false,
})
@ -2472,7 +2487,7 @@ class Studentshavecompletedthelist extends Component {
render() {
const isAdmin = this.props.isAdmin();
let {data, datas, page, columns, course_groupyslsthree, columnstwo, styletable, course_groupyslstwodatas, limit, course_groupysls, course_groupyslstwodata, course_groupyslstwo, teacherlists, Teacherliststudentlist, order, columnss, course_groupsdatas, course_groups, Evaluationarray, unlimited, unlimiteds, unlimitedtwo, teacherlist, searchtext, loadingstate, review, nocomment, commented, unsubmitted, submitted, columnsys, exercise_users,mylistansum} = this.state;
let {data, datas, page, columns, course_groupyslsthree, columnstwo, styletable,exercise_status, course_groupyslstwodatas, limit, course_groupysls, course_groupyslstwodata, course_groupyslstwo, teacherlists, Teacherliststudentlist, order, columnss, course_groupsdatas, course_groups, Evaluationarray, unlimited, unlimiteds, unlimitedtwo, teacherlist, searchtext, loadingstate, review, nocomment, commented, unsubmitted, submitted, columnsys, exercise_users,mylistansum} = this.state;
// console.log("Studentshavecompletedthelist");
// console.log(this.props.current_status);
return (
@ -2483,202 +2498,209 @@ class Studentshavecompletedthelist extends Component {
" min-width": " 1200px",
}}>
{/*老师*/}
<div className="edu-back-white" >
<ul className="clearfix" style={{padding: '10px 30px 10px 30px'}}>
{
exercise_status===0 || exercise_status===1 ?
<NoneData></NoneData>
:
<div>
<div className="edu-back-white" >
<ul className="clearfix" style={{padding: '10px 30px 10px 30px'}}>
{/*你的评阅:*/}
{
Teacherliststudentlist === undefined || Teacherliststudentlist.exercise_types.subjective === 0 ?
<li className="clearfix mt10">
<span className="fl mr10 color-grey-8 ">作品状态</span>
<span className="fl "><a id="graduation_comment_no_limit"
className={unlimiteds === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.notlimiteds()}>不限</a></span>
<CheckboxGroup value={course_groupyslstwo}
onChange={(e) => this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}>
{
course_groupyslstwodata.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.id}
value={item.id}>{item.tu}<span>({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
<div className="fr mr5 search-new" style={{marginBottom: '1px'}}>
<Search
placeholder="请输入姓名或学号搜索"
id="subject_search_input"
autoComplete="off"
value={searchtext}
onKeyUp={(e) => this.onSearchKeywordKeyUp(e)}
onInput={this.inputSearchValues}
onSearch={this.searchValues}
></Search>
</div>
</li>
:
<div>
<li className="clearfix mt10">
<span className="fl mr10 color-grey-8 ">你的评阅</span>
<span className="fl "><a id="graduation_comment_no_limit"
className={unlimited === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.notlimited()}>不限</a></span>
<CheckboxGroup value={course_groupyslsthree}
onChange={(e) => this.checkeboxs(e, course_groupyslstwodata && course_groupyslstwodata)}>
{
course_groupyslstwodatas.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.id}
value={item.id}>{item.tu}<span>({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unreview_counts : Teacherliststudentlist.exercise_types.review_counts})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
<div className="fr mr5 search-new" style={{marginBottom: '1px'}}>
<Search
placeholder="请输入姓名或学号搜索"
id="subject_search_input"
autoComplete="off"
value={searchtext}
onKeyUp={(e) => this.onSearchKeywordKeyUp(e)}
onInput={this.inputSearchValues}
onSearch={this.searchValues}
></Search>
</div>
</li>
{/*作品状态*/}
<li className="clearfix mt10">
<span className="fl mr10 color-grey-8 ">作品状态</span>
<span className="fl "><a id="graduation_comment_no_limit"
className={unlimiteds === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.notlimiteds()}>不限</a></span>
<CheckboxGroup value={course_groupyslstwo}
onChange={(e) => this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}>
{
course_groupyslstwodata.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.id}
value={item.id}>{item.tu}<span>({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
</li>
</div>
{/*你的评阅:*/}
{
Teacherliststudentlist === undefined || Teacherliststudentlist.exercise_types.subjective === 0 ?
<li className="clearfix mt10">
<span className="fl mr10 color-grey-8 ">作品状态</span>
<span className="fl "><a id="graduation_comment_no_limit"
className={unlimiteds === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.notlimiteds()}>不限</a></span>
<CheckboxGroup value={course_groupyslstwo}
onChange={(e) => this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}>
{
course_groupyslstwodata.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.id}
value={item.id}>{item.tu}<span>({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
<div className="fr mr5 search-new" style={{marginBottom: '1px'}}>
<Search
placeholder="请输入姓名或学号搜索"
id="subject_search_input"
autoComplete="off"
value={searchtext}
onKeyUp={(e) => this.onSearchKeywordKeyUp(e)}
onInput={this.inputSearchValues}
onSearch={this.searchValues}
></Search>
</div>
</li>
:
<div>
<li className="clearfix mt10">
<span className="fl mr10 color-grey-8 ">你的评阅</span>
<span className="fl "><a id="graduation_comment_no_limit"
className={unlimited === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.notlimited()}>不限</a></span>
<CheckboxGroup value={course_groupyslsthree}
onChange={(e) => this.checkeboxs(e, course_groupyslstwodata && course_groupyslstwodata)}>
{
course_groupyslstwodatas.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.id}
value={item.id}>{item.tu}<span>({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unreview_counts : Teacherliststudentlist.exercise_types.review_counts})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
<div className="fr mr5 search-new" style={{marginBottom: '1px'}}>
<Search
placeholder="请输入姓名或学号搜索"
id="subject_search_input"
autoComplete="off"
value={searchtext}
onKeyUp={(e) => this.onSearchKeywordKeyUp(e)}
onInput={this.inputSearchValues}
onSearch={this.searchValues}
></Search>
</div>
</li>
{/*作品状态*/}
<li className="clearfix mt10">
<span className="fl mr10 color-grey-8 ">作品状态</span>
<span className="fl "><a id="graduation_comment_no_limit"
className={unlimiteds === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.notlimiteds()}>不限</a></span>
<CheckboxGroup value={course_groupyslstwo}
onChange={(e) => this.checkeboxstwo(e, course_groupyslstwodata && course_groupyslstwodata)}>
{
course_groupyslstwodata.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.id}
value={item.id}>{item.tu}<span>({Teacherliststudentlist === undefined ? "0" : key === 0 ? Teacherliststudentlist.exercise_types.unanswer_users : Teacherliststudentlist.exercise_types.answer_users})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
</li>
</div>
}
{/*分班情况*/}
{course_groups === undefined ? "" : course_groups === null ? "" : course_groups.length < 2 ? "" : JSON.stringify(course_groups) === "[]" ? "" :
<li className="clearfix mt10">
<tr>
<td className="w80" style={{"vertical-align": "top"}}><span
className=" mr10 color-grey-8 ">分班情况</span></td>
<td className="w70" style={{"vertical-align": "top"}}><span><a
id="graduation_comment_no_limit"
className={unlimitedtwo === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.funtaskstatustwos()}>不限</a></span>
</td>
<td>
<CheckboxGroup value={course_groupysls}
onChange={(e) => this.funtaskstatustwo(e, course_groups && course_groups)}
style={{paddingTop: '4px', display: "inline"}}>
{
course_groups.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.exercise_group_id}
value={item.exercise_group_id}>{item.exercise_group_name}<span>({item.exercise_group_students})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
}
{/*分班情况*/}
{course_groups === undefined ? "" : course_groups === null ? "" : course_groups.length < 2 ? "" : JSON.stringify(course_groups) === "[]" ? "" :
<li className="clearfix mt10">
<tr>
<td className="w80" style={{"vertical-align": "top"}}><span
className=" mr10 color-grey-8 ">分班情况</span></td>
<td className="w70" style={{"vertical-align": "top"}}><span><a
id="graduation_comment_no_limit"
className={unlimitedtwo === 0 ? "pl10 pr10 mr20 check_on" : "pl10 pr10 mr20 "}
onClick={() => this.funtaskstatustwos()}>不限</a></span>
</td>
<td>
<CheckboxGroup value={course_groupysls}
onChange={(e) => this.funtaskstatustwo(e, course_groups && course_groups)}
style={{paddingTop: '4px', display: "inline"}}>
{
course_groups.map((item, key) => {
return (
<span key={key}><Checkbox className="fl mt5"
key={item.exercise_group_id}
value={item.exercise_group_id}>{item.exercise_group_name}<span>({item.exercise_group_students})</span></Checkbox></span>
)
})
}
</CheckboxGroup>
</td>
</tr>
</td>
</tr>
</li>
}
</li>
}
</ul>
</ul>
<div id="graduation_work_list" style={{padding: '0px 30px 10px 30px'}}>
<div className="clearfix">
<div id="graduation_work_list" style={{padding: '0px 30px 10px 30px'}}>
<div className="clearfix">
<span
className="fl color-grey-6 font-12"><span
style={{color: '#FF6800'}}>{Teacherliststudentlist === undefined ? "0" : Teacherliststudentlist.exercise_types.total_users}</span><span
className="color-orange-tip"></span>{Teacherliststudentlist === undefined ? "0" : Teacherliststudentlist.exercise_types.exercise_all_users} </span>
<div className="fr color-grey-6 edu-menu-panel">
<ul>
<li className="edu-position edu-position-hidebox">
<a className="font-12">
{order === "end_at" ? "时间" : order === "score" ? "成绩" : order === "student_id" ? "学号" : ""}排序</a>
<i className="iconfont icon-xiajiantou ml5 font-12"></i>
<ul className="edu-position-hide undis mt10">
<li><a onClick={(e) => this.funordersy("end_at")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>提交时间</a></li>
<li><a onClick={(e) => this.funordersy("score")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>最终成绩</a></li>
<li><a onClick={(e) => this.funordersy("student_id")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>学生学号</a></li>
</ul>
</li>
</ul>
</div>
<div className="fr color-grey-6 edu-menu-panel">
<ul>
<li className="edu-position edu-position-hidebox">
<a className="font-12">
{order === "end_at" ? "时间" : order === "score" ? "成绩" : order === "student_id" ? "学号" : ""}排序</a>
<i className="iconfont icon-xiajiantou ml5 font-12"></i>
<ul className="edu-position-hide undis mt10">
<li><a onClick={(e) => this.funordersy("end_at")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>提交时间</a></li>
<li><a onClick={(e) => this.funordersy("score")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>最终成绩</a></li>
<li><a onClick={(e) => this.funordersy("student_id")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>学生学号</a></li>
</ul>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
{JSON.stringify(data) !== "[]" ?
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
{JSON.stringify(data) !== "[]" ?
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
`}</style>
<div className="edu-table edu-back-white">
{data === undefined ? "" : <Table
dataSource={data}
columns={columnsys}
className="mysjysltable1"
pagination={false}
loading={loadingstate}
// onChange={this.TablePaginationsy}
/>}
</div>
</div>
<div className="edu-table edu-back-white">
{data === undefined ? "" : <Table
dataSource={data}
columns={columnsys}
className="mysjysltable1"
pagination={false}
loading={loadingstate}
// onChange={this.TablePaginationsy}
/>}
</div>
</div>
:
<div id="forum_list" className="forum_table">
<div className="minH-560 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
:
<div id="forum_list" className="forum_table">
<div className="minH-560 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
</div>
}
</div>
}
</div>
{
Teacherliststudentlist && Teacherliststudentlist.exercise_types.total_users && Teacherliststudentlist.exercise_types.total_users > limit ?
<div className="edu-txt-center mt30 mb50">
<Pagination showQuickJumper current={page} onChange={this.paginationonChange}
pageSize={limit}
total={Teacherliststudentlist.exercise_types.total_users}></Pagination>
</div>
{
Teacherliststudentlist && Teacherliststudentlist.exercise_types.total_users && Teacherliststudentlist.exercise_types.total_users > limit ?
<div className="edu-txt-center mt30 mb50">
<Pagination showQuickJumper current={page} onChange={this.paginationonChange}
pageSize={limit}
total={Teacherliststudentlist.exercise_types.total_users}></Pagination>
</div>
: ""
}
</div>
: ""
}
</div>
@ -2691,16 +2713,20 @@ class Studentshavecompletedthelist extends Component {
<div>
<div className=" clearfix "
style={{"margin": "0 auto", "padding-bottom": "100px", " min-width": " 1200px"}}>
<div className={"educontent mb20"}>
{
exercise_status === 0 || exercise_status === 1 ?
<NoneData></NoneData>
:
<div className={"educontent mb20"}>
<div className="edu-back-white" id="graduation_work_list"
style={{
padding: '0px 30px 10px 30px',
"height": "50px",
"margin-bottom": "10px"
}}>
<div className="edu-back-white" id="graduation_work_list"
style={{
padding: '0px 30px 10px 30px',
"height": "50px",
"margin-bottom": "10px"
}}>
<div className="clearfix ">
<div className="clearfix ">
<span className="fl color-grey-6 font-12 mt10">
<span className="color-orange-tip"
style={{color: '#FF6800'}}>{Teacherliststudentlist === undefined ? "0" : Teacherliststudentlist.exercise_types.answer_users}</span><span
@ -2716,45 +2742,45 @@ class Studentshavecompletedthelist extends Component {
</span>}
</span>
</div>
</div>
</div>
</div>
{JSON.stringify(datas) === "[]" ?
<div id="forum_list" className="forum_table">
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
{JSON.stringify(datas) === "[]" ?
<div id="forum_list" className="forum_table">
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
</div>
:
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
</div>
:
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
`}</style>
<div className="edu-table edu-back-white minH-560">
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columnss}
className="mysjysltable2"
pagination={false}
loading={false}
/>}
</div>
</div>
}
<div className="edu-table edu-back-white minH-560">
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columnss}
className="mysjysltable2"
pagination={false}
loading={false}
/>}
</div>
</div>
}
</div>
</div>
}
</div>
</div>
@ -2766,10 +2792,15 @@ class Studentshavecompletedthelist extends Component {
"padding-bottom": "100px",
" min-width": " 1200px"
}}>
<div className={"educontent mb20 edu-back-white"}>
<style>
{
`
{
exercise_status === 0 || exercise_status === 1 ?
<NoneData></NoneData>
:
<div>
<div className={"educontent mb20 edu-back-white"}>
<style>
{
`
.edu-table .ant-table-tbody > tr > td {
height: 58px;
}
@ -2786,40 +2817,40 @@ class Studentshavecompletedthelist extends Component {
padding: 9px;
}
`
}
</style>
<div className={"justify break_full_word new_li edu-back-white ysltableows"}
>
{data === undefined ? "" : <Table
dataSource={data}
columns={columnstwo}
className="mysjysltable3"
pagination={false}
loading={false}
showHeader={false}
/>}
</div>
{JSON.stringify(datas) === "[]" ?
<div id="forum_list" className="forum_table ">
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
}
</style>
<div className={"justify break_full_word new_li edu-back-white ysltableows"}
>
{data === undefined ? "" : <Table
dataSource={data}
columns={columnstwo}
className="mysjysltable3"
pagination={false}
loading={false}
showHeader={false}
/>}
</div>
</div>
{JSON.stringify(datas) === "[]" ?
</div>
:
<div className="edu-back-white">
< div id="graduation_work_list" style={{
padding: '0px 30px 10px 30px',
"margin-top": "20px",
"margin-bottom": "10px"
}}>
<div className="clearfix">
<div id="forum_list" className="forum_table ">
<div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
</div>
:
<div className="edu-back-white">
< div id="graduation_work_list" style={{
padding: '0px 30px 10px 30px',
"margin-top": "20px",
"margin-bottom": "10px"
}}>
<div className="clearfix">
<span className="fl color-grey-6 font-12"><span
className="color-orange-tip"
style={{color: '#FF6800'}}>{Teacherliststudentlist === undefined ? "0" : Teacherliststudentlist.exercise_types.answer_users}</span><span
@ -2832,32 +2863,32 @@ class Studentshavecompletedthelist extends Component {
<span
style={{color: '#FF6800'}}> {Teacherliststudentlist === undefined ? "0" : Teacherliststudentlist.exercise_types.exercise_end_time}</span>}
</span>
<div className="fr color-grey-6 edu-menu-panel">
<ul>
<li className="edu-position edu-position-hidebox">
<a className="font-12 ">
{order === "end_at" ? "时间" : order === "score" ? "成绩" : order === "student_id" ? "学号" : ""}排序</a>
<i className="iconfont icon-xiajiantou ml5 font-12 color-grey-6"></i>
<ul className="edu-position-hide undis mt10">
<li><a onClick={(e) => this.funorder("end_at")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>提交时间</a>
</li>
<li><a onClick={(e) => this.funorder("score")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>最终成绩</a>
</li>
<li><a onClick={(e) => this.funorder("student_id")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>学生学号</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
<div className="fr color-grey-6 edu-menu-panel">
<ul>
<li className="edu-position edu-position-hidebox">
<a className="font-12 ">
{order === "end_at" ? "时间" : order === "score" ? "成绩" : order === "student_id" ? "学号" : ""}排序</a>
<i className="iconfont icon-xiajiantou ml5 font-12 color-grey-6"></i>
<ul className="edu-position-hide undis mt10">
<li><a onClick={(e) => this.funorder("end_at")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>提交时间</a>
</li>
<li><a onClick={(e) => this.funorder("score")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>最终成绩</a>
</li>
<li><a onClick={(e) => this.funorder("student_id")} data-remote="true"
className=" font-12" style={{textAlign: "center "}}>学生学号</a>
</li>
</ul>
</li>
</ul>
</div>
</div>
</div>
<div className={"justify break_full_word new_li edu-back-white"}
style={{minHeight: "480px"}}>
<style>{`
.ant-spin-nested-loading > div > .ant-spin .ant-spin-dot {
top: 72%;}
}
@ -2877,30 +2908,32 @@ class Studentshavecompletedthelist extends Component {
padding: 9px;
}
`}</style>
<div className="edu-table edu-back-white minH-560 ysltableowss">
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columns}
pagination={false}
className="mysjysltable4"
loading={loadingstate}
/>}</div>
</div>
<div className="edu-table edu-back-white minH-560 ysltableowss">
{datas === undefined ? "" : <Table
dataSource={datas}
columns={columns}
pagination={false}
className="mysjysltable4"
loading={loadingstate}
/>}</div>
</div>
</div>
</div>
}
</div>
}
</div>
{
mylistansum && mylistansum > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination showQuickJumper current={page}
onChange={this.paginationonChanges} pageSize={limit}
total={mylistansum}></Pagination>
{
mylistansum && mylistansum > limit ?
<div className="edu-txt-center mt30 mb20">
<Pagination showQuickJumper current={page}
onChange={this.paginationonChanges} pageSize={limit}
total={mylistansum}></Pagination>
</div>
: ""
}
</div>
: ""
}
</div>

@ -436,7 +436,7 @@ class Testpapersettinghomepage extends Component{
/>
{
// 教师列表
parseInt(tab[0])==0 && <Studentshavecompletedthelist {...this.props} {...this.state} triggerRef={this.bindRef} setcourse_groupysls={(value)=>this.setcourse_groupysls(value)} current_status = {this.state.current_status}></Studentshavecompletedthelist>
parseInt(tab[0])==0 && <Studentshavecompletedthelist {...this.props} {...this.state} triggerRef={this.bindRef} setcourse_groupysls={(value)=>this.setcourse_groupysls(value)} current_status = {this.state.current_status} Commonheadofthetestpaper={this.state.Commonheadofthetestpaper}></Studentshavecompletedthelist>
}
{/*统计结果*/}

@ -182,6 +182,10 @@ class SingleEditor extends Component{
this.setState({ standard_answers })
}
onOptionContentChange = (value, index) => {
if (index >= this.state.question_choices.length) {
// TODO 新建然后删除CD选项再输入题干会调用到这里且index是3
return;
}
let question_choices = this.state.question_choices.slice(0);
question_choices[index] = value;
this.setState({ question_choices })

@ -25,16 +25,61 @@ class Eduinforms extends Component{
eduintits:"",
informs:[],
yslbool:false,
dataquerys:{},
}
}
componentDidMount() {
console.log("Eduinformss");
console.log("获取到数据");
console.log(this.props);
this.getinputdata();
// console.log(this.props);
const query = this.props.location.search;
// const type = query.split('?chinaoocTimestamp=');
// console.log("Eduinforms12345");
// console.log(this.foo(query));
// console.log(JSON.stringify(this.foo(query)));
var dataqueryss={}
try {
var foqus=this.foo(query);
if(JSON.stringify(foqus) ==="{}"){
this.setState({
dataquerys:{},
});
}else {
this.setState({
dataquerys:foqus,
});
dataqueryss=foqus;
}
}catch (e) {
this.setState({
dataquerys:{},
})
}
this.getinputdatas(dataqueryss);
}
//截取数据
foo=(url)=> {
var json = {};
var regExp = /[\?\&](\w+)(=?)(\w*)/g;
var arr;
do {
arr = regExp.exec(url);
// console.log(arr); // arr = [完整的字符串, key, 等号或'', value或'']
if (arr) {
var key = arr[1];
var value = arr[3];
// arr[2] === ''时, value = undefined
if (!arr[2])
value = undefined;
json[key] = value;
}
} while (arr);
return json;
}
getyslbooltrue(){
console.log("调用了getyslbooltrue");
this.setState({
@ -54,7 +99,47 @@ class Eduinforms extends Component{
})
let url = `/courses/${this.props.match.params.coursesId}/informs.json`;
//
axios.get(url).then((response) => {
axios.get(url,
{params:this.state.dataquerys}
).then((response) => {
if(response){
if(response.data){
this.setState({
informs:response.data.informs,
isSpin:false,
})
}else {
this.setState({
informs:[],
isSpin:false,
})
}
}else {
this.setState({
informs:[],
isSpin:false,
})
}
}).catch((error) => {
console.log(error)
this.setState({
informs:[],
isSpin:false,
})
});
}
getinputdatas=(yslwebobject)=>{
this.setState({
isSpin:true,
})
let url = `/courses/${this.props.match.params.coursesId}/informs.json`;
//
axios.get(url,
{params:yslwebobject}
).then((response) => {
if(response){
if(response.data){
this.setState({

@ -389,7 +389,7 @@ class GraduationTasksSubmitedit extends Component{
let listid=[];
for(var list of fileList){
listid.push(list.response.id)
listid.push(list.response == undefined ? list.id : list.response.id)
}
this.props.form.validateFields((err, values) => {

@ -15,7 +15,7 @@ class CourseSupports extends Component {
this.state={
data:'',
ec_courses_list:[],
editcourse:[{"weigths": 0,
editcourse:[{"weights": 0,
"ec_course_name":'',
"top_relation": false,
"ec_course_id":''
@ -61,13 +61,15 @@ class CourseSupports extends Component {
this.setState({
data:response.data
})
}
if(response.data.graduation_subitems.length===0){
this.setState({
console.log(response.data.graduation_subitems.length)
if(response.data.graduation_subitems.length===0){
this.setState({
Supportstype:true,
Supportslist:'数据为空,请去毕业要求——>毕业要求指标点分解列表配置数据'
})
})
}
}
})
.catch(function (error) {
console.log(error);
@ -153,12 +155,14 @@ class CourseSupports extends Component {
if(item.course_supports.length>0){
this.setState({
editcourse:item.course_supports,
Editkey:key
Editkey:key,
index:subindex,
})
}else if(item.course_supports.length===0){
this.setState({
editcourse:[{weights: 0,top_relation: false,ec_course_name:'',ec_course_id:''}],
Editkey:key
Editkey:key,
index:subindex,
})
}
@ -173,7 +177,7 @@ class CourseSupports extends Component {
Addcourse=(e)=>{
let {editcourse} =this.state;
let neweditcourse=editcourse;
let newadd = {weigths: 0,top_relation: false,ec_course_name:'',ec_course_id:''};
let newadd = {weights: 0,top_relation: false,ec_course_name:'',ec_course_id:''};
neweditcourse.push(newadd);
this.setState({
editcourse:neweditcourse
@ -194,10 +198,10 @@ class CourseSupports extends Component {
neweditcourse.splice(e,1);
let newnum=0;
for(var j=0;j<neweditcourse.length;j++){
if(neweditcourse[j].weigths===undefined){
if(neweditcourse[j].weights===undefined){
newnum=0
}else{
newnum=newnum+neweditcourse[j].weigths;
newnum=newnum+neweditcourse[j].weights;
}
}
newnum= Math.round(newnum*100)/100;
@ -231,7 +235,7 @@ class CourseSupports extends Component {
const person = new Object ();
person.weigths=value;
person.weights=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;
@ -242,12 +246,12 @@ class CourseSupports extends Component {
let newnum=0;
for(var j=0;j<neweditcourse.length;j++){
if(neweditcourse[j].weigths===undefined){
if(neweditcourse[j].weights===undefined){
newnum=newnum+0;
}else if(neweditcourse[j].weigths===""){
}else if(neweditcourse[j].weights===""){
newnum=newnum+0;
}else{
newnum=newnum+neweditcourse[j].weigths;
newnum=newnum+neweditcourse[j].weights;
}
}
@ -362,8 +366,8 @@ class CourseSupports extends Component {
// }
editcourse.map((item,key)=>{
if(item.weigths===""){
item.weigths=0;
if(item.weights===""){
item.weights=0;
}
if(item.ec_course_id===""){
this.setState({
@ -426,7 +430,7 @@ class CourseSupports extends Component {
}
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;
let {data,ec_courses_list,editcourse,editnum,index,ec_year_id,Supportsclasskey,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++) {
@ -480,7 +484,7 @@ class CourseSupports extends Component {
</div>
<div className="padding20-30" id="training_objective_contents">
<span className="fl SystemParameters" >毕业要求指标点<a href={data.subitems_url}><span className="Systemnum">{data.subitems_count}</span></a></span>
<span className="fl SystemParameters" >毕业要求指标点<a href={data.subitems_url}><span className="Systemnum">{data.count}</span></a></span>
<span className="fl ml20 SystemParameters">课程体系<a href={data.course_url}><span className="Systemnum">{data.course_count}</span></a></span>
</div>
@ -504,24 +508,25 @@ class CourseSupports extends Component {
return (
<li className={data.graduation_subitems.length===key+1?"clearfix mb10":"clearfix"} key={key} style={{width: 120*data.max_support_count > 1134 ? 136*data.max_support_count : 1134+"px",margin: '0px 0px'}}>
<Tooltip placement="bottom" title={item.sequence_title}>
<span className="column-1 columnlocation" style={{display:Editkey!=key?"block":'none',width: '95px', paddingLeft: '23px'}}>{item.sequence_num}</span>
<span className="column-1 columnlocation" style={{display:Editkey!=key?"block":'none',width: '95px', paddingLeft: '23px'}}>{item.graduation_requirement_position+"-"+item.position}</span>
</Tooltip>
{
item.course_supports.map((t,kes)=>{
return(
<span key={kes} className="column-1"
style={{
display:Editkey!=key?"block":'none',
marginRight: '-1px'
}}>
<div data-tip-down={t.name} className={t.top_relation===true?"DDred columnbox":"columnbox"}
<div data-tip-down={t.ec_course_name} className={t.top_relation===true?"DDred columnbox":"columnbox"}
style={{textAlign: 'center'}}
>{t.name.length>12?t.name.substring(0, 10)+"...":t.name}</div>
>{t.ec_course_name.length>12?t.ec_course_name.substring(0, 10)+"...":t.ec_course_name}</div>
<div className={t.top_relation===true?"DDred":""}
style={{textAlign: 'center'}}
>{t.weigths}</div>
>{t.weights}</div>
</span>
)
@ -586,7 +591,7 @@ class CourseSupports extends Component {
size="large"
className={Supportssum===true?"inputWeight bor-red":"inputWeight"}
id={key}
value={it.weigths}
value={it.weights}
onInput={this.enterweight.bind(this)}
/>

@ -101,9 +101,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback){
});
$("#"+ id +" [type=\"inline\"]").bind("click", function(){
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch-2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch-3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -408,7 +408,7 @@ class ShixunsHome extends Component {
<img src={getImageUrl("images/educoder/huangguan-two.png")} className="huangguan" />
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url} />
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -422,7 +422,7 @@ class ShixunsHome extends Component {
<img src={getImageUrl("images/educoder/huangguan.png")} className="huangguan" />
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url} />
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -436,7 +436,7 @@ class ShixunsHome extends Component {
<img src={getImageUrl("images/educoder/huangguan-three.png")} className="huangguan" />
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url} />
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -452,7 +452,7 @@ class ShixunsHome extends Component {
<li key={key}>
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url}/>
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -484,7 +484,7 @@ class ShixunsHome extends Component {
<img src={getImageUrl("images/educoder/huangguan-two.png")} className="huangguan" />
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url} />
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -498,7 +498,7 @@ class ShixunsHome extends Component {
<img src={getImageUrl("images/educoder/huangguan.png")} className="huangguan" />
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url} />
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -512,7 +512,7 @@ class ShixunsHome extends Component {
<img src={getImageUrl("images/educoder/huangguan-three.png")} className="huangguan" />
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url} />
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)
@ -528,7 +528,7 @@ class ShixunsHome extends Component {
<li key={key}>
<a href={"/users/"+item.login} className="color-dark">
<img src={'/images/'+item.image_url}/>
<span className="task-hide rankName">{item.username}</span>
<p className="task-hide rankName mt5">{item.username}</p>
</a>
</li>
)

@ -5,7 +5,7 @@ import {
} from "antd";
import axios from 'axios';
import moment from 'moment';
import {getImageUrl,markdownToHTML,ImageLayerHook} from 'educoder';
import {getImageUrl,markdownToHTML,ImageLayer2} from 'educoder';
import "../css/messagemy.css"
import WriteaprivateletterModal from '../messagemodal/WriteaprivateletterModal';
//私信页面
@ -51,8 +51,8 @@ class Leftdialogue extends Component{
</a>
<div className="fl pr OtherSide-info">
<span className="trangle"></span>
<ImageLayerHook parentSel={`#Leftdialogue${this.props.keys}`} parentSel={`#Leftdialogue${this.props.keys}`}>
</ImageLayerHook>
<ImageLayer2 parentSel={`#Leftdialogue${this.props.keys}`} parentSel={`#Leftdialogue${this.props.keys}`}>
</ImageLayer2>
<div className="sms break_word markdown-body" id={`Leftdialogue${this.props.keys}`} dangerouslySetInnerHTML={{__html: markdownToHTML(this.props.objeysl.content).replace(/▁/g, "▁▁▁")}}></div>
<div className="edu-txt-right mt5">
<a className="color-grey-c" onClick={()=>this.mydelete(this.props.objeysl.sender.id,this.props.objeysl.id)} >删除</a>

@ -5,7 +5,7 @@ import {
} from "antd";
import axios from 'axios';
import moment from 'moment';
import {getImageUrl,markdownToHTML,ImageLayerHook} from 'educoder';
import {getImageUrl,markdownToHTML,ImageLayer2} from 'educoder';
import "../css/messagemy.css"
import WriteaprivateletterModal from '../messagemodal/WriteaprivateletterModal';
//私信页面
@ -51,8 +51,8 @@ class Rightdialogue extends Component{
</a>
<div className="fr pr ThisSide-info">
<span className="trangle"></span>
<ImageLayerHook parentSel={`#Rightdialogue${this.props.keys}`} parentSel={`#Rightdialogue${this.props.keys}`}>
</ImageLayerHook>
<ImageLayer2 parentSel={`#Rightdialogue${this.props.keys}`} parentSel={`#Rightdialogue${this.props.keys}`}>
</ImageLayer2>
<div className="sms break_word markdown-body" id={`Rightdialogue${this.props.keys}`} dangerouslySetInnerHTML={{__html: markdownToHTML(this.props.objeysl.content).replace(/▁/g, "▁▁▁")}}></div>
<div className="edu-txt-left mt5">
<a className="color-grey-c" onClick={()=>this.mydelete(this.props.objeysl.sender.id,this.props.objeysl.id)}

@ -308,11 +308,12 @@ class MainContentContainer extends Component {
// })
}).then((fetchRepositoryCodeResponse) => {
// monaca 需要刷新,不然无法编辑
if (this.retryAndRefresh && fetchRepositoryCodeResponse.data.content) {
this.retryAndRefresh = false;
window.location.reload()
return;
}
// 加了dispose应该不会重现了暂时注释掉reload
// if (this.retryAndRefresh && fetchRepositoryCodeResponse.data.content) {
// this.retryAndRefresh = false;
// window.location.reload()
// return;
// }
// 空字符串还是正常切换
if (fetchRepositoryCodeResponse.data.status == 0) {
readingRepoTimes = readingRepoTimes + 1;
@ -530,7 +531,7 @@ class MainContentContainer extends Component {
let codeContent = this.state.repositoryCode;
if (window['editor_CodeMirror']) {
codeContent = window.editor_CodeMirror.getValue();
} else if (window.editor_monaco) {
} else if (window.editor_monaco && window.editor_monaco.getModel()) { // (编程切选择题) 如果dispose了model为空
codeContent = window.editor_monaco.getValue()
}
if (checkIfCodeChanged === true && this.oldRepositoryCode == codeContent) {

@ -17,6 +17,8 @@ import * as monaco from 'monaco-editor'
import { fromStore, toStore } from 'educoder'
import './TPIMonacoConfig'
// https://microsoft.github.io/monaco-editor/playground.html#customizing-the-appearence-exposed-colors
monaco.editor.defineTheme('myCoolTheme', {
base: 'vs-dark',
inherit: true,
@ -35,6 +37,8 @@ monaco.editor.defineTheme('myCoolTheme', {
// 'input.border': '#ffffff',
'editor.lineHighlightBorder': '#222c34', // .current-line
// 'editor.selectionBackground': '#FFFF0030',
// 'editor.selectionHighlightBackground' :'#0000FFFF',
}
});
@ -245,6 +249,10 @@ class TPIMonaco extends Component {
// extend_editor.clearHistory()
}
}
componentWillUnmount() {
this.editor_monaco && this.editor_monaco.dispose()
}
componentDidMount() {
checkIfLoaded(() => {
let value = [
@ -282,6 +290,7 @@ class TPIMonaco extends Component {
// theme: "vs-dark",
theme: "myCoolTheme",
insertSpaces: false,
fontSize: this.state.cmFontSize
});

@ -43,7 +43,7 @@ class Index extends Component{
<Route path="/paths/:pathId/edit" exact
render={(props)=>(<PathsNew {...this.props} {...this.state} {...props}/>)}
></Route>
{/*编辑页面*/}
<Route path="/paths/:pathId" exact
render={(props)=>(<PathsDetail {...this.props} {...this.state} {...props}/>)}
></Route>

@ -1,5 +1,5 @@
import React, { Component } from 'react';
import {getImageUrl,markdownToHTML} from 'educoder';
import {getImageUrl,markdownToHTML, configShareForCustom} from 'educoder';
import DetailTop from './DetailTop.js';
import DetailCards from './DetailCards.js'
import AddCollaborators from "./addCollaborators.js";
@ -83,7 +83,8 @@ class PathDetailIndex extends Component{
loadtype:false,
courses:undefined,
items: getItems(10),
pathtopskey:1
pathtopskey:1,
dataquerys:{},
}
this.onDragEnd = this.onDragEnd.bind(this);
@ -146,14 +147,62 @@ class PathDetailIndex extends Component{
}
componentDidMount(){
this.getdatasindex()
}
getdatasindex=(key)=>{
const query = this.props.location.search;
// const type = query.split('?chinaoocTimestamp=');
// console.log("Eduinforms12345");
// console.log(this.foo(query));
// console.log(JSON.stringify(this.foo(query)));
var dataqueryss={}
try {
var foqus=this.foo(query);
if(JSON.stringify(foqus) ==="{}"){
this.setState({
dataquerys:{},
});
}else{
this.setState({
dataquerys:foqus,
});
dataqueryss=foqus;
}
}catch (e) {
this.setState({
dataquerys:{},
})
}
this.getdatasindexs(undefined,dataqueryss);
}
//截取url 数据的
foo=(url)=> {
var json = {};
var regExp = /[\?\&](\w+)(=?)(\w*)/g;
var arr;
do {
arr = regExp.exec(url);
// console.log(arr); // arr = [完整的字符串, key, 等号或'', value或'']
if (arr) {
var key = arr[1];
var value = arr[3];
// arr[2] === ''时, value = undefined
if (!arr[2])
value = undefined;
json[key] = value;
}
} while (arr);
return json;
}
getdatasindexs=(key,yslwebobject)=>{
// yslwebobject 后端需要的接口
let pathid=this.props.match.params.pathId;
let url="/paths/"+pathid+".json";
axios.get(url).then((result)=>{
axios.get(url,
{params:yslwebobject}
).then((result)=>{
if (result.data.status === 407 || result.data.status === 401) {
debugger
return;
@ -164,6 +213,7 @@ class PathDetailIndex extends Component{
// window.location.href = "/403";
return;
}
configShareForCustom(result.data.name, result.data.description)
if(result.data.allow_visit===true){
this.setState({
@ -179,6 +229,65 @@ class PathDetailIndex extends Component{
})
let righturl="/paths/"+pathid+"/right_banner.json";
axios.get(righturl).then((result)=>{
if (result.data.status === 407 || result.data.status === 401) {
debugger
return;
}
if (result.data.status === 403) {
debugger
// window.location.href = "/403";
return;
}
this.setState({
// detailInfoList:result.data,
tags:result.data.tags,
progress:result.data.progress,
members:result.data.members,
items: getItems(result.data.members.length),
})
}).catch((error)=>{
console.log(error);
})
};
getdatasindex=(key)=>{
// yslwebobject 后端需要的接口
let pathid=this.props.match.params.pathId;
let url="/paths/"+pathid+".json";
axios.get(url,
{params:this.state.dataquerys}
).then((result)=>{
if (result.data.status === 407 || result.data.status === 401) {
debugger
return;
}
if (result.data.status === 403) {
debugger
// window.location.href = "/403";
return;
}
configShareForCustom(result.data.name, result.data.description)
if(result.data.allow_visit===true){
this.setState({
detailInfoList:result.data,
courses:result.data.courses,
pathtopskey:key===undefined?1:key,
// items: getItems(result.data.members.length),
})
}
}).catch((error)=>{
console.log(error);
});
let righturl="/paths/"+pathid+"/right_banner.json";
axios.get(righturl).then((result)=>{
if (result.data.status === 407 || result.data.status === 401) {

@ -48,6 +48,8 @@ function create_editorMD(id, width, high, placeholder, imageUrl,initValue, callb
imageUploadURL: imageUrl,//url
onload: function () {
// this.previewing();
var id = this.id;
var editorName = this;
$("#" + id + " [type=\"latex\"]").bind("click", function () {
editorName.cm.replaceSelection("```latex");
editorName.cm.replaceSelection("\n");
@ -58,9 +60,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl,initValue, callb
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -1,203 +1,212 @@
import React,{ Component } from "react";
import {Pagination} from 'antd';
import axios from 'axios';
const $ = window.$;
const echarts = require('echarts');
function InitChapterUsageSituation(_data){
var Color = ['#49A9EE', '#FFD86E', '#98D87D', '#8996E6','#F3857B', '#B97BF3','#4DE8B4','#f76d0c','#510cf7','#def70c','#3bf70c','#0cf7e1'];
var option = {
title: {
show:false
},
tooltip : {
trigger: 'item',
formatter: "{d}%"
},
legend: {
//orient: 'vertical',
// top: 'middle',
bottom: 30,
//left: 20,
data:["第1章", "第2章", "第3章", "第4章", "第5章"],
selectedMode:false
},
series : [{
name: '使用情况',
type: 'pie',
radius : '50%',
center: ['50%', '40%'],
selectedMode: 'single',
label: {
normal: {
// {abg|}
// {a|{a}}\n
formatter: ' {b|{b}} ',
backgroundColor: '#eee',
borderColor: '#aaa',
borderWidth: 1,
borderRadius: 4,
rich: {
a: {
color: '#999',
lineHeight: 22,
align: 'center'
},
hr: {
borderColor: '#aaa',
width: '100%',
borderWidth: 0.5,
height: 0
},
b: {
fontSize: 16,
lineHeight: 33
},
per: {
color: '#eee',
backgroundColor: '#334455',
padding: [2, 4],
borderRadius: 2
}
}
},
},
data: _data,
// [{"value":19,"name":"\u7b2c1\u7ae0"},{"value":45,"name":"\u7b2c2\u7ae0"},{"value":16,"name":"\u7b2c3\u7ae0"},{"value":10,"name":"\u7b2c4\u7ae0"},{"value":10,"name":"\u7b2c5\u7ae0"}],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
normal:{
show: true,
color: function(params) {
return Color[params.dataIndex]
}
}
}
}]
};
var myChart = echarts.init(document.getElementById('chapterUsageSituation'));
myChart.setOption(option);
}
class FirstTab extends Component{
constructor(props){
super(props);
this.state = {
page:1,
total:undefined
}
}
onChange=(pageNumber)=>{
this.setState({
page:pageNumber
})
this.getData(pageNumber);
}
getData=(page)=>{
var pathId = this.props.match.params.pathId;
const url = `/paths/${pathId}/statistics.json?page=`+page;
axios.get(url, {
})
.then((response) => {
// TODO 没用404返回的error
if (response.data.status == 404) {
this.props.showSnackbar('未找到对应数据,请查看地址是否正确。')
return
}
this.setState({ ...response.data })
const _data = response.data.stage_info.map( (item, index) => {
return {
value: item.value,
name: item.stage_no
}
})
InitChapterUsageSituation(_data);
const { course_count, learn_count, school_total_count, subject_name, subject_id } = response.data
this.props.initBannerData({
course_count,
learn_count,
school_total_count,
subject_name,
subject_id
})
this.setState({
total:response.data.school_total_count
})
})
.catch(function (error) {
console.log(error);
});
}
componentDidMount(){
let {page}=this.state;
this.getData(page);
}
render(){
const { schools, stage_info,page,total } = this.state;
return(
<div className="clearfix panelForm-1">
<div className="with60 pr40 fl">
<div className="static_shadow edu-back-white">
<p className="padding30-20 clearfix"><span className="font-24 fl">课堂使用概况</span><span className="fr color-grey-9">{total}</span></p>
<div className="minH-440">
<table className="edu-pop-table head-color edu-txt-center bor-top-greyE" cellSpacing="0" cellPadding="0">
<thead>
<tr><th>序号</th>
<th className="edu-txt-left" width="35%">所属院校</th>
<th>课堂</th>
<th>学生</th>
<th>选用实训</th>
</tr></thead>
{/*
course_count: 30
homework_count: 117
name: "国防科技大学"
student_count: 2700
*/}
<tbody>
{
schools && schools.map( (school, index) => {
return (
<tr>
<td>{ index + 1 }</td>
<td className="edu-txt-left task-hide" style={{"maxWidth":"238px"}}>{school.name}</td>
<td>{school.course_count}</td>
<td>{school.student_count}</td>
<td><span className="color-blue mr3">{school.homework_count}</span></td>
</tr>)
})
}
</tbody>
</table>
</div>
<div className="pt35 edu-txt-center" style={{"height":"102px"}}>
{
total > 10 &&
<Pagination showQuickJumper defaultCurrent={page} pageSize={10} total={total} onChange={this.onChange} />
}
</div>
</div>
</div>
<div className="with40 fl static_shadow edu-back-white">
<p className="font-24 padding30-20">章节使用情况</p>
<div id="chapterUsageSituation" style={{"width":"480px","height":"542px"}}></div>
</div>
</div>
)
}
}
import React,{ Component } from "react";
import {Pagination} from 'antd';
import axios from 'axios';
const $ = window.$;
const echarts = require('echarts');
function InitChapterUsageSituation(_data){
var myChart = echarts.init(document.getElementById('chapterUsageSituation'));
myChart.showLoading({
text: "数据获取中",
effect: 'whirling'
})
var Color = ['#49A9EE', '#FFD86E', '#98D87D', '#8996E6','#F3857B', '#B97BF3','#4DE8B4','#f76d0c','#510cf7','#def70c','#3bf70c','#0cf7e1'];
var option = {
title: {
show:false
},
tooltip : {
trigger: 'item',
formatter: "{d}%"
},
legend: {
//orient: 'vertical',
// top: 'middle',
bottom: 30,
//left: 20,
data:["第1章", "第2章", "第3章", "第4章", "第5章"],
selectedMode:false
},
series : [{
name: '使用情况',
type: 'pie',
radius : '50%',
center: ['50%', '40%'],
selectedMode: 'single',
label: {
normal: {
// {abg|}
// {a|{a}}\n
formatter: ' {b|{b}} ',
backgroundColor: '#eee',
borderColor: '#aaa',
borderWidth: 1,
borderRadius: 4,
rich: {
a: {
color: '#999',
lineHeight: 22,
align: 'center'
},
hr: {
borderColor: '#aaa',
width: '100%',
borderWidth: 0.5,
height: 0
},
b: {
fontSize: 16,
lineHeight: 33
},
per: {
color: '#eee',
backgroundColor: '#334455',
padding: [2, 4],
borderRadius: 2
}
}
},
},
data: _data,
// [{"value":19,"name":"\u7b2c1\u7ae0"},{"value":45,"name":"\u7b2c2\u7ae0"},{"value":16,"name":"\u7b2c3\u7ae0"},{"value":10,"name":"\u7b2c4\u7ae0"},{"value":10,"name":"\u7b2c5\u7ae0"}],
itemStyle: {
emphasis: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
normal:{
show: true,
color: function(params) {
return Color[params.dataIndex]
}
}
}
}]
};
setTimeout(() => {
myChart.setOption(option);
myChart.hideLoading();
}, 1000)
}
class FirstTab extends Component{
constructor(props){
super(props);
this.state = {
page:1,
total:undefined
}
}
onChange=(pageNumber)=>{
this.setState({
page:pageNumber
})
this.getData(pageNumber);
}
getData=(page)=>{
var pathId = this.props.match.params.pathId;
const url = `/paths/${pathId}/statistics.json?page=`+page;
axios.get(url, {
})
.then((response) => {
// TODO 没用404返回的error
if (response.data.status == 404) {
this.props.showSnackbar('未找到对应数据,请查看地址是否正确。')
return
}
this.setState({ ...response.data })
const _data = response.data.stage_info.map( (item, index) => {
return {
value: item.value,
name: item.stage_no
}
})
InitChapterUsageSituation(_data);
const { course_count, learn_count, school_total_count, subject_name, subject_id } = response.data
this.props.initBannerData({
course_count,
learn_count,
school_total_count,
subject_name,
subject_id
})
this.setState({
total:response.data.school_total_count
})
})
.catch(function (error) {
console.log(error);
});
}
componentDidMount(){
let {page}=this.state;
this.getData(page);
}
render(){
const { schools, stage_info,page,total } = this.state;
return(
<div className="clearfix panelForm-1">
<div className="with60 pr40 fl">
<div className="static_shadow edu-back-white">
<p className="padding30-20 clearfix"><span className="font-24 fl">课堂使用概况</span><span className="fr color-grey-9">{total}</span></p>
<div className="minH-440">
<table className="edu-pop-table head-color edu-txt-center bor-top-greyE" cellSpacing="0" cellPadding="0">
<thead>
<tr><th>序号</th>
<th className="edu-txt-left" width="35%">所属院校</th>
<th>课堂</th>
<th>学生</th>
<th>选用实训</th>
</tr></thead>
{/*
course_count: 30
homework_count: 117
name: "国防科技大学"
student_count: 2700
*/}
<tbody>
{
schools && schools.map( (school, index) => {
return (
<tr>
<td>{ index + 1 }</td>
<td className="edu-txt-left task-hide" style={{"maxWidth":"238px"}}>{school.name}</td>
<td>{school.course_count}</td>
<td>{school.student_count}</td>
<td><span className="color-blue mr3">{school.homework_count}</span></td>
</tr>)
})
}
</tbody>
</table>
</div>
<div className="pt35 edu-txt-center" style={{"height":"102px"}}>
{
total > 10 &&
<Pagination showQuickJumper defaultCurrent={page} pageSize={10} total={total} onChange={this.onChange} />
}
</div>
</div>
</div>
<div className="with40 fl static_shadow edu-back-white">
<p className="font-24 padding30-20">章节使用情况</p>
<div id="chapterUsageSituation" style={{"width":"480px","height":"542px"}}></div>
</div>
</div>
)
}
}
export default FirstTab;

@ -1,271 +1,291 @@
import React,{ Component } from "react";
import axios from 'axios';
const $ = window.$;
const echarts = require('echarts');
function InitShixunStudyStatistics(yAxisMonth_a, barData_a, mapByNumber, myChart){
let yAxisMonth = yAxisMonth_a
// [
// "1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1",
// "1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1",
// "1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1", "3-2"];
let barData = barData_a
// [
// 1164, 739, 784, 720, 726, 556, 381, 432,
// 1164, 739, 784, 720, 726, 556, 381, 432,
// 1164, 739, 784, 720, 726, 556, 381, 432, 239];
// let yAxisMonth = yAxisMonth_a;
// let barData = barData_a;
let barDataTwo = [];
let coordData2 = [];
let coordData = [];
for (let i = 0; i < barData.length; i++) {
barDataTwo.push(Math.max.apply(Math, barData) + 5000);
coordData.push({
"coord": [Number(barData[i]) - 1, i]
});
coordData2.push({
"coord": [Math.max.apply(Math, barData) + 5000, i]
})
}
var option = {
backgroundColor: "#fff",
title: {
text: ''
},
legend: null,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'none'
},
formatter: function(params) {
return params[0].name + ":" + (mapByNumber[params[0].name] && mapByNumber[params[0].name].shixun_name) + "<br/>" + '学习人数: ' + params[0].value;
}
},
grid: {
containLabel: true,
left: "30px",
top: "0",
bottom:"10px"
},
yAxis: [{
data: yAxisMonth,
inverse: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
margin: 10,
textStyle: {
fontSize: 12,
color: '#747A7F'
},
formatter: function(value) {
return '{Sunny|' + value + '}';
},
rich: {
value: {
lineHeight: 20
},
Sunny: {
height: 25,
padding: [0, 8, 0, 8],
align: 'center',
backgroundColor: '#fff'
}
}
}
},{
data: yAxisMonth,
inverse: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
}
}
],
xAxis: [{
type: "value",
splitLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
}
}, {
type: "value",
splitLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
}
}],
series: [{
z: 10,
xAxisIndex: 0,
yAxisIndex: 0,
name: '',
type: 'pictorialBar',
data: barData,
barCategoryGap: '90%',
label: {
normal: {
show: true,
position: 'inside',
textStyle: {
fontSize: 12,
color: '#666'
}
}
},
symbolRepeat: false,
symbolSize: ['100%', 25],
symbolOffset: [-16.5, 0],
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#FFD86E'
}], false),
borderRadius:'10'
}
},
symbolClip: true,
symbolPosition: 'end',
symbol: 'rect'
}]
};
myChart.setOption(option);
}
class SecondTab extends Component{
constructor(props){
super(props);
this.state = {
}
}
componentDidMount(){
var pathId = this.props.match.params.pathId;
var myChart = echarts.init(document.getElementById('shixunStudyStatistics'));
myChart.showLoading({
text: "数据获取中",
effect: 'whirling'
})
const url = `/paths/${pathId}/shixun_report.json`
axios.get(url, {
})
.then((response) => {
// TODO 没用404返回的error
if (response.data.status == 404) {
this.props.showSnackbar('未找到对应数据,请查看地址是否正确。')
return
}
/**
let yAxisMonth = ["1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1", "3-2"];
let barData = [1164, 739, 784, 720, 726, 556, 381, 432, 239];
{
"number": "6-1",
"shixun_name": "网页抓取及信息提取",
"member_count": 0,
"school_count": 0
}
*/
let yAxisMonth = []
let barData = []
let shixunList = []
let mapByNumber = {}
const _data = response.data.shixun_lists.forEach( (ar, index) => {
ar.forEach( (item, itemIndex) => {
shixunList.push(item)
yAxisMonth.push(item.number)
barData.push(item.member_count)
mapByNumber[item.number] = item
})
})
this.setState({ shixunList }, () => {
InitShixunStudyStatistics(yAxisMonth, barData, mapByNumber, myChart);
myChart.hideLoading()
})
})
.catch(function (error) {
console.log(error);
});
}
render(){
const { shixunList } = this.state;
return(
<div className="clearfix panelForm-2">
<div className="with60 pr40 fl">
<div className="static_shadow edu-back-white">
<p className="font-24 padding30-20">实训使用详情</p>
<div className="minH-440" id="tableHeight">
<table className="edu-pop-table head-color edu-txt-center bor-top-greyE" cellSpacing="0" cellPadding="0">
<thead>
<tr>
<th>章节</th>
<th className="edu-txt-left" width="40%">实训名称</th>
<th>学习人数</th>
<th>受用院校</th>
</tr>
</thead>
<tbody>
{
shixunList && shixunList.map( (shixun, index) => {
return (
<tr>
<td>{shixun.number}</td>
<td className="edu-txt-left task-hide" style={{"maxWidth":"272px"}}>{shixun.shixun_name}</td>
<td>{shixun.member_count}</td>
<td className="color-blue">{shixun.school_count}</td>
</tr>)
})
}
</tbody>
</table>
</div>
</div>
</div>
<div className="with40 fl static_shadow edu-back-white">
<p className="font-24 padding30-20">实训学习统计</p>
<div id="shixunStudyStatistics"
style={{"width":"480px","height": shixunList ? `${shixunList.length * 35 + 100}px` : "440px"}}></div>
</div>
</div>
)
}
}
import React,{ Component } from "react";
import axios from 'axios';
const $ = window.$;
const echarts = require('echarts');
function InitShixunStudyStatistics(yAxisMonth_a, barData_a, mapByNumber, myChart){
let yAxisMonth = yAxisMonth_a
// [
// "1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1",
// "1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1",
// "1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1", "3-2"];
let barData = barData_a
// [
// 1164, 739, 784, 720, 726, 556, 381, 432,
// 1164, 739, 784, 720, 726, 556, 381, 432,
// 1164, 739, 784, 720, 726, 556, 381, 432, 239];
// let yAxisMonth = yAxisMonth_a;
// let barData = barData_a;
let barDataTwo = [];
let coordData2 = [];
let coordData = [];
for (let i = 0; i < barData.length; i++) {
barDataTwo.push(Math.max.apply(Math, barData) + 5000);
coordData.push({
"coord": [Number(barData[i]) - 1, i]
});
coordData2.push({
"coord": [Math.max.apply(Math, barData) + 5000, i]
})
}
var option = {
backgroundColor: "#fff",
title: {
text: ''
},
legend: null,
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'none'
},
formatter: function(params) {
return params[0].name + ":" + (mapByNumber[params[0].name] && mapByNumber[params[0].name].shixun_name) + "<br/>" + '学习人数: ' + params[0].value;
}
},
grid: {
containLabel: true,
left: "30px",
top: "0",
bottom:"10px"
},
yAxis: [{
data: yAxisMonth,
inverse: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
margin: 10,
textStyle: {
fontSize: 12,
color: '#747A7F'
},
formatter: function(value) {
return '{Sunny|' + value + '}';
},
rich: {
value: {
lineHeight: 20
},
Sunny: {
height: 25,
padding: [0, 8, 0, 8],
align: 'center',
backgroundColor: '#fff'
}
}
}
},{
data: yAxisMonth,
inverse: true,
axisLine: {
show: false
},
axisTick: {
show: false
},
axisLabel: {
show: false
}
}
],
xAxis: [{
type: "value",
splitLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
}
}, {
type: "value",
splitLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
},
axisLine: {
show: false
}
}],
series: [{
z: 10,
xAxisIndex: 0,
yAxisIndex: 0,
name: '',
type: 'pictorialBar',
data: barData,
barCategoryGap: '90%',
label: {
normal: {
show: true,
position: 'inside',
textStyle: {
fontSize: 12,
color: '#666'
}
}
},
symbolRepeat: false,
symbolSize: ['100%', 25],
symbolOffset: [-16.5, 0],
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
offset: 0,
color: '#FFD86E'
}], false),
borderRadius:'10'
}
},
symbolClip: true,
symbolPosition: 'end',
symbol: 'rect'
}]
};
myChart.setOption(option);
}
class SecondTab extends Component{
constructor(props){
super(props);
this.state = {
}
}
componentDidMount(){
var pathId = this.props.match.params.pathId;
var myCharts = echarts.init(document.getElementById('showloding'));
myCharts.showLoading({
text: "数据获取中",
effect: 'whirling'
})
const url = `/paths/${pathId}/shixun_report.json`
axios.get(url, {
})
.then((response) => {
// TODO 没用404返回的error
if (response.data.status == 404) {
this.props.showSnackbar('未找到对应数据,请查看地址是否正确。')
return
}
/**
let yAxisMonth = ["1-1", "1-2", "1-3", "1-4", "2-1", "2-2", "2-3", "3-1", "3-2"];
let barData = [1164, 739, 784, 720, 726, 556, 381, 432, 239];
{
"number": "6-1",
"shixun_name": "网页抓取及信息提取",
"member_count": 0,
"school_count": 0
}
*/
let yAxisMonth = []
let barData = []
let shixunList = []
let mapByNumber = {}
const _data = response.data.shixun_lists.forEach( (ar, index) => {
ar.forEach( (item, itemIndex) => {
shixunList.push(item)
yAxisMonth.push(item.number)
barData.push(item.member_count)
mapByNumber[item.number] = item
})
})
this.setState({
shixunList
})
var myChart = echarts.init(document.getElementById('shixunStudyStatistics'));
myChart.showLoading({
text: "数据获取中",
effect: 'whirling'
})
setTimeout(() => {
InitShixunStudyStatistics(yAxisMonth, barData, mapByNumber, myChart);
myCharts.hideLoading();
myChart.hideLoading();
}, 1000)
})
.catch(function (error) {
console.log(error);
});
}
render(){
const { shixunList } = this.state;
return(
<div className="clearfix panelForm-2">
<div className="with60 pr40 fl">
<div className="static_shadow edu-back-white">
<div className="font-24 padding30-20">实训使用详情</div>
<div className="minH-440" id="tableHeight">
<table className="edu-pop-table head-color edu-txt-center bor-top-greyE" cellSpacing="0" cellPadding="0">
<thead>
<tr>
<th>章节</th>
<th className="edu-txt-left" width="40%">实训名称</th>
<th>学习人数</th>
<th>受用院校</th>
</tr>
</thead>
<tbody>
{
shixunList && shixunList.map( (shixun, index) => {
return (
<tr>
<td>{shixun.number}</td>
<td className="edu-txt-left task-hide" style={{"maxWidth":"272px"}}>{shixun.shixun_name}</td>
<td>{shixun.member_count}</td>
<td className="color-blue">{shixun.school_count}</td>
</tr>)
})
}
</tbody>
</table>
</div>
</div>
</div>
<div className="with40 fl static_shadow edu-back-white">
<style>
{
`
.padding23-20{
padding: 23px 20px;
box-sizing: border-box;
}
`
}
</style>
<div className="font-24 padding23-20">实训学习统计</div>
{shixunList===undefined?<div id="showloding"
style={{"width":"480px","height":"440px"}}></div>:""}
{shixunList===undefined?"":<div id="shixunStudyStatistics"
style={{"width":"480px","minHeight":`${shixunList&&shixunList.length *50}px`}}></div>}
</div>
</div>
)
}
}
export default SecondTab;

@ -1,247 +1,247 @@
import React,{ Component } from "react";
import axios from 'axios';
const $ = window.$
const echarts = require('echarts');
function InitCollegeStatistic(_data, myChart){
var data = _data
var _yData = data.map( item => {
return item.name
})
// [{name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4},{name: "长沙理工大学", 已通关: 0, 未通关: 7, sum: 7},{name: "安徽大学", 已通关: 1, 未通关: 8, sum: 9},{name: "湘潭大学兴湘学院", 已通关: 12, 未通关: 0, sum: 12},
// {name: "湖南师范大学", 已通关: 10, 未通关: 2, sum: 12},{name: "湖南软件职业学院", 已通关: 11, 未通关: 1, sum: 12},{name: "湖南科技大学", 已通关: 91, 未通关: 34, sum: 125},{name: "湘潭大学", 已通关: 110, 未通关: 45, sum: 155},
// {name: "湖南工业大学", 已通关: 133, 未通关: 41, sum: 174},{name: "国防科技大学", 已通关: 853, 未通关: 23, sum: 876}];
// <% @schools.each do |s| %>
// data.push({name: "<%= s['name'] %>", '已通关': <%= s['pass_count'] %>, '未通关': <%= s['unpass_count'] %>});
// <% end %>
// =================右边要放的字段名及颜色===========
var items = [{
key: '学习人数', color: "#29BD8B"
}, {
key: '已通关', color: "#FF954C"
}, {
key: '未通关', color: "#CBCBCB"
}]
data.forEach((d) => {
var sum = 0
items.forEach((i) => {
sum += (d[i.key] || 0)
})
d.sum = sum;
})
// =========================排序================
data.sort((a, b) => a.sum - b.sum)
var yData = _yData.reverse();
// ["湖南科技大学潇湘学院", "长沙理工大学", "安徽大学", "湖南软件职业学院", "湖南师范大学", "湘潭大学兴湘学院", "湖南科技大学", "湘潭大学", "湖南工业大学", "国防科技大学"]
var itemSeries = items.map((d, i) => {
var values = data.map((p) => p[d.key])
return {
type: 'bar',
name: d.key,
data: values,
stack: 'all',
xAxisIndex: 1,
yAxisIndex: 1,
label: {
normal: {
color:'#FFF',
// show: ( i == 1 ? true :false),
show: true,
position: 'inside'
}
},
itemStyle: {
normal: {
color: d.color
}
}
}
})
var option = {
backgroundColor: '#fff', // 背景
tooltip : {
trigger: 'axis',
axisPointer : {
type : ''
}
},
legend: {
data: ['学习人数','已通关','未通关'],
textStyle: {
color: '#05101A'
},
right:"20px",
selectedMode:false
},
grid: [{
right: '56%',
top: '20',
containLabel: true
}, {
left: '45%',
width:'100%',
top: '20',
containLabel: true
}],
xAxis: [{
type: 'value',
inverse: true,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
}
}, {
type: 'value',
gridIndex: 1,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
}
}],
yAxis: [{
type: 'category',
data: yData,
max:10,
axisLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
}
}, {
type: 'category',
data: yData,
max:10,
gridIndex: 1,
axisLine: {
show: false
},
axisTick: {
show: false
}
}],
series: [...itemSeries,
{
name: '总计',
type: 'bar',
data: data.map((d) => d.sum),
xAxisIndex: 1,
yAxisIndex: 1,
barCategoryGap:'40%',
stack: 'all',
label: {
normal: {
show: true,
position: 'inside',
color: '#666'
}
},
itemStyle: {
normal: {
color: '#fff'
}
}
},
// ===================左边===================
{
type: 'bar',
data: data.map((d) => d.sum),
barCategoryGap:'40%',
label: {
normal: {
show: true,
position: 'left',
color: '#29BD8B'
}
},
itemStyle: {
normal: {
color: '#29BD8B'
}
}
}]
}
myChart.setOption(option);
}
class ThirdTab extends Component{
constructor(props){
super(props);
}
componentDidMount(){
var pathId = this.props.match.params.pathId;
var myChart = echarts.init(document.getElementById('collegeStatistic'));
myChart.showLoading({
text: "数据获取中",
effect: 'whirling'
})
const url = `/paths/${pathId}/school_report.json`
axios.get(url, {
})
.then((response) => {
// TODO 没用404返回的error
if (response.data.status == 404) {
this.props.showSnackbar('未找到对应数据,请查看地址是否正确。')
return
}
this.setState({ ...response.data })
// name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4
/**
"name": "国防科技大学",
"student_count": 9269,
"pass_count": 6061,
"unpass_count": 3208
*/
const _data = response.data.schools.map( (item, index) => {
return {
name: item.name,
sum: item.student_count,
已通关: item.pass_count,
未通关: item.unpass_count,
}
})
InitCollegeStatistic(_data, myChart);
myChart.hideLoading()
})
.catch(function (error) {
console.log(error);
});
}
render(){
return(
<div className="clearfix mb30 static_shadow edu-back-white panelForm panelForm-3">
<p className="font-24 padding30-20">院校学习情况</p>
<div id="collegeStatistic" style={{"width":"1200px","height":"540px"}}></div>
</div>
)
}
}
import React,{ Component } from "react";
import axios from 'axios';
const $ = window.$
const echarts = require('echarts');
function InitCollegeStatistic(_data, myChart){
var data = _data
var _yData = data.map( item => {
return item.name
})
// [{name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4},{name: "长沙理工大学", 已通关: 0, 未通关: 7, sum: 7},{name: "安徽大学", 已通关: 1, 未通关: 8, sum: 9},{name: "湘潭大学兴湘学院", 已通关: 12, 未通关: 0, sum: 12},
// {name: "湖南师范大学", 已通关: 10, 未通关: 2, sum: 12},{name: "湖南软件职业学院", 已通关: 11, 未通关: 1, sum: 12},{name: "湖南科技大学", 已通关: 91, 未通关: 34, sum: 125},{name: "湘潭大学", 已通关: 110, 未通关: 45, sum: 155},
// {name: "湖南工业大学", 已通关: 133, 未通关: 41, sum: 174},{name: "国防科技大学", 已通关: 853, 未通关: 23, sum: 876}];
// <% @schools.each do |s| %>
// data.push({name: "<%= s['name'] %>", '已通关': <%= s['pass_count'] %>, '未通关': <%= s['unpass_count'] %>});
// <% end %>
// =================右边要放的字段名及颜色===========
var items = [{
key: '学习人数', color: "#29BD8B"
}, {
key: '已通关', color: "#FF954C"
}, {
key: '未通关', color: "#CBCBCB"
}]
data.forEach((d) => {
var sum = 0
items.forEach((i) => {
sum += (d[i.key] || 0)
})
d.sum = sum;
})
// =========================排序================
data.sort((a, b) => a.sum - b.sum)
var yData = _yData.reverse();
// ["湖南科技大学潇湘学院", "长沙理工大学", "安徽大学", "湖南软件职业学院", "湖南师范大学", "湘潭大学兴湘学院", "湖南科技大学", "湘潭大学", "湖南工业大学", "国防科技大学"]
var itemSeries = items.map((d, i) => {
var values = data.map((p) => p[d.key])
return {
type: 'bar',
name: d.key,
data: values,
stack: 'all',
xAxisIndex: 1,
yAxisIndex: 1,
label: {
normal: {
color:'#FFF',
// show: ( i == 1 ? true :false),
show: true,
position: 'inside'
}
},
itemStyle: {
normal: {
color: d.color
}
}
}
})
var option = {
backgroundColor: '#fff', // 背景
tooltip : {
trigger: 'axis',
axisPointer : {
type : ''
}
},
legend: {
data: ['学习人数','已通关','未通关'],
textStyle: {
color: '#05101A'
},
right:"20px",
selectedMode:false
},
grid: [{
right: '56%',
top: '20',
containLabel: true
}, {
left: '45%',
width:'100%',
top: '20',
containLabel: true
}],
xAxis: [{
type: 'value',
inverse: true,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
}
}, {
type: 'value',
gridIndex: 1,
splitLine: {
show: false
},
axisLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
}
}],
yAxis: [{
type: 'category',
data: yData,
max:10,
axisLine: {
show: false
},
axisLabel: {
show: false
},
axisTick: {
show: false
}
}, {
type: 'category',
data: yData,
max:10,
gridIndex: 1,
axisLine: {
show: false
},
axisTick: {
show: false
}
}],
series: [...itemSeries,
{
name: '总计',
type: 'bar',
data: data.map((d) => d.sum),
xAxisIndex: 1,
yAxisIndex: 1,
barCategoryGap:'40%',
stack: 'all',
label: {
normal: {
show: true,
position: 'inside',
color: '#666'
}
},
itemStyle: {
normal: {
color: '#fff'
}
}
},
// ===================左边===================
{
type: 'bar',
data: data.map((d) => d.sum),
barCategoryGap:'40%',
label: {
normal: {
show: true,
position: 'left',
color: '#29BD8B'
}
},
itemStyle: {
normal: {
color: '#29BD8B'
}
}
}]
}
myChart.setOption(option);
}
class ThirdTab extends Component{
constructor(props){
super(props);
}
componentDidMount(){
var pathId = this.props.match.params.pathId;
var myChart = echarts.init(document.getElementById('collegeStatistic'));
myChart.showLoading({
text: "数据获取中",
effect: 'whirling'
})
const url = `/paths/${pathId}/school_report.json`
axios.get(url, {
})
.then((response) => {
// TODO 没用404返回的error
if (response.data.status == 404) {
this.props.showSnackbar('未找到对应数据,请查看地址是否正确。')
return
}
this.setState({ ...response.data })
// name: "湖南科技大学潇湘学院", 已通关: 0, 未通关: 4, sum: 4
/**
"name": "国防科技大学",
"student_count": 9269,
"pass_count": 6061,
"unpass_count": 3208
*/
const _data = response.data.schools.map( (item, index) => {
return {
name: item.name,
sum: item.student_count,
已通关: item.pass_count,
未通关: item.unpass_count,
}
})
InitCollegeStatistic(_data, myChart);
myChart.hideLoading()
})
.catch(function (error) {
console.log(error);
});
}
render(){
return(
<div className="clearfix mb30 static_shadow edu-back-white panelForm panelForm-3">
<div className="font-24 padding30-20">院校学习情况</div>
<div id="collegeStatistic" style={{"width":"1200px","height":"540px"}}></div>
</div>
)
}
}
export default ThirdTab;

@ -168,7 +168,7 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback, initV
$("#" + _id + " [type=\"inline\"]").bind("click", function () {
_editorName.cm.replaceSelection("`$$$$`");
var __Cursor = _editorName.cm.getDoc().getCursor();
_editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
_editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
_editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -81,7 +81,8 @@ export function TPMIndexHOC(WrappedComponent) {
isRender: false,
AccountProfiletype: false,
globalLoading: false
globalLoading: false,
dataquerys:{},
}
}
@ -165,7 +166,32 @@ export function TPMIndexHOC(WrappedComponent) {
$.ajaxSetup({
cache: true
});
this.fetchUser();
//帮助后台传参数
const query = this.props.location.search;
// const type = query.split('?chinaoocTimestamp=');
// console.log("Eduinforms12345");
// console.log(this.foo(query));
// console.log(JSON.stringify(this.foo(query)));
var dataqueryss={}
try {
var foqus=this.foo(query);
if(JSON.stringify(foqus) ==="{}"){
this.setState({
dataquerys:{},
});
}else{
this.setState({
dataquerys:foqus,
});
dataqueryss=foqus;
}
}catch (e) {
this.setState({
dataquerys:{},
})
}
this.fetchUsers(dataqueryss);
let url=`/users/get_navigation_info.json`;
axios.get(url, {
@ -260,10 +286,23 @@ export function TPMIndexHOC(WrappedComponent) {
courseId = parseInt(type[2])
// url += `?course_id=${courseId}`
}
axios.get(url,{params:{
course_id:isNaN(courseId)?undefined:courseId,
school:1
}
var datay={};
if(JSON.stringify(this.state.dataquerys) ==="{}"){
datay={
course_id:isNaN(courseId)?undefined:courseId,
school:1
}
}else{
datay={
course_id:isNaN(courseId)?undefined:courseId,
school:1,
chinaoocTimestamp:this.state.dataquerys.chinaoocTimestamp,
websiteName:this.state.dataquerys.websiteName,
chinaoocKey:this.state.dataquerys.chinaoocKey,
}
}
axios.get(url,{params:
datay
},
{
// withCredentials: true
@ -301,7 +340,93 @@ export function TPMIndexHOC(WrappedComponent) {
}).catch((error) => {
console.log(error)
})
}
};
fetchUsers = (yslurlobject) => {
let url = `/users/get_user_info.json`
let courseId;
let query = this.props.location.pathname;
const type = query.split('/');
if (type[1] == 'courses' && type[2]) {
courseId = parseInt(type[2])
// url += `?course_id=${courseId}`
}
var datay={};
if(JSON.stringify(yslurlobject) ==="{}"){
datay={
course_id:isNaN(courseId)?undefined:courseId,
school:1
}
}else{
datay={
course_id:isNaN(courseId)?undefined:courseId,
school:1,
chinaoocTimestamp:yslurlobject.chinaoocTimestamp,
websiteName:yslurlobject.websiteName,
chinaoocKey:yslurlobject.chinaoocKey,
}
}
axios.get(url,{params:
datay
},
{
// withCredentials: true
}
).then((response) => {
/*
{
"username": "黄井泉",
"login": "Hjqreturn",
"user_id": 12,
"image_url": "avatar/User/12",
"admin": true,
"is_teacher": false,
"tidding_count": 0
}
*/
if(response=== undefined){
return
}
if (response.data) {
this.initCommonState(response.data)
this.setState({
tpmLoading: false,
coursedata: {
course_identity: response.data.course_identity >= 0 ? response.data.course_identity : undefined,
course_public: response.data.course_public,
name: response.data.course_name,
userid:response.data.user_id
},
})
}
}).catch((error) => {
console.log(error)
})
};
//截取url 数据的
foo=(url)=> {
var json = {};
var regExp = /[\?\&](\w+)(=?)(\w*)/g;
var arr;
do {
arr = regExp.exec(url);
// console.log(arr); // arr = [完整的字符串, key, 等号或'', value或'']
if (arr) {
var key = arr[1];
var value = arr[3];
// arr[2] === ''时, value = undefined
if (!arr[2])
value = undefined;
json[key] = value;
}
} while (arr);
return json;
};
hideLoginDialog = () => {
this.setState({
isRender: false

@ -156,9 +156,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl,initValue, callb
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -130,9 +130,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -73,9 +73,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -51,9 +51,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -160,9 +160,9 @@ function create_editorMD(id, width, high, placeholder, imageUrl, callback) {
});
$("#" + id + " [type=\"inline\"]").bind("click", function () {
editorName.cm.replaceSelection("$$$$");
editorName.cm.replaceSelection("`$$$$`");
var __Cursor = editorName.cm.getDoc().getCursor();
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 2);
editorName.cm.setCursor(__Cursor.line, __Cursor.ch - 3);
editorName.cm.focus();
});
$("[type=\"inline\"]").attr("title", "行内公式");

@ -8,7 +8,7 @@ import PropTypes from 'prop-types';
import classNames from 'classnames';
import { getImageUrl ,markdownToHTML} from 'educoder'
import { getImageUrl ,markdownToHTML, configShareForCustom} from 'educoder'
import { CircularProgress } from 'material-ui/Progress';
@ -51,6 +51,7 @@ class Challenges extends Component {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else{
configShareForCustom(this.props.shixunsDetails.name, response.data.description)
this.setState({
ChallengesDataList: response.data,
sumidtype: false,

@ -2,7 +2,7 @@ import React, { Component } from "react";
import { message, Icon, Input, Form, Upload} from "antd";
import axios from 'axios'
import ModalWrapper from "../../courses/common/ModalWrapper"
import { City, getUploadActionUrl, getImageUrl, ImageLayerHook, getUploadActionUrlOfAuth } from 'educoder'
import { City, getUploadActionUrl, getImageUrl, ImageLayer2, getUploadActionUrlOfAuth } from 'educoder'
import '../account/common.css'
import authImg from '../../../images/account/auth.png'
@ -308,8 +308,8 @@ class RealNameCertificationModal extends Component{
<div className="df mt10 color-grey-9" style={{ justifyContent: 'center' }} >
<span className="fl mr20 edu-txt-center" style={{width:"160px"}}>示例图片</span>
<span className="fl edu-txt-center mr20" style={{width:"160px"}}>
<ImageLayerHook parentSel={'#imageLayerBtn'} parentSel={'#imageLayerBtn'}
></ImageLayerHook>
<ImageLayer2 parentSel={'#imageLayerBtn'} parentSel={'#imageLayerBtn'}
></ImageLayer2>
<a href="javascript:void(0)" id="imageLayerBtn" src={imageUrl || imageUrl2} className="color-orange" style={{borderBottom:"1px solid #ff6800"}}>查看大图</a>
</span>
</div>

@ -370,17 +370,17 @@ class InfosTopics extends Component{
{
`
::-webkit-scrollbar-thumb {
background-color: #cde5fe;
box-shadow: 0px 0px black;
}
::-webkit-scrollbar-track {
-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
background-color: #fff;
}
// ::-webkit-scrollbar-thumb {
// background-color: #cde5fe;
//
// box-shadow: 0px 0px black;
// }
//
//
// ::-webkit-scrollbar-track {
// -webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0);
// background-color: #fff;
// }
.shaiContent li.shaiItem {
padding: 0px 9px;

@ -429,4 +429,8 @@
.topsicinline{
display: inline-block;
}
/* 防抖 */
.educontent .square-list {
min-height: 400px;
}

@ -1,3 +1,7 @@
/* 撑开滚动条,防抖 */
.educontent > .itemWrap {
min-height: 400px;
}
.itemWrap {
display: flex;
flex-wrap: wrap;

Loading…
Cancel
Save