Merge branches 'dev_aliyun' and 'develop' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_forum
杨树明 5 years ago
commit c1505d1e1f

@ -230,13 +230,18 @@ class ChallengesController < ApplicationController
def crud_answer def crud_answer
raise '参考答案不能为空' if params[:challenge_answer].empty? raise '参考答案不能为空' if params[:challenge_answer].empty?
raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100 raise '占比之和必须为100%' if params[:challenge_answer].map{|a| a[:score]}.sum != 100
ActiveRecord::Base.transaction do
@challenge.challenge_answers.destroy_all if @challenge.challenge_answers @challenge.challenge_answers.destroy_all if @challenge.challenge_answers
params[:challenge_answer].each_with_index do |answer, index| params[:challenge_answer].each_with_index do |answer, index|
# 内容为空不保存
next if answer[:contents].blank?
ChallengeAnswer.create(name: answer[:name], contents: answer[:contents], ChallengeAnswer.create(name: answer[:name], contents: answer[:contents],
level: index+1, score: answer[:score], challenge_id: @challenge.id) level: index+1, score: answer[:score], challenge_id: @challenge.id)
end end
end end
end
# 查看参考答案接口 # 查看参考答案接口
def answer def answer
@answers = @challenge.challenge_answers @answers = @challenge.challenge_answers

@ -315,7 +315,7 @@ class CoursesController < ApplicationController
# @users = User.where.not(id: user_ids_of_course_members) # @users = User.where.not(id: user_ids_of_course_members)
@users = User.where(status: User::STATUS_ACTIVE) @users = User.where(status: User::STATUS_ACTIVE)
@users = @users.where("concat(users.firstname, users.lastname) like '%#{name}%'") if name.present? @users = @users.where("concat(users.lastname, users.firstname) like '%#{name}%'") if name.present?
# REDO:Extension # REDO:Extension
@users = @users.joins(user_extension: :school).where("schools.name like '%#{school_name}%'") if school_name.present? @users = @users.joins(user_extension: :school).where("schools.name like '%#{school_name}%'") if school_name.present?

@ -1597,7 +1597,7 @@ class HomeworkCommonsController < ApplicationController
att = attachment.copy att = attachment.copy
att.author_id = homework_bank.user_id att.author_id = homework_bank.user_id
att.copy_from = attachment.id att.copy_from = attachment.id
att.attachtype = attachment.attachtype att.attachtype = attachment.attachtype || 1
homework_bank.attachments << att homework_bank.attachments << att
end end
homework_bank homework_bank

@ -154,7 +154,7 @@ class QuestionBanksController < ApplicationController
att.container_id = nil att.container_id = nil
att.container_type = nil att.container_type = nil
att.author_id = homework.user_id att.author_id = homework.user_id
att.attachtype = attachment.attachtype att.attachtype = attachment.attachtype || 1
# att.attachtype = 1 # att.attachtype = 1
att.copy_from = attachment.id att.copy_from = attachment.id
att.save! att.save!

@ -0,0 +1,17 @@
class Users::ProjectPackagesController < Users::BaseController
def index
packages = Users::ProjectPackageService.call(observed_user, query_params)
@count = packages.count
@packages = paginate(packages.includes(:project_package_category))
bidding_users = BiddingUser.where(project_package_id: @packages.map(&:id), user_id: observed_user.id)
bidding_users = bidding_users.group(:project_package_id).select(:project_package_id, :status)
@bidding_status_map = bidding_users.each_with_object({}) { |u, h| h[u.project_package_id] = u.status }
end
def query_params
params.permit(:category, :status, :sort_by, :sort_direction)
end
end

@ -31,7 +31,7 @@ class Game < ApplicationRecord
# 根据得分比例来算实际得分(试卷、实训作业) # 根据得分比例来算实际得分(试卷、实训作业)
def real_score score def real_score score
(final_score.to_f / challenge.all_score) * score ((final_score < 0 ? 0 : final_score).to_f / challenge.all_score) * score
end end
# 判断实训是否全部通关 # 判断实训是否全部通关

@ -13,6 +13,9 @@ class ProjectPackage < ApplicationRecord
has_many :attachments, as: :container, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy
scope :visible, -> { where(status: %i[published bidding_ended bidding_finished]) }
scope :invisible, -> { where(status: %i[pending applying refused]) }
aasm(:status) do aasm(:status) do
state :pending, initiali: true state :pending, initiali: true
state :applying state :applying

@ -123,6 +123,11 @@ class User < ApplicationRecord
has_many :user_interests, dependent: :delete_all has_many :user_interests, dependent: :delete_all
has_many :interests, through: :user_interests, source: :repertoire has_many :interests, through: :user_interests, source: :repertoire
# 众包
has_many :project_packages, foreign_key: :creator_id, dependent: :destroy
has_many :bidding_users, dependent: :destroy
has_many :bidden_project_packages, through: :bidding_users, source: :project_package
# Groups and active users # Groups and active users
scope :active, lambda { where(status: STATUS_ACTIVE) } scope :active, lambda { where(status: STATUS_ACTIVE) }
@ -572,6 +577,10 @@ class User < ApplicationRecord
Attendance.find_by(user_id: id)&.next_gold || 60 # 基础50连续签到+10 Attendance.find_by(user_id: id)&.next_gold || 60 # 基础50连续签到+10
end end
def admin_or_business?
admin? || business?
end
protected protected
def validate_password_length def validate_password_length
# 管理员的初始密码是5位 # 管理员的初始密码是5位

@ -0,0 +1,76 @@
class Users::ProjectPackageService < ApplicationService
include CustomSortable
sort_columns :published_at, default_by: :published_at, default_direction: :desc
attr_reader :user, :params
def initialize(user, params)
@user = user
@params = params
end
def call
packages = category_scope_filter
packages = user_policy_filter(packages)
custom_sort(packages, :published_at, params[:sort_direction])
end
private
def category_scope_filter
case params[:category]
when 'bidden' then
user.bidden_project_packages
when 'manage' then
user.project_packages
else
ids = user.bidding_users.pluck(:project_package_id) + user.project_packages.pluck(:id)
ProjectPackage.where(id: ids)
end
end
def user_policy_filter(relations)
if self_or_admin?
status_filter(relations)
else
relations.visible
end
end
def status_filter(relations)
return relations unless self_or_admin?
case params[:category]
when 'bidden' then bidding_status_filter(relations)
when 'manage' then package_status_filter(relations)
else relations
end
end
def bidding_status_filter(relations)
case params[:status]
when 'bidding_lost' then
relations.where(bidding_users: { status: :bidding_lost })
when 'bidding_won' then
relations.where(bidding_users: { status: :bidding_won })
else
relations
end
end
def package_status_filter(relations)
case params[:status]
when 'unpublished' then relations.invisible
when 'bidding' then relations.where(status: :published)
when 'finished' then relations.where(status: %w[bidding_ended bidding_finished])
else relations
end
end
def self_or_admin?
User.current&.id == user.id || User.current&.admin_or_business?
end
end

@ -1,7 +1,7 @@
json.candidates do json.candidates do
json.array! @users do |user| json.array! @users do |user|
json.id user.id json.id user.id
json.name user.firstname + user.lastname json.name user.real_name
json.nickname user.nickname json.nickname user.nickname
json.school_name user.user_extension.school.try(:name) json.school_name user.user_extension.school.try(:name)
json.school_id user.user_extension.school.try(:id) json.school_id user.user_extension.school.try(:id)

@ -21,7 +21,8 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选
user_answer_b = user_answer.include?(a.id) user_answer_b = user_answer.include?(a.id)
json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现 json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现
json.choice_id a.id json.choice_id a.id
json.choice_text (edit_type.present? || question.question_type == 2) ? a.choice_text : "#{(index+65).chr}.#{a.choice_text}" # json.choice_text (edit_type.present? || question.question_type == 2) ? a.choice_text : "#{(index+65).chr}.#{a.choice_text}"
json.choice_text a.choice_text
json.choice_position a.choice_position json.choice_position a.choice_position
if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题2为空白试卷即标准答案和用户答案都不显示3为用户开始答题的显示4为老师评阅试卷或学生在截止后查看试卷 if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题2为空白试卷即标准答案和用户答案都不显示3为用户开始答题的显示4为老师评阅试卷或学生在截止后查看试卷
json.standard_boolean standard_answer_b json.standard_boolean standard_answer_b

@ -35,15 +35,16 @@ json.commit_results do
if q[:type] != Exercise::PRACTICAL if q[:type] != Exercise::PRACTICAL
json.ques_details do json.ques_details do
json.array! q[:ques_details].each_with_index.to_a do |d,index| json.array! q[:ques_details].each_with_index.to_a do |d,index|
if q[:type] <= Exercise::MULTIPLE # if q[:type] <= Exercise::MULTIPLE
ques_index = (index+65).chr # ques_index = (index+65).chr
elsif q[:type] == Exercise::JUDGMENT # elsif q[:type] == Exercise::JUDGMENT
ques_index = (index+1).to_s # ques_index = (index+1).to_s
else # else
ques_index = nil # ques_index = nil
end # end
json.choice_position d[:choice_position] json.choice_position d[:choice_position]
json.choice_text ques_index.present? ? "#{ques_index}.#{d[:choice_text]}" : d[:choice_text] # json.choice_text ques_index.present? ? "#{ques_index}.#{d[:choice_text]}" : d[:choice_text]
json.choice_text d[:choice_text]
json.choice_users_count d[:choice_users_count] json.choice_users_count d[:choice_users_count]
json.choice_percent d[:choice_percent] json.choice_percent d[:choice_percent]
json.choice_right_boolean d[:right_answer] json.choice_right_boolean d[:right_answer]

@ -0,0 +1,20 @@
user = observed_user
json.count @count
json.project_packages do
json.array! @packages.each do |package|
json.extract! package, :id, :title, :status, :min_price, :max_price, :visit_count, :bidding_users_count
is_creator = user.id == package.creator_id
json.type is_creator ? 'manage' : 'bidden'
json.category_id package.project_package_category_id
json.category_name package.category_name
unless is_creator
json.bidden_status @bidding_status_map[package.id]
end
json.deadline_at package.display_deadline_at
json.published_at package.display_published_at
end
end

@ -50,6 +50,7 @@ Rails.application.routes.draw do
resource :experience_records, only: [:show] resource :experience_records, only: [:show]
resource :grade_records, only: [:show] resource :grade_records, only: [:show]
resource :watch, only: [:create, :destroy] resource :watch, only: [:create, :destroy]
resources :project_packages, only: [:index]
end end

@ -0,0 +1,6 @@
class DeleteContentsIsNullForChallengeAnswers < ActiveRecord::Migration[5.2]
def change
contents = ChallengeAnswer.where("contents = ''")
contents.delete_all
end
end

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

@ -2,7 +2,7 @@ import React from "react";
import axios from 'axios'; import axios from 'axios';
import { requestProxy } from "./indexEduplus2RequestProxy"; import { requestProxy } from "./indexEduplus2RequestProxy";
import { broadcastChannelOnmessage ,SetAppModel} from 'educoder'; import { broadcastChannelOnmessage ,SetAppModel, isDev, queryString} from 'educoder';
import { notification } from 'antd'; import { notification } from 'antd';
import './index.css' import './index.css'
broadcastChannelOnmessage('refreshPage', () => { broadcastChannelOnmessage('refreshPage', () => {
@ -18,10 +18,19 @@ function locationurl(list){
} }
// TODO 开发期多个身份切换 // TODO 开发期多个身份切换
const debugType ="" let debugType = ""
// window.location.search.indexOf('debug=t') != -1 ? 'teacher' : if (isDev) {
// window.location.search.indexOf('debug=s') != -1 ? 'student' : 'admin' const _search = window.location.search;
// window._debugType = debugType; let parsed = {};
if (_search) {
parsed = queryString.parse(_search);
}
debugType = window.location.search.indexOf('debug=t') != -1 ? 'teacher' :
window.location.search.indexOf('debug=s') != -1 ? 'student' :
window.location.search.indexOf('debug=a') != -1 ? 'admin' : parsed.debug || ''
}
window._debugType = debugType;
export function initAxiosInterceptors(props) { export function initAxiosInterceptors(props) {
// TODO 避免重复的请求 https://github.com/axios/axios#cancellation // TODO 避免重复的请求 https://github.com/axios/axios#cancellation

@ -574,7 +574,7 @@ class Comments 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 mb20">暂时还没有评论~</p> <p className="edu-nodata-p mb20">暂时还没有相关数据哦</p>
</div> </div>
</div> </div>
: '' } : '' }

@ -956,7 +956,7 @@ class Fileslists 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" src="/images/educoder/nodata.png" /> <img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">无数据哦~</p></div> <p className="edu-nodata-p mb20">时还没有相关数据哦</p></div>
</div> </div>

@ -145,7 +145,7 @@ class CoursesHome extends Component{
{coursesHomelist===undefined?"":coursesHomelist.courses.length===0?<div className="edu-tab-con-box clearfix edu-txt-center mb50"> {coursesHomelist===undefined?"":coursesHomelist.courses.length===0?<div className="edu-tab-con-box clearfix edu-txt-center mb50">
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div>:""} </div>:""}
{ {

@ -9,7 +9,7 @@ class NoneData extends Component{
return( return(
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
) )
} }

@ -773,7 +773,7 @@ class GraduationTasks 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" src="/images/educoder/nodata.png" /> <img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">无数据哦~</p></div> <p className="edu-nodata-p mb20">时还没有相关数据哦</p></div>
</div> </div>
<div> <div>

@ -838,7 +838,7 @@ class ShixunStudentWork extends Component {
{datalist === undefined ? "" : datalist.length===0? <div className="alltask"> {datalist === undefined ? "" : datalist.length===0? <div className="alltask">
<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="/images/educoder/nodata.png" /> <img className="edu-nodata-img mb20" src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div>:<Table </div>:<Table
dataSource={datalist} dataSource={datalist}

@ -1203,7 +1203,7 @@ class ShixunHomework extends Component{
> >
<div className="edu-tab-con-box clearfix edu-txt-center"><img className="edu-nodata-img mb20" <div className="edu-tab-con-box clearfix edu-txt-center"><img className="edu-nodata-img mb20"
src="/images/educoder/nodata.png" /> src="/images/educoder/nodata.png" />
<p className="edu-nodata-p mb20">无数据哦~</p></div> <p className="edu-nodata-p mb20">时还没有相关数据哦</p></div>
</div> </div>
</Spin> </Spin>

@ -68,7 +68,7 @@ class ShixunPathCard extends Component{
):( ):(
<div className="edu-tab-con-box clearfix edu-txt-center mb50"> <div className="edu-tab-con-box clearfix edu-txt-center mb50">
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
) )
} }

@ -348,14 +348,14 @@ class Challenges 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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div> : ChallengesDataList.challenge_list === undefined ? </div> : ChallengesDataList.challenge_list === undefined ?
<div className="alltask"> <div className="alltask">
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div> </div>
: ChallengesDataList.challenge_list.length === 0 ? : ChallengesDataList.challenge_list.length === 0 ?
@ -363,7 +363,7 @@ class Challenges 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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div> </div>
: ChallengesDataList.challenge_list.map((item, key) => { : ChallengesDataList.challenge_list.map((item, key) => {

@ -92,7 +92,7 @@ class Propaedeutics extends Component {
<div className="alltask"> <div className="alltask">
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div> </div>
</div> </div>

@ -164,7 +164,7 @@ class Repository extends Component {
trees === undefined || trees === null ? <div className="alltask"> trees === undefined || trees === null ? <div className="alltask">
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div> : </div> :
<div> <div>

@ -64,7 +64,7 @@ class ShixunCard extends Component {
<div className="square-list clearfix"> <div className="square-list clearfix">
<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 mb20">无数据哦~</p> <p className="edu-nodata-p mb20">时还没有相关数据哦</p>
</div> </div>
</div> </div>
<div className="educontent edu-txt-center mb80"> <div className="educontent edu-txt-center mb80">

@ -444,8 +444,9 @@ ul.abouttable li .minh-label{min-width: 150px;height: 28px;line-height: 28px;tex
.allNone tr{height: 30px!important;} .allNone tr{height: 30px!important;}
/*数据为空公共页面*/ /*数据为空公共页面*/
img.edu-nodata-img{ width:300px; margin:50px auto 20px; display: block;} img.edu-nodata-img{ width:300px; margin:50px auto 20px; display: block; width: 128px;}
.edu-nodata-p{ font-size: 20px; text-align: center; color:#999;border-bottom:none!important;padding-left: 18px;box-sizing: border-box;} /* 不能加 padding-left: 18px; 会影响其他地方的居中 */
.edu-nodata-p{ font-size: 20px; text-align: center; color:#999;border-bottom:none!important;box-sizing: border-box;}
/*输入为空或者错误的提示*/ /*输入为空或者错误的提示*/
.input-none{box-shadow: 0px 0px 2px rgba(0,0,0,0.1);} .input-none{box-shadow: 0px 0px 2px rgba(0,0,0,0.1);}

Loading…
Cancel
Save