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 class Member < ApplicationRecord
has_many :member_roles, dependent: :destroy belongs_to :user
belongs_to :course, optional: true belongs_to :course, optional: true
belongs_to :project, optional: true belongs_to :project, optional: true
belongs_to :user
has_many :member_roles, dependent: :destroy
has_many :roles, through: :member_roles
end end

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

@ -1,9 +1,12 @@
class Project < ApplicationRecord class Project < ApplicationRecord
belongs_to :owner, class_name: 'User', foreign_key: :user_id belongs_to :owner, class_name: 'User', foreign_key: :user_id
has_many :members has_many :members
has_many :manager_members, -> { joins(:roles).where(roles: { name: 'Manager' }) }, class_name: 'Member'
has_one :project_score, dependent: :destroy has_one :project_score, dependent: :destroy
has_many :issues has_many :issues
has_many :user_grades, dependent: :destroy
# 创建者 # 创建者
def creator 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 private
def check_searchable_dependents 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 # reindex shixun
created_shixuns.each(&:reindex) created_shixuns.each(&:reindex)

@ -128,6 +128,9 @@ class User < ApplicationRecord
has_many :bidding_users, dependent: :destroy has_many :bidding_users, dependent: :destroy
has_many :bidden_project_packages, through: :bidding_users, source: :project_package has_many :bidden_project_packages, through: :bidding_users, source: :project_package
# 项目
has_many :applied_projects, dependent: :destroy
# Groups and active users # Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) } 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, fragment_size: EduSetting.get('es_highlight_fragment_size') || 30,
tag: '<span class="highlight">', tag: '<span class="highlight">',
fields: { fields: {
name: { type: 'plain' },
challenge_names: { type: 'plain' }, challenge_names: { type: 'plain' },
challenge_tag_names: { type: 'plain' }, challenge_tag_names: { type: 'plain' },
description: { 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 end
resources :libraries, only: [:index, :show, :create, :update, :destroy] resources :libraries, only: [:index, :show, :create, :update, :destroy]
scope module: :projects do
resources :applied_projects, only: [:create]
end
end end
#git 认证回调 #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*/ /*头部导航条样式---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{ .newHeader .logoimg{
margin-top: 16px; margin-top: 16px;
float: left; float: left;
width: 97px;} 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{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{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} .head-nav ul#header-nav li a{display: block;height: 100%;width: 100%;color: #fff}

@ -87,7 +87,7 @@
</noscript> </noscript>
<!--用于markdown转html --> <!--用于markdown转html -->
<div id="md_div" style="display: none;"></div> <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">-->
<!--<div class="d2-home__main">--> <!--<div class="d2-home__main">-->
<!--&lt;!&ndash;<img class="d2-home__loading"&ndash;&gt;--> <!--&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.trustie.net"
// proxy = "http://testbdweb.educoder.net" // proxy = "http://testbdweb.educoder.net"
// proxy = "https://testeduplus2.educoder.net" // proxy = "https://testeduplus2.educoder.net"
proxy="http://47.96.87.25:48080" proxy="http://47.96.87.25:48080/"
// 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求 // 在这里使用requestMap控制避免用户通过双击等操作发出重复的请求

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

@ -400,7 +400,12 @@ class CommonWorkList extends Component{
componentDidMount() { componentDidMount() {
this.fetchList() this.fetchList()
on('commonwork_fetch_all', this.fetchAllListener) 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() { componentWillUnmount() {
@ -767,7 +772,7 @@ class CommonWorkList extends Component{
<div className="mh650 edu-back-white"> <div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <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> </div>
</div> </div>

@ -52,7 +52,7 @@ class Exercisetablesmubus extends Component {
dataIndex: 'commit_percent', dataIndex: 'commit_percent',
key: 'commit_percent', key: 'commit_percent',
render: (text, record, index) => { 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" && {text.value!="有效填写量"&&text.value!="wrong" &&
<MarkdownToHtml content={text.value} selector={(tableNum+1) + '' + (index+1)}></MarkdownToHtml> <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"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" <img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/> src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p> <p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>
@ -2630,7 +2630,7 @@ class Studentshavecompletedthelist extends Component {
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" <img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/> src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p> <p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>
@ -2692,7 +2692,7 @@ class Studentshavecompletedthelist extends Component {
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" <img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/> src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p> <p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>

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

@ -190,7 +190,7 @@ export default ImageLayerOfCommentHOC() (GraduationTasksappraiseReply);
{/*className="edu-tab-con-box clearfix edu-txt-center">*/} {/*className="edu-tab-con-box clearfix edu-txt-center">*/}
{/*<img className="edu-nodata-img mb20"*/} {/*<img className="edu-nodata-img mb20"*/}
{/*src={getImageUrl("images/educoder/nodata.png")}/>*/} {/*src={getImageUrl("images/educoder/nodata.png")}/>*/}
{/*<p className="edu-nodata-p mb30">没有数据可以显示</p>*/} {/*<p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>*/}
{/*</div>*/} {/*</div>*/}
{/*</div>*/} {/*</div>*/}
{/*</div>*/} {/*</div>*/}

@ -1307,7 +1307,7 @@ class GraduationTaskssettinglist extends Component{
<div className="mh650 edu-back-white"> <div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <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> </div>
@ -1573,7 +1573,7 @@ class GraduationTaskssettinglist extends Component{
className="edu-tab-con-box clearfix edu-txt-center"> className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" <img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/> src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p> <p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>

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

@ -2528,7 +2528,7 @@ class Listofworksstudentone extends Component {
<div className="mh650 edu-back-white"> <div className="mh650 edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <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> </div>
@ -2747,7 +2747,7 @@ class Listofworksstudentone extends Component {
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" <img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/> src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p> <p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>
@ -2945,7 +2945,7 @@ class Listofworksstudentone extends Component {
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" <img className="edu-nodata-img mb20"
src={getImageUrl("images/educoder/nodata.png")}/> src={getImageUrl("images/educoder/nodata.png")}/>
<p className="edu-nodata-p mb30">没有数据可以显示</p> <p className="edu-nodata-p mb30">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>

@ -258,7 +258,7 @@ class ShixunWorkModal extends Component{
<div className=" edu-back-white"> <div className=" edu-back-white">
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <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> </div>

@ -31,7 +31,7 @@ class MemoList extends Component {
{!memo_list || memo_list.length === 0 ? {!memo_list || memo_list.length === 0 ?
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <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>
: renderMemoList() : renderMemoList()
} }

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

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

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

@ -649,10 +649,22 @@ submittojoinclass=(value)=>{
{...this.state} {...this.state}
{...this.props} {...this.props}
/>:""} />:""}
<a href="/" className={" fl"}> <a href="/" className={"fl mr60 ml25"}>
<img alt="高校智能化教学与实训平台" className="logoimg" src={getImageUrl("images/educoder/headNavLogo.png?1526520218")}></img> <img alt="高校智能化教学与实训平台" className="logoimg" src={getImageUrl("images/educoder/headNavLogo.png?1526520218")}></img>
</a> </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 %>*/} {/*<%= link_to image_tag("/images/educoder/logo.png", alt:"高校智能化教学与实训平台", className:"logoimg"), home_path %>*/}
<div className="head-nav pr"> <div className="head-nav pr">
@ -711,6 +723,10 @@ submittojoinclass=(value)=>{
><a href={this.props.Headertop===undefined?"":this.props.Headertop.auth}>工程认证</a></li> ><a href={this.props.Headertop===undefined?"":this.props.Headertop.auth}>工程认证</a></li>
</ul> </ul>
</div>
</div>
<style> <style>
{ {
` `
@ -719,8 +735,8 @@ submittojoinclass=(value)=>{
position: absolute; position: absolute;
top: -2px; top: -2px;
background: #fff; background: #fff;
z-index: 2; z-index:10000;
right: -241px; right: 185px;
} }
` `
} }
@ -769,24 +785,22 @@ submittojoinclass=(value)=>{
</div> </div>
</div> </div>
</div>
{/*<span className="font-15 fr mt17"> {/*<span className="font-15 fr mt17">
<%= link_to '登录', signin_path, :className => "mr5" %> <%= link_to '登录', signin_path, :className => "mr5" %>
<em className="vertical-line"></em> <em className="vertical-line"></em>
<%= link_to '注册', user_join_path, :className => "ml5" %> <%= link_to '注册', user_join_path, :className => "ml5" %>
</span>*/} </span>*/}
{ user===undefined? { 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> <a onClick={()=>this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em> <em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a> <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> <a onClick={()=>this.educoderlogin()} className="mr5 color-white">登录</a>
<em className="vertical-line"></em> <em className="vertical-line"></em>
<a href={"/register"} className="mr5 color-white">注册</a> <a href={"/register"} className="mr5 color-white">注册</a>
</span>: </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"> <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" <img alt="头像" className="radius mt13" height="34" id="nh_user_logo" name="avatar_image"
src={getImageUrl(`images/`+user.image_url)} width="34"> src={getImageUrl(`images/`+user.image_url)} width="34">
@ -814,7 +828,7 @@ submittojoinclass=(value)=>{
</div> </div>
} }
{/*href="https://www.educoder.net/login"*/} {/*href="https://www.educoder.net/login"*/}
<div className="fr head-right "> <div className="fr head-right">
{/*{ loadHeader()}*/} {/*{ loadHeader()}*/}
{showSearchOpentype===true?"":<a id="search-open" className="fl mr30 headIcon" onClick={(e)=>this.showSearchOpen(e)}> {showSearchOpentype===true?"":<a id="search-open" className="fl mr30 headIcon" onClick={(e)=>this.showSearchOpen(e)}>
{/*"/images/educoder/icon/search.svg" {/*"/images/educoder/icon/search.svg"
@ -852,7 +866,7 @@ submittojoinclass=(value)=>{
{/* /courses/join_course_multi_role */} {/* /courses/join_course_multi_role */}
{/*<li>*/} {/*<li>*/}
{/* <a onClick={this.tojoinitem}>加入项目</a>*/} <a onClick={this.tojoinitem}>加入项目</a>
{/*</li>*/} {/*</li>*/}
<Modal <Modal
keyboard={false} keyboard={false}
@ -949,7 +963,7 @@ submittojoinclass=(value)=>{
</Modal> </Modal>
</div> </div>
</div>
</div> </div>
); );

@ -201,3 +201,11 @@ body>.-task-title {
.HeaderSearch{ .HeaderSearch{
width: 325px; 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 = getUrl()
let _url_origin=''; let _url_origin='';
if(window.location.port === "3007"){ 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`; // let _url_origin=`https://www.educoder.net`;

@ -547,7 +547,7 @@ class LoginRegisterComponent extends Component {
}).catch((error) => { }).catch((error) => {
}) })
} };
//短信验证 //短信验证
SMSverification = () => { SMSverification = () => {
var url = `/accounts/get_verification_code.json`; var url = `/accounts/get_verification_code.json`;
@ -678,60 +678,6 @@ class LoginRegisterComponent extends Component {
} }
//失去焦点判断 //失去焦点判断
inputOnBlur = (e, id) => { 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); this.Emailphonenumberverification(e.target.value, 1);
} }
inputOnBlurzhuche = (e, id) => { inputOnBlurzhuche = (e, id) => {

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

@ -151,7 +151,7 @@ class ChangeHeaderPicModal extends Component{
text-align: center; text-align: center;
width: 120px; width: 120px;
height: 120px; height: 120px;
border: 1px solid #eee; /* border: 1px solid #eee; */
} }
.previewWrap { .previewWrap {
flex-direction: column; 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> : "" 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)=>{ data && data.courses && data.courses.map((item,key)=>{
@ -147,7 +147,7 @@ class InfosCourse extends Component{
{ {
item.can_visited ==false? item.can_visited ==false?
<div className="closeSquare"> <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> <p className="font-14 color-white">非成员不能访问</p>
</div>:"" </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>:"" 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)=>{ 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>:"" <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)=>{ data && data.projects && data.projects.map((item,key)=>{
@ -142,7 +142,7 @@ class InfosProject extends Component{
{ {
item.can_visited ==false? item.can_visited ==false?
<div className="closeSquare"> <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> <p className="font-14 color-white">非成员不能访问</p>
</div>:"" </div>:""
} }

@ -161,7 +161,7 @@ class InfosShixun extends Component{
<Create href={"/shixuns/new"} name={"新建实训"} index="2"></Create>:"" <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)=>{ data && data.shixuns && data.shixuns.map((item,key)=>{

@ -164,7 +164,7 @@ class SearchPage extends Component{
<div className="mh650 bjyss"> <div className="mh650 bjyss">
<div className="edu-tab-con-box clearfix edu-txt-center"> <div className="edu-tab-con-box clearfix edu-txt-center">
<img className="edu-nodata-img mb20" src={getImageUrl("images/educoder/nodata.png")}/> <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> </div>

@ -1,11 +1,25 @@
/*--------------------------首页*/ /*--------------------------首页*/
/*头部导航条样式---2018-03-19--by-cs*/ /*头部导航条样式---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{ .newHeader .logoimg{
margin-top: 16px; margin-top: 16px;
float: left; float: left;
width: 97px;} 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{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{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} .head-nav ul#header-nav li a{display: block;height: 100%;width: 100%;color: #fff}

Loading…
Cancel
Save