censor_bear 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +80 -0
  4. data/Rakefile +18 -0
  5. data/app/assets/config/censor_bear_manifest.js +1 -0
  6. data/app/assets/stylesheets/censor_bear/application.css +15 -0
  7. data/app/assets/stylesheets/censor_bear/logs.css +4 -0
  8. data/app/assets/stylesheets/censor_bear/mod_logs.css +4 -0
  9. data/app/assets/stylesheets/censor_bear/stop_words.css +4 -0
  10. data/app/assets/stylesheets/censor_bear/tailwind.min.css +1 -0
  11. data/app/assets/stylesheets/scaffold.css +80 -0
  12. data/app/controllers/censor_bear/application_controller.rb +9 -0
  13. data/app/controllers/censor_bear/logs_controller.rb +62 -0
  14. data/app/controllers/censor_bear/mod_logs_controller.rb +87 -0
  15. data/app/controllers/censor_bear/stop_words_controller.rb +69 -0
  16. data/app/helpers/censor_bear/application_helper.rb +5 -0
  17. data/app/helpers/censor_bear/logs_helper.rb +4 -0
  18. data/app/helpers/censor_bear/mod_logs_helper.rb +4 -0
  19. data/app/helpers/censor_bear/stop_words_helper.rb +4 -0
  20. data/app/jobs/censor_bear/application_job.rb +4 -0
  21. data/app/mailers/censor_bear/application_mailer.rb +6 -0
  22. data/app/models/censor_bear/application_record.rb +5 -0
  23. data/app/models/censor_bear/log.rb +4 -0
  24. data/app/models/censor_bear/mod_log.rb +50 -0
  25. data/app/models/censor_bear/stop_word.rb +7 -0
  26. data/app/views/censor_bear/logs/_form.html.erb +37 -0
  27. data/app/views/censor_bear/logs/edit.html.erb +6 -0
  28. data/app/views/censor_bear/logs/index.html.erb +35 -0
  29. data/app/views/censor_bear/logs/new.html.erb +5 -0
  30. data/app/views/censor_bear/logs/show.html.erb +24 -0
  31. data/app/views/censor_bear/mod_logs/_form.html.erb +37 -0
  32. data/app/views/censor_bear/mod_logs/edit.html.erb +6 -0
  33. data/app/views/censor_bear/mod_logs/index.html.erb +44 -0
  34. data/app/views/censor_bear/mod_logs/new.html.erb +5 -0
  35. data/app/views/censor_bear/mod_logs/show.html.erb +24 -0
  36. data/app/views/censor_bear/stop_words/_form.html.haml +30 -0
  37. data/app/views/censor_bear/stop_words/_stop_word.html.haml +33 -0
  38. data/app/views/censor_bear/stop_words/destroy.turbo_stream.haml +1 -0
  39. data/app/views/censor_bear/stop_words/edit.html.haml +6 -0
  40. data/app/views/censor_bear/stop_words/index.html.haml +20 -0
  41. data/app/views/censor_bear/stop_words/new.html.haml +5 -0
  42. data/app/views/censor_bear/stop_words/show.html.haml +1 -0
  43. data/app/views/layouts/censor_bear/application.html.haml +18 -0
  44. data/config/cable.yml +9 -0
  45. data/config/initializers/censor_bear.rb +6 -0
  46. data/config/locales/censor_bear.yml +7 -0
  47. data/config/routes.rb +12 -0
  48. data/db/migrate/20211126133758_create_censor_bear_stop_words.rb +16 -0
  49. data/db/migrate/20211129093508_create_censor_bear_logs.rb +12 -0
  50. data/db/migrate/20211129110218_create_censor_bear_mod_logs.rb +18 -0
  51. data/lib/censor_bear/censor.rb +64 -0
  52. data/lib/censor_bear/configuration.rb +12 -0
  53. data/lib/censor_bear/engine.rb +11 -0
  54. data/lib/censor_bear/version.rb +3 -0
  55. data/lib/censor_bear.rb +36 -0
  56. data/lib/tasks/censor_bear_tasks.rake +4 -0
  57. metadata +177 -0
@@ -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,9 @@
1
+ module CensorBear
2
+ class ApplicationController < ActionController::Base
3
+ include Pagy::Backend
4
+
5
+ def current_user
6
+ main_app.scope.request.env['warden'].user
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,62 @@
1
+ require_dependency "censor_bear/application_controller"
2
+
3
+ module CensorBear
4
+ class LogsController < ApplicationController
5
+ before_action :set_log, only: [:show, :edit, :update, :destroy]
6
+
7
+ # GET /logs
8
+ def index
9
+ @logs = Log.all
10
+ end
11
+
12
+ # GET /logs/1
13
+ def show
14
+ end
15
+
16
+ # GET /logs/new
17
+ def new
18
+ @log = Log.new
19
+ end
20
+
21
+ # GET /logs/1/edit
22
+ def edit
23
+ end
24
+
25
+ # POST /logs
26
+ def create
27
+ @log = Log.new(log_params)
28
+
29
+ if @log.save
30
+ redirect_to @log, notice: 'Log was successfully created.'
31
+ else
32
+ render :new
33
+ end
34
+ end
35
+
36
+ # PATCH/PUT /logs/1
37
+ def update
38
+ if @log.update(log_params)
39
+ redirect_to @log, notice: 'Log was successfully updated.'
40
+ else
41
+ render :edit
42
+ end
43
+ end
44
+
45
+ # DELETE /logs/1
46
+ def destroy
47
+ @log.destroy
48
+ redirect_to logs_url, notice: 'Log was successfully destroyed.'
49
+ end
50
+
51
+ private
52
+ # Use callbacks to share common setup or constraints between actions.
53
+ def set_log
54
+ @log = Log.find(params[:id])
55
+ end
56
+
57
+ # Only allow a list of trusted parameters through.
58
+ def log_params
59
+ params.require(:log).permit(:original_content, :action, :filtered_content, :mod_words)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,87 @@
1
+ require_dependency "censor_bear/application_controller"
2
+
3
+ module CensorBear
4
+ class ModLogsController < ApplicationController
5
+ before_action :set_mod_log, only: [:show, :edit, :update, :destroy, :ignore, :approve, :ban, :delete]
6
+
7
+ # GET /mod_logs
8
+ def index
9
+ @mod_logs = ModLog.pending.all
10
+ end
11
+
12
+ # GET /mod_logs/1
13
+ def show
14
+ end
15
+
16
+ # GET /mod_logs/new
17
+ def new
18
+ @mod_log = ModLog.new
19
+ end
20
+
21
+ # GET /mod_logs/1/edit
22
+ def edit
23
+ end
24
+
25
+ # POST /mod_logs
26
+ def create
27
+ @mod_log = ModLog.new(mod_log_params)
28
+
29
+ if @mod_log.save
30
+ redirect_to @mod_log, notice: 'Mod log was successfully created.'
31
+ else
32
+ render :new
33
+ end
34
+ end
35
+
36
+ # PATCH/PUT /mod_logs/1
37
+ def update
38
+ if @mod_log.update(mod_log_params)
39
+ redirect_to @mod_log, notice: 'Mod log was successfully updated.'
40
+ else
41
+ render :edit
42
+ end
43
+ end
44
+
45
+ # DELETE /mod_logs/1
46
+ def destroy
47
+ @mod_log.destroy
48
+ redirect_to mod_logs_url, notice: 'Mod log was successfully destroyed.'
49
+ end
50
+
51
+ def ignore
52
+ @mod_log.suspend!
53
+
54
+ redirect_to mod_logs_url, notice: 'Mod log was successfully ignored.'
55
+ end
56
+
57
+ def delete
58
+ # TODO: 判断参数不能为空
59
+ @mod_log.delete(params[:reason])
60
+
61
+ redirect_to mod_logs_url, notice: 'Mod log was successfully deleted.'
62
+ end
63
+
64
+ def approve
65
+ @mod_log.approve
66
+
67
+ redirect_to mod_logs_url, notice: 'Mod log was successfully approved.'
68
+ end
69
+
70
+ def ban
71
+ @mod_log.ban_user
72
+
73
+ redirect_to mod_logs_url, notice: 'successfully baned.'
74
+ end
75
+
76
+ private
77
+ # Use callbacks to share common setup or constraints between actions.
78
+ def set_mod_log
79
+ @mod_log = ModLog.find(params[:id] || params[:mod_log_id])
80
+ end
81
+
82
+ # Only allow a list of trusted parameters through.
83
+ def mod_log_params
84
+ params.require(:mod_log).permit(:record_id, :record_type, :mod_words, :user_id, :reason)
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,69 @@
1
+ require_dependency "censor_bear/application_controller"
2
+
3
+ module CensorBear
4
+ class StopWordsController < ApplicationController
5
+ before_action :set_stop_word, only: [:show, :edit, :update, :destroy]
6
+
7
+ def index
8
+ load_stop_words
9
+ end
10
+
11
+ def show; end
12
+
13
+ def new
14
+ @stop_word = StopWord.new
15
+ end
16
+
17
+ def edit; end
18
+
19
+ def create
20
+ @stop_word = StopWord.new(stop_word_params)
21
+ @stop_word.user = current_user
22
+
23
+ if @stop_word.save
24
+ redirect_to @stop_word, notice: 'Stop word was successfully created.'
25
+ else
26
+ render :new
27
+ end
28
+ end
29
+
30
+ def update
31
+ if @stop_word.update(stop_word_params)
32
+ redirect_to @stop_word, notice: 'Stop word was successfully updated.'
33
+ else
34
+ render :edit
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ @stop_word.destroy
40
+
41
+ respond_to do |format|
42
+ format.turbo_stream
43
+ format.html { redirect_to stop_words_url, notice: 'Stop word was successfully destroyed.' }
44
+ end
45
+ end
46
+
47
+ def load_stop_words
48
+ builder ||= stop_word_scope
49
+ builder = builder.where("word ilike ?", "%#{params[:q]}%") if params[:q].present?
50
+ builder = builder.order(id: :desc)
51
+
52
+ @pagy, @stop_words = pagy(builder)
53
+ end
54
+
55
+ private
56
+
57
+ def set_stop_word
58
+ @stop_word = StopWord.find(params[:id])
59
+ end
60
+
61
+ def stop_word_scope
62
+ StopWord
63
+ end
64
+
65
+ def stop_word_params
66
+ params.require(:stop_word).permit(:key, :user_id, :ugc, :username, :signature, :dialog, :nickname, :replacement)
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,5 @@
1
+ module CensorBear
2
+ module ApplicationHelper
3
+ include Pagy::Frontend
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module CensorBear
2
+ module LogsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module CensorBear
2
+ module ModLogsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module CensorBear
2
+ module StopWordsHelper
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module CensorBear
2
+ class ApplicationJob < ActiveJob::Base
3
+ end
4
+ end
@@ -0,0 +1,6 @@
1
+ module CensorBear
2
+ class ApplicationMailer < ActionMailer::Base
3
+ default from: 'from@example.com'
4
+ layout 'mailer'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module CensorBear
2
+ class ApplicationRecord < ActiveRecord::Base
3
+ self.abstract_class = true
4
+ end
5
+ end
@@ -0,0 +1,4 @@
1
+ module CensorBear
2
+ class Log < ApplicationRecord
3
+ end
4
+ end
@@ -0,0 +1,50 @@
1
+ module CensorBear
2
+ class ModLog < ApplicationRecord
3
+ REASONS = %w(无 广告/SPAM 恶意灌水 违规内容 文不对题 重复发布 其它)
4
+ belongs_to :record, polymorphic: true, required: false
5
+
6
+ def record_path
7
+ return '#' if record.blank?
8
+
9
+ record.censor_show_path
10
+ end
11
+
12
+ def delete(reason)
13
+ # ugc内容需要开软删,便于撤销&查看统计,可以定时删除统计并删除软删内容,类似回收站机制
14
+ raise NoMethodError.new("undefined censor_delete for record") unless record.respond_to?(:censor_delete)
15
+
16
+ ret = record.censor_delete
17
+ handled!(reason) if ret
18
+ end
19
+
20
+ def approve
21
+ raise NoMethodError unless record.respond_to?(:censor_approve)
22
+
23
+ ret = record.censor_approve
24
+ handled! if ret
25
+ end
26
+
27
+ def ban_user
28
+ raise NoMethodError unless record.respond_to?(:censor_ban_user)
29
+
30
+ ret = record.censor_ban_user
31
+ delete if ret
32
+ end
33
+
34
+ scope :pending, -> { where(status: 0) }
35
+ scope :handled, -> { where(status: 1) }
36
+ scope :suspended, -> { where(status: 2) }
37
+
38
+ def handled!(reason = nil)
39
+ update_columns(status: 1, reason: reason)
40
+ end
41
+
42
+ def pend!
43
+ update_columns(status: 0)
44
+ end
45
+
46
+ def suspend!
47
+ update_columns(status: 2)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,7 @@
1
+ module CensorBear
2
+ class StopWord < ApplicationRecord
3
+ FIELDS = %w(ugc username nickname signature dialog)
4
+ ACTIONS_MAP = %w(ignore mod banned replace)
5
+ belongs_to :user, class_name: CensorBear.config.user_class
6
+ end
7
+ end
@@ -0,0 +1,37 @@
1
+ <%= form_with(model: log) do |form| %>
2
+ <% if log.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(log.errors.count, "error") %> prohibited this log from being saved:</h2>
5
+
6
+ <ul>
7
+ <% log.errors.each do |error| %>
8
+ <li><%= error.full_message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field">
15
+ <%= form.label :original_content %>
16
+ <%= form.text_area :original_content %>
17
+ </div>
18
+
19
+ <div class="field">
20
+ <%= form.label :action %>
21
+ <%= form.text_field :action %>
22
+ </div>
23
+
24
+ <div class="field">
25
+ <%= form.label :filtered_content %>
26
+ <%= form.text_area :filtered_content %>
27
+ </div>
28
+
29
+ <div class="field">
30
+ <%= form.label :mod_words %>
31
+ <%= form.text_field :mod_words %>
32
+ </div>
33
+
34
+ <div class="actions">
35
+ <%= form.submit %>
36
+ </div>
37
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing Log</h1>
2
+
3
+ <%= render 'form', log: @log %>
4
+
5
+ <%= link_to 'Show', @log %> |
6
+ <%= link_to 'Back', logs_path %>
@@ -0,0 +1,35 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <h1>Logs</h1>
4
+
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <th>Orginal content</th>
9
+ <th>Action</th>
10
+ <th>Filtered content</th>
11
+ <th>Mod words</th>
12
+ <th colspan="3"></th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <tbody>
17
+ <% @logs.each do |log| %>
18
+ <tr>
19
+ <td><%= log.original_content %></td>
20
+ <td><%= log.action %></td>
21
+ <td><%= log.filtered_content %></td>
22
+ <td><%= log.mod_words %></td>
23
+ <td><%= link_to 'Show', log %></td>
24
+ <td><%= link_to 'Edit', edit_log_path(log) %></td>
25
+ <td><%= link_to 'Destroy', log, method: :delete, data: { confirm: 'Are you sure?' } %></td>
26
+ </tr>
27
+ <% end %>
28
+ </tbody>
29
+ </table>
30
+
31
+ <br>
32
+
33
+ <%= link_to 'New Log', new_log_path %>
34
+
35
+
@@ -0,0 +1,5 @@
1
+ <h1>New Log</h1>
2
+
3
+ <%= render 'form', log: @log %>
4
+
5
+ <%= link_to 'Back', logs_path %>
@@ -0,0 +1,24 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <strong>Orginal content:</strong>
5
+ <%= @log.original_content %>
6
+ </p>
7
+
8
+ <p>
9
+ <strong>Action:</strong>
10
+ <%= @log.action %>
11
+ </p>
12
+
13
+ <p>
14
+ <strong>Filtered content:</strong>
15
+ <%= @log.filtered_content %>
16
+ </p>
17
+
18
+ <p>
19
+ <strong>Mod words:</strong>
20
+ <%= @log.mod_words %>
21
+ </p>
22
+
23
+ <%= link_to 'Edit', edit_log_path(@log) %> |
24
+ <%= link_to 'Back', logs_path %>
@@ -0,0 +1,37 @@
1
+ <%= form_with(model: mod_log) do |form| %>
2
+ <% if mod_log.errors.any? %>
3
+ <div id="error_explanation">
4
+ <h2><%= pluralize(mod_log.errors.count, "error") %> prohibited this mod_log from being saved:</h2>
5
+
6
+ <ul>
7
+ <% mod_log.errors.each do |error| %>
8
+ <li><%= error.full_message %></li>
9
+ <% end %>
10
+ </ul>
11
+ </div>
12
+ <% end %>
13
+
14
+ <div class="field">
15
+ <%= form.label :record_id %>
16
+ <%= form.text_field :record_id %>
17
+ </div>
18
+
19
+ <div class="field">
20
+ <%= form.label :record_type %>
21
+ <%= form.text_field :record_type %>
22
+ </div>
23
+
24
+ <div class="field">
25
+ <%= form.label :mod_words %>
26
+ <%= form.text_field :mod_words %>
27
+ </div>
28
+
29
+ <div class="field">
30
+ <%= form.label :user_id %>
31
+ <%= form.text_field :user_id %>
32
+ </div>
33
+
34
+ <div class="actions">
35
+ <%= form.submit %>
36
+ </div>
37
+ <% end %>
@@ -0,0 +1,6 @@
1
+ <h1>Editing Mod Log</h1>
2
+
3
+ <%= render 'form', mod_log: @mod_log %>
4
+
5
+ <%= link_to 'Show', @mod_log %> |
6
+ <%= link_to 'Back', mod_logs_path %>
@@ -0,0 +1,44 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <h1>Mod Logs</h1>
4
+
5
+ <table>
6
+ <thead>
7
+ <tr>
8
+ <th>Record</th>
9
+ <th>Record type</th>
10
+ <th>Mod words</th>
11
+ <th>User</th>
12
+ <th colspan="3"></th>
13
+ </tr>
14
+ </thead>
15
+
16
+ <tbody>
17
+ <% @mod_logs.each do |mod_log| %>
18
+ <tr>
19
+ <td><%= mod_log.record_id %></td>
20
+ <td><%= mod_log.record_type %></td>
21
+ <td><%= mod_log.mod_words %></td>
22
+ <td><%= mod_log.user_id %></td>
23
+ <td><%= link_to 'Show', mod_log %></td>
24
+ <td><%= link_to 'Show', mod_log %></td>
25
+ <td><%= link_to 'Edit', edit_mod_log_path(mod_log) %></td>
26
+ <td><%= link_to 'Destroy', mod_log, method: :delete, data: { confirm: 'Are you sure?' } %></td>
27
+ <td><%= link_to "查看详情", mod_log.record_path %></td>
28
+ <td><%= link_to "忽略内容", mod_log_ignore_path(mod_log) %></td>
29
+ <td><%= link_to "通过内容", mod_log_approve_path(mod_log) %></td>
30
+ <td><%= link_to "封禁用户", mod_log_ban_path(mod_log) %></td>
31
+ <td>
32
+ <%= form_with(url: mod_log_delete_path(mod_log), method: :get, class: "flex items-center") do |f| %>
33
+ <%= f.text_field :reason, value: mod_log.reason, placeholder: "原因", class: "border rounded-md m py-0.5 px-1" %>
34
+ <td><%= f.submit "删除内容", class: "rounded-md px-2 py-1 text-sm bg-black text-white cursor-pointer" %></td>
35
+ <% end %>
36
+ </td>
37
+ </tr>
38
+ <% end %>
39
+ </tbody>
40
+ </table>
41
+
42
+ <br>
43
+
44
+ <%= link_to 'New Mod Log', new_mod_log_path %>
@@ -0,0 +1,5 @@
1
+ <h1>New Mod Log</h1>
2
+
3
+ <%= render 'form', mod_log: @mod_log %>
4
+
5
+ <%= link_to 'Back', mod_logs_path %>
@@ -0,0 +1,24 @@
1
+ <p id="notice"><%= notice %></p>
2
+
3
+ <p>
4
+ <strong>Record:</strong>
5
+ <%= @mod_log.record_id %>
6
+ </p>
7
+
8
+ <p>
9
+ <strong>Record type:</strong>
10
+ <%= @mod_log.record_type %>
11
+ </p>
12
+
13
+ <p>
14
+ <strong>Mod words:</strong>
15
+ <%= @mod_log.mod_words %>
16
+ </p>
17
+
18
+ <p>
19
+ <strong>User:</strong>
20
+ <%= @mod_log.user_id %>
21
+ </p>
22
+
23
+ <%= link_to 'Edit', edit_mod_log_path(@mod_log) %> |
24
+ <%= link_to 'Back', mod_logs_path %>
@@ -0,0 +1,30 @@
1
+ = form_with(model: stop_word, class: "py-2") do |form|
2
+ - if stop_word.errors.any?
3
+ %h2= "#{pluralize(stop_word.errors.count, "error")} prohibited this stop_word from being saved:"
4
+ %ul
5
+ - stop_word.errors.each do |error|
6
+ %li= error.full_message
7
+ %div{class: "space-y-2"}
8
+ %div
9
+ %div{class: "text-gray-500 text-xs"}= form.label :key, "敏感词"
10
+ %div= form.text_field :key, class: "border p-1 w-full rounded-md"
11
+ %div
12
+ %div{class: "text-gray-500 text-xs"}= form.label :ugc, "UGC内容处理方式"
13
+ %div= form.select :ugc, options_for_select(CensorBear.action_options, params[:action_type]), class: "border p-1 w-full rounded-md"
14
+ %div
15
+ %div{class: "text-gray-500 text-xs"}= form.label :username, "用户名处理方式"
16
+ %div= form.select :username, options_for_select(CensorBear.action_options, params[:action_type]), class: "border p-1 w-full rounded-md"
17
+ %div
18
+ %div{class: "text-gray-500 text-xs"}= form.label :nickname, "用户昵称处理方式"
19
+ %div= form.select :nickname, options_for_select(CensorBear.action_options, params[:action_type]), class: "border p-1 w-full rounded-md"
20
+ %div
21
+ %div{class: "text-gray-500 text-xs"}= form.label :signature, "签名处理方式"
22
+ %div= form.select :signature, options_for_select(CensorBear.action_options, params[:action_type]), class: "border p-1 w-full rounded-md"
23
+ %div
24
+ %div{class: "text-gray-500 text-xs"}= form.label :dialog, "私信处理方式"
25
+ %div= form.select :dialog, options_for_select(CensorBear.action_options, params[:action_type]), class: "border p-1 w-full rounded-md"
26
+ %div
27
+ %div{class: "text-gray-500 text-xs"}= form.label :replacement, "过滤词替换"
28
+ %div= form.text_field :replacement, class: "border p-1 w-full rounded-md"
29
+ %div
30
+ %div= form.submit "确认", class: "px-2 py-0.5 rounded-md bg-gray-800 text-white"