diff --git a/app/controllers/users/project_packages_controller.rb b/app/controllers/users/project_packages_controller.rb new file mode 100644 index 000000000..edd6bd29b --- /dev/null +++ b/app/controllers/users/project_packages_controller.rb @@ -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 \ No newline at end of file diff --git a/app/models/project_package.rb b/app/models/project_package.rb index fc541097a..219f60ca4 100644 --- a/app/models/project_package.rb +++ b/app/models/project_package.rb @@ -13,6 +13,9 @@ class ProjectPackage < ApplicationRecord 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 state :pending, initiali: true state :applying diff --git a/app/models/user.rb b/app/models/user.rb index 73036c73e..03c97b9f3 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -123,6 +123,11 @@ class User < ApplicationRecord has_many :user_interests, dependent: :delete_all 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 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 end + def admin_or_business? + admin? || business? + end + protected def validate_password_length # 管理员的初始密码是5位 diff --git a/app/services/users/project_package_service.rb b/app/services/users/project_package_service.rb new file mode 100644 index 000000000..870cdc98e --- /dev/null +++ b/app/services/users/project_package_service.rb @@ -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 \ No newline at end of file diff --git a/app/views/exercise_questions/_exercise_questions.json.jbuilder b/app/views/exercise_questions/_exercise_questions.json.jbuilder index b9565535e..51c30ad92 100644 --- a/app/views/exercise_questions/_exercise_questions.json.jbuilder +++ b/app/views/exercise_questions/_exercise_questions.json.jbuilder @@ -21,7 +21,8 @@ if question.question_type <= 2 #当为选择题或判断题时,只显示选 user_answer_b = user_answer.include?(a.id) json.c_position (index+1) if ex_choice_random_boolean #当选项随机时,选项位置以此为准,否则不出现 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 if exercise_type == 1 || exercise_type == 4 #1为教师编辑/预览 试卷或问题,2为空白试卷,即标准答案和用户答案都不显示,3为用户开始答题的显示,4为老师评阅试卷或学生在截止后查看试卷 json.standard_boolean standard_answer_b diff --git a/app/views/exercises/exercise_result.json.jbuilder b/app/views/exercises/exercise_result.json.jbuilder index 2c4b3ded7..1ceb8209d 100644 --- a/app/views/exercises/exercise_result.json.jbuilder +++ b/app/views/exercises/exercise_result.json.jbuilder @@ -35,15 +35,16 @@ json.commit_results do if q[:type] != Exercise::PRACTICAL json.ques_details do json.array! q[:ques_details].each_with_index.to_a do |d,index| - if q[:type] <= Exercise::MULTIPLE - ques_index = (index+65).chr - elsif q[:type] == Exercise::JUDGMENT - ques_index = (index+1).to_s - else - ques_index = nil - end + # if q[:type] <= Exercise::MULTIPLE + # ques_index = (index+65).chr + # elsif q[:type] == Exercise::JUDGMENT + # ques_index = (index+1).to_s + # else + # ques_index = nil + # end 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_percent d[:choice_percent] json.choice_right_boolean d[:right_answer] diff --git a/app/views/users/project_packages/index.json.jbuilder b/app/views/users/project_packages/index.json.jbuilder new file mode 100644 index 000000000..a2574d558 --- /dev/null +++ b/app/views/users/project_packages/index.json.jbuilder @@ -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 \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 16140e99c..bb5bc49cc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -50,6 +50,7 @@ Rails.application.routes.draw do resource :experience_records, only: [:show] resource :grade_records, only: [:show] resource :watch, only: [:create, :destroy] + resources :project_packages, only: [:index] end diff --git a/public/react/src/AppConfig.js b/public/react/src/AppConfig.js index 003ef5a9b..cf62730d7 100644 --- a/public/react/src/AppConfig.js +++ b/public/react/src/AppConfig.js @@ -25,9 +25,7 @@ if (isDev) { 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 || '' + debugType = window.location.search.indexOf('debug=t') != -1 ? "cxt" : '' } window._debugType = debugType; @@ -144,6 +142,7 @@ export function initAxiosInterceptors(props) { // } if (response.data.status === 403) { // props.history.replace('/403') + debugger // 这里会分2个情况,1、刚进入页面发请求返回的403;2、进入页面后,其他用户操作触发请求返回的403; // TODO 这里做一个403弹框比较好? locationurl('/403'); diff --git a/public/react/src/modules/courses/coursesPublic/Addcourses.js b/public/react/src/modules/courses/coursesPublic/Addcourses.js index e8bd8b9cf..922c68650 100644 --- a/public/react/src/modules/courses/coursesPublic/Addcourses.js +++ b/public/react/src/modules/courses/coursesPublic/Addcourses.js @@ -147,6 +147,8 @@ class Addcourses extends Component{ if(Addcoursestype===true){ this.props.hideAddcoursestype(); + }else{ + window.location.href = "/"; } } diff --git a/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js b/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js index 5f41cdefb..b4adea17f 100644 --- a/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js +++ b/public/react/src/modules/courses/shixunHomework/ShixunhomeWorkItem.js @@ -382,7 +382,7 @@ class ShixunhomeWorkItem extends Component{ 实训详情 {this.props.isAdminOrCreator()?this.editname(discussMessage.name,discussMessage.homework_id)} className={"btn colorblue ml20 font-16"}>重命名:""} {/* 设置*/} - 设置 + 设置 :""} diff --git a/public/react/src/modules/tpm/NewHeader.js b/public/react/src/modules/tpm/NewHeader.js index da8e71a40..830c8b1d4 100644 --- a/public/react/src/modules/tpm/NewHeader.js +++ b/public/react/src/modules/tpm/NewHeader.js @@ -487,10 +487,11 @@ submittojoinclass=(value)=>{ } showSearchOpen=(e)=>{ + debugger this.setState({ showSearchOpentype:true }) - e.stopPropagation(e);//阻止冒泡 + } hideshowSearchOpen=(e)=>{ @@ -500,7 +501,7 @@ submittojoinclass=(value)=>{ showSearchOpentype:false, setevaluatinghides:false }) - e.stopPropagation(e);//阻止冒泡 + } }