From 4d3a6c4811fae4ebaa716dd47e6c5534f7bca5fe Mon Sep 17 00:00:00 2001 From: "sylor_huang@126.com" Date: Mon, 12 Oct 2020 14:25:02 +0800 Subject: [PATCH] Add Memo related models-1 --- app/models/apply_forum.rb | 4 + app/models/banned_forum.rb | 8 + app/models/forum_moderator.rb | 6 + app/models/forum_section.rb | 38 ++++ app/models/memo.rb | 389 ++++++++++++++++++++++++++++++++++ app/models/memo_forum.rb | 3 + app/models/section_notice.rb | 1 + app/models/visit_action.rb | 5 + 8 files changed, 454 insertions(+) diff --git a/app/models/apply_forum.rb b/app/models/apply_forum.rb index 1457f9bf..f0ed1e95 100644 --- a/app/models/apply_forum.rb +++ b/app/models/apply_forum.rb @@ -1,2 +1,6 @@ class ApplyForum < ApplicationRecord + #is_confirm 默认为0, 1为通过,2为拒绝 + belongs_to :user + belongs_to :forum_section + has_many :reviews, as: :reviewable,dependent: :destroy end diff --git a/app/models/banned_forum.rb b/app/models/banned_forum.rb index 1fa372d0..a5b05d00 100644 --- a/app/models/banned_forum.rb +++ b/app/models/banned_forum.rb @@ -1,2 +1,10 @@ class BannedForum < ApplicationRecord + # user_id #被禁言用户 + # author_id #禁言的创建者 + # memo_id #禁言的帖子id + # banned_count, default: 0 #被禁言的次数,每次禁言的时候+1 + # is_banned, default: false #是否禁言 + belongs_to :user + belongs_to :memo + belongs_to :author, :class_name => 'User', :foreign_key => 'author_id' end diff --git a/app/models/forum_moderator.rb b/app/models/forum_moderator.rb index 5d0c29d0..f6b62a62 100644 --- a/app/models/forum_moderator.rb +++ b/app/models/forum_moderator.rb @@ -1,2 +1,8 @@ class ForumModerator < ApplicationRecord + #版主的表 + # attr_accessible :title, :body + belongs_to :forum_section + belongs_to :user + + scope :children_moder, -> {where(is_children: true)} end diff --git a/app/models/forum_section.rb b/app/models/forum_section.rb index db05e78b..121139a4 100644 --- a/app/models/forum_section.rb +++ b/app/models/forum_section.rb @@ -1,2 +1,40 @@ class ForumSection < ApplicationRecord + has_ancestry + #论坛板块的表 + # attr_accessible :title, :body + has_many :forum_moderators + belongs_to :user + has_many :apply_forums, dependent: :destroy + has_many :memo_forums, :dependent => :destroy, foreign_key: "forum_id" + has_many :memos, dependent: :destroy + has_one :section_notice, dependent: :destroy + # scope :group_today, -> {joins(:memos).where("memos.hidden = false and memos.created_at between ? and ?", Time.current.beginning_of_day, Time.current.end_of_day)} + acts_as_watchable + acts_as_attachable + + def group_today + memos.where("memos.hidden = false and memos.created_at between ? and ?", Time.current.beginning_of_day, Time.current.end_of_day) + end + + def visible_memos_count + memos.posts.visible.size + end + + def image_attachment + Attachment.find_by_id(attachment_id) + end + + def children_forum + ForumSection.where(parent_id: id) + end + + def parent_forum + ForumSection.find_by_id(parent_id) + end + + def get_children_section(type) + children.order("position #{type}") + # ForumSection.where(parent_id: id).order("position #{type}") + end + end diff --git a/app/models/memo.rb b/app/models/memo.rb index 1094bca0..666cc0b4 100644 --- a/app/models/memo.rb +++ b/app/models/memo.rb @@ -1,2 +1,391 @@ +# root_id:nil => 主贴; 有值 => 主帖的ID(值为帖子的ID) +# parent_id: 回复(对这个id的回复) +# sticky 顶置 1 +# is_fine 是否加精,默认为false +# hidden 是否隐藏 + +require 'elasticsearch/model' class Memo < ApplicationRecord + + include Redmine::SafeAttributes + include UserScoreHelper + include ApplicationHelper + include Elasticsearch::Model + #敏感词过滤 + include DunCheckAble + has_many :forums, :through => :memo_forums + belongs_to :forum_section, counter_cache: true + has_many :memo_forums, :dependent => :destroy + has_many :visit_actions, as: :visitable, dependent: :destroy + #用户是否禁言 + has_many :banned_forums + has_many_kindeditor_assets :assets, :dependent => :destroy + has_many :tidings, :as => :container , :dependent => :destroy + belongs_to :author, :class_name => "User", :foreign_key => 'author_id' + validates_presence_of :author_id, :subject,:content + # 若是主题帖,则内容可以是空 + #validates :content, presence: true, if: Proc.new{|o| !o.parent_id.nil? } + validates_length_of :subject, maximum: 50 + + validate :cannot_reply_to_locked_topic, :on => :create + + scope :total_replies, ->{where("hidden = false and root_id is not null")} + + # 创意征集方式 0-默认,1-申请, ps. 删除后,该帖子即删除, 拒绝后,该帖子状态将为初始状态 + as_enum :memo_destroy_status, %i{common apply_destroy}, :column => 'destroy_status' + acts_as_watchable + #elasticsearch kaminari init + Kaminari::Hooks.init + Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari + settings index: { + number_of_shards: 5 , + analysis: { + char_filter: { + and_filter: { + type: "mapping", + mappings: [ "&=> and "] + } + }, + analyzer: { + my_analyzer: { + type: 'custom', + tokenizer: 'standard', + filter: ['classic'], + char_filter: ['html_strip'] + } + } + } + } do + mappings dynamic: 'false' do + indexes :subject, analyzer: 'smartcn',index_options: 'offsets'#, char_filter: 'html_strip' + indexes :content, analyzer:'my_analyzer',index_options: 'offsets',search_analyzer: 'smartcn' + indexes :updated_at,index:"not_analyzed" ,type:'date' + end + end + + acts_as_tree :counter_cache => :replies_count, :order => "#{Memo.table_name}.created_at ASC", dependent: :destroy + acts_as_attachable + has_many :user_score_details, :class_name => 'UserScoreDetails',:as => :score_changeable_obj + has_many :praise_tread, as: :praise_tread_object, dependent: :destroy + has_one :praise_tread_cache, as: :object, dependent: :destroy + + # 消息 + has_many :memo_messages, :class_name =>'MemoMessage', :dependent => :destroy + # end + belongs_to :last_reply, :class_name => 'Memo', :foreign_key => 'last_reply_id' + # acts_as_searchable :column => ['subject', 'content'], + # #:include => { :forum => :p} + # #:project_key => "#{Forum.table_name}.project_id" + # :date_column => "#{table_name}.created_at" + #acts_as_event :title => Proc.new {|o| "#{o.forum.name}: #{o.subject}"}, + #:datetime => :updated_at, + # :datetime => :created_at, + #:description => :content, + #:author => :author, + #:type => Proc.new {|o| o.parent_id.nil? ? 'Memo' : 'Reply'}, + #:url => Proc.new {|o| {:controller => 'memos', :action => 'show', :forum_id => o.forum_id}.merge(o.parent_id.nil? ? {:id => o.id} : {:id => o.parent_id, :r => o.id, :anchor => "reply-#{o.id}"})} + acts_as_activity_provider :author_key => :author_id, + :func => 'memos', + :timestamp => 'created_at' + # :find_options => {:type => 'memos'} + # acts_as_watchable + + safe_attributes "author_id", + "subject", + "content", + "last_memo_id", + "lock", + "sticky", + "parent_id", + "replies_count", + "root_id", + "language" + + # after_create :add_author_as_watcher, :reset_counters!, :send_tiding + # after_create :add_author_as_watcher #浏览记录 + after_update + # after_destroy :reset_counters!,:delete_kindeditor_assets #,:down_user_score -- 公共区发帖暂不计入得分, + # after_create :send_notification + # after_save :plusParentAndForum + # after_destroy :minusParentAndForum + #before_save :be_user_score + # scope :visible, lambda { |*args| + # includes(:forum => ).where() + # } + scope :indexable,lambda { + where('parent_id is null') + } + scope :visible, lambda{where(hidden: false)} + scope :hidden_memos, lambda{where(hidden: true)} + scope :field_for_list, lambda{ + select([:id, :subject,:destroy_status, :author_id, :sticky, :published_at, :language, :reward, :replies_count,:is_fine, :viewed_count, :praises_count,:forum_section_id, :tag_id, :is_original]) + } + scope :field_for_recommend, lambda{select([:id, :subject, :replies_count, :language])} + scope :user_posts, ->(user_id){where(root_id: nil, author_id: user_id)} + scope :user_replies, ->(user_id){where("root_id is not null and author_id = ?", user_id)} + scope :memo_replies, ->(id){where(:root_id => id)} + scope :hot, lambda{order("replies_count desc")} + scope :posts, lambda{ where(root_id: nil) } + scope :recommend_memos, lambda{ where(is_fine: true) } + scope :in_week, lambda{ where("published_at >= ?",7.days.ago ) } + scope :related_search_name, -> (name) {ransack(subject_cont: "#{name}").result(distinct: true)} + + scope :order_index, -> (sort_params) {reorder("sticky desc, is_fine desc, #{sort_params} desc")} + + def self.search_by_time(time_type, start_time, end_time) + where("#{time_type} between ? and ?",start_time.present? ? start_time.to_time : Time.now, end_time.present? ? end_time.to_time.end_of_day : Time.now) + end + + + def self.search(query) + __elasticsearch__.search( + { + query: { + multi_match: { + query: query, + type:"most_fields", + operator: "or", + fields: ['subject','content^0.5'] + } + }, + sort: { + _score:{order: "desc" }, + updated_at:{order: "desc" } + }, + highlight: { + pre_tags: [''], + post_tags: [''], + fields: { + subject: {}, + content: {} + } + } + } + ) + end + + def memo_parent + Memo.find(parent_id) + end + + def last_reply_memo(show_hidden_memo) + memo_children = self.children + if !show_hidden_memo + memo_children = memo_children.visible + end + memo_children&.reorder("created_at desc")&.first + end + + + def reply_for_memo + Memo.where(:parent_id => self.id) + end + + def all_replies + Memo.where(:root_id => self.id) + end + + #未审核发布的帖子数 + def uncheck_memo_count + self&.reply_for_memo&.where(hidden: true).size + end + + def can_see_reply_count(user) + memo_replies_count = self.replies_count + unless user.try(:admin?) + uncheck_memos_count = self.uncheck_memo_count #全部未审核的 + user_uncheck_memos_count = self&.reply_for_memo&.where("hidden = true and author_id = ?", user.id)&.size #当前用户发布的,且未审核的 + memo_replies_count = memo_replies_count - uncheck_memos_count + user_uncheck_memos_count + end + memo_replies_count + end + + def self.hottest_five_memos + order("replies_count desc, praises_count desc, viewed_count desc").limit(8).select([:id,:subject]) + end + + def self.recommend_five_memos + recommend_memos.order("updated_at desc").limit(8).select([:id,:subject]) + end + + + def send_mail + # Mailer.run.forum_message_added(self) if Setting.notified_events.include?('forum_message_added') + end + + def creator_user + self.author + end + + def created_time + self.created_on + end + + def content_detail + self.content + end + + # 公共贴吧消息记录 + # 原则:新帖子给超级管理员发消息 + def send_tiding + if self.parent_id.present? + # self.tidings << Tiding.new(:user_id => self.parent.author_id, :trigger_user_id => self.author_id, :parent_container_id => self.root_id, :parent_container_type => "Memo", + # :belong_container_id => self.forum_id, :belong_container_type => "Forum", :viewed => 0, :tiding_type => "Comment") + else + self.tidings << Tiding.new(:user_id => 1, :trigger_user_id => self.author_id, :parent_container_id => self.id, :parent_container_type => "Memo", :viewed => 0, :tiding_type => "Comment") + end + end + + def cannot_reply_to_locked_topic + errors.add :base, l(:label_memo_locked) if root.locked? && self != root + end + + # def update_memos_forum + # if forum_id_changed? + # Message.update_all({:board_id => board_id}, ["id = ? OR parent_id = ?", root.id, root.id ]) + # Forum.reset_counters!(forum_id_was) + # Forum.reset_counters!(forum_id) + # end + # end + + def reset_counters! + if parent && parent.id + parent.update_attribute(:last_reply_id, parent.children.maximum(:id)) + end + if root + root.update_attribute(:last_reply_id, Memo.where(:root_id => root.id).maximum(:id)) unless root.destroyed? + end + forum.reset_counters! + end + + def sticky? + sticky == 1 + end + + def replies + Memo.where("parent_id = ?", id) + end + + def locked? + self.lock + end + + def editable_by? user + # user && user.logged? || (self.author == usr && usr.allowed_to?(:edit_own_messages, project)) + user.admin? || self.author == user + end + + def destroyable_by? user + (user && self.author == user) || user.admin? || self.forum.creator == user || Memo.find(self.root_id).author == user + #self.author == user || user.admin? + end + + def deleted_attach_able_by? user + (user && user.logged? && (self.author == user) ) || user.admin? + end + + def meno_tag_name + tag_id.to_i == 1 ? "交流" : "求助" + end + + def update_attachments(attachment_ids) + Attachment.where(id: attachment_ids).update_all(container_id: id, container_type: "Memo") + end + + private + + def add_author_as_watcher + Watcher.create(:watchable => self.root, :user => author) + end + + def send_notification + # if Setting.notified_events.include?('message_posted') + # Mailer.run.message_posted(self) + # end + end + + # def update_reply_count + # if self.root_id + # self.root.increment!(:replies_count) + # end + # end + + def plusParentAndForum + @forum = Forum.find(self.forum_id) + @forum.memo_count = @forum.memo_count.to_int + 1 + @forum.last_memo_id = self.id + if self.parent_id + @parent_memo = Memo.find_by_id(self.parent_id) + @parent_memo.last_reply_id = self + @parent_memo.replies_count = @parent_memo.replies_count.to_int + 1 + @parent_memo.save + else + @forum.topic_count = @forum.topic_count.to_int + 1 + end + @forum.save + end + + def minusParentAndForum + @forum = Forum.find(self.forum_id) + @forum.memo_count = @forum.memo_count.to_int - 1 + @forum.memo_count = 0 if @forum.memo_count.to_int < 0 + # @forum.last_memo_id = Memo.reorder('created_at ASC').find_all_by_forum_id(self.forum_id).last.id + if self.parent_id + @parent_memo = Memo.find_by_id(self.parent_id) + # @parent_memo.last_reply_id = Memo.reorder('created_at ASC').find_all_by_parent_id(self.parent_id).last.id + @parent_memo.replies_count = @parent_memo.replies_count.to_int - 1 + @parent_memo.replies_count = 0 if @parent_memo.replies_count.to_int < 0 + @parent_memo.save + else + @forum.topic_count = @forum.topic_count.to_int - 1 + @forum.topic_count = 0 if @forum.topic_count.to_int < 0 + end + @forum.save + end + + #更新用户分数 -by zjc + def be_user_score + #新建memo且无parent的为发帖 + if self.parent_id.nil? + UserScore.joint(:post_message, User.current,nil,self ,{ memo_id: self.id }) + update_memo_number(User.current,1) + + #新建memo且有parent的为回帖 + elsif !self.parent_id.nil? + UserScore.joint(:reply_posting, User.current,self.parent.author,self, { memo_id: self.id }) + update_replay_for_memo(User.current,1) + end + end + + #被删除时更新用户分数 + def down_user_score + update_memo_number(User.current,1) + update_replay_for_memo(User.current,1) + end + + + # Time 2015-03-26 15:20:24 + # Author lizanle + # Description 从硬盘上删除资源 + def delete_kindeditor_assets + delete_kindeditor_assets_from_disk self.id,OwnerTypeHelper::MEMO + end + + def create_memo_ealasticsearch_index + if self.parent_id.nil? + self.__elasticsearch__.index_document + end + end + def update_memo_ealasticsearch_index + if self.parent_id.nil? + self.__elasticsearch__.update_document + end + end + def delete_memo_ealasticsearch_index + if self.parent_id.nil? + self.__elasticsearch__.delete_document + end + end + + end diff --git a/app/models/memo_forum.rb b/app/models/memo_forum.rb index 0fef720d..d972bb27 100644 --- a/app/models/memo_forum.rb +++ b/app/models/memo_forum.rb @@ -1,2 +1,5 @@ class MemoForum < ApplicationRecord + belongs_to :memo + belongs_to :forum + belongs_to :forum_section, foreign_key: "forum_id" end diff --git a/app/models/section_notice.rb b/app/models/section_notice.rb index 29148932..1665271f 100644 --- a/app/models/section_notice.rb +++ b/app/models/section_notice.rb @@ -1,2 +1,3 @@ class SectionNotice < ApplicationRecord + belongs_to :forum_section end diff --git a/app/models/visit_action.rb b/app/models/visit_action.rb index b439de0a..4fcb4c2a 100644 --- a/app/models/visit_action.rb +++ b/app/models/visit_action.rb @@ -1,2 +1,7 @@ class VisitAction < ApplicationRecord + belongs_to :visitable, polymorphic: true + + def self.search_by_time(time_type, start_time, end_time) + where("#{time_type} between ? and ?",start_time.present? ? start_time.to_time : Time.now, end_time.present? ? end_time.to_time.end_of_day : Time.now) + end end