From c90358cdfaa96f47674c751823430288e2a17124 Mon Sep 17 00:00:00 2001 From: p31729568 Date: Tue, 30 Jul 2019 14:57:25 +0800 Subject: [PATCH] private message feature apis --- app/controllers/concerns/paginate_helper.rb | 2 +- app/controllers/users/base_controller.rb | 17 +++++++- .../private_message_details_controller.rb | 23 +++++++++++ .../users/private_messages_controller.rb | 39 +++++++++++++++++++ .../users/recent_contacts_controller.rb | 8 ++++ .../users/unread_message_infos_controller.rb | 12 ++++++ .../users_for_private_messages_controller.rb | 17 ++++++++ app/decorators/private_message_decorator.rb | 9 +++++ app/models/private_message.rb | 6 +++ app/models/user.rb | 3 +- .../private_messages/create_service.rb | 35 +++++++++++++++++ .../show.json.jbuilder | 11 ++++++ .../private_messages/create.json.jbuilder | 10 +++++ .../private_messages/index.json.jbuilder | 13 +++++++ .../users/recent_contacts/index.json.jbuilder | 2 + .../index.json.jbuilder | 2 + config/routes.rb | 6 +++ 17 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 app/controllers/users/private_message_details_controller.rb create mode 100644 app/controllers/users/private_messages_controller.rb create mode 100644 app/controllers/users/recent_contacts_controller.rb create mode 100644 app/controllers/users/unread_message_infos_controller.rb create mode 100644 app/controllers/users_for_private_messages_controller.rb create mode 100644 app/decorators/private_message_decorator.rb create mode 100644 app/services/private_messages/create_service.rb create mode 100644 app/views/users/private_message_details/show.json.jbuilder create mode 100644 app/views/users/private_messages/create.json.jbuilder create mode 100644 app/views/users/private_messages/index.json.jbuilder create mode 100644 app/views/users/recent_contacts/index.json.jbuilder create mode 100644 app/views/users_for_private_messages/index.json.jbuilder diff --git a/app/controllers/concerns/paginate_helper.rb b/app/controllers/concerns/paginate_helper.rb index 34740eb5d..bbe84a348 100644 --- a/app/controllers/concerns/paginate_helper.rb +++ b/app/controllers/concerns/paginate_helper.rb @@ -1,7 +1,7 @@ module PaginateHelper def paginate(objs, **opts) 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) end diff --git a/app/controllers/users/base_controller.rb b/app/controllers/users/base_controller.rb index afc03ee13..fd138a182 100644 --- a/app/controllers/users/base_controller.rb +++ b/app/controllers/users/base_controller.rb @@ -26,9 +26,22 @@ class Users::BaseController < ApplicationController render_forbidden 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) - page = params[:page].to_i <= 0 ? 1 : params[:page].to_i - per_page = params[:per_page].to_i > 0 ? params[:per_page].to_i : 20 + page = page_value + per_page = per_page_value return Kaminari.paginate_array(objs).page(page).per(per_page) unless observed_logged_user? && opts[:special] diff --git a/app/controllers/users/private_message_details_controller.rb b/app/controllers/users/private_message_details_controller.rb new file mode 100644 index 000000000..486d23d7f --- /dev/null +++ b/app/controllers/users/private_message_details_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users/private_messages_controller.rb b/app/controllers/users/private_messages_controller.rb new file mode 100644 index 000000000..b80b6152b --- /dev/null +++ b/app/controllers/users/private_messages_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users/recent_contacts_controller.rb b/app/controllers/users/recent_contacts_controller.rb new file mode 100644 index 000000000..bc4b8ea8f --- /dev/null +++ b/app/controllers/users/recent_contacts_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users/unread_message_infos_controller.rb b/app/controllers/users/unread_message_infos_controller.rb new file mode 100644 index 000000000..7abd36304 --- /dev/null +++ b/app/controllers/users/unread_message_infos_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/users_for_private_messages_controller.rb b/app/controllers/users_for_private_messages_controller.rb new file mode 100644 index 000000000..bbd5682a1 --- /dev/null +++ b/app/controllers/users_for_private_messages_controller.rb @@ -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 \ No newline at end of file diff --git a/app/decorators/private_message_decorator.rb b/app/decorators/private_message_decorator.rb new file mode 100644 index 000000000..6db17acf3 --- /dev/null +++ b/app/decorators/private_message_decorator.rb @@ -0,0 +1,9 @@ +module PrivateMessageDecorator + extend ApplicationDecorator + + display_time_method :send_time + + def unread? + status.zero? + end +end \ No newline at end of file diff --git a/app/models/private_message.rb b/app/models/private_message.rb index 1db4c9f66..640e48db7 100644 --- a/app/models/private_message.rb +++ b/app/models/private_message.rb @@ -1,3 +1,9 @@ class PrivateMessage < ApplicationRecord 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 diff --git a/app/models/user.rb b/app/models/user.rb index 14d7b2697..ed9d70c00 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -54,7 +54,8 @@ class User < ApplicationRecord 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 :games, :dependent => :destroy diff --git a/app/services/private_messages/create_service.rb b/app/services/private_messages/create_service.rb new file mode 100644 index 000000000..560f1a540 --- /dev/null +++ b/app/services/private_messages/create_service.rb @@ -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 \ No newline at end of file diff --git a/app/views/users/private_message_details/show.json.jbuilder b/app/views/users/private_message_details/show.json.jbuilder new file mode 100644 index 000000000..065767fb4 --- /dev/null +++ b/app/views/users/private_message_details/show.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/users/private_messages/create.json.jbuilder b/app/views/users/private_messages/create.json.jbuilder new file mode 100644 index 000000000..888cfeff6 --- /dev/null +++ b/app/views/users/private_messages/create.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/users/private_messages/index.json.jbuilder b/app/views/users/private_messages/index.json.jbuilder new file mode 100644 index 000000000..c18a7d209 --- /dev/null +++ b/app/views/users/private_messages/index.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/users/recent_contacts/index.json.jbuilder b/app/views/users/recent_contacts/index.json.jbuilder new file mode 100644 index 000000000..f2f7f025a --- /dev/null +++ b/app/views/users/recent_contacts/index.json.jbuilder @@ -0,0 +1,2 @@ +json.users @contacts, partial: 'users/user_simple', as: :user +json.count @contacts.size \ No newline at end of file diff --git a/app/views/users_for_private_messages/index.json.jbuilder b/app/views/users_for_private_messages/index.json.jbuilder new file mode 100644 index 000000000..be040e368 --- /dev/null +++ b/app/views/users_for_private_messages/index.json.jbuilder @@ -0,0 +1,2 @@ +json.users @users, partial: 'users/user_simple', as: :user +json.count @users.size \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 6623edd99..2f9eed61b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -53,6 +53,11 @@ Rails.application.routes.draw do resource :grade_records, only: [:show] resource :watch, only: [:create, :destroy] 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 @@ -91,6 +96,7 @@ Rails.application.routes.draw do end end end + resources :users_for_private_messages, only: [:index] resources :myshixuns, param: :identifier, shallow: true do member do