censor_bear 0.1.0

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 (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"