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

dev_forum
daiao 5 years ago
commit e85a2cbc33

@ -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

@ -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

@ -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 认证回调

@ -15,7 +15,7 @@
text-align: center; text-align: center;
height: 60px; height: 60px;
box-sizing: border-box; box-sizing: border-box;
min-width: 1200px; min-width: 950px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;

@ -384,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,8 +400,13 @@ 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 });
this.props.triggerRef(this); try {
this.props.triggerRef(this);
}catch (e) {
}
} }
componentWillUnmount() { componentWillUnmount() {
off('commonwork_fetch_all', this.fetchAllListener) off('commonwork_fetch_all', this.fetchAllListener)

@ -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>
} }

@ -678,63 +678,6 @@ class LoginRegisterComponent extends Component {
} }
//失去焦点判断 //失去焦点判断
inputOnBlur = (e, id) => { inputOnBlur = (e, id) => {
// debugger
// // 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 {
// console.log("706");
// 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 {
// console.log("729");
// 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) => {

@ -15,7 +15,7 @@
text-align: center; text-align: center;
height: 60px; height: 60px;
box-sizing: border-box; box-sizing: border-box;
min-width: 1200px; min-width: 950px;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
white-space: nowrap; white-space: nowrap;

Loading…
Cancel
Save