beetle_reporter 0.1.0 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +20 -0
- data/README.md +70 -16
- data/Rakefile +5 -9
- data/app/assets/config/beetle_reporter_manifest.js +1 -0
- data/app/assets/stylesheets/beetle_reporter/application.css +15 -0
- data/app/assets/stylesheets/beetle_reporter/home.css +4 -0
- data/app/assets/stylesheets/beetle_reporter/reports.css +4 -0
- data/app/assets/stylesheets/beetle_reporter/tailwind.min.css +1 -0
- data/app/assets/stylesheets/scaffold.css +80 -0
- data/app/controllers/beetle_reporter/application_controller.rb +11 -0
- data/app/controllers/beetle_reporter/home_controller.rb +8 -0
- data/app/controllers/beetle_reporter/reports_controller.rb +166 -0
- data/app/helpers/beetle_reporter/application_helper.rb +9 -0
- data/app/helpers/beetle_reporter/home_helper.rb +4 -0
- data/app/helpers/beetle_reporter/reports_helper.rb +4 -0
- data/app/jobs/beetle_reporter/application_job.rb +4 -0
- data/app/mailers/beetle_reporter/application_mailer.rb +6 -0
- data/app/models/beetle_reporter/application_record.rb +5 -0
- data/app/models/beetle_reporter/report.rb +123 -0
- data/app/views/beetle_reporter/home/index.html.haml +4 -0
- data/app/views/beetle_reporter/reports/_form.html.haml +14 -0
- data/app/views/beetle_reporter/reports/_report.html.haml +55 -0
- data/app/views/beetle_reporter/reports/destroy.turbo_stream.haml +1 -0
- data/app/views/beetle_reporter/reports/edit.html.haml +6 -0
- data/app/views/beetle_reporter/reports/index.html.haml +38 -0
- data/app/views/beetle_reporter/reports/new.html.haml +5 -0
- data/app/views/beetle_reporter/reports/show.html.haml +1 -0
- data/app/views/layouts/beetle_reporter/application.html.haml +22 -0
- data/config/locales/beetle_reporter.yml +18 -0
- data/config/routes.rb +13 -0
- data/db/migrate/20211216073022_create_beetle_reporter_reports.rb +20 -0
- data/lib/beetle_reporter/configuration.rb +9 -0
- data/lib/beetle_reporter/engine.rb +9 -0
- data/lib/beetle_reporter/version.rb +1 -3
- data/lib/beetle_reporter.rb +46 -4
- data/lib/tasks/beetle_reporter_tasks.rake +4 -0
- metadata +137 -15
- data/.rspec +0 -3
- data/.rubocop.yml +0 -13
- data/CHANGELOG.md +0 -5
- data/Gemfile +0 -12
- data/LICENSE.txt +0 -21
- data/beetle_reporter.gemspec +0 -39
- data/bin/console +0 -15
- 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,166 @@
|
|
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
|
+
respond_to do |format|
|
73
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
74
|
+
format.html { redirect_to reports_url, notice: 'report was successfully ignored.' }
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def suspend
|
79
|
+
@report.suspend!
|
80
|
+
|
81
|
+
respond_to do |format|
|
82
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
83
|
+
format.html { redirect_to reports_url, notice: 'report was successfully suspended.' }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def hide
|
88
|
+
@report.beetle_hide(params[:reason])
|
89
|
+
|
90
|
+
respond_to do |format|
|
91
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
92
|
+
format.html { redirect_to reports_url, notice: 'report was successfully hidden.' }
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def remove
|
97
|
+
@report.beetle_remove(params[:reason])
|
98
|
+
|
99
|
+
respond_to do |format|
|
100
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
101
|
+
format.html { redirect_to reports_url, notice: 'report was successfully removed.' }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def mute
|
106
|
+
# TODO: 禁言时间
|
107
|
+
@report.beetle_mute(params[:reason])
|
108
|
+
|
109
|
+
respond_to do |format|
|
110
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
111
|
+
format.html { redirect_to reports_url, notice: 'report was successfully muted.' }
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def forbid
|
116
|
+
@report.beetle_forbid(params[:reason])
|
117
|
+
|
118
|
+
respond_to do |format|
|
119
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
120
|
+
format.html { redirect_to reports_url, notice: 'report was successfully forbiden.' }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def undo
|
125
|
+
@report.undo!
|
126
|
+
|
127
|
+
respond_to do |format|
|
128
|
+
format.turbo_stream { render turbo_stream: turbo_stream.remove(dom_id(@report)) }
|
129
|
+
format.html { redirect_to reports_url, notice: 'report was successfully undo.' }
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
def load_reports
|
136
|
+
builder = report_scope.includes(:record)
|
137
|
+
builder = builder.where("reason ilike ?", "%#{params[:q]}%") if params[:q].present?
|
138
|
+
|
139
|
+
if params[:filter] != 'all'
|
140
|
+
builder = builder.pending
|
141
|
+
builder = builder.unscope(where: :aasm_state).where(aasm_state: params[:state]) if params[:state].present?
|
142
|
+
end
|
143
|
+
builder = builder.where(record_type: params[:type]&.classify) if params[:type].present?
|
144
|
+
|
145
|
+
builder = builder.order(id: :desc, reported_count: :desc)
|
146
|
+
builder = builder.reorder(updated_at: :desc) if params[:order] == 'last_updated'
|
147
|
+
builder = builder.reorder(created_at: :desc) if params[:order] == 'last_created'
|
148
|
+
builder = builder.reorder(updated_at: :asc) if params[:order] == 'oldest_updated'
|
149
|
+
builder = builder.reorder(created_at: :asc) if params[:order] == 'oldest_created'
|
150
|
+
|
151
|
+
@pagy, @reports = pagy(builder)
|
152
|
+
end
|
153
|
+
|
154
|
+
def load_report
|
155
|
+
@report = report_scope.find(params[:id] || params[:report_id])
|
156
|
+
end
|
157
|
+
|
158
|
+
def report_scope
|
159
|
+
BeetleReporter::Report.kept
|
160
|
+
end
|
161
|
+
|
162
|
+
def report_params
|
163
|
+
params.require(:report).permit(:id, :record_id, :record_type, :reason, :user_id, :device_id)
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
module BeetleReporter
|
2
|
+
class Report < ApplicationRecord
|
3
|
+
include AASM
|
4
|
+
include Discard::Model
|
5
|
+
|
6
|
+
REASON_TYPES = %w(垃圾广告营销 侮辱谩骂内容 淫秽色情内容 涉政敏感信息 违法有害信息 内容令人不适 内容存在错误)
|
7
|
+
|
8
|
+
belongs_to :record, polymorphic: true, required: false
|
9
|
+
belongs_to :user, class_name: BeetleReporter.config.user_class, optional: true
|
10
|
+
|
11
|
+
aasm do
|
12
|
+
state :pending, initial: true
|
13
|
+
state :ignored, :hidden, :removed, :muted, :forbiden, :suspended
|
14
|
+
|
15
|
+
event :ignore do
|
16
|
+
transitions from: :pending, to: :ignored
|
17
|
+
end
|
18
|
+
|
19
|
+
event :hide do
|
20
|
+
transitions from: %i[pending ignored], to: :hidden, after: Proc.new {|*args| set_reason(*args) }
|
21
|
+
end
|
22
|
+
|
23
|
+
event :remove do
|
24
|
+
transitions from: %i[pending ignored], to: :removed, after: Proc.new {|*args| set_reason(*args) }
|
25
|
+
end
|
26
|
+
|
27
|
+
event :mute do
|
28
|
+
transitions from: %i[pending ignored], to: :muted, after: Proc.new {|*args| set_reason(*args) }
|
29
|
+
end
|
30
|
+
|
31
|
+
event :forbid do
|
32
|
+
transitions from: %i[pending muted], to: :forbiden, after: Proc.new {|*args| set_reason(*args) }
|
33
|
+
end
|
34
|
+
|
35
|
+
event :suspend do
|
36
|
+
transitions from: :pending, to: :suspended
|
37
|
+
end
|
38
|
+
|
39
|
+
event :undo do
|
40
|
+
transitions from: %i[ignored hidden removed muted forbiden suspended], to: :pending, after: :undo_callback
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def beetle_hide(reason)
|
45
|
+
return if record.blank?
|
46
|
+
raise NoMethodError unless record.respond_to?(:beetle_hide)
|
47
|
+
|
48
|
+
ret = record.beetle_hide
|
49
|
+
hide!(reason) if ret
|
50
|
+
end
|
51
|
+
|
52
|
+
def beetle_remove(reason)
|
53
|
+
return if record.blank?
|
54
|
+
raise NoMethodError unless record.respond_to?(:beetle_remove)
|
55
|
+
|
56
|
+
ret = record.beetle_remove
|
57
|
+
remove!(reason) if ret
|
58
|
+
end
|
59
|
+
|
60
|
+
def beetle_mute(reason)
|
61
|
+
return if record.blank?
|
62
|
+
return if record&.user.blank?
|
63
|
+
raise NoMethodError unless record.respond_to?(:beetle_mute)
|
64
|
+
|
65
|
+
ret = record.beetle_mute
|
66
|
+
mute!(reason) if ret
|
67
|
+
end
|
68
|
+
|
69
|
+
def beetle_mute(reason)
|
70
|
+
return if record.blank?
|
71
|
+
return if record&.user.blank?
|
72
|
+
raise NoMethodError unless record.respond_to?(:beetle_mute)
|
73
|
+
|
74
|
+
ret = record.beetle_mute
|
75
|
+
mute!(reason) if ret
|
76
|
+
end
|
77
|
+
|
78
|
+
def beetle_forbid(reason)
|
79
|
+
return if record.blank?
|
80
|
+
return if record&.user.blank?
|
81
|
+
raise NoMethodError unless record.respond_to?(:beetle_forbid)
|
82
|
+
|
83
|
+
ret = record.beetle_forbid
|
84
|
+
forbid!(reason) if ret
|
85
|
+
end
|
86
|
+
|
87
|
+
def record_path
|
88
|
+
return '#' if record.blank?
|
89
|
+
|
90
|
+
record.beetle_record_path
|
91
|
+
end
|
92
|
+
|
93
|
+
def record_partial_path
|
94
|
+
record.beetle_record_partial_path
|
95
|
+
end
|
96
|
+
|
97
|
+
def undo_callback
|
98
|
+
if hidden?
|
99
|
+
ret = record.beetle_undo_hide
|
100
|
+
update_columns(reason: nil) if ret
|
101
|
+
elsif removed?
|
102
|
+
ret = record.beetle_undo_remove
|
103
|
+
update_columns(reason: nil) if ret
|
104
|
+
elsif muted?
|
105
|
+
ret = record.beetle_undo_mute
|
106
|
+
update_columns(reason: nil) if ret
|
107
|
+
elsif forbiden?
|
108
|
+
ret = record.beetle_undo_forbid
|
109
|
+
update_columns(reason: nil) if ret
|
110
|
+
else
|
111
|
+
update_columns(reason: nil)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def set_reason(reason)
|
116
|
+
update_columns(reason: reason)
|
117
|
+
end
|
118
|
+
|
119
|
+
def self.record_type_options
|
120
|
+
select(:record_type).where.not(record_type: nil).distinct.map{|t| [t.record_type, t.record_type.downcase]}
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -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,55 @@
|
|
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
|
+
- unless report.reasons.blank?
|
10
|
+
- report.reasons.each do |reason|
|
11
|
+
%span{class: "border border-red-600 text-red-600 rounded-lg text-xs p-0.5"}= reason
|
12
|
+
%span{class: "flex space-x-2 items-center text-sm"}
|
13
|
+
- if report.reason
|
14
|
+
%span{class: "bg-red-100 text-red-600 p-1 rounded-lg"}= "处置原因:#{report.reason}"
|
15
|
+
%span{class: "space-x-1"}
|
16
|
+
- report.user_ids.compact.uniq.each do |uid|
|
17
|
+
= link_to main_app.send(BeetleReporter.config.main_app_user_path_method.to_sym, uid), data: {turbo: false} do
|
18
|
+
%span{class: "bg-blue-100 rounded-lg px-1 py-0.5"}= "#{uid}"
|
19
|
+
%span{class: "bg-red-600 text-white rounded-full w-5 h-5 flex justify-center items-center"}= "#{report.reported_count}"
|
20
|
+
%span{class: "bg-gray-100 text-gray-600 py-1 px-2 rounded-lg"}
|
21
|
+
= link_to report.created_at, report_path(report), data: {turbo: false}
|
22
|
+
- unless current_user&.admin?
|
23
|
+
= 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"
|
24
|
+
%div{class: "flex justify-between items-center py-2 w-full"}
|
25
|
+
%div{class: "flex flex-col rounded-lg bg-gray-50 p-3 text-sm space-y-4 w-full"}
|
26
|
+
- unless report.record
|
27
|
+
%h3{class: "text-2xl text-red-600 flex items-center"}
|
28
|
+
对应条目已被永久删除,当前审核请求已无效
|
29
|
+
=button_to "点我删除", report, method: :delete, class: "ml-2 bg-yellow-500 text-white rounded-lg px-2 py-0.5 cursor-pointer"
|
30
|
+
- else
|
31
|
+
= render report.record_partial_path, record: report.record
|
32
|
+
%div{class: "flex flex-col space-y-2"}
|
33
|
+
- if report.may_ignore?
|
34
|
+
= button_to "无效举报", report_ignore_path(report), class: "text-yellow-600 cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
35
|
+
- if report.may_suspend?
|
36
|
+
= button_to "暂缓处理", report_suspend_path(report), class: "text-indigo-600 cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
37
|
+
- if report.may_undo?
|
38
|
+
= button_to "撤销", report_undo_path(report), class: "text-red-600 cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
39
|
+
- if report.may_hide?
|
40
|
+
= form_with(url: report_hide_path(report), class: "space-x-1 flex items-center") do |f|
|
41
|
+
= f.text_field :reason, value: report.reason, placeholder: "隐藏原因是什么?", class: "border rounded-md m py-0.5 px-1"
|
42
|
+
= f.submit "隐藏内容", class: "bg-red-500 text-white cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
43
|
+
- if report.may_remove?
|
44
|
+
= form_with(url: report_remove_path(report), class: "space-x-1 flex items-center") do |f|
|
45
|
+
= f.text_field :reason, value: report.reason, placeholder: "删除原因是什么?", class: "border rounded-md m py-0.5 px-1"
|
46
|
+
= f.submit "删除内容", class: "bg-red-600 text-white cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
47
|
+
- if report.may_mute?
|
48
|
+
= form_with(url: report_mute_path(report), class: "space-x-1 flex items-center") do |f|
|
49
|
+
-# = f.text_field :mute_days, value: report.mute_days, placeholder: "禁言天数", class: "border rounded-md m py-0.5 px-1"
|
50
|
+
= f.text_field :reason, value: report.reason, placeholder: "禁言原因是什么?", class: "border rounded-md m py-0.5 px-1"
|
51
|
+
= f.submit "禁言用户", class: "bg-red-700 text-white cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
52
|
+
- if report.may_forbid?
|
53
|
+
= form_with(url: report_forbid_path(report), class: "space-x-1 flex items-center") do |f|
|
54
|
+
= f.text_field :reason, value: report.reason, placeholder: "封禁原因是什么?", class: "border rounded-md m py-0.5 px-1"
|
55
|
+
= f.submit "封禁用户", class: "bg-red-800 text-white cursor-pointer px-2 py-0.5 bg-gray-100 rounded-lg"
|
@@ -0,0 +1 @@
|
|
1
|
+
= turbo_stream.remove(@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 @@
|
|
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,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
|