beetle_reporter 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +70 -16
  4. data/Rakefile +5 -9
  5. data/app/assets/config/beetle_reporter_manifest.js +1 -0
  6. data/app/assets/stylesheets/beetle_reporter/application.css +15 -0
  7. data/app/assets/stylesheets/beetle_reporter/home.css +4 -0
  8. data/app/assets/stylesheets/beetle_reporter/reports.css +4 -0
  9. data/app/assets/stylesheets/beetle_reporter/tailwind.min.css +1 -0
  10. data/app/assets/stylesheets/scaffold.css +80 -0
  11. data/app/controllers/beetle_reporter/application_controller.rb +11 -0
  12. data/app/controllers/beetle_reporter/home_controller.rb +8 -0
  13. data/app/controllers/beetle_reporter/reports_controller.rb +143 -0
  14. data/app/helpers/beetle_reporter/application_helper.rb +9 -0
  15. data/app/helpers/beetle_reporter/home_helper.rb +4 -0
  16. data/app/helpers/beetle_reporter/reports_helper.rb +4 -0
  17. data/app/jobs/beetle_reporter/application_job.rb +4 -0
  18. data/app/mailers/beetle_reporter/application_mailer.rb +6 -0
  19. data/app/models/beetle_reporter/application_record.rb +5 -0
  20. data/app/models/beetle_reporter/report.rb +126 -0
  21. data/app/views/beetle_reporter/home/index.html.haml +4 -0
  22. data/app/views/beetle_reporter/reports/_form.html.haml +14 -0
  23. data/app/views/beetle_reporter/reports/_report.html.haml +57 -0
  24. data/app/views/beetle_reporter/reports/destroy.turbo_stream.haml +1 -0
  25. data/app/views/beetle_reporter/reports/edit.html.haml +6 -0
  26. data/app/views/beetle_reporter/reports/index.html.haml +38 -0
  27. data/app/views/beetle_reporter/reports/new.html.haml +5 -0
  28. data/app/views/beetle_reporter/reports/show.html.haml +1 -0
  29. data/app/views/layouts/beetle_reporter/application.html.haml +22 -0
  30. data/config/locales/beetle_reporter.yml +18 -0
  31. data/config/routes.rb +13 -0
  32. data/db/migrate/20211216073022_create_beetle_reporter_reports.rb +20 -0
  33. data/lib/beetle_reporter/configuration.rb +9 -0
  34. data/lib/beetle_reporter/engine.rb +9 -0
  35. data/lib/beetle_reporter/version.rb +1 -3
  36. data/lib/beetle_reporter.rb +46 -4
  37. data/lib/tasks/beetle_reporter_tasks.rake +4 -0
  38. metadata +137 -15
  39. data/.rspec +0 -3
  40. data/.rubocop.yml +0 -13
  41. data/CHANGELOG.md +0 -5
  42. data/Gemfile +0 -12
  43. data/LICENSE.txt +0 -21
  44. data/beetle_reporter.gemspec +0 -39
  45. data/bin/console +0 -15
  46. data/bin/setup +0 -8
@@ -0,0 +1,80 @@
1
+ body {
2
+ background-color: #fff;
3
+ color: #333;
4
+ margin: 33px;
5
+ }
6
+
7
+ body, p, ol, ul, td {
8
+ font-family: verdana, arial, helvetica, sans-serif;
9
+ font-size: 13px;
10
+ line-height: 18px;
11
+ }
12
+
13
+ pre {
14
+ background-color: #eee;
15
+ padding: 10px;
16
+ font-size: 11px;
17
+ }
18
+
19
+ a {
20
+ color: #000;
21
+ }
22
+
23
+ a:visited {
24
+ color: #666;
25
+ }
26
+
27
+ a:hover {
28
+ color: #fff;
29
+ background-color: #000;
30
+ }
31
+
32
+ th {
33
+ padding-bottom: 5px;
34
+ }
35
+
36
+ td {
37
+ padding: 0 5px 7px;
38
+ }
39
+
40
+ div.field,
41
+ div.actions {
42
+ margin-bottom: 10px;
43
+ }
44
+
45
+ #notice {
46
+ color: green;
47
+ }
48
+
49
+ .field_with_errors {
50
+ padding: 2px;
51
+ background-color: red;
52
+ display: table;
53
+ }
54
+
55
+ #error_explanation {
56
+ width: 450px;
57
+ border: 2px solid red;
58
+ padding: 7px 7px 0;
59
+ margin-bottom: 20px;
60
+ background-color: #f0f0f0;
61
+ }
62
+
63
+ #error_explanation h2 {
64
+ text-align: left;
65
+ font-weight: bold;
66
+ padding: 5px 5px 5px 15px;
67
+ font-size: 12px;
68
+ margin: -7px -7px 0;
69
+ background-color: #c00;
70
+ color: #fff;
71
+ }
72
+
73
+ #error_explanation ul li {
74
+ font-size: 12px;
75
+ list-style: square;
76
+ }
77
+
78
+ label {
79
+ display: block;
80
+ }
@@ -0,0 +1,11 @@
1
+ module BeetleReporter
2
+ class ApplicationController < ActionController::Base
3
+ include ActionView::RecordIdentifier
4
+
5
+ include Pagy::Backend
6
+
7
+ def current_user
8
+ main_app.scope.request.env['warden']&.user
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,8 @@
1
+ require_dependency "beetle_reporter/application_controller"
2
+
3
+ module BeetleReporter
4
+ class HomeController < ApplicationController
5
+ def index
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,143 @@
1
+ module BeetleReporter
2
+ class ReportsController < BeetleReporter::ApplicationController
3
+ before_action :load_report, only: %w[show edit update destroy ignore undo suspend hide remove mute forbid]
4
+
5
+ def index
6
+ # authorize Report
7
+
8
+ load_reports
9
+
10
+ # skip_policy_scope
11
+ end
12
+
13
+ def show
14
+ # authorize @report
15
+ end
16
+
17
+ def new
18
+ # authorize Report
19
+
20
+ @report = Report.new
21
+ end
22
+
23
+ def create
24
+ # authorize Report
25
+
26
+ create_params = report_params.to_hash.deep_symbolize_keys
27
+ @report = report_scope.new(create_params)
28
+ @report.user = current_user
29
+
30
+ respond_to do |format|
31
+ if @report.save
32
+ format.turbo_stream { render turbo_stream: turbo_stream.replace(dom_id(@report), partial: "report", locals: {report: @report}) }
33
+ format.html { redirect_to reports_path, notice: "report was successfully created." }
34
+ else
35
+ format.html { render :edit, status: :unprocessable_entity }
36
+ end
37
+ end
38
+ end
39
+
40
+ def edit
41
+ # authorize @report
42
+ end
43
+
44
+ def update
45
+ # authorize @report
46
+
47
+ update_params = report_params.to_hash.deep_symbolize_keys
48
+
49
+ respond_to do |format|
50
+ if @report.update(update_params)
51
+ format.turbo_stream { render turbo_stream: turbo_stream.replace(dom_id(@report), partial: "report", locals: {report: @report}) }
52
+ format.html { redirect_to reports_path, notice: "report was successfully updated." }
53
+ else
54
+ format.html { render :edit, status: :unprocessable_entity }
55
+ end
56
+ end
57
+ end
58
+
59
+ def destroy
60
+ # authorize @report
61
+
62
+ @report.discard
63
+
64
+ respond_to do |format|
65
+ format.turbo_stream
66
+ end
67
+ end
68
+
69
+ def ignore
70
+ @report.ignore!
71
+
72
+ redirect_to reports_url, notice: 'report was successfully ignored.'
73
+ end
74
+
75
+ def suspend
76
+ @report.suspend!
77
+
78
+ redirect_to reports_url, notice: 'report was successfully ignored.'
79
+ end
80
+
81
+ def hide
82
+ @report.beetle_hide("fooobar hide")
83
+
84
+ redirect_to reports_url, notice: 'report was successfully hidden.'
85
+ end
86
+
87
+ def remove
88
+ @report.beetle_remove("fooobar remove")
89
+
90
+ redirect_to reports_url, notice: 'report was successfully removed.'
91
+ end
92
+
93
+ def mute
94
+ @report.beetle_mute("fooobar mute")
95
+
96
+ redirect_to reports_url, notice: 'report was successfully muted.'
97
+ end
98
+
99
+ def forbid
100
+ @report.beetle_forbid("fooobar forbid")
101
+
102
+ redirect_to reports_url, notice: 'report was successfully forbiden.'
103
+ end
104
+
105
+ def undo
106
+ @report.undo!
107
+
108
+ redirect_to reports_url, notice: 'report was successfully ignored.'
109
+ end
110
+
111
+ private
112
+
113
+ def load_reports
114
+ builder = report_scope.includes(:record)
115
+ builder = builder.where("reason ilike ?", "%#{params[:q]}%") if params[:q].present?
116
+ if params[:filter] != 'all'
117
+ builder = builder.pending
118
+ builder = builder.unscope(where: :aasm_state).where(aasm_state: params[:state]) if params[:state].present?
119
+ end
120
+ builder = builder.where(record_type: params[:type]&.classify) if params[:type]
121
+
122
+ builder = builder.order(id: :desc, reported_count: :desc)
123
+ builder = builder.reorder(updated_at: :desc) if params[:order] == 'last_updated'
124
+ builder = builder.reorder(created_at: :desc) if params[:order] == 'last_created'
125
+ builder = builder.reorder(updated_at: :asc) if params[:order] == 'oldest_updated'
126
+ builder = builder.reorder(created_at: :asc) if params[:order] == 'oldest_created'
127
+
128
+ @pagy, @reports = pagy(builder)
129
+ end
130
+
131
+ def load_report
132
+ @report = report_scope.find(params[:id] || params[:report_id])
133
+ end
134
+
135
+ def report_scope
136
+ BeetleReporter::Report.kept
137
+ end
138
+
139
+ def report_params
140
+ params.require(:report).permit(:id, :record_id, :record_type, :reason, :user_id, :device_id)
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,9 @@
1
+ module BeetleReporter
2
+ module ApplicationHelper
3
+ include Pagy::Frontend
4
+
5
+ def current_user
6
+ main_app.scope.request.env['warden']&.user
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,4 @@
1
+ module BeetleReporter
2
+ module HomeHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module BeetleReporter
2
+ module ReportsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module BeetleReporter
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module BeetleReporter
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module BeetleReporter
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,126 @@
1
+ module BeetleReporter
2
+ class Report < ApplicationRecord
3
+ include AASM
4
+ include Discard::Model
5
+
6
+ belongs_to :record, polymorphic: true, required: false
7
+ belongs_to :user, class_name: BeetleReporter.config.user_class, optional: true
8
+
9
+ aasm do
10
+ state :pending, initial: true
11
+ state :ignored, :hidden, :removed, :muted, :forbiden, :suspended
12
+
13
+ event :ignore do
14
+ transitions from: :pending, to: :ignored
15
+ end
16
+
17
+ event :hide do
18
+ transitions from: %i[pending ignored], to: :hidden, after: Proc.new {|*args| set_reason(*args) }
19
+ end
20
+
21
+ event :remove do
22
+ transitions from: %i[pending ignored], to: :removed, after: Proc.new {|*args| set_reason(*args) }
23
+ end
24
+
25
+ event :mute do
26
+ transitions from: %i[pending ignored], to: :muted, after: Proc.new {|*args| set_reason(*args) }
27
+ end
28
+
29
+ event :forbid do
30
+ transitions from: %i[pending muted], to: :forbiden, after: Proc.new {|*args| set_reason(*args) }
31
+ end
32
+
33
+ event :suspend do
34
+ transitions from: :pending, to: :suspended
35
+ end
36
+
37
+ event :undo do
38
+ transitions from: %i[ignored hidden removed muted forbiden suspended], to: :pending, after: :undo_callback
39
+ end
40
+ end
41
+
42
+ def beetle_hide(reason)
43
+ return if record.blank?
44
+ raise NoMethodError unless record.respond_to?(:beetle_hide)
45
+
46
+ ret = record.beetle_hide
47
+ hide!(reason) if ret
48
+ end
49
+
50
+ def beetle_remove(reason)
51
+ return if record.blank?
52
+ raise NoMethodError unless record.respond_to?(:beetle_remove)
53
+
54
+ ret = record.beetle_remove
55
+ remove!(reason) if ret
56
+ end
57
+
58
+ def beetle_mute(reason)
59
+ return if record.blank?
60
+ return if record&.user.blank?
61
+ raise NoMethodError unless record.respond_to?(:beetle_mute)
62
+
63
+ ret = record.beetle_mute
64
+ mute!(reason) if ret
65
+ end
66
+
67
+ def beetle_mute(reason)
68
+ return if record.blank?
69
+ return if record&.user.blank?
70
+ raise NoMethodError unless record.respond_to?(:beetle_mute)
71
+
72
+ ret = record.beetle_mute
73
+ mute!(reason) if ret
74
+ end
75
+
76
+ def beetle_forbid(reason)
77
+ return if record.blank?
78
+ return if record&.user.blank?
79
+ raise NoMethodError unless record.respond_to?(:beetle_forbid)
80
+
81
+ ret = record.beetle_forbid
82
+ forbid!(reason) if ret
83
+ end
84
+
85
+ def record_path
86
+ return '#' if record.blank?
87
+
88
+ record.beetle_record_path
89
+ end
90
+
91
+ def undo_callback
92
+ if hidden?
93
+ ret = record.beetle_undo_hide
94
+ update_columns(reason: nil) if ret
95
+ elsif removed?
96
+ ret = record.beetle_undo_remove
97
+ update_columns(reason: nil) if ret
98
+ elsif muted?
99
+ ret = record.beetle_undo_mute
100
+ update_columns(reason: nil) if ret
101
+ elsif forbiden?
102
+ ret = record.beetle_undo_forbid
103
+ update_columns(reason: nil) if ret
104
+ else
105
+ update_columns(reason: nil)
106
+ end
107
+ end
108
+
109
+ def images
110
+ return [] if record.blank?
111
+
112
+ raise NoMethodError, 'undefined beetle_images for record' unless record.respond_to?(:beetle_images)
113
+
114
+ record.beetle_images
115
+ end
116
+
117
+
118
+ def set_reason(reason)
119
+ update_columns(reason: reason)
120
+ end
121
+
122
+ def self.record_type_options
123
+ select(:record_type).where.not(record_type: nil).distinct.map{|t| [t.record_type, t.record_type.downcase]}
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,4 @@
1
+ %h1{class: "text-red-400 text-xl"} Home#index
2
+ %p Find me in app/views/beetle_reporter/home/index.html.erb2
3
+
4
+ %div=link_to "举报中心", reports_path
@@ -0,0 +1,14 @@
1
+ - url = report&.id.blank? ? reports_path : report_path(report)
2
+
3
+ = form_with(model: report, id: dom_id(report), url: url, local: true ) do |form|
4
+ - if report.errors.any?
5
+ %h2= "#{pluralize(report.errors.count, "error")} prohibited this report from being saved:"
6
+ %ul
7
+ - report.errors.each do |error|
8
+ %li= error.full_message
9
+ %div{class: "space-y-2"}
10
+ %div
11
+ %div{class: "text-gray-500 text-xs"}= form.label :reason, "举报原因"
12
+ %div= form.text_field :reason, class: "border p-1 w-full rounded-md"
13
+ %div
14
+ %div= form.submit "确认", class: "px-2 py-0.5 rounded-md bg-gray-800 text-white"
@@ -0,0 +1,57 @@
1
+ = turbo_frame_tag dom_id(report) do
2
+ %div{class: "flex flex-col space-y-2 border rounded-md p-2 mt-2"}
3
+ %div{class: "flex justify-between text-xs"}
4
+ %span{class: "space-x-2"}
5
+ - unless report.record.blank?
6
+ = link_to report.record_path, data: { turbo: false }, target: "_blank" do
7
+ %span{class: "bg-indigo-100 text-indigo-600 py-1 px-2 rounded-lg"}="#{report.record_type.upcase}##{report.record_id}"
8
+ %span{class: "bg-yellow-100 text-yellow-600 rounded-md p-1"}=t("beetle_reporter.aasm_state.#{report.aasm_state}")
9
+ %span{class: "flex space-x-2 items-center text-sm"}
10
+ - if report.reason
11
+ %span{class: "bg-red-100 text-red-600 p-1 rounded-lg"}= "处置原因:#{report.reason}"
12
+ %span{class: "space-x-1"}
13
+ - report.user_ids.each do |uid|
14
+ = link_to main_app.send(BeetleReporter.config.main_app_user_path_method.to_sym, uid), data: {turbo: false} do
15
+ %span{class: "bg-blue-100 rounded-lg px-1 py-0.5"}= "#{uid}"
16
+ %span{class: "bg-red-600 text-white rounded-full w-5 h-5 flex justify-center items-center"}= "#{report.reported_count}"
17
+ %span{class: "bg-gray-100 text-gray-600 py-1 px-2 rounded-lg"}
18
+ = link_to report.created_at, report_path(report), data: {turbo: false}
19
+ - unless current_user&.admin?
20
+ = button_to '删除', report, method: :delete, data: { confirm: 'Are you sure?'}, class: "bg-red-600 text-white rounded-md px-2 py-0.5 cursor-pointer"
21
+ %div{class: "flex justify-between items-center py-2 w-full"}
22
+ %div{class: "flex flex-col rounded-lg bg-gray-50 p-3 text-sm space-y-4 w-full"}
23
+ -unless report.record
24
+ %h3{class: "text-2xl text-red-600"} 对应条目已被永久删除,当前审核请求已无效,请删除
25
+ - else
26
+ %div
27
+ %span{class: "#{report.record.is_private ? 'bg-black text-white' : 'border border-black text-black' } rounded-lg text-xs p-0.5 px-1"}=report.record.is_private ? "🙈 隐私" : "🙉 公开"
28
+ %span{class: "border border-blue-600 text-blue-600 rounded-lg text-xs p-0.5"}=report.record.is_approved ? "审核通过" : "审核中..."
29
+ - unless report.reasons.blank?
30
+ - report.reasons.each do |reason|
31
+ %span{class: "border border-red-600 text-red-600 rounded-lg text-xs p-0.5"}= reason
32
+ - unless report&.record&.user_id&.blank?
33
+ = link_to main_app.send(CensorBear.config.main_app_user_path_method.to_sym, report.record.user_id), data: {turbo: false} do
34
+ %span{class: "text-sm bg-gray-100 text-gray-600 py-1 px-2 rounded-lg font-bold"}="✍️ ##{report.record.user_id}"
35
+ - if report.record.discarded?
36
+ %div{class: "text-gray-900 leading-relaxed"}
37
+ %del= report.record.content
38
+ - else
39
+ %div{class: "text-gray-900 leading-relaxed"}= report.record.content
40
+ %div
41
+ - report.images.each do |img|
42
+ = image_tag img[:src], class: "w-16 rounded-md"
43
+ %div{class: "flex space-x-2 items-center justify-end"}
44
+ - if report.may_ignore?
45
+ = link_to "忽略", report_ignore_path(report), class: "text-yellow-600 cursor-pointer"
46
+ - if report.may_hide?
47
+ = link_to "隐藏内容", report_hide_path(report), class: "text-purple-600 cursor-pointer"
48
+ - if report.may_remove?
49
+ = link_to "删除内容", report_remove_path(report), class: "text-red-800 cursor-pointer"
50
+ - if report.may_mute?
51
+ = link_to "禁言用户", report_mute_path(report), class: "text-red-600 cursor-pointer"
52
+ - if report.may_forbid?
53
+ = link_to "封禁用户",report_forbid_path(report), class: "text-red-700 cursor-pointer"
54
+ - if report.may_suspend?
55
+ = link_to "暂缓处理", report_suspend_path(report), class: "text-indigo-600 cursor-pointer"
56
+ - if report.may_undo?
57
+ = link_to "撤销", report_undo_path(report), class: "text-red-600 cursor-pointer"
@@ -0,0 +1 @@
1
+ = turbo_stream.remove(@report)
@@ -0,0 +1,6 @@
1
+ = turbo_frame_tag dom_id(@report) do
2
+ %div{class: "bg-gray-100 p-2 rounded-lg"}
3
+ %div{class: "flex justify-between"}
4
+ %div{class: "text-lg font-bold"} 编辑
5
+ %div= link_to '返回', reports_path, class: "text-gray-500"
6
+ = render 'form', report: @report
@@ -0,0 +1,38 @@
1
+ %div{class: "flex flex-col space-y-2 justify-center"}
2
+ %div{class: "flex justify-between"}
3
+ %div
4
+ = form_with(url: reports_path, method: :get, class: "flex items-center") do |f|
5
+ %div{class: "space-x-0.5"}
6
+ = f.text_field :q, value: params[:q], placeholder: "关键词", class: "border rounded-md m py-0.5 px-1"
7
+ = f.select :type, options_for_select(BeetleReporter::Report.record_type_options, params[:type]), {include_blank: "-- 筛选 --"}, class: "border rounded-md m py-0.5 px-1"
8
+ = f.select :order, options_for_select([%w[按最近创建 last_created], %w[按最晚创建 oldest_created]], params[:order]), {include_blank: "-- 排序 --"}, class: "border rounded-md m py-0.5 px-1"
9
+ = f.hidden_field :state, value: params[:state]
10
+ = f.hidden_field :filter, value: params[:filter]
11
+ = f.submit "检索", class: "rounded-md px-2 py-1 text-sm bg-black text-white cursor-pointer"
12
+ = link_to "重置", reports_path, class: "text-sm"
13
+ %div{class: "flex items-center space-x-2"}
14
+ %div{class: "text-sm text-gray-600"}="共 #{@pagy.count} 条"
15
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state].blank? && params[:filter].blank? ? 'font-bold' : ''}"}
16
+ = link_to "待处理", request.params.merge(state: "", filter: "")
17
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'ignored' ? 'font-bold' : ''}"}
18
+ = link_to "无效举报", request.params.merge(state: "ignored", filter: "")
19
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'hidden' ? 'font-bold' : ''}"}
20
+ = link_to "已隐藏", request.params.merge(state: "hidden", filter: "")
21
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'removed' ? 'font-bold' : ''}"}
22
+ = link_to "已删除", request.params.merge(state: "removed", filter: "")
23
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'muted' ? 'font-bold' : ''}"}
24
+ = link_to "已禁言用户", request.params.merge(state: "muted", filter: "")
25
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'forbiden' ? 'font-bold' : ''}"}
26
+ = link_to "已封禁用户", request.params.merge(state: "forbiden", filter: "")
27
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:state] == 'suspended' ? 'font-bold' : ''}"}
28
+ = link_to "暂缓处理", request.params.merge(state: "suspended", filter: "")
29
+ %div{class: "bg-gray-200 rounded-full px-3 py-1 text-xs #{params[:filter] == "all" ? 'font-bold' : ''}"}
30
+ = link_to "全部", request.params.merge(filter: "all", state: "")
31
+ %div
32
+ - if @reports.blank?
33
+ %div{class: "flex justify-center text-gray-500 p-8 border rounded-md"} 空空如也
34
+ - else
35
+ - @reports.each do |report|
36
+ = render report
37
+ %div{class: "flex justify-center mt-2"}
38
+ = raw pagy_nav(@pagy)
@@ -0,0 +1,5 @@
1
+ %div{class: "bg-gray-100 p-2 rounded-lg"}
2
+ %div{class: "flex justify-between"}
3
+ %div{class: "text-lg font-bold"} 添加
4
+ %div= link_to '返回', reports_path, class: "text-gray-500"
5
+ = render 'form', report: @report
@@ -0,0 +1 @@
1
+ = render @report
@@ -0,0 +1,22 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title 🐞 举报中心
5
+ = csrf_meta_tags
6
+ = csp_meta_tag
7
+ = stylesheet_link_tag "beetle_reporter/application", media: "all"
8
+ = javascript_include_tag "turbo", type: "module"
9
+ = yield :head
10
+ %body{class: "flex flex-col space-y-6 p-4"}
11
+ %div{class: "flex justify-between items-center"}
12
+ %h2{class: "text-xl bg-black text-white rounded-full py-1 px-4 cursor-pointer"}
13
+ %span{class: "shadow-lg"} 🐞
14
+ %span 举报中心
15
+
16
+ %ul{class: "flex justify-end items-center space-x-2 text-blue-600"}
17
+ %li= link_to "待处理(#{BeetleReporter::Report.pending.count})", reports_path
18
+ %li= link_to "控制台", main_app.send(BeetleReporter.config.main_app_root_path_method.to_sym)
19
+ %li= current_user.email
20
+
21
+ %div
22
+ = yield
@@ -0,0 +1,18 @@
1
+ "zh-CN":
2
+ beetle_reporter:
3
+ action:
4
+ mod: 审核
5
+ banned: 禁用
6
+ ignore: 忽略
7
+ replace: 替换
8
+ block: 禁用
9
+ pass: 忽略
10
+ review: 审核
11
+ aasm_state:
12
+ pending: 待审
13
+ suspended: 暂缓处理
14
+ ignored: 无效举报
15
+ hidden: 已隐藏
16
+ removed: 已删除
17
+ muted: 已禁言用户
18
+ forbiden: 已封禁用户
data/config/routes.rb ADDED
@@ -0,0 +1,13 @@
1
+ BeetleReporter::Engine.routes.draw do
2
+ resources :reports do
3
+ get :ignore
4
+ get :suspend
5
+ get :undo
6
+ get :hide
7
+ get :remove
8
+ get :mute
9
+ get :forbid
10
+ end
11
+
12
+ root "reports#index"
13
+ end
@@ -0,0 +1,20 @@
1
+ class CreateBeetleReporterReports < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table :beetle_reporter_reports do |t|
4
+ t.bigint :record_id
5
+ t.string :record_type
6
+ t.string :reason
7
+ t.bigint :user_id
8
+ t.bigint :user_ids, array: true, default: []
9
+ t.string :reasons, array: true, default: []
10
+ t.integer :reported_count, default: 0
11
+ t.string :device_id
12
+ t.string :aasm_state
13
+ t.string :treatment_reason
14
+ t.datetime :discarded_at
15
+
16
+ t.timestamps
17
+ end
18
+ add_index :beetle_reporter_reports, :discarded_at
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ module BeetleReporter
2
+ class Configuration
3
+ attr_accessor :user_class
4
+ attr_accessor :current_user_method
5
+ attr_accessor :user_name_method
6
+ attr_accessor :main_app_root_path_method
7
+ attr_accessor :main_app_user_path_method
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module BeetleReporter
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace BeetleReporter
4
+
5
+ initializer "beetle_reporter.assets.precompile" do |app|
6
+ app.config.assets.precompile += %w( beetle_reporter/application.css )
7
+ end
8
+ end
9
+ end
@@ -1,5 +1,3 @@
1
- # frozen_string_literal: true
2
-
3
1
  module BeetleReporter
4
- VERSION = "0.1.0"
2
+ VERSION = '0.1.1'
5
3
  end