beetle_reporter 0.1.0 → 0.1.4
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.
- 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
|