Merge branch 'develop' into dev_daiao

dev_daiao
daiao 5 years ago
commit 8deb23a919

@ -0,0 +1,5 @@
class Projects::BaseController < ApplicationController
include PaginateHelper
before_action :require_login, :check_auth
end

@ -0,0 +1,14 @@
class Projects::ProjectAppliesController < Projects::BaseController
def create
project = Projects::ApplyJoinService.call(current_user, create_params)
render_ok(project_id: project.id)
rescue Projects::ApplyJoinService::Error => ex
render_error(ex.message)
end
private
def create_params
params.permit(:code, :role)
end
end

@ -0,0 +1,31 @@
# 申请成为 管理员、开发者 加入项目 消息通知
class ApplyJoinProjectNotifyJob < ApplicationJob
queue_as :notify
def perform(user_id, project_id, role)
user = User.find_by(id: user_id)
project = Project.find_by(id: project_id)
return if user.blank? || project.blank?
attrs = %i[user_id trigger_user_id container_id container_type status
belong_container_id belong_container_type tiding_type extra created_at updated_at]
same_attrs = {
trigger_user_id: user.id, status: 0, tiding_type: 'Apply', extra: role,
container_id: project.id, container_type: 'JoinProject',
belong_container_id: project.id, belong_container_type: 'Project'
}
# 报告人员加入时消息为系统通知消息
if role == 5
same_attrs[:container_type] = 'ReporterJoinProject'
same_attrs[:tiding_type] = 'System'
end
Tiding.bulk_insert(*attrs) do |worker|
project.manager_members.each do |manager|
worker.add(same_attrs.merge(user_id: manager.user_id))
end
end
end
end

@ -0,0 +1,9 @@
class AppliedProject < ApplicationRecord
belongs_to :user
belongs_to :project
has_many :applied_messages, as: :applied, dependent: :destroy
has_many :forge_activities, as: :forge_act, dependent: :destroy
scope :pending, -> { where(status: 0) }
end

@ -0,0 +1,5 @@
class ForgeActivity < ApplicationRecord
belongs_to :user
belongs_to :project
belongs_to :forge_act, polymorphic: true
end

@ -1,6 +1,8 @@
class Member < ApplicationRecord
has_many :member_roles, dependent: :destroy
belongs_to :user
belongs_to :course, optional: true
belongs_to :project, optional: true
belongs_to :user
has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles
end

@ -1,3 +1,4 @@
class MemberRole < ApplicationRecord
belongs_to :role
belongs_to :member
end

@ -1,9 +1,12 @@
class Project < ApplicationRecord
belongs_to :owner, class_name: 'User', foreign_key: :user_id
has_many :members
has_many :manager_members, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
has_one :project_score, dependent: :destroy
has_many :issues
has_many :user_grades, dependent: :destroy
# 创建者
def creator

@ -0,0 +1,3 @@
class Role < ApplicationRecord
has_many :member_roles, dependent: :destroy
end

@ -8,7 +8,7 @@ module Searchable::Dependents::User
private
def check_searchable_dependents
if firstname_previously_changed? || lastname_previously_changed? || user_extension.school_id_previously_changed?
if firstname_previously_changed? || lastname_previously_changed? || user_extension&.school_id_previously_changed?
# reindex shixun
created_shixuns.each(&:reindex)

@ -128,6 +128,9 @@ class User < ApplicationRecord
has_many :bidding_users, dependent: :destroy
has_many :bidden_project_packages, through: :bidding_users, source: :project_package
# 项目
has_many :applied_projects, dependent: :destroy
# Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) }

@ -0,0 +1,4 @@
class UserGrade < ApplicationRecord
belongs_to :project
belongs_to :user
end

@ -22,6 +22,7 @@ module ElasticsearchAble
fragment_size: EduSetting.get('es_highlight_fragment_size') || 30,
tag: '<span class="highlight">',
fields: {
name: { type: 'plain' },
challenge_names: { type: 'plain' },
challenge_tag_names: { type: 'plain' },
description: { type: 'plain' },

@ -0,0 +1,82 @@
class Projects::ApplyJoinService < ApplicationService
Error = Class.new(StandardError)
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
validate!
# 项目报告人员直接加入项目
if params[:role] == 'reporter'
Projects::JoinService.call(project, user, role: 'reporter')
return project
end
ActiveRecord::Base.transaction do
apply = user.applied_projects.create!(project: project, role: role_value)
apply.forge_activities.find_or_create_by!(user: user, project: project)
notify_project_manager!
end
# notify_project_owner
ApplyJoinProjectNotifyJob.perform_later(user.id, project.id, role_value)
project
end
private
def project
@_project ||= Project.find_by(invite_code: params[:code].to_s.strip)
end
def role_value
@_role ||=
case params[:role]
when 'manager' then 3
when 'developer' then 4
when 'reporter' then 5
else raise Error, '角色无效'
end
end
def notify_project_manager!
columns = %i[user_id applied_id applied_type status viewed applied_user_id role project_id created_at updated_at]
AppliedMessage.bulk_insert(*columns) do |worker|
base_attr = { status: false, viewed: false, applied_user_id: user.id, role: role_value, project_id: project.id }
project.manager_members.each do |manager|
worker.add(base_attr.merge(user_id: manager.user_id))
end
end
end
def notify_project_owner
owner = project.user
return if owner.phone.blank?
Educoder::Sms.send(mobile: owner.phone, send_type:'applied_project_info',
user_name: owner.show_name, name: project.name)
rescue Exception => ex
Rails.logger.error("发送短信失败 => #{ex.message}")
end
def validate!
# params check
raise Error, '邀请码不能为空' if params[:code].blank?
raise Error, '角色不能为空' if params[:role].blank?
raise Error, '角色无效' unless %w(manager developer reporter).include?(params[:role])
# logical check
raise Error, '邀请码无效' if project.blank?
raise Error, '您已在该项目中' if project.member?(user)
raise Error, '您已经提交过申请' if user.applied_projects.pending.exists?(project: project)
end
end

@ -0,0 +1,35 @@
class Projects::JoinService < ApplicationService
attr_reader :project, :user, :opts
def initialize(project, user, **opts)
@project = project
@user = user
@opts = opts
end
def call
ActiveRecord::Base.transaction do
member = project.members.create!(user: user)
member.member_roles.create!(role_id: role_value)
project.user_grades.find_or_create_by!(user: user)
end
ApplyJoinProjectNotifyJob.perform_later(user, project, role_value)
project
end
private
def role_value
@_role ||=
case opts[:role]
when 'manager' then 3
when 'developer' then 4
when 'reporter' then 5
else raise ArgumentError
end
end
end

@ -695,6 +695,10 @@ Rails.application.routes.draw do
end
resources :libraries, only: [:index, :show, :create, :update, :destroy]
scope module: :projects do
resources :applied_projects, only: [:create]
end
end
#git 认证回调

@ -1,8 +0,0 @@
class ModifyLoginForUsers < ActiveRecord::Migration[5.2]
def change
users = User.where("created_on > '2019-07-26 19:00:00'")
users.find_each do |use|
use.update_column(:login, use.login.strip)
end
end
end

@ -0,0 +1,9 @@
class ModifyLoginForUsers < ActiveRecord::Migration[5.2]
def change
users = User.where("created_on > '2019-07-26 19:00:00'")
users.find_each do |use|
use.update_attributes(login: use.login&.strip, phone: use.phone&.strip)
use.user_extension.update_column(:student_id, use.user_extension&.student_id&.strip) if use.user_extension
end
end
end

@ -0,0 +1,11 @@
class DeleteErrorMyshixunFromMyshxiuns < ActiveRecord::Migration[5.2]
def change
myshixuns = Myshixun.where("created_at > '2019-07-26 00:00:00' and repo_name is null")
myshixuns.find_each do |myshixun|
if myshixun.games.blank?
puts("###########user_login: #{User.find(myshixun.user_id).login}")
myshixun.destroy!
end
end
end
end

@ -0,0 +1,11 @@
class DeleteMyshixunGamesForUsers < ActiveRecord::Migration[5.2]
def change
myshixuns = Myshixun.where("created_at > '2019-07-26 19:00:00' and repo_name is null")
myshixuns.find_each do |m|
if m.games.count == m.games.select{|g| g.status == 3}.count
puts("#######login: #{User.find(m.user_id).login}")
m.destroy!
end
end
end
end

@ -1,11 +1,25 @@
/*--------------------------首页*/
/*头部导航条样式---2018-03-19--by-cs*/
.newHeader{background: #24292D !important; width:100%; height: 60px !important; min-width: 1200px;position: fixed;top: 0px;left: 0px;z-index:1000;-moz-box-shadow: 0px 0px 12px rgba(0,0,0,0.1); /* 老的 Firefox */box-shadow: 0px 0px 12px rgba(0,0,0,0.1);}
.newHeader{
/*overflow:hidden;*/
/*text-overflow:ellipsis;*/
/*white-space:nowrap;*/
background: #24292D !important; width:100%; height: 60px !important; min-width: 1200px;position: fixed;top: 0px;left: 0px;z-index:1000;-moz-box-shadow: 0px 0px 12px rgba(0,0,0,0.1); /* 老的 Firefox */box-shadow: 0px 0px 12px rgba(0,0,0,0.1);
}
.newHeader .logoimg{
margin-top: 16px;
float: left;
width: 97px;}
.head-nav{float: left;width: 830px;text-align: center;height: 60px;box-sizing: border-box; min-width: 400px;}
.head-nav{
float: left;
text-align: center;
height: 60px;
box-sizing: border-box;
min-width: 785px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.head-nav ul#header-nav{position: absolute;top: 0px;z-index: 3;height: 60px;box-sizing: border-box;}
.head-nav ul#header-nav li{float: left;height: 60px;line-height: 60px;margin-right: 30px;cursor: pointer;position: relative;font-size: 16px}
.head-nav ul#header-nav li a{display: block;height: 100%;width: 100%;color: #fff}

@ -87,7 +87,7 @@
</noscript>
<!--用于markdown转html -->
<div id="md_div" style="display: none;"></div>
<div id="root" class="page -layout-v -fit" >
<div id="root" class="page -layout-v -fit widthunit" style="min-width: 1535px;">
<!--<div class="d2-home">-->
<!--<div class="d2-home__main">-->
<!--&lt;!&ndash;<img class="d2-home__loading"&ndash;&gt;-->

@ -41,7 +41,7 @@ export function initAxiosInterceptors(props) {
// proxy = "http://testbdweb.trustie.net"
// proxy = "http://testbdweb.educoder.net"
// proxy = "https://testeduplus2.educoder.net"
proxy="http://47.96.87.25:48080"
proxy="http://47.96.87.25:48080/"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求

@ -136,7 +136,7 @@ class CommonWorkDetailIndex extends Component{
DownloadMessageval:undefined
})
}
bindRef = ref => { this.child = ref };
render() {
@ -171,8 +171,10 @@ class CommonWorkDetailIndex extends Component{
let params = {}
if (isListModule) {
// TODO
// params = this.refs.commonWorkList._getRequestParams()
params =this.child._getRequestParams()!==undefined?this.child._getRequestParams():{};
}
// console.log("普通作业176176176");
// console.log(params);
let exportUrl = `/homework_commons/${workId}/works_list.zip?${queryString.stringify(params)}`
let exportResultUrl = `/homework_commons/${workId}/works_list.xlsx?${queryString.stringify(params)}`
return (
@ -356,7 +358,7 @@ class CommonWorkDetailIndex extends Component{
{/* 作品列表 */}
<Route exact path="/courses/:coursesId/common_homeworks/:workId/list"
render={
(props) => (<CommonWorkList ref="commonWorkList" {...this.props} {...props} {...this.state} {...commonHandler}/>)
(props) => (<CommonWorkList ref="commonWorkList" triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler}/>)
}
></Route>
@ -382,7 +384,7 @@ class CommonWorkDetailIndex extends Component{
{/* 作品列表 */}
<Route exact path="/courses/:coursesId/group_homeworks/:workId/list"
render={
(props) => (<CommonWorkList {...this.props} {...props} {...this.state} {...commonHandler}/>)
(props) => (<CommonWorkList triggerRef={this.bindRef} {...this.props} {...props} {...this.state} {...commonHandler}/>)
}
></Route>

@ -400,7 +400,12 @@ class CommonWorkList extends Component{
componentDidMount() {
this.fetchList()
on('commonwork_fetch_all', this.fetchAllListener)
$("html").animate({ scrollTop: $('html').scrollTop() - 100 })
$("html").animate({ scrollTop: $('html').scrollTop() - 100 });
try {
this.props.triggerRef(this);
}catch (e) {
}
}
componentWillUnmount() {
@ -767,7 +772,7 @@ class CommonWorkList extends Component{
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
</div>

@ -52,7 +52,7 @@ class Exercisetablesmubus extends Component {
dataIndex: 'commit_percent',
key: 'commit_percent',
render: (text, record, index) => {
const _content = <span style={{color:text.type===true? "#29BD8B":'#333333'}}>
const _content = <span style={{color:text.type===true? "#29BD8B":'#333333', width: '100%'}}>
{text.value!="有效填写量"&&text.value!="wrong" &&
<MarkdownToHtml content={text.value} selector={(tableNum+1) + '' + (index+1)}></MarkdownToHtml>
}

@ -2565,7 +2565,7 @@ class Studentshavecompletedthelist extends Component {
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
@ -2630,7 +2630,7 @@ class Studentshavecompletedthelist extends Component {
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
@ -2692,7 +2692,7 @@ class Studentshavecompletedthelist extends Component {
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>

@ -7,7 +7,7 @@ import {
} from 'antd';
import axios from 'axios'
import { qNameArray } from './common'
import {getUrl, ActionBtn, markdownToHTML} from 'educoder';
import {getUrl, ActionBtn, markdownToHTML, MarkdownToHtml } from 'educoder';
import QestionDisplayHeader from './QestionDisplayHeader'
const { TextArea } = Input;
const confirm = Modal.confirm;

@ -190,7 +190,7 @@ export default ImageLayerOfCommentHOC() (GraduationTasksappraiseReply);
{/*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>*/}
{/*<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>*/}
{/*</div>*/}
{/*</div>*/}
{/*</div>*/}

@ -1307,7 +1307,7 @@ class GraduationTaskssettinglist extends Component{
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
@ -1573,7 +1573,7 @@ class GraduationTaskssettinglist extends Component{
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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>

@ -36,8 +36,10 @@ const buildColumns = (that) => {
key: 'login',
align:'center',
className:"color-grey-6",
render: (name, record) => {
return <span className="color-dark overflowHidden1" style={{maxWidth: '110px'}}>{name}</span>
render: (login, record) => {
return <span className="color-dark overflowHidden1" style={{maxWidth: '160px'}}
title={login && login.length > 10 ? login : ''}
>{login}</span>
}
}, {
title: '姓名',
@ -57,8 +59,8 @@ const buildColumns = (that) => {
align:'center',
className:"color-grey-6",
render: (student_id, record) => {
return <span className="color-dark overflowHidden1"
style={{maxWidth: '110px'}} >{student_id}</span>
return <span className="color-dark overflowHidden1 "title={student_id && student_id.length > 10 ? student_id : ''}
style={{maxWidth: '160px'}} >{student_id}</span>
}
}];
if (course_groups && course_groups.length) {

@ -2528,7 +2528,7 @@ class Listofworksstudentone extends Component {
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
@ -2747,7 +2747,7 @@ class Listofworksstudentone extends Component {
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>
@ -2945,7 +2945,7 @@ class Listofworksstudentone extends Component {
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>

@ -258,7 +258,7 @@ class ShixunWorkModal extends Component{
<div className=" 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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>

@ -31,7 +31,7 @@ class MemoList extends Component {
{!memo_list || memo_list.length === 0 ?
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
: renderMemoList()
}

@ -123,7 +123,7 @@ class ShixunsHome extends Component {
<Spin spinning={hometypepvisible} size="large" style={{marginTop:'15%'}}>
{/*懒加载*/}
<SiderBar/>
{/*<SiderBar/>*/}
<div className="clearfix">
<div className="clearfix edu-back-white pb40 pt30 mb20" id="index-top" onMouseMove={this.bannaronmousemove} onMouseOut={this.bannaronmouseout}>
<div className="educontent pr educontentSlider">

@ -102,6 +102,8 @@ class LoginDialog extends Component {
authCodeclass:'log-botton mt5',
isRender: false,
MyEduCoderModals:false,
Phonenumberisnotco:undefined,
Phonenumberisnotcobool:false,
};
}
@ -112,26 +114,103 @@ class LoginDialog extends Component {
register=(num) =>{
this.setState({login:1,speedy:num,dialogBox:'dialogBox2'});
}
loginChange = () =>{
let reg = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/;
let reg1 = /^1\d{10}$/;
let reg2=/^[a-zA-z]\w{3,14}$/;
// let reg3=/^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
let value=this.refs.loginPassText.value;
let valuenum= value.length;
if(valuenum>0){
if(!reg.test(value)&&!reg1.test(value)&&!reg2.test(value)){
this.setState({regular:1})
return
}else{
this.setState({loginValue:value})
this.setState({regular:0})
inputOnBlur = (e, id) => {
this.Emailphonenumberverification(e.target.value, 1);
};
// 输入页面
loginChange = (e) =>{
var stirngt="";
if(e.target.value.length>0){
var str= e.target.value.replace(/\s*/g,"")
stirngt=str;
}else{
stirngt= e.target.value;
}
if (e.target.value.length === 0) {
this.setState({
loginValue: stirngt,
Phonenumberisnotco:undefined,
})
}else{
this.setState({
loginValue: stirngt,
Phonenumberisnotco:undefined,
})
}
// let reg = /^(\w-*\.*)+@(\w-?)+(\.\w{2,})+$/;
// let reg1 = /^1\d{10}$/;
// let reg2=/^[a-zA-z]\w{3,14}$/;
// // let reg3=/^[a-zA-Z0-9]+([.\-_\\]*[a-zA-Z0-9])*@([a-z0-9]+[-a-z0-9]*[a-z0-9]+.){1,63}[a-z0-9]+$/;
// let value=this.refs.loginPassText.value;
// let valuenum= value.length;
// if(valuenum>0){
// if(!reg.test(value)&&!reg1.test(value)&&!reg2.test(value)){
// this.setState({regular:1})
// return
// }else{
// // this.setState({loginValue:value});
// this.setState({regular:0});
// var stirngt;
// if(value.length>0){
// var str= value.replace(/\s*/g,"")
// stirngt=str;
// }else{
// stirngt= value;
// }
// this.setState({
// loginValue:stirngt,
// });
// }
// }else{
// this.setState({loginValue:value});
// var stirngt;
// if(value.length>0){
// var str= value.replace(/\s*/g,"")
// stirngt=str;
// }else{
// stirngt= value;
// }
// this.setState({
// loginValue:stirngt,
// });
// }
};
//邮箱手机号验证
Emailphonenumberverification = (value, id) => {
var url = `/accounts/valid_email_and_phone.json`;
axios.get((url), {
params: {
login: value,
type: 1,
}
}).then((result) => {
if(result){
if(result.data.status===-2){
if(result.data.message==="该手机号码或邮箱已被注册"){
this.setState({
Phonenumberisnotco: undefined,
Phonenumberisnotcobool: false,
})
}else {
this.setState({
Phonenumberisnotco: result.data.message,
Phonenumberisnotcobool: true,
})
}
return;
}else {
this.setState({
Phonenumberisnotco: undefined,
Phonenumberisnotcobool: false,
})
return;
}
}else{
this.setState({loginValue:value})
}
}
}).catch((error) => {
})
};
passwordChange = () =>{
let value =this.refs.passwordText.value;
@ -411,7 +490,7 @@ class LoginDialog extends Component {
window.location.href = url;
};
render() {
let{open,login,speedy,loginValue,regular,isGoing,isGoingValue,disabled,bottonclass,
let{open,login,speedy,loginValue,regular,isGoing,isGoingValue,disabled,bottonclass,Phonenumberisnotco,
dialogBox,shortcutnum,disabledType,gaincode,authCodeType,authCodeclass, isRender}=this.state;
if (isRender === undefined) {
@ -457,11 +536,13 @@ class LoginDialog extends Component {
id="name_loggin_input"
ref="loginPassText"
onInput={this.loginChange}
onBlur={(e) => this.inputOnBlur(e, 1)}
value={this.state.loginValue}
name="username"
placeholder="请输入有效的手机号/邮箱号" ></input>
<div style={{height: '25px'}}><p className="color-orange edu-txt-left none" id="username_error_notice"
style={{display: regular==0?'none':'block'}}>请输入有效的手机号/邮箱号</p></div>
style={{display: Phonenumberisnotco===undefined?'none':'block'}}>{Phonenumberisnotco}</p></div>
<div>
<input type="password" id="password_loggin_input"

@ -16,7 +16,8 @@ class NewFooter extends Component {
render() {
return (
<div className="newFooter edu-txt-center newContainers">
<div className="newFooter edu-txt-center ">
{/*newContainers*/}
<div className="inner-footer_con">
<div className="footercon">
{/* <div className="inline mt40 mb5">

@ -649,10 +649,22 @@ submittojoinclass=(value)=>{
{...this.state}
{...this.props}
/>:""}
<a href="/" className={" fl"}>
<a href="/" className={"fl mr60 ml25"}>
<img alt="高校智能化教学与实训平台" className="logoimg" src={getImageUrl("images/educoder/headNavLogo.png?1526520218")}></img>
</a>
<div className="educontent">
<style>
{
`
.educontents{
margin: 0px auto;
box-sizing: border-box;
}
`
}
</style>
<div className="educontents fl">
{/*<%= link_to image_tag("/images/educoder/logo.png", alt:"高校智能化教学与实训平台", className:"logoimg"), home_path %>*/}
<div className="head-nav pr">
@ -711,65 +723,67 @@ submittojoinclass=(value)=>{
><a href={this.props.Headertop===undefined?"":this.props.Headertop.auth}>工程认证</a></li>
</ul>
<style>
{
`
</div>
</div>
<style>
{
`
.posi-searchs{
opacity: 1;
position: absolute;
top: -2px;
background: #fff;
z-index: 2;
right: -241px;
opacity: 1;
position: absolute;
top: -2px;
background: #fff;
z-index:10000;
right: 185px;
}
`
}
</style>
<div className="posi-searchs" >
<div className="search-all clearfix">
{/*<!--<a href="javascript:void(0)" className="search-clear fl" onclick="closeSearch();">×</a>-->*/}
<div className="fl pr search-clear edu-menu-panel" style={{display: 'none'}}>
<input type="hidden" id="search_type" value="1"></input>
<span className="searchkey">实训</span>
<i className="fa fa-angle-down ml5 font-16"></i>
<ul id="searchkey" className="edu-menu-list edu-txt-center" style={{minWidth: '80px',right: '-10px',top: '50px'}}>
<li><a>实训</a></li>
<li><a>课堂</a></li>
<li><a>用户</a></li>
</ul>
</div>
{/*<input type="text" className="search-input fl" id="search-input" */}
{/*onKeyDown={this.onKeywordSearchKeyDown} name="search_keyword" placeholder="搜索实训项目"/>*/}
{/*搜索框*/}
{showSearchOpentype===true?<div
className={"HeaderSearch"}
onBlur={(e)=>this.hideshowSearchOpen(e)} onMouseLeave={()=>this.setevaluatinghides()}>
<Search
id={"HeaderSearchs"}
placeholder="实践课程/翻转课堂/开发社区/交流问答"
onInput={()=>this.onKeywordSearchKeyDowns()}
onSearch={(value) => this.onKeywordSearchKeyDown(value)}
// onPressEnter={this.onKeywordSearchKeyDown}
style={{ width: 300,height:32}}
autoFocus={true}
/>
</div>:""}
{/*<a className="search-icon fl" id="header_keyword_search" onClick={this.onKeywordSearch}>*/}
{/*/!*<i className="fa fa-search font-16 mt23 color-grey-6"></i>*!/*/}
{/*<i className="iconfont icon-sousuo color-blue"></i>*/}
{/*</a>*/}
{/* TODO
}
</style>
<div className="posi-searchs" >
<div className="search-all clearfix">
{/*<!--<a href="javascript:void(0)" className="search-clear fl" onclick="closeSearch();">×</a>-->*/}
<div className="fl pr search-clear edu-menu-panel" style={{display: 'none'}}>
<input type="hidden" id="search_type" value="1"></input>
<span className="searchkey">实训</span>
<i className="fa fa-angle-down ml5 font-16"></i>
<ul id="searchkey" className="edu-menu-list edu-txt-center" style={{minWidth: '80px',right: '-10px',top: '50px'}}>
<li><a>实训</a></li>
<li><a>课堂</a></li>
<li><a>用户</a></li>
</ul>
</div>
{/*<input type="text" className="search-input fl" id="search-input" */}
{/*onKeyDown={this.onKeywordSearchKeyDown} name="search_keyword" placeholder="搜索实训项目"/>*/}
{/*搜索框*/}
{showSearchOpentype===true?<div
className={"HeaderSearch"}
onBlur={(e)=>this.hideshowSearchOpen(e)} onMouseLeave={()=>this.setevaluatinghides()}>
<Search
id={"HeaderSearchs"}
placeholder="实践课程/翻转课堂/开发社区/交流问答"
onInput={()=>this.onKeywordSearchKeyDowns()}
onSearch={(value) => this.onKeywordSearchKeyDown(value)}
// onPressEnter={this.onKeywordSearchKeyDown}
style={{ width: 300,height:32}}
autoFocus={true}
/>
</div>:""}
{/*<a className="search-icon fl" id="header_keyword_search" onClick={this.onKeywordSearch}>*/}
{/*/!*<i className="fa fa-search font-16 mt23 color-grey-6"></i>*!/*/}
{/*<i className="iconfont icon-sousuo color-blue"></i>*/}
{/*</a>*/}
{/* TODO
<div className="search-content none" style="width: 86%;left: 0px;">
<div className="search-title">最近搜索</div>
<div><a href="javascript:void(0)" className="search_history">绿盟</a></div>
<div><a href="javascript:void(0)" className="search_history">qwe</a></div>
</div>*/}
</div>
</div>
</div>
</div>
</div>
{/*<span className="font-15 fr mt17">
<%= link_to '登录', signin_path, :className => "mr5" %>
@ -777,16 +791,16 @@ submittojoinclass=(value)=>{
<%= link_to '注册', user_join_path, :className => "ml5" %>
</span>*/}
{ user===undefined?
<span className="font-15 fr mt17 ml20">
<span className="font-15 fr mt17 ml10 mr25">
<a onClick={()=>this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a>
</span> :user.login===""?<span className="font-15 fr mt17 ml20">
</span> :user.login===""?<span className="font-15 fr mt17 ml20 mr25">
<a onClick={()=>this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a>
</span>:
<div className="fr edu-menu-panel" style={{height:'60px'}}>
<div className="fr edu-menu-panel mr25" style={{height:'60px'}}>
<a href={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/courses`} className="fl ml15">
<img alt="头像" className="radius mt13" height="34" id="nh_user_logo" name="avatar_image"
src={getImageUrl(`images/`+user.image_url)} width="34">
@ -814,7 +828,7 @@ submittojoinclass=(value)=>{
</div>
}
{/*href="https://www.educoder.net/login"*/}
<div className="fr head-right ">
<div className="fr head-right">
{/*{ loadHeader()}*/}
{showSearchOpentype===true?"":<a id="search-open" className="fl mr30 headIcon" onClick={(e)=>this.showSearchOpen(e)}>
{/*"/images/educoder/icon/search.svg"
@ -852,7 +866,7 @@ submittojoinclass=(value)=>{
{/* /courses/join_course_multi_role */}
{/*<li>*/}
{/* <a onClick={this.tojoinitem}>加入项目</a>*/}
<a onClick={this.tojoinitem}>加入项目</a>
{/*</li>*/}
<Modal
keyboard={false}
@ -949,7 +963,7 @@ submittojoinclass=(value)=>{
</Modal>
</div>
</div>
</div>
);

@ -200,4 +200,12 @@ body>.-task-title {
.HeaderSearch{
width: 325px;
}
.mainheighs{
height: 100%;
display: block;
}
.ml18a{
margin-left:18%;
}

@ -20,7 +20,7 @@ const versionNum = '0001';
// let _url_origin = getUrl()
let _url_origin='';
if(window.location.port === "3007"){
_url_origin="https://newweb.educoder.net";
_url_origin="http://47.96.87.25:48080/";
}
// let _url_origin=`https://www.educoder.net`;

@ -547,7 +547,7 @@ class LoginRegisterComponent extends Component {
}).catch((error) => {
})
}
};
//短信验证
SMSverification = () => {
var url = `/accounts/get_verification_code.json`;
@ -678,60 +678,6 @@ class LoginRegisterComponent extends Component {
}
//失去焦点判断
inputOnBlur = (e, id) => {
// this.isCorrectname(e.target.value, id);
// this.Emailphonenumberverification(e.target.value, id);
if (e.target.value.length === 0) {
this.setState({
Phonenumberisnotco: undefined,
Phonenumberisnotcobool: false,
})
return;
}
// var telephone = $("#telephoneAdd.tianjia_phone").val();
var regph = /^[1][3,4,5,6,7,8][0-9]{9}$/;
// var email = $("#add_email.tianjia_email").val();
var regemail = /^\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/;
// [1]手机号开头必须是1 [3,4,5,6,7,8] 第二位是3-8中的一个 [0-9]{9} 后边9位可以是0-9的任意数字。
var stringdata = undefined;
if (!regph.test(e.target.value)) {
stringdata = "手机号格式不正确";
this.setState({
Phonenumberisnotco: stringdata,
Phonenumberisnotcobool: true,
dragOk:false,
Whethertoverify:this.state.Whethertoverify===true?false:true,
})
} else {
this.setState({
Phonenumberisnotco: undefined,
Phonenumberisnotcobool: false,
})
return
}
if (!regemail.test(e.target.value)) {
if ((e.target.value.indexOf("@") != -1) === true) {
stringdata = "邮箱格式不正确";
} else {
stringdata = "手机号格式不正确";
}
this.setState({
Phonenumberisnotco: stringdata,
Phonenumberisnotcobool: true,
dragOk:false,
Whethertoverify:this.state.Whethertoverify===true?false:true,
})
return
} else {
this.setState({
Phonenumberisnotco: undefined,
Phonenumberisnotcobool: false,
})
this.Emailphonenumberverification(e.target.value, 1);
return
}
this.Emailphonenumberverification(e.target.value, 1);
}
inputOnBlurzhuche = (e, id) => {

@ -52,7 +52,7 @@ class Notcompletedysl extends Component {
render() {
console.log(this.props)
// console.log(this.props)
return(
<Modal
keyboard={false}

@ -151,7 +151,7 @@ class ChangeHeaderPicModal extends Component{
text-align: center;
width: 120px;
height: 120px;
border: 1px solid #eee;
/* border: 1px solid #eee; */
}
.previewWrap {
flex-direction: column;

@ -130,7 +130,7 @@ class InfosCourse extends Component{
this.props.current_user && this.props.current_user.user_identity != "学生" ? <Create href={"/courses/new"} name={"新建课堂"} index="1"></Create> : ""
}
{
(!data || data.courses.length==0) && (this.props.current_user && this.props.current_user.user_identity === "学生" ) && <NoneData></NoneData>
(!data || data.courses.length==0) && (!is_current || (this.props.current_user && this.props.current_user.user_identity === "学生" )) && <NoneData></NoneData>
}
{
data && data.courses && data.courses.map((item,key)=>{
@ -147,7 +147,7 @@ class InfosCourse extends Component{
{
item.can_visited ==false?
<div className="closeSquare">
<img src={getImageUrl("/images/educoder/icon/lockclose.svg")} className="mt80 mb25"/>
<img src={getImageUrl("images/educoder/icon/lockclose.svg")} className="mt80 mb25"/>
<p className="font-14 color-white">非成员不能访问</p>
</div>:""
}

@ -152,7 +152,7 @@ class InfosPath extends Component{
this.props.current_user && this.props.current_user.user_identity != "学生" ? <Create href={"/paths/new"} name={"新建实践课程"} index="3"></Create>:""
}
{
(!data || data.subjects.length==0) && (this.props.current_user && this.props.current_user.user_identity === "学生" ) && <NoneData></NoneData>
(!data || data.subjects.length==0) && (!is_current || (this.props.current_user && this.props.current_user.user_identity === "学生" )) && <NoneData></NoneData>
}
{
data && data.subjects && data.subjects.map((item,key)=>{

@ -125,7 +125,7 @@ class InfosProject extends Component{
<Create href={`${this.props.Headertop && this.props.Headertop.old_url}/projects/new`} name={"新建项目"} index="4"></Create>:""
}
{
(!data || data.projects.length==0) && (this.props.current_user && this.props.current_user.user_identity === "学生" ) && <NoneData></NoneData>
(!data || data.projects.length==0) && (!is_current || (this.props.current_user && this.props.current_user.user_identity === "学生" )) && <NoneData></NoneData>
}
{
data && data.projects && data.projects.map((item,key)=>{
@ -142,7 +142,7 @@ class InfosProject extends Component{
{
item.can_visited ==false?
<div className="closeSquare">
<img src={getImageUrl("/images/educoder/icon/lockclose.svg")} className="mt80 mb25"/>
<img src={getImageUrl("images/educoder/icon/lockclose.svg")} className="mt80 mb25"/>
<p className="font-14 color-white">非成员不能访问</p>
</div>:""
}

@ -161,7 +161,7 @@ class InfosShixun extends Component{
<Create href={"/shixuns/new"} name={"新建实训"} index="2"></Create>:""
}
{
(!data || data.shixuns.length==0) && (this.props.current_user && this.props.current_user.user_identity === "学生" ) && <NoneData></NoneData>
(!data || data.shixuns.length==0) && (!is_current || (this.props.current_user && this.props.current_user.user_identity === "学生" )) && <NoneData></NoneData>
}
{
data && data.shixuns && data.shixuns.map((item,key)=>{

@ -164,7 +164,7 @@ class SearchPage extends Component{
<div className="mh650 bjyss">
<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>
<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div>
</div>

@ -1,11 +1,25 @@
/*--------------------------首页*/
/*头部导航条样式---2018-03-19--by-cs*/
.newHeader{background: #24292D !important; width:100%; height: 60px !important; min-width: 1200px;position: fixed;top: 0px;left: 0px;z-index:1000;-moz-box-shadow: 0px 0px 12px rgba(0,0,0,0.1); /* 老的 Firefox */box-shadow: 0px 0px 12px rgba(0,0,0,0.1);}
.newHeader{
/*overflow:hidden;*/
/*text-overflow:ellipsis;*/
/*white-space:nowrap;*/
background: #24292D !important; width:100%; height: 60px !important; min-width: 1200px;position: fixed;top: 0px;left: 0px;z-index:1000;-moz-box-shadow: 0px 0px 12px rgba(0,0,0,0.1); /* 老的 Firefox */box-shadow: 0px 0px 12px rgba(0,0,0,0.1);
}
.newHeader .logoimg{
margin-top: 16px;
float: left;
width: 97px;}
.head-nav{float: left;width:830px;text-align: center;height: 60px;box-sizing: border-box; min-width: 400px;}
.head-nav{
float: left;
text-align: center;
height: 60px;
box-sizing: border-box;
min-width: 785px;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.head-nav ul#header-nav{position: absolute;top: 0px;z-index: 3;height: 60px;box-sizing: border-box;}
.head-nav ul#header-nav li{float: left;height: 60px;line-height: 60px;margin-right: 30px;cursor: pointer;position: relative;font-size: 16px}
.head-nav ul#header-nav li a{display: block;height: 100%;width: 100%;color: #fff}

Loading…
Cancel
Save