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

dev_forum
daiao 5 years ago
commit 0bf4705cb9

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

@ -0,0 +1,2 @@
// Place all the behaviors and hooks related to the matching controller here.
// All this logic will automatically be available in application.js.

@ -0,0 +1,3 @@
// Place all the styles related to the forums controller here.
// They will automatically be included in application.css.
// You can use Sass (SCSS) here: http://sass-lang.com/

@ -1,7 +1,7 @@
module PaginateHelper module PaginateHelper
def paginate(objs, **opts) def paginate(objs, **opts)
page = params[:page].to_i <= 0 ? 1 : params[:page].to_i page = params[:page].to_i <= 0 ? 1 : params[:page].to_i
per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : opts[:per_page] || 20 per_page = params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : opts[:per_page] || 20
Kaminari.paginate_array(objs).page(page).per(per_page) Kaminari.paginate_array(objs).page(page).per(per_page)
end end

@ -0,0 +1,2 @@
class ForumsController < ApplicationController
end

@ -26,9 +26,22 @@ class Users::BaseController < ApplicationController
render_forbidden render_forbidden
end end
def page_value
params[:page].to_i <= 0 ? 1 : params[:page].to_i
end
def per_page_value
params[:per_page].to_i > 0 && params[:per_page].to_i < 50 ? params[:per_page].to_i : 20
end
alias_method :limit_value, :per_page_value
def offset_value
(page_value - 1) * limit_value
end
def paginate(objs, **opts) def paginate(objs, **opts)
page = params[:page].to_i <= 0 ? 1 : params[:page].to_i page = page_value
per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20 per_page = per_page_value
return Kaminari.paginate_array(objs).page(page).per(per_page) unless observed_logged_user? && opts[:special] return Kaminari.paginate_array(objs).page(page).per(per_page) unless observed_logged_user? && opts[:special]

@ -0,0 +1,23 @@
class Users::PrivateMessageDetailsController < Users::BaseController
before_action :private_user_resources!
after_action :update_message_status, only: [:show]
def show
messages = observed_user.private_messages.without_deleted.where(target: target_user)
@count = messages.count
@messages = messages.order(send_time: :asc).includes(sender: :user_extension)
end
private
def target_user
@_target_user ||= User.find(params[:target_id])
end
# 置为已读
def update_message_status
observed_user.private_messages.only_unread.where(target: target_user).update_all(status: 1)
end
end

@ -0,0 +1,39 @@
class Users::PrivateMessagesController < Users::BaseController
before_action :private_user_resources!
after_action :update_onclick_time!, only: [:index]
def index
@count = observed_user.private_messages.without_deleted.group(:target_id).count.count
subquery = observed_user.private_messages.without_deleted.order(send_time: :desc).to_sql
query = "SELECT subquery.*, COUNT(*) message_count FROM (#{subquery}) subquery "\
"GROUP BY subquery.target_id ORDER BY subquery.send_time desc LIMIT #{limit_value} OFFSET #{offset_value}"
@messages = PrivateMessage.select('*').from("(#{query}) AS query").includes(target: :user_extension)
end
def create
receiver = User.find_by(id: params[:target_id])
return render_error('用户未找到') if receiver.blank?
@message = PrivateMessages::CreateService.call(observed_user, receiver, create_params)
rescue PrivateMessages::CreateService::Error => ex
render_error(ex.message)
end
def destroy
message = observed_user.private_messages.without_deleted.find(params[:id])
message.destroy!
render_ok
end
private
def update_onclick_time!
current_user.onclick_time.touch(:onclick_time)
end
def create_params
params.permit(:content)
end
end

@ -0,0 +1,8 @@
class Users::RecentContactsController < Users::BaseController
before_action :private_user_resources!
def index
contacts = observed_user.recent_contacts.distinct
@contacts = contacts.order('private_messages.created_at DESC').limit(10).includes(:user_extension)
end
end

@ -0,0 +1,12 @@
class Users::UnreadMessageInfosController < Users::BaseController
before_action :private_user_resources!
def show
click_time = observed_user.click_time
unread_tiding_count = observed_user.tidings.where('created_at > ?', click_time).count
unread_message_count = observed_user.private_messages.only_unread.group(:target_id).count.count
render_ok(unread_tiding_count: unread_tiding_count, unread_message_count: unread_message_count)
end
end

@ -0,0 +1,17 @@
class UsersForPrivateMessagesController < ApplicationController
before_action :require_login, :check_auth
def index
users = User.active.where.not(id: current_user.id)
keyword = params[:keyword].to_s.strip
if keyword.blank?
@users = []
return
end
users = users.where('LOWER(concat(lastname, firstname, nickname)) LIKE ?', "%#{keyword}%")
@users = users.limit(10).includes(:user_extension)
end
end

@ -0,0 +1,9 @@
module PrivateMessageDecorator
extend ApplicationDecorator
display_time_method :send_time
def unread?
status.zero?
end
end

@ -497,7 +497,7 @@ module ExportHelper
def make_zip_name(work, file_name="") def make_zip_name(work, file_name="")
Rails.logger.info("######################file_name: #{file_name}") Rails.logger.info("######################file_name: #{file_name}")
# name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_") # name = file_name === "" ? "" : (file_name[0, file_name.rindex('.')]+"_")
"#{work&.user&.student_id}_#{work.&user.&real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}" "#{work&.user&.student_id}_#{work&.user&.real_name}_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
end end
def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[]) def zipping(zip_name_refer, files_paths, output_path, is_attachment=false, not_exist_file=[])

@ -0,0 +1,2 @@
module ForumsHelper
end

@ -0,0 +1,2 @@
class Forum < ApplicationRecord
end

@ -1,3 +1,9 @@
class PrivateMessage < ApplicationRecord class PrivateMessage < ApplicationRecord
belongs_to :user belongs_to :user
belongs_to :target, class_name: "User"
belongs_to :sender, class_name: "User"
belongs_to :receiver, class_name: "User"
scope :without_deleted, -> { where.not(status: 2) }
scope :only_unread, -> { where(status: 0) }
end end

@ -54,7 +54,8 @@ class User < ApplicationRecord
has_one :onclick_time, :dependent => :destroy has_one :onclick_time, :dependent => :destroy
# 新版私信 # 新版私信
has_many :private_messages, :dependent => :destroy has_many :private_messages, dependent: :destroy
has_many :recent_contacts, through: :private_messages, source: :target
has_many :tidings, :dependent => :destroy has_many :tidings, :dependent => :destroy
has_many :games, :dependent => :destroy has_many :games, :dependent => :destroy

@ -0,0 +1,35 @@
class PrivateMessages::CreateService < ApplicationService
Error = Class.new(StandardError)
attr_reader :sender, :receiver, :params
def initialize(sender, receiver, **params)
@sender = sender
@receiver = receiver
@params = params
end
def call
validate!
same_attr = { sender: sender, receiver: receiver, content: content, send_time: Time.now }
message = nil
ActiveRecord::Base.transaction do
message = sender.private_messages.create!(same_attr.merge(target: receiver, status: 1))
receiver.private_messages.create!(same_attr.merge(target: sender, status: 0))
end
message
end
private
def content
@_content ||= params[:content].to_s.strip
end
def validate!
raise Error, '内容不能为空' if content.blank?
raise Error, '内容太长' if content.size > 255
end
end

@ -15,7 +15,7 @@ class ProjectPackages::SaveService < ApplicationService
is_create = package.new_record? is_create = package.new_record?
raise Error, '类型不存在' unless ProjectPackageCategory.where(id: params[:category_id]).exists? raise Error, '类型不存在' unless ProjectPackageCategory.where(id: params[:category_id]).exists?
params[:project_package_category_id] = params[:category_id].to_i params[:project_package_category_id] = params.delete(:category_id).to_i
raise Error, '竞标截止时间不能小于当前时间' if params[:deadline_at].present? && params[:deadline_at].to_time < Time.now raise Error, '竞标截止时间不能小于当前时间' if params[:deadline_at].present? && params[:deadline_at].to_time < Time.now
@ -25,7 +25,9 @@ class ProjectPackages::SaveService < ApplicationService
end end
ActiveRecord::Base.transaction do ActiveRecord::Base.transaction do
package.assign_attributes(params) columns = %i[project_package_category_id title content deadline_at
min_price max_price contact_name contact_phone]
package.assign_attributes(params.slice(*columns))
package.save! package.save!
# 处理附件 # 处理附件

@ -0,0 +1,11 @@
json.count @count
json.messages do
json.array! @messages.each do |message|
json.extract! message, :id, :user_id, :receiver_id, :sender_id, :content
json.send_time message.display_send_time
json.sender do
json.partial! 'users/user_simple', user: message.sender
end
end
end

@ -0,0 +1,10 @@
json.status 0
json.message 'success'
json.private_message do
json.extract! @message, :id, :user_id, :receiver_id, :sender_id, :content
json.send_time @message.display_send_time
json.sender do
json.partial! 'users/user_simple', user: @message.sender
end
end

@ -0,0 +1,13 @@
json.count @count
json.private_messages do
json.array! @messages.each do |message|
json.extract! message, :id, :content, :message_count
json.unread message.unread?
json.send_time message.display_send_time
json.target do
json.partial! 'users/user_simple', user: message.target
end
end
end

@ -0,0 +1,2 @@
json.users @contacts, partial: 'users/user_simple', as: :user
json.count @contacts.size

@ -0,0 +1,2 @@
json.users @users, partial: 'users/user_simple', as: :user
json.count @users.size

@ -53,6 +53,11 @@ Rails.application.routes.draw do
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] resources :project_packages, only: [:index]
# 私信
resources :private_messages, only: [:index, :create, :destroy]
resources :recent_contacts, only: [:index]
resource :private_message_details, only: [:show]
resource :unread_message_info, only: [:show]
end end
@ -91,6 +96,7 @@ Rails.application.routes.draw do
end end
end end
end end
resources :users_for_private_messages, only: [:index]
resources :myshixuns, param: :identifier, shallow: true do resources :myshixuns, param: :identifier, shallow: true do
member do member do

@ -0,0 +1,8 @@
class CreateForums < ActiveRecord::Migration[5.2]
def change
create_table :forums do |t|
t.timestamps
end
end
end

@ -305,9 +305,6 @@ class CommonWorkDetailIndex extends Component{
.floatSpinParent .ant-spin-nested-loading { .floatSpinParent .ant-spin-nested-loading {
float: right; float: right;
} }
.floatSpinParent .ant-spin-nested-loading .ant-spin-spinning{
top: 10px;
}
`}</style> `}</style>
{this.props.isAdmin()? <Spin spinning={this.state.donwloading} style={{ }}> {this.props.isAdmin()? <Spin spinning={this.state.donwloading} style={{ }}>
<li className="li_line drop_down fr color-blue font-16 mr8 mt20" style={{"padding":"0 20px"}}> <li className="li_line drop_down fr color-blue font-16 mr8 mt20" style={{"padding":"0 20px"}}>

@ -14,6 +14,7 @@ let categorylist=[
{name:"数据库",value:"database"}, {name:"数据库",value:"database"},
{name:"云计算和大数据",value:"cloud_compute_and_big_data"}, {name:"云计算和大数据",value:"cloud_compute_and_big_data"},
{name:"人工智能",value:"ai"}, {name:"人工智能",value:"ai"},
{name:"运维与测试",value:"devops_and_test"},
{name:"其他",value:"other"}, {name:"其他",value:"other"},
] ]
// //

@ -252,7 +252,7 @@ class PackageIndexNEITaskDetails extends Component {
<Breadcrumb separator={'>'} className={"fl"}> <Breadcrumb separator={'>'} className={"fl"}>
{/*<Breadcrumb.Item>{this.props.current_user.username}</Breadcrumb.Item>*/} {/*<Breadcrumb.Item>{this.props.current_user.username}</Breadcrumb.Item>*/}
<Breadcrumb.Item> <Breadcrumb.Item>
<a href="/crowdsourcing">众包创新</a> <a href="/crowdsourcings">众包创新</a>
</Breadcrumb.Item> </Breadcrumb.Item>
<Breadcrumb.Item><span className={"tabelcli"} title={data&&data.title}>{data&&data.title}</span></Breadcrumb.Item> <Breadcrumb.Item><span className={"tabelcli"} title={data&&data.title}>{data&&data.title}</span></Breadcrumb.Item>

@ -407,7 +407,7 @@ class PackageIndexNEIBannerConcent extends Component {
// } // }
if(modalCancel===true||this.props.current_user.phone===null){ if(this.props.current_user&&this.props.current_user.phone===null||modalCancel===true){
if(contact_phone===undefined||contact_phone===null||contact_phone===""){ if(contact_phone===undefined||contact_phone===null||contact_phone===""){
this.setState({ this.setState({
contact_phonetype:true contact_phonetype:true
@ -445,7 +445,7 @@ class PackageIndexNEIBannerConcent extends Component {
min_price:parseInt(min_price), min_price:parseInt(min_price),
max_price:parseInt(max_price), max_price:parseInt(max_price),
contact_name: contact_name===null||contact_name===undefined?this.props.current_user.username:contact_name, contact_name: contact_name===null||contact_name===undefined?this.props.current_user.username:contact_name,
contact_phone: contact_phone===undefined?this.props.current_user.phone:contact_phone, contact_phone: contact_phone===undefined?this.props.current_user&&this.props.current_user.phone:contact_phone,
code:code, code:code,
publish:types publish:types
} }
@ -493,7 +493,7 @@ class PackageIndexNEIBannerConcent extends Component {
min_price:parseInt(min_price), min_price:parseInt(min_price),
max_price:parseInt(max_price), max_price:parseInt(max_price),
contact_name: contact_name===null||contact_name===undefined?this.props.current_user.username:contact_name, contact_name: contact_name===null||contact_name===undefined?this.props.current_user.username:contact_name,
contact_phone: contact_phone===undefined?this.props.current_user.phone:contact_phone, contact_phone: contact_phone===undefined?this.props.current_user&&this.props.current_user.phone:contact_phone,
code:code, code:code,
publish:types publish:types
} }
@ -629,7 +629,7 @@ class PackageIndexNEIBannerConcent extends Component {
// }) // })
// } // }
// } // }
if(modalCancel===true||this.props.current_user.phone===null){ if(this.props.current_user&&this.props.current_user.phone===null||modalCancel===true){
if(e.target.value===undefined||e.target.value===null||e.target.value===""){ if(e.target.value===undefined||e.target.value===null||e.target.value===""){
this.setState({ this.setState({
contact_phonetype:true contact_phonetype:true
@ -847,12 +847,12 @@ class PackageIndexNEIBannerConcent extends Component {
{this.state.contact_nametype===true?<div className={"color-red ml100"}>不能为空</div>:""} {this.state.contact_nametype===true?<div className={"color-red ml100"}>不能为空</div>:""}
</p> </p>
{modalCancel===false&&this.props.current_user.phone!=null?<p className="clearfix mb20 shaiContent"> {this.props.current_user&&this.props.current_user.phone!=null&&modalCancel===false?<p className="clearfix mb20 shaiContent">
<span className="shaiTitle fl mt5 ml25">手机号</span> <span className="shaiTitle fl mt5 ml25">手机号</span>
<Input <Input
className={"fafafas fl"} className={"fafafas fl"}
style={{"width": "260px"}} style={{"width": "260px"}}
value={this.state.phones===undefined?this.props.current_user.phone:this.state.phones} value={this.state.phones===undefined?this.props.current_user&&this.props.current_user.phone:this.state.phones}
placeholder="请输入手机号" placeholder="请输入手机号"
disabled={true} disabled={true}
/> />
@ -861,7 +861,7 @@ class PackageIndexNEIBannerConcent extends Component {
</a> </a>
</p>:""} </p>:""}
{/*{this.state.current_userphonetype===true?<div className={"color-red ml100"}>不能为空</div>:""}*/} {/*{this.state.current_userphonetype===true?<div className={"color-red ml100"}>不能为空</div>:""}*/}
{modalCancel===true||this.props.current_user.phone===null?<p className="clearfix mb20 shaiContent"> {this.props.current_user&&this.props.current_user.phone===null||modalCancel===true?<p className="clearfix mb20 shaiContent">
<span className="shaiTitle mt5 fl"> <span className="shaiTitle mt5 fl">
<span className="shaiTitle fl mt5 ml25"> <span className="shaiTitle fl mt5 ml25">
{/*未注册才显示!*/} {/*未注册才显示!*/}

@ -718,7 +718,7 @@ submittojoinclass=(value)=>{
<li className=""><a href={this.props.Headertop===undefined?"":this.props.Headertop.moop_cases_url}>教学案例</a></li> <li className=""><a href={this.props.Headertop===undefined?"":this.props.Headertop.moop_cases_url}>教学案例</a></li>
<li className=""><a <li className=""><a
// href={this.props.Headertop===undefined?"":this.props.Headertop.crowdsourcing_url} // href={this.props.Headertop===undefined?"":this.props.Headertop.crowdsourcing_url}
href={'/crowdsourcings'} href={'/crowdsourcing'}
>众包创新</a></li> >众包创新</a></li>
<li className={`${activeForums === true ? 'active' : ''}`}><a href={this.props.Headertop===undefined?"":this.props.Headertop.topic_url}>交流问答</a></li> <li className={`${activeForums === true ? 'active' : ''}`}><a href={this.props.Headertop===undefined?"":this.props.Headertop.topic_url}>交流问答</a></li>
<li <li
@ -816,6 +816,7 @@ submittojoinclass=(value)=>{
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/shixuns`}>我的实训</Link></li> <li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/shixuns`}>我的实训</Link></li>
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/paths`}>我的实践课程</Link></li> <li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/paths`}>我的实践课程</Link></li>
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/projects`}>我的项目</Link></li> <li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/projects`}>我的项目</Link></li>
<li><Link to={`/users/${this.props.current_user===undefined?"":this.props.current_user.login}/projects`}>我的众包</Link></li>
<li><a href={`/account/profile`}>账号管理</a></li> <li><a href={`/account/profile`}>账号管理</a></li>
{/*<li><a onClick={()=>this.educoderlogin()} >登入测试接口</a></li>*/} {/*<li><a onClick={()=>this.educoderlogin()} >登入测试接口</a></li>*/}
{/*<li><a onClick={()=>this.trialapplications()} >试用申请</a> </li>*/} {/*<li><a onClick={()=>this.trialapplications()} >试用申请</a> </li>*/}

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe ForumsController, type: :controller do
end

@ -0,0 +1,15 @@
require 'rails_helper'
# Specs in this file have access to a helper object that includes
# the ForumsHelper. For example:
#
# describe ForumsHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# expect(helper.concat_strings("this","that")).to eq("this that")
# end
# end
# end
RSpec.describe ForumsHelper, type: :helper do
pending "add some examples to (or delete) #{__FILE__}"
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe Forum, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save