Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

issues25489
杨树林 5 years ago
commit 51bdfbb941

@ -6,6 +6,7 @@ class Admins::BaseController < ApplicationController
layout 'admin'
skip_before_action :verify_authenticity_token
skip_before_action :setup_laboratory
before_action :require_login, :require_admin!

@ -6,6 +6,16 @@ class Admins::CompetitionPrizeUsersController < Admins::BaseController
include_class = [:competition_team, :competition_prize, :approver,
user: [:process_real_name_apply, :process_professional_apply, user_extension: :school]]
@prize_users = paginate(prize_users.preload(include_class))
respond_to do |format|
format.js
format.html
format.xlsx do
@all_prize_users = prize_users
filename = "#{@competition.name}竞赛获奖人信息列表_#{Time.current.strftime('%Y%m%d%H%M%S')}.xlsx"
render xlsx: 'index', filename: filename
end
end
end
def create

@ -12,10 +12,6 @@ class Admins::EnrollListsController < Admins::BaseController
respond_to do |format|
format.js
format.html
format.xls{
filename = "#{@competition.name}竞赛报名列表_#{Time.now.strftime('%Y-%m-%d %H:%M:%S')}.xls"
send_data(shixun_list_xls(shixuns), :type => 'application/octet-stream', :filename => filename_for_content_disposition(filename))
}
end
end

@ -1,7 +1,6 @@
class Admins::LaboratoriesController < Admins::BaseController
def index
params[:sort_by] = params[:sort_by].presence || 'id'
params[:sort_direction] = params[:sort_direction].presence || 'desc'
default_sort('id', 'desc')
laboratories = Admins::LaboratoryQuery.call(params)
@laboratories = paginate laboratories.preload(:school, :laboratory_users)

@ -288,11 +288,11 @@ class CoursesController < ApplicationController
inform = @course.informs.find_by(id: params[:inform_id])
next_inform = inform.next_inform
ActiveRecord::Base.transaction do
if next_inform
if next_inform.blank?
render_error('已经到达最顶部')
else
inform.update_attribute(:position, (position + 1))
next_inform.update_attribute(:position, last_inform.position - 1)
inform.update_attribute(:position, (inform.position + 1))
next_inform.update_attribute(:position, inform.position - 1)
render_ok
end
end
@ -302,11 +302,11 @@ class CoursesController < ApplicationController
inform = @course.informs.find_by(id: params[:inform_id])
last_inform = inform.last_inform
ActiveRecord::Base.transaction do
if last_inform
if last_inform.blank?
render_error('已经到达最底部')
else
inform.update_attribute(:position, (position - 1))
last_inform.update_attribute(:position, last_inform.position + 1)
inform.update_attribute(:position, (inform.position - 1))
last_inform.update_attribute(:position, inform.position + 1)
render_ok
end
end
@ -317,7 +317,7 @@ class CoursesController < ApplicationController
inform = Inform.new(container: @course)
inform.name = params[:name]
inform.description = params[:description]
inform.position = @course.informs.maximum(:position) + 1
inform.position = @course.informs.maximum(:position).to_i + 1
inform.save!
normal_status("创建成功")
end

@ -26,13 +26,28 @@ class HomeController < ApplicationController
@rep_list << {rep_id: rep.id, rep_name: rep.name, sub_rep_list: sub_rep_list}
end
@shixuns = Shixun.where(homepage_show: 1).includes(:tag_repertoires, :challenges).limit(8)
shixuns = current_laboratory.shixuns
subjects = current_laboratory.subjects
if current_laboratory.main_site?
shixuns = shixuns.where(homepage_show: true)
subjects = subjects.where(homepage_show: true)
else
shixuns = shixuns.where(laboratory_shixuns: { homepage: true })
subjects = subjects.where(laboratory_subjects: { homepage: true })
end
@shixuns = shixuns.includes(:tag_repertoires, :challenges).limit(8)
@subjects = subjects.includes(:repertoire, :shixuns).limit(8)
@subjects = Subject.where(homepage_show: 1).includes(:shixuns, :repertoire).limit(8)
@main_shixuns = Shixun.where(homepage_show: true).includes(:tag_repertoires, :challenges).limit(8)
@main_subjects = Subject.where(homepage_show: true).includes(:shixuns, :repertoire).limit(8)
if current_laboratory.main_site?
@tea_users = User.where(homepage_teacher: 1).includes(:user_extension).limit(10).order("experience desc")
@stu_users = User.where(is_test: 0).includes(:user_extension).where(user_extensions: {identity: 1}).limit(10).order("experience desc")
end
end
def search
@fuzzy_searchs = params[:keyword].split(" ").join("%")

@ -103,11 +103,14 @@ class MessagesController < ApplicationController
return normal_status(403, "您没有权限进行该操作") if current_user != @message.author && !current_user.teacher_of_course?(@message.board.course)
begin
h = {is_md: true}
email_notify = @message.email_notify ? 1 : @board.course.email_notify && params[:email_notify]
send_email = !@message.email_notify && email_notify
h = {is_md: true, email_notify: email_notify}
m_params = message_params.merge(h)
@message.update_attributes(m_params)
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
@message.update_content(params[:content])
notify_course_students(@message, @board.course) if send_email
rescue Exception => e
uid_logger_error(e.message)
tip_exception("修改失败")
@ -123,6 +126,7 @@ class MessagesController < ApplicationController
@message.author = current_user
@message.board_id = params[:select_board_id]
@message.message_detail_attributes = {content: params[:content]}
@message.email_notify = @board.course.email_notify && params[:email_notify] ? 1 : 0
@message.save!
Attachment.associate_container(params[:attachment_ids], @message.id, @message.class.name)
if @board.course.email_notify && params[:email_notify]
@ -189,7 +193,7 @@ class MessagesController < ApplicationController
private
def validate_sort_type
normal_status(2, "参数sort_tyope暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
normal_status(2, "参数sort_type暂时只支持 'time', 'hot'两种") if params.has_key?(:sort_type) && !SORT_TYPE.include?(params[:sort_type].strip)
end
def find_message
@ -207,7 +211,7 @@ class MessagesController < ApplicationController
def notify_course_students message, course
course.students.includes(:user).each do |student|
UserMailer.course_message_email(student&.user&.mail, message.id).deliver_now if student&.user&.mail
UserMailer.course_message_email(student&.user&.mail, message.id).deliver_later if student&.user&.mail
end
end
end

@ -35,6 +35,11 @@ class ShixunsController < ApplicationController
Shixun.unhidden
end
## 云上实验室过滤
unless current_laboratory.main_site?
@shixuns = @shixuns.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: current_laboratory.id })
end
## 方向
if params[:tag_level].present? && params[:tag_id].present?
@shixuns = @shixuns.filter_tag(params[:tag_level].to_i, params[:tag_id].to_i)

@ -23,16 +23,17 @@ class SubjectsController < ApplicationController
# 最热排序
if reorder == "myshixun_count"
laboratory_join = current_laboratory.main_site? ? '' : " JOIN laboratory_subjects ls ON ls.subject_id = subjects.id AND ls.laboratory_id = #{current_laboratory.id} "
if select
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id #{laboratory_join} where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
AND subjects.repertoire_id = #{select} GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
else
@subjects = Subject.find_by_sql("SELECT subjects.id, subjects.user_id, subjects.name, subjects.stages_count, subjects.repertoire_id, subjects.status,
subjects.shixuns_count, subjects.excellent, sum(shixuns.myshixuns_count) AS myshixun_member_count FROM subjects join stage_shixuns
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id where
on stage_shixuns.subject_id = subjects.id join shixuns on shixuns.id = stage_shixuns.shixun_id #{laboratory_join} where
subjects.hidden = 0 AND subjects.status = 2 AND subjects.name like '%#{search}%'
GROUP BY subjects.id ORDER BY myshixun_member_count DESC")
end
@ -52,6 +53,11 @@ class SubjectsController < ApplicationController
@subjects = Subject.visible.unhidden
end
# 云上实验室过滤
unless current_laboratory.main_site?
@subjects = @subjects.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: current_laboratory.id })
end
# 类型
if select
@subjects = @subjects.where(repertoire_id: select)

@ -12,6 +12,6 @@ class UserMailer < ApplicationMailer
def course_message_email(mail, message_id)
@message = Message.find_by(id: message_id)
@course = @message&.board&.course
mail(to: mail, subject: '课堂通知') if @message.present? && @course.present?
mail(to: mail, subject: '课堂发布了新的帖子') if @message.present? && @course.present?
end
end

@ -7,11 +7,11 @@ class Inform < ApplicationRecord
has_many :attachments, as: :container, dependent: :destroy
def next_inform
Inform.where(position: self.position+1, container_id: self.container_id, container_type: self.container_type)
Inform.find_by(position: self.position+1, container_id: self.container_id, container_type: self.container_type)
end
def last_inform
Inform.where(position: self.position-1, container_id: self.container_id, container_type: self.container_type)
Inform.find_by(position: self.position-1, container_id: self.container_id, container_type: self.container_type)
end
end

@ -38,4 +38,17 @@ class Laboratory < ApplicationRecord
def self.current
Thread.current[:current_laboratory] ||= Laboratory.find(1)
end
def shixuns
main_site? ? Shixun.all : Shixun.joins(:laboratory_shixuns).where(laboratory_shixuns: { laboratory_id: id })
end
def subjects
main_site? ? Subject.all : Subject.joins(:laboratory_subjects).where(laboratory_subjects: { laboratory_id: id })
end
# 是否为主站
def main_site?
id == 1
end
end

@ -235,6 +235,28 @@ class User < ApplicationRecord
end
end
# 实名认证状态
def auth_status
status = if authentication
"已认证"
elsif process_real_name_apply.present?
"待审核"
else
"未认证"
end
end
# 职业认证状态
def pro_status
status = if professional_certification
"已认证"
elsif process_professional_apply.present?
"待审核"
else
"未认证"
end
end
# 判断当前用户是否通过职业认证
def pro_certification?
professional_certification

@ -94,8 +94,8 @@ class DuplicateCourseService < ApplicationService
exercise = course.exercises.create!(attrs.merge(user_id: user.id))
origin_exercise.exercise_questions.find_each do |origin_question|
question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score])
question_attrs[:question_type] ||= 1
question_attrs = origin_question.as_json(only: %i[question_title question_type question_number question_score shixun_name shixun_id is_ordered level])
# question_attrs[:question_type] ||= 1
question = exercise.exercise_questions.create!(question_attrs)
exercise_choice_map = {}
@ -103,15 +103,20 @@ class DuplicateCourseService < ApplicationService
choice_attrs = { choice_position: index + 1, choice_text: origin_choice.choice_text }
choice = question.exercise_choices.create!(choice_attrs)
exercise_choice_map[origin_choice.id] = choice.id
# exercise_choice_map[origin_choice.id] = choice.id 标准答案中存的是choice_position, 直接取原题的exercise_choice_id就行
end
origin_question.exercise_standard_answers.find_each do |origin_answer|
question.exercise_standard_answers.create!(
exercise_choice_id: exercise_choice_map[origin_answer.exercise_choice_id],
exercise_choice_id: origin_answer.exercise_choice_id,
answer_text: origin_answer.answer_text
)
end
origin_question.exercise_shixun_challenges.each_with_index do |sc, index|
question.exercise_shixun_challenges.create!({position: index+1, challenge_id: sc.challenge_id,
shixun_id: sc.shixun_id, question_score: sc.question_score})
end
end
origin_exercise.exercise_bank.increment!(:quotes) if exercise.exercise_bank

@ -50,6 +50,12 @@
<%= submit_tag('搜索', class: 'btn btn-primary ml-3', 'data-disable-with': '搜索中...') %>
<%= link_to '清除', admins_competition_competition_prize_users_path(@competition), class: "btn btn-default",'data-disable-with': '清除中...' %>
<% end %>
<div class="mt-3 d-flex align-items-end">
<%= link_to '导出', admins_competition_competition_prize_users_path(competition_id: @competition.id, format: :xlsx), class: 'btn btn-primary' %>
<%#= javascript_void_link '导出', class: 'btn btn-primary', 'data-url': admins_competition_competition_prize_users_path(competition_id: @competition.id, format: :xlsx) %>
</div>
</div>
</div>

@ -0,0 +1,33 @@
wb = xlsx_package.workbook
wb.styles do |s|
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 25,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
wb.add_worksheet(name: "#{@competition.name}证书审批列表") do |sheet|
sheet.add_row %w(序号 排名 奖项 战队ID 战队名称 姓名 职业 学号 学校名称 学院名称 地区 实名认证 职业认证 手机号码 队长 签领/开户行及银行卡号 审批时间 审批人), :height => 25,:style => blue_cell
@all_prize_users.each_with_index do |prize_user, index|
user = prize_user.user
data = [
index + 1,
prize_user.rank,
prize_user.competition_prize.name,
prize_user.competition_team_id,
prize_user.competition_team.name,
user.real_name,
user.identity,
user.student_id,
user.school_name,
user.department_name,
user.location,
user.auth_status,
user.pro_status,
user.phone,
prize_user.leader? ? "是" : "-",
[prize_user.extra&.[]('bank'), prize_user.extra&.[]('second_bank'), prize_user.extra&.[]('card_no')].compact.join('/'),
prize_user.approved_at&.strftime('%Y-%m-%d %H:%M'),
prize_user.approver&.real_name
]
sheet.add_row(data)
end
end
end

@ -3,17 +3,19 @@ json.images_url @images_url
json.reps @rep_list
json.shixuns do
json.partial! 'shixuns/shixun', locals: {shixuns: @shixuns}
json.partial! 'shixuns/shixun', locals: {shixuns: @shixuns.present? ? @shixuns : @main_shixuns}
end
json.subjects do
json.partial! 'subjects/subject', locals: {subjects: @subjects}
json.partial! 'subjects/subject', locals: {subjects: @subjects.present? ? @subjects : @main_subjects}
end
json.teachers do
if current_laboratory.main_site?
json.teachers do
json.partial! 'users/user_small', users: @tea_users
end
end
json.students do
json.students do
json.partial! 'users/user_small', users: @stu_users
end
end

@ -1,2 +1,2 @@
json.extract! message, :id, :parent_id, :subject, :created_on, :total_replies_count, :total_praises_count,
:is_md, :praises_count, :visits, :sticky, :is_hidden, :is_public
:is_md, :praises_count, :visits, :sticky, :is_hidden, :is_public, :email_notify

@ -1,7 +1,7 @@
<html>
<head>
<meta charset="utf-8">
<title><%= @course.name %>通知</title>
<title><%= @course.name %> 发布了新的帖子</title>
<style type="text/css">
/* 验证链接页面 */
body,h1,h2,h3,h4,h5,h6,hr,p,blockquote,dl,dt,dd,ul,ol,li,pre,form,fieldset,legend,button,input,textarea,th,td{ margin:0; padding:0;}
@ -36,22 +36,16 @@
<p style="color:#333; font-size:16px; margin-bottom:15px;font-weight: bold">
您好!
</p>
<p style="color:#333;">
正在注册Educoder请在10分钟内在注册页输入此验证码并进行下一步操作。
如非你本人操作,请忽略此邮件。
<p style="color:#333; ">
参与的课堂:<%= @course.name %>,有新的帖子发布了:
<a href="https://www.educoder.net/courses/<%= @course.id %>/boards/<%= @message.board_id %>/messages/<%= @message.id %>" style="font-weight: normal; color:#ff7500;"><%= @message.subject %></a>
</p>
<div style="text-align: center;">
<div style="display:block; height: 45px; line-height:45px;padding:0 30px; width:100px; font-size: 20px; font-weight: bold; background:#ffd9d9; color:#e72c37; margin:30px auto;">
<p><%= @code %></p>
</div>
<div style="text-align: center; margin-top:40px;">
<span style="font-weight: normal;color:#666;">
此邮件为系统所发,请勿直接回复。<br/>
要解决问题或了解您的帐户详情,您可以访问 <a href="https://www.educoder.net/help?index=5" style="font-weight: normal; color:#ff7500;">帮助中心</a>。
</span>
</div>
<p style="color:#666; margin-top:30px;">
如果您并未发过此请求,则可能是因为其他用户在注册时误输了您的邮件地址,而使您收到了这封邮件,那么您可以放心的忽略此邮件,无需进一步采取任何操作。
</p>
</div>
<div style="padding:20px; color:#333; line-height: 1.9;background:#46484c;border:1px solid #ddd; border-top:none; width: 558px;">
<a href="https:///www.educoder.net/" style="font-weight: normal; color:#fff;">www.educoder.net</a>

@ -0,0 +1,5 @@
class AddEmailNotifyToMessages < ActiveRecord::Migration[5.2]
def change
add_column :messages, :email_notify, :boolean, default: 0
end
end

@ -394,6 +394,7 @@ class ShixunsHome extends Component {
{/*导师排行榜*/}
{ homedatalist !== undefined && homedatalist.teachers !== undefined && (
<div className="pt60 pb60 mb30 mentor-ranking">
<div className="educontent">
<div className="edu-txt-center">
@ -470,8 +471,10 @@ class ShixunsHome extends Component {
</div>
</div>
)}
{/*程序员排行榜*/}
{ homedatalist !== undefined && homedatalist.students !== undefined && (
<div className="pt60 pb60 mb30 pro-ranking">
<div className="educontent">
<div className="edu-txt-center">
@ -544,6 +547,7 @@ class ShixunsHome extends Component {
</div>
</div>
</div>
)}
</div>
</Spin>
</div>

@ -4,10 +4,15 @@
-ms-flex-direction: column;
flex-direction: column;
}
.textright{
text-align: right;
}
.textcenter{
text-align: center;
}
.Osshackathonfont{
width: 80px;
height: 28px;
@ -26,7 +31,7 @@
}
.OsshackathonCard{
width:1200px;
height:150px;
min-height:150px;
background:rgba(248,248,248,1);
border:1px solid rgba(235,235,235,1);
}
@ -67,3 +72,84 @@
.Searchant-btn-primary .ant-input-group .ant-input{
height:42px;
}
.Breadcrumbfont{
color:#4CACFF;
}
.ant-breadcrumb-separator{
color:#BCBCBC;
}
.minheight50px{
min-height: 50px;
}
.borderDEDEDE{
border-left:1px solid #DEDEDE;
}
.pl80pt6{
padding-top: 6px;
padding-left: 80px;
}
.OsshackprimaryButton{
width: 100%;
height: 45px;
}
.OsshackprimaryButtonsyle{
background: rgba(255,255,255,1) !important;
border: 1px solid rgba(76,172,255,1);
color: rgba(76,172,255,1);
line-height: 16px;
border-radius: unset;
box-shadow:none;
}
.h45input input{
height:45px;
}
.width14bai{
width: 14%;
}
.Osshackprimaryfonttop{
font-size: 20px;
color: rgba(5,16,26,1);
text-align: center;
}
.Osshackathonmodelinput{
width: 97% !important;
margin-left: 7px;
}
.Osshackathonmodelinput .ant-input::-webkit-input-placeholder{
color: #999;
font-size: 14px;
}
.Osshackathonmodelinput .ant-input::-moz-placeholder{color: #cccccc;font-size:14px;}
.Osshackathonmodelinput .ant-input::-webkit-input-placeholder{color: #cccccc;font-size:14px;}
.Osshackathonmodelinput .ant-input:-ms-input-placeholder{color: #cccccc;font-size:14px;}
.Osshackathonmodelinput .ant-input-group-addon {
color: #adadad !important;
}
.iscursor{
cursor: pointer;
}
.issignup:hover, .issignup:focus {
color: #fff !important;
background-color: #40a9ff;
border-color: #40a9ff;
}
.Osshackathon-btn-primary .ant-btn-primary:hover, .Osshackathon-btn-primary .ant-btn-primary:focus {
color: #fff !important;
background-color: #40a9ff;
border-color: #40a9ff;
}

@ -1,10 +1,12 @@
import React, {Component} from 'react';
import axios from 'axios';
import {SnackbarHOC, WordsBtn,getImageUrl,markdownToHTML} from 'educoder';
import {Row, Col,Input,Divider,Card,Button} from 'antd';
import {Row, Col,Input,Divider,Card,Button,Pagination,Breadcrumb,Icon,Spin} from 'antd';
import { TPMIndexHOC } from '../tpm/TPMIndexHOC';
import { CNotificationHOC } from '../courses/common/CNotificationHOC';
import Osshackathonmd from './Osshackathonmd';
import './Osshackathon.css';
import Osshackathonmodel from "./Osshackathonmodel";
const { Search } = Input;
class Osshackathon extends Component {
@ -14,16 +16,22 @@ class Osshackathon extends Component {
page:1,
limit:10,
search:undefined,
data:undefined
data:undefined,
hackathonedit:false,
Osshackathonmodeltype:false,
spinning:false,
}
}
componentDidMount() {
this.getosshackathon();
this.getosshackathonlist();
window.document.title = '竞赛报名';
}
getosshackathon=()=>{
let {page,limit,search}=this.state;
getosshackathon=(page,limit,search)=>{
this.setState({
spinning:true
})
let url=`/osshackathon.json`;
axios.get(url,{params:{
page:page,
@ -33,22 +41,150 @@ class Osshackathon extends Component {
if(result.status==200){
console.log(result)
this.setState({
data:result.data
data:result.data,
spinning:false
})
}
}).catch((error)=>{
console.log(error);
this.setState({
spinning:true
})
})
}
getosshackathonlist=()=>{
let {page,limit,search}=this.state;
this.setState({
page:1,
search:undefined
})
this.getosshackathon(1,limit,undefined)
}
componentDidUpdate = (prevProps) => {
}
PaginationTask=(pageNumber)=>{
this.setState({
page:pageNumber
})
let {page,limit,search}=this.state;
this.getosshackathon(pageNumber,limit,search)
}
hackathonedit=(id)=>{
//管理员编辑title
this.setState({
hackathonedit:true
})
}
hidehackathonedit=()=>{
this.setState({
hackathonedit:false
})
}
Signupentry=(id)=>{
// 用户报名
this.props.confirm({
content: `是否确认报名?`,
onOk: () => {
this.Signupentrys(id)
}
})
}
Signupentrys=(id)=>{
let url=`/osshackathon/${id}/entry.json`;
axios.post(url
).then((response) => {
if(response.data.status===0){
this.getosshackathonlist()
this.props.showNotification(`报名成功,预祝您夺得桂冠`);
}
}).catch((error) => {
console.log(error)
})
}
editSignupentry=(id,name,description)=>{
// 管理员编辑项目
this.setState({
Osshackathonmodeltype:true
})
if(id===undefined){
this.setState({
modelid:undefined,
modelname:undefined,
modeldescription:undefined
})
}else{
this.setState({
modelid:id,
modelname:name,
modeldescription:description
})
}
}
hideeditSignupentry=(id)=>{
// 管理员取消项目
this.setState({
Osshackathonmodeltype:false
})
}
delSignupentry=(id)=>{
// 管理员删除项目
this.props.confirm({
content: `是否确认删除该项目?`,
onOk: () => {
this.delSignupentrys(id)
}
})
}
delSignupentrys=(id)=>{
let url=`/osshackathon/${id}.json`;
axios.delete(url)
.then((response) => {
if (response.data.status == 0) {
// {"status":1,"message":"删除成功"}
this.getosshackathonlist()
this.props.showNotification(`删除成功`);
}
})
.catch(function (error) {
console.log(error);
});
}
onsearchvalue=(value)=>{
this.setState({
search:value
})
let {page,limit,search}=this.state;
this.getosshackathon(page,limit,value)
}
onsetsearchvalue=(e)=>{
this.setState({
search:e.target.value
})
}
render() {
let{data}=this.state;
console.log(this.state.data)
let {page,data,hackathonedit}=this.state;
return (
<div className="newMain clearfix newMainybot">
@ -59,6 +195,11 @@ class Osshackathon extends Component {
background: #4CACFF;
border-color: #4CACFF;
}
.ant-btn-primary:hover, .ant-btn-primary:focus {
color: #4CACFF;
background-color: #40a9ff;
border-color: #40a9ff;
}
`
}
</style>
@ -68,16 +209,18 @@ class Osshackathon extends Component {
<div className="registrationback"
style={{"background": `url(${getImageUrl(`images/educoder/competitions/tipregistit.jpg`)})`,"height":"360px"}}
></div>
<Row className={"mt20"}>
<Spin spinning={this.state.spinning}>
{this.props.user&&this.props.user.admin===true?<Row className={"mt20"}>
<Col span={6}>
<Search
className={"Searchant-btn-primary"}
className={"Osshackathon-btn-primary"}
placeholder="请输入项目名称进行搜索"
enterButton="搜索"
size="large"
onSearch={value => console.log(value)}
value={this.state.search}
onInput={(e)=>this.onsetsearchvalue(e)}
onSearch={value => this.onsearchvalue(value)}
/>
</Col>
@ -87,17 +230,17 @@ class Osshackathon extends Component {
</div>
</Col>
</Row>
</Row>:""}
<Row className={"mt20"}>
{hackathonedit===true?"":<Row className={"mt20"}>
<Col span={6} className={"Osshackathonfont"}>
{data&&data.hackathon.name}
</Col>
<Col span={3} className={"fr textright"}>
<Button type="primary">编辑</Button>
</Col>
</Row>
<style>
{this.props.user&&this.props.user.admin===true?<Col span={3} className={"fr textright"}>
<Button type="primary" className={"OsshackprimaryButtonsyle"} onClick={()=>this.hackathonedit(data&&data.hackathon.id)}>编辑</Button>
</Col>:""}
</Row>}
{hackathonedit===true?"": <style>
{
`
.ant-divider-horizontal{
@ -105,59 +248,126 @@ class Osshackathon extends Component {
}
`
}
</style>
</style>}
<Divider />
{hackathonedit===true?"":<Divider />}
<p className={"Osshackathonfontlist mb30"}>
{hackathonedit===true?"":<p className={"Osshackathonfontlist mb30"}>
{data&&data.hackathon.description===null?"":<div className={"markdown-body"}
dangerouslySetInnerHTML={{__html: markdownToHTML(data&&data.hackathon.description).replace(/▁/g, "▁▁▁")}}></div>}
</p>
</p>}
{hackathonedit===true?<Osshackathonmd
getosshackathon={()=>this.getosshackathonlist()}
hidehackathonedit={()=>this.hidehackathonedit()}
{...this.props}
{...this.state}
/>:""}
{this.state.Osshackathonmodeltype===true?<Osshackathonmodel
getosshackathon={()=>this.getosshackathonlist()}
hideeditSignupentry={()=>this.hideeditSignupentry()}
{...this.props}
{...this.state}
/>:""}
{this.props.user&&this.props.user.admin===true?<Row className={"mb20"}>
<Col span={8}></Col>
<Col span={8}><Button type="primary" className={"OsshackprimaryButton OsshackprimaryButtonsyle"} onClick={()=>this.editSignupentry()}><Icon type="plus" />新建项目</Button></Col>
<Col span={8}></Col>
</Row>:""}
{/*学生身份*/}
{
data&&data.hacks.length==0?"":data&&data.hacks.map((item,key)=>{
this.props.user&&this.props.user.admin===false?data&&data.hacks.length==0?"":data&&data.hacks.map((item,key)=>{
return(
<span></span>
)
})
}
{/*学生身份*/}
<Card className={"OsshackathonCard mb20"}>
<Card className={"OsshackathonCard mb20"} key={key}>
<Row>
<Col span={6} className={"OsshackathonCardtitle"}>
大赛介绍
{item.name}
</Col>
<Col span={6} className={"fr textright"}>
<Button type="primary fr ">立即报名</Button>
<Button type="primary fr mr20" disabled>
{item.entry_info===true?<Button type="primary fr mr20" disabled>
已报名
</Button>
</Button>:<Button type="primary fr issignup" onClick={()=>this.Signupentry(item.id)}></Button>}
</Col>
</Row>
<p>Card content</p>
<p>Card content</p>
<p className={"mt20"}>{item.description}</p>
</Card>
)
}):""
}
{/*教师身份*/}
<Card className={"OsshackathonCard"}>
{/*教师身份*/}
{this.props.user&&this.props.user.admin===true?<style>
{
`
.ant-col-pull-6 {
right: 17%;
}
.ant-col-18 {
width: 82%;
}
.CompetitionsIndexbottomvalue{
text-align: center;
}
`
}
</style>:""}
{
this.props.user&&this.props.user.admin===true?data&&data.hacks.length==0?"":data&&data.hacks.map((item,key)=>{
return(
<Card className={"OsshackathonCard mb20"}>
<Row>
<Col span={6} className={"OsshackathonCardtitle"}>
大赛介绍
{item.name}
</Col>
<Col span={6} className={"fr textright"}>
<Button type="primary fr ">立即报名</Button>
<Button type="primary fr mr20" disabled>
已报名
</Button>
<Col span={4} className={"fr textcenter width14bai"}>
<Breadcrumb separator="">
<Breadcrumb.Item className={"Breadcrumbfont iscursor"} onClick={()=>this.editSignupentry(item.id,item.name,item.description)}>编辑</Breadcrumb.Item>
<Breadcrumb.Item className={"Breadcrumbfont iscursor"} onClick={()=>this.delSignupentry(item.id)}>删除</Breadcrumb.Item>
</Breadcrumb>
</Col>
</Row>
<p>Card content</p>
<p>Card content</p>
<Row className={"mt20"}>
<Col span={4} push={20} className={"minheight50px borderDEDEDE"}>
<div className={"pl80pt6"}>
<Row gutter={16}>
<Col className="gutter-row" span={15}>
<div className="gutter-box Osshackprimaryfonttop">{item.hack_users_count}</div>
</Col>
</Row>
<Row gutter={16}>
<Col className="gutter-row" span={15}>
<div className="gutter-box CompetitionsIndexbottomvalue">报名数</div>
</Col>
</Row>
</div>
</Col>
<Col span={18} pull={6} className={"minheight50px "}>
{item.description}
</Col>
</Row>
</Card>
)}):""
}
{data&&data.hacks_count>10?data&&data.hacks.length===0?"":<div className="mb40 edu-txt-center padding20-30" >
<Pagination
showQuickJumper
defaultCurrent={1}
pageSize={10}
total={data&&data.hacks_count}
current={page}
onChange={this.PaginationTask}
/>
</div>:""}
</Spin>
</div>
</div>

@ -0,0 +1,111 @@
import React, { Component } from 'react';
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs,Form,Input} from 'antd';
import axios from 'axios';
import {getImageUrl,getUrl} from 'educoder';
import TPMMDEditor from '../tpm/challengesnew/TPMMDEditor';
class Osshackathonmd extends Component{
constructor(props) {
super(props)
this.contentMdRef = React.createRef();
this.state={
title_num: 0,
title_value: undefined
}
}
componentDidUpdate =(prevState)=>{
// if(prevState!=this.props){
// let url=`/osshackathon/edit_hackathon.json`;
// axios.get(url).then((result)=>{
// if(result.status==200){
// this.setState({
// title_value:result.data.name
// })
// this.contentMdRef.current.setValue(result.data.description);
// }
// })
// }
}
componentDidMount(){
let url=`/osshackathon/edit_hackathon.json`;
axios.get(url).then((result)=>{
if(result.status==200){
this.setState({
title_value:result.data.name
})
this.contentMdRef.current.setValue(result.data.description);
}
})
}
// 输入title
changeTitle = (e) => {
// title_num: 60 - parseInt(e.target.value.length),
this.setState({
title_num: e.target.value.length,
title_value: e.target.value
})
}
handleSubmit = () => {
let {title_value}=this.state;
const mdContnet = this.contentMdRef.current.getValue().trim();
// if(mdContnet.length>10000){
// this.props.showNotification("内容超过10000个字");
// return
// }
let url=`/osshackathon/update_hackathon.json`;
axios.post(url,{
name:title_value,
description:mdContnet,
}
).then((response) => {
if(response.data.status===0){
this.props.getosshackathon()
this.props.hidehackathonedit()
this.props.showNotification(`提交成功`);
}
}).catch((error) => {
console.log(error)
})
}
render() {
// console.log(this.props.tabkey)
// console.log(chart_rules)
return (
<div className={"mt20"}>
<Form>
<Form.Item label="标题">
<Input placeholder="请输入标题"
value={this.state.title_value}
onInput={this.changeTitle}
className="searchView searchViewAfter h45input" style={{"width": "100%"}} maxLength="60"
addonAfter={String(this.state.title_value===undefined?0:this.state.title_value.length)+"/60"}
/>
</Form.Item>
<Form.Item label="描述">
<TPMMDEditor ref={this.contentMdRef} placeholder="请输入描述" mdID={'courseContentMD'} refreshTimeout={1500}
className="courseMessageMD" initValue={this.state.description}></TPMMDEditor>
</Form.Item>
</Form>
<div className="clearfix mt30 mb30">
<div className={"fr"}>
<Button type="primary" onClick={this.handleSubmit} className="defalutSubmitbtn fl mr20">提交</Button>
<a className="defalutCancelbtn fl" onClick={() => this.props.hidehackathonedit()}>取消</ a>
</div>
</div>
</div>
)
}
}
export default Osshackathonmd;

@ -0,0 +1,217 @@
import React, { Component } from 'react';
import {Button, Card, Row, Col ,Upload,Icon,message,Tabs,Form,Input,Modal} from 'antd';
import axios from 'axios';
import {getImageUrl,getUrl,WordNumberTextarea} from 'educoder';
class Osshackathonmodel extends Component{
constructor(props) {
super(props)
this.state={
title_num: 0,
title_value: undefined,
Textarea_comment:undefined
}
}
componentDidUpdate =(prevState)=>{
// if(prevState!=this.props){
// let name=this.props&&this.props.modelname;
// let mdvalue=this.props&&this.props.modeldescription;
// this.setState({
// title_value:name,
// Textarea_comment:mdvalue
// })
// }
}
componentDidMount(){
if(this.props.modelid===undefined){
this.setState({
title_value:undefined,
Textarea_comment:undefined
})
}else{
let url=`/osshackathon/${this.props.modelid}/edit.json`;
axios.get(url).then((result)=>{
if(result.status==200){
this.setState({
title_value:result.data.name,
Textarea_comment:result.data.description
})
}
})
}
}
handleSubmit = () => {
let {title_value,Textarea_comment}=this.state;
// if(mdContnet.length>10000){
// this.props.showNotification("内容超过10000个字");
// return
// }
//
if(this.props.modelid===undefined){
let url=`/osshackathon.json`;
axios.post(url,{
name:title_value,
description:Textarea_comment,
}
).then((response) => {
if(response.data.status===0){
this.props.getosshackathon()
this.props.hideeditSignupentry()
this.props.showNotification(`提交成功`);
}
}).catch((error) => {
console.log(error)
})
}else{
let url=`/osshackathon/${this.props.modelid}.json`
axios.put(url,{
name:title_value,
description:Textarea_comment,
}
).then((response) => {
if(response.data.status===0){
this.props.getosshackathon()
this.props.hideeditSignupentry()
this.props.showNotification(`提交成功`);
}
}).catch((error) => {
console.log(error)
})
}
}
changeTitle=(e)=>{
this.setState({
title_value:e.target.value,
title_num:e.target.value.length,
})
}
Textarea_comment=(e)=>{
this.setState({
Textarea_comment:e.target.value,
})
}
render() {
let {textareavaltype}=this.state;
// console.log(this.props.tabkey)
console.log(this.props.Osshackathonmodeltype)
return (
<div>
<style>
{
`
@media (max-width: 2000px) {
.WordNumberTextarea{
height: 130px !important;
}
}
@media (max-width: 1350px) {
.HomeworkModal{
top:10px !important;
}
.WordNumberTextarea{
height: 80px !important;
}
}
@media (max-width: 1250px) {
.HomeworkModal{
top:0px !important;
}
.WordNumberTextarea{
height: 40px !important;
}
}
`
}
</style>
<Modal
keyboard={false}
className={"HomeworkModal"}
title={"新建项目"}
visible={this.props.Osshackathonmodeltype}
closable={false}
footer={null}
destroyOnClose={true}
>
<div className={"pd015"}>
<style>
{
`
.pd015{
padding: 0px 15px 15px 15px;
}
.font{
font-size: 14px;
font-weight: 400;
color: rgba(5,16,26,1);
}
.newfont{
height: 16px;
font-size: 16px;
font-weight: 400;
color: rgba(5,16,26,1);
line-height: 16px;
margin-bottom: 5px;
}
.Osshackathonmodelinput .ant-input, .ant-input .ant-input-suffix{
background: #fff !important;
}
.Osshackathonmodelinput .ant-input-group-wrapper{
width:510px !important;
margin-left: 10px;
}
`
}
</style>
<div className="clearfix">
<p className={"font mt10 mb10 ml10"}>
名称
</p>
<Input placeholder="请输入项目名称"
value={this.state.title_value}
onInput={(e)=>this.changeTitle(e)}
className={"Osshackathonmodelinput"}
style={{"width": "100%"}} maxLength="60"
addonAfter={String(this.state.title_value===undefined?0:this.state.title_value.length)+"/60"}
/>
<p className={"font mt10 mb10 ml10"}>
描述
</p>
<WordNumberTextarea
placeholder={"请输入项目描述"}
onInput={(e)=>this.Textarea_comment(e)}
value={this.state.Textarea_comment}
maxlength={500}
/>
<li style={{height:"20px",lineHeight:"20px"}} className={textareavaltype===true?"color-red mt20 mb10":"none"}><span>评阅内容至少有一个不为空</span></li>
</div>
<div className={textareavaltype===false?"mt20 clearfix edu-txt-center":"clearfix edu-txt-center mt20"}>
<a className="task-btn color-white mr30" onClick={()=>this.props.hideeditSignupentry()}>取消</a>
<a className="task-btn task-btn-orange" onClick={()=>this.handleSubmit()}>确定</a>
</div>
</div>
</Modal>
</div>
)
}
}
export default Osshackathonmodel;
Loading…
Cancel
Save