功能:禁用词管理支持批量添加
- 新增 ForbiddenUsernameController::batchStore() 支持换行、逗号、中文逗号、空格多种分隔格式 自动去重、跳过已存在词语、忽略超长词 返回成功数/跳过数详细提示 - 新增路由 POST /admin/forbidden-usernames/batch - View 新增卡片加「单个/批量」两 Tab 切换 批量 Tab 使用 textarea 多行输入
This commit is contained in:
@@ -25,12 +25,14 @@
|
||||
|
||||
{{-- 新增表单 + 搜索栏 --}}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6" x-data="{
|
||||
tab: 'single',
|
||||
username: '',
|
||||
words: '',
|
||||
reason: '',
|
||||
saving: false,
|
||||
msg: '',
|
||||
msgOk: true,
|
||||
async addWord() {
|
||||
async addSingle() {
|
||||
if (!this.username.trim()) return;
|
||||
this.saving = true;
|
||||
this.msg = '';
|
||||
@@ -50,28 +52,84 @@
|
||||
if (this.msgOk) { this.username = '';
|
||||
this.reason = '';
|
||||
setTimeout(() => location.reload(), 800); }
|
||||
},
|
||||
async addBatch() {
|
||||
if (!this.words.trim()) return;
|
||||
this.saving = true;
|
||||
this.msg = '';
|
||||
const res = await fetch('{{ route('admin.forbidden-usernames.batch') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ words: this.words, reason: this.reason }),
|
||||
});
|
||||
const data = await res.json();
|
||||
this.saving = false;
|
||||
this.msgOk = data.status === 'success';
|
||||
this.msg = data.message;
|
||||
if (this.msgOk) { this.words = '';
|
||||
this.reason = '';
|
||||
setTimeout(() => location.reload(), 1200); }
|
||||
}
|
||||
}">
|
||||
|
||||
{{-- 新增卡片 --}}
|
||||
{{-- 新增卡片(单个 + 批量 Tab) --}}
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm p-5">
|
||||
<h3 class="font-bold text-gray-700 text-sm mb-3">➕ 新增禁用词</h3>
|
||||
{{-- Tab 切换 --}}
|
||||
<div class="flex border-b border-gray-200 mb-4 -mx-5 px-5 gap-1">
|
||||
<button @click="tab='single'; msg=''"
|
||||
:class="tab === 'single' ? 'border-b-2 border-indigo-600 text-indigo-700 font-bold' :
|
||||
'text-gray-500 hover:text-gray-700'"
|
||||
class="pb-2 text-sm px-1 transition">➕ 单个添加</button>
|
||||
<button @click="tab='batch'; msg=''"
|
||||
:class="tab === 'batch' ? 'border-b-2 border-indigo-600 text-indigo-700 font-bold' :
|
||||
'text-gray-500 hover:text-gray-700'"
|
||||
class="pb-2 text-sm px-1 transition">📋 批量添加</button>
|
||||
</div>
|
||||
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block">禁用词(用户名)<span class="text-red-500">*</span></label>
|
||||
{{-- 单个模式 --}}
|
||||
<div x-show="tab==='single'">
|
||||
<label class="text-xs text-gray-500 mb-1 block">禁用词 <span class="text-red-500">*</span></label>
|
||||
<input x-model="username" type="text" maxlength="50" placeholder="如:admin、习近平、fuck…"
|
||||
@keydown.enter="addWord()"
|
||||
@keydown.enter="addSingle()"
|
||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none">
|
||||
</div>
|
||||
|
||||
{{-- 批量模式 --}}
|
||||
<div x-show="tab==='batch'">
|
||||
<label class="text-xs text-gray-500 mb-1 block">
|
||||
批量词语 <span class="text-red-500">*</span>
|
||||
<span class="text-gray-400 font-normal">(每行一个,或用逗号/空格分隔)</span>
|
||||
</label>
|
||||
<textarea x-model="words" rows="6" maxlength="5000"
|
||||
placeholder="admin root fuck 操,草,傻 …(每行一个或逗号分隔)"
|
||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none resize-y font-mono"></textarea>
|
||||
<p class="text-xs text-gray-400 mt-1">
|
||||
自动去重,跳过已存在的词语,超过50字符的词语忽略
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{-- 共用原因 --}}
|
||||
<div>
|
||||
<label class="text-xs text-gray-500 mb-1 block">禁用原因(备注,选填)</label>
|
||||
<label class="text-xs text-gray-500 mb-1 block">禁用原因(选填)</label>
|
||||
<input x-model="reason" type="text" maxlength="100" placeholder="如:国家领导人姓名 / 攻击性词汇"
|
||||
class="w-full border border-gray-300 rounded-lg px-3 py-2 text-sm focus:ring-2 focus:ring-indigo-400 outline-none">
|
||||
</div>
|
||||
<button @click="addWord()" :disabled="saving || !username.trim()"
|
||||
|
||||
{{-- 提交按钮 --}}
|
||||
<button x-show="tab==='single'" @click="addSingle()" :disabled="saving || !username.trim()"
|
||||
class="w-full bg-indigo-600 hover:bg-indigo-700 disabled:opacity-40 text-white rounded-lg px-4 py-2 text-sm font-bold transition">
|
||||
<span x-text="saving ? '添加中…' : '➕ 添加到禁用列表'"></span>
|
||||
</button>
|
||||
<button x-show="tab==='batch'" @click="addBatch()" :disabled="saving || !words.trim()"
|
||||
class="w-full bg-indigo-600 hover:bg-indigo-700 disabled:opacity-40 text-white rounded-lg px-4 py-2 text-sm font-bold transition">
|
||||
<span x-text="saving ? '处理中…' : '📋 批量添加到禁用列表'"></span>
|
||||
</button>
|
||||
|
||||
<p x-show="msg" x-text="msg" :class="msgOk ? 'text-green-600' : 'text-red-500'"
|
||||
class="text-xs font-bold"></p>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user