功能:禁用用户名管理(永久禁词列表)
数据库:
- 新增迁移 username_blacklist 表加 type/reason 列
type: temp(改名30天保留)| permanent(管理员永久禁用)
reason: 禁用原因备注(最长100字符)
核心逻辑:
- UsernameBlacklist::isBlocked() 同时拦截两种类型
也包含 isReserved() 兼容旧调用
增加 scopePermanent()/scopeTemp() 查询作用域
- AuthController 注册时加 isBlocked() 拦截
禁词/保留期内均不可注册
- ShopService::useRenameCard() 已有 isReserved() 调用
因已改用 isBlocked() 别名,无需修改
后台:
- ForbiddenUsernameController:index/store/update/destroy
- 路由:/admin/forbidden-usernames(chat.site_owner 中间件)
- 视图:admin/forbidden-usernames/index.blade.php
新增表单、关键词搜索、分页、行内编辑原因、删除
- 侧边栏加「🚫 禁用用户名」入口(仅站长可见)
This commit is contained in:
115
app/Http/Controllers/Admin/ForbiddenUsernameController.php
Normal file
115
app/Http/Controllers/Admin/ForbiddenUsernameController.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:禁用用户名管理控制器(站长专用)
|
||||
*
|
||||
* 管理 username_blacklist 表中 type=permanent 的永久禁用词列表。
|
||||
* 包含:国家领导人名称、攻击性词汇、违禁词等不允许注册或改名的词语。
|
||||
*
|
||||
* 用户在注册(AuthController)和改名(ShopService::useRenameCard)时均会经过该表检测。
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Admin;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\UsernameBlacklist;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Carbon;
|
||||
|
||||
class ForbiddenUsernameController extends Controller
|
||||
{
|
||||
/**
|
||||
* 分页列出所有永久禁用词。
|
||||
* 支持关键词模糊搜索(GET ?q=xxx)。
|
||||
*/
|
||||
public function index(Request $request): \Illuminate\View\View
|
||||
{
|
||||
$q = $request->query('q', '');
|
||||
|
||||
$items = UsernameBlacklist::permanent()
|
||||
->when($q, fn ($query) => $query->where('username', 'like', "%{$q}%"))
|
||||
->orderByDesc('created_at')
|
||||
->paginate(20)
|
||||
->withQueryString();
|
||||
|
||||
return view('admin.forbidden-usernames.index', [
|
||||
'items' => $items,
|
||||
'q' => $q,
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增一条永久禁用词。
|
||||
*
|
||||
* @param Request $request 请求体:username(必填),reason(选填)
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'username' => ['required', 'string', 'max:50'],
|
||||
'reason' => ['nullable', 'string', 'max:100'],
|
||||
], [
|
||||
'username.required' => '禁用词不能为空。',
|
||||
'username.max' => '禁用词最长50字符。',
|
||||
]);
|
||||
|
||||
$username = trim($validated['username']);
|
||||
|
||||
// 已存在同名的永久记录则不重复插入
|
||||
$exists = UsernameBlacklist::permanent()
|
||||
->where('username', $username)
|
||||
->exists();
|
||||
|
||||
if ($exists) {
|
||||
return response()->json(['status' => 'error', 'message' => '该词语已在永久禁用列表中。'], 422);
|
||||
}
|
||||
|
||||
UsernameBlacklist::create([
|
||||
'username' => $username,
|
||||
'type' => 'permanent',
|
||||
'reserved_until' => null,
|
||||
'reason' => $validated['reason'] ?? null,
|
||||
'created_at' => Carbon::now(),
|
||||
]);
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => "「{$username}」已加入永久禁用列表。"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新指定禁用词的原因备注。
|
||||
*
|
||||
* @param int $id 记录 ID
|
||||
* @param Request $request 请求体:reason
|
||||
*/
|
||||
public function update(Request $request, int $id): JsonResponse
|
||||
{
|
||||
$item = UsernameBlacklist::permanent()->findOrFail($id);
|
||||
|
||||
$validated = $request->validate([
|
||||
'reason' => ['nullable', 'string', 'max:100'],
|
||||
]);
|
||||
|
||||
$item->update(['reason' => $validated['reason']]);
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => '备注已更新。']);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除指定永久禁用词。
|
||||
*
|
||||
* @param int $id 记录 ID
|
||||
*/
|
||||
public function destroy(int $id): JsonResponse
|
||||
{
|
||||
$item = UsernameBlacklist::permanent()->findOrFail($id);
|
||||
$name = $item->username;
|
||||
$item->delete();
|
||||
|
||||
return response()->json(['status' => 'success', 'message' => "「{$name}」已从永久禁用列表移除。"]);
|
||||
}
|
||||
}
|
||||
@@ -11,10 +11,11 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\LoginRequest;
|
||||
use App\Models\Sysparam;
|
||||
use App\Models\User;
|
||||
use App\Models\UsernameBlacklist;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Sysparam;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Redis;
|
||||
@@ -99,6 +100,11 @@ class AuthController extends Controller
|
||||
return response()->json(['status' => 'error', 'message' => '您所在的 IP 地址已被管理员封禁,禁止注册新账号。'], 403);
|
||||
}
|
||||
|
||||
// 检测用户名是否在禁用词列表(永久禁用 或 改名临时保留期内)
|
||||
if (UsernameBlacklist::isBlocked($username)) {
|
||||
return response()->json(['status' => 'error', 'message' => '该用户名已被系统禁止注册,请更换其他名称。'], 422);
|
||||
}
|
||||
|
||||
$newUser = User::create([
|
||||
'username' => $username,
|
||||
'password' => Hash::make($password),
|
||||
@@ -123,7 +129,7 @@ class AuthController extends Controller
|
||||
|
||||
// 递增访问次数
|
||||
$user->increment('visit_num');
|
||||
|
||||
|
||||
// 更新最后登录IP和时间
|
||||
$user->update([
|
||||
'last_ip' => $ip,
|
||||
|
||||
@@ -2,7 +2,16 @@
|
||||
|
||||
/**
|
||||
* 文件功能:用户名黑名单模型
|
||||
* 用户改名后旧名称写入此表,保留期间其他人无法注册该名称
|
||||
*
|
||||
* 支持两种类型的禁用记录:
|
||||
* temp — 用户改名后旧名称的临时保留(30天),到期后其他人可注册
|
||||
* permanent — 管理员设置的永久禁用词(攻击性词汇、领导人名称等),永不可注册
|
||||
*
|
||||
* 凡是 isBlocked() 返回 true 的名称,无论注册还是改名均不允许使用。
|
||||
*
|
||||
* @author ChatRoom Laravel
|
||||
*
|
||||
* @version 2.0.0
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
@@ -13,22 +22,76 @@ class UsernameBlacklist extends Model
|
||||
{
|
||||
protected $table = 'username_blacklist';
|
||||
|
||||
public $timestamps = false; // 只有 created_at 无 updated_at
|
||||
/** 只有 created_at,无 updated_at */
|
||||
public $timestamps = false;
|
||||
|
||||
protected $fillable = ['username', 'reserved_until', 'created_at'];
|
||||
protected $fillable = ['username', 'type', 'reserved_until', 'reason', 'created_at'];
|
||||
|
||||
protected $casts = [
|
||||
'reserved_until' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
];
|
||||
protected function casts(): array
|
||||
{
|
||||
return [
|
||||
'reserved_until' => 'datetime',
|
||||
'created_at' => 'datetime',
|
||||
];
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// 公共查询方法
|
||||
// ──────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 判断给定名称是否在黑名单有效期内
|
||||
* 判断给定名称是否被禁止使用。
|
||||
*
|
||||
* 满足以下任一条件时返回 true:
|
||||
* 1. 存在 type=permanent 的永久禁用记录
|
||||
* 2. 存在 type=temp 且 reserved_until 尚未过期的临时保留记录
|
||||
*
|
||||
* @param string $username 要检测的用户名
|
||||
*/
|
||||
public static function isBlocked(string $username): bool
|
||||
{
|
||||
return static::where('username', $username)
|
||||
->where(function ($q) {
|
||||
// 永久禁用
|
||||
$q->where('type', 'permanent')
|
||||
// 或:临时保留且尚未到期
|
||||
->orWhere(function ($q2) {
|
||||
$q2->where('type', 'temp')
|
||||
->where('reserved_until', '>', now());
|
||||
});
|
||||
})
|
||||
->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* 兼容旧调用:isReserved() 等同于 isBlocked()。
|
||||
*
|
||||
* @param string $username 要检测的用户名
|
||||
*
|
||||
* @deprecated 请使用 isBlocked()
|
||||
*/
|
||||
public static function isReserved(string $username): bool
|
||||
{
|
||||
return static::where('username', $username)
|
||||
->where('reserved_until', '>', now())
|
||||
->exists();
|
||||
return static::isBlocked($username);
|
||||
}
|
||||
|
||||
// ──────────────────────────────────────────
|
||||
// 作用域(Scopes)
|
||||
// ──────────────────────────────────────────
|
||||
|
||||
/**
|
||||
* 仅查询永久禁用词(管理员维护的列表)。
|
||||
*/
|
||||
public function scopePermanent($query)
|
||||
{
|
||||
return $query->where('type', 'permanent');
|
||||
}
|
||||
|
||||
/**
|
||||
* 仅查询临时保留记录(改名后旧名)。
|
||||
*/
|
||||
public function scopeTemp($query)
|
||||
{
|
||||
return $query->where('type', 'temp');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 文件功能:为 username_blacklist 表新增 type 和 reason 字段
|
||||
*
|
||||
* type 区分临时保留(改名后30天)与永久禁用(管理员设置)
|
||||
* reason 记录永久禁用的原因(如:攻击性词汇、领导人名称等)
|
||||
*/
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* 执行迁移:新增 type 和 reason 列。
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('username_blacklist', function (Blueprint $table) {
|
||||
// 类型:temp = 改名后临时保留;permanent = 管理员永久禁用
|
||||
$table->enum('type', ['temp', 'permanent'])
|
||||
->default('temp')
|
||||
->after('username')
|
||||
->comment('temp=改名临时保留 | permanent=管理员永久禁用词');
|
||||
|
||||
// 禁用原因(permanent 时填写)
|
||||
$table->string('reason', 100)
|
||||
->nullable()
|
||||
->after('reserved_until')
|
||||
->comment('永久禁用原因(攻击性词汇、领导人名称等)');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 回滚:删除新增列。
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('username_blacklist', function (Blueprint $table) {
|
||||
$table->dropColumn(['type', 'reason']);
|
||||
});
|
||||
}
|
||||
};
|
||||
210
resources/views/admin/forbidden-usernames/index.blade.php
Normal file
210
resources/views/admin/forbidden-usernames/index.blade.php
Normal file
@@ -0,0 +1,210 @@
|
||||
{{--
|
||||
文件功能:后台禁用用户名管理页面(仅站长 id=1 可访问)
|
||||
|
||||
管理 username_blacklist.type=permanent 的永久禁止词列表。
|
||||
用户在注册或使用改名卡时,系统自动查询此表进行拦截。
|
||||
|
||||
@extends admin.layouts.app
|
||||
--}}
|
||||
@extends('admin.layouts.app')
|
||||
|
||||
@section('title', '禁用用户名管理')
|
||||
|
||||
@section('content')
|
||||
|
||||
{{-- 标题 --}}
|
||||
<div class="flex items-start justify-between mb-6">
|
||||
<div>
|
||||
<h2 class="text-xl font-bold text-gray-800">🚫 禁用用户名管理</h2>
|
||||
<p class="text-sm text-gray-500 mt-1">
|
||||
以下词语永久禁止注册或改名使用(领导人名称、攻击性词汇、违禁词等)。
|
||||
临时保留的旧昵称(改名后30天)不在此列表中显示。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 新增表单 + 搜索栏 --}}
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6" x-data="{
|
||||
username: '',
|
||||
reason: '',
|
||||
saving: false,
|
||||
msg: '',
|
||||
msgOk: true,
|
||||
async addWord() {
|
||||
if (!this.username.trim()) return;
|
||||
this.saving = true;
|
||||
this.msg = '';
|
||||
const res = await fetch('{{ route('admin.forbidden-usernames.store') }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({ username: this.username, reason: this.reason }),
|
||||
});
|
||||
const data = await res.json();
|
||||
this.saving = false;
|
||||
this.msgOk = data.status === 'success';
|
||||
this.msg = data.message;
|
||||
if (this.msgOk) { this.username = '';
|
||||
this.reason = '';
|
||||
setTimeout(() => location.reload(), 800); }
|
||||
}
|
||||
}">
|
||||
|
||||
{{-- 新增卡片 --}}
|
||||
<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>
|
||||
<div class="space-y-3">
|
||||
<div>
|
||||
<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()"
|
||||
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>
|
||||
<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()"
|
||||
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>
|
||||
</div>
|
||||
|
||||
{{-- 搜索卡片 --}}
|
||||
<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>
|
||||
<form method="GET" action="{{ route('admin.forbidden-usernames.index') }}" class="space-y-3">
|
||||
<input type="text" name="q" value="{{ $q }}" 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 class="flex gap-2">
|
||||
<button type="submit"
|
||||
class="flex-1 bg-gray-600 hover:bg-gray-700 text-white rounded-lg px-4 py-2 text-sm font-bold transition">
|
||||
搜索
|
||||
</button>
|
||||
@if ($q)
|
||||
<a href="{{ route('admin.forbidden-usernames.index') }}"
|
||||
class="px-4 py-2 text-sm text-gray-500 border border-gray-300 rounded-lg hover:bg-gray-50 transition">
|
||||
✕ 清除
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
<p class="text-xs text-gray-400 mt-3">
|
||||
共 <strong>{{ $items->total() }}</strong> 条永久禁用词
|
||||
@if ($q)
|
||||
(当前筛选"{{ $q }}")
|
||||
@endif
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{-- 禁用词列表 --}}
|
||||
<div class="bg-white rounded-xl border border-gray-200 shadow-sm overflow-hidden">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-gray-50 border-b border-gray-200">
|
||||
<tr>
|
||||
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">词语</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">禁用原因</th>
|
||||
<th class="px-4 py-3 text-left text-xs font-bold text-gray-500 uppercase">添加时间</th>
|
||||
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-100">
|
||||
@forelse ($items as $item)
|
||||
<tr x-data="{
|
||||
editing: false,
|
||||
reason: @js($item->reason ?? ''),
|
||||
saving: false,
|
||||
async saveReason() {
|
||||
this.saving = true;
|
||||
await fetch('/admin/forbidden-usernames/{{ $item->id }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-HTTP-Method-Override': 'PUT',
|
||||
},
|
||||
body: JSON.stringify({ reason: this.reason, _method: 'PUT' }),
|
||||
});
|
||||
this.saving = false;
|
||||
this.editing = false;
|
||||
},
|
||||
async destroy() {
|
||||
if (!confirm('确定要从禁用列表中移除「{{ $item->username }}」吗?')) return;
|
||||
await fetch('/admin/forbidden-usernames/{{ $item->id }}', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name=csrf-token]').content,
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json',
|
||||
'X-HTTP-Method-Override': 'DELETE',
|
||||
},
|
||||
body: JSON.stringify({ _method: 'DELETE' }),
|
||||
});
|
||||
location.reload();
|
||||
}
|
||||
}" class="hover:bg-gray-50 transition">
|
||||
{{-- 词语 --}}
|
||||
<td class="px-4 py-3">
|
||||
<span
|
||||
class="font-mono font-bold text-gray-800 bg-red-50 border border-red-200 px-2 py-0.5 rounded text-xs">
|
||||
{{ $item->username }}
|
||||
</span>
|
||||
</td>
|
||||
{{-- 原因(点击编辑) --}}
|
||||
<td class="px-4 py-3 text-gray-600">
|
||||
<span x-show="!editing" @click="editing = true" class="cursor-pointer hover:text-indigo-600"
|
||||
x-text="reason || '(点击添加原因)'"></span>
|
||||
<div x-show="editing" class="flex items-center gap-2">
|
||||
<input x-model="reason" type="text" maxlength="100" @keydown.enter="saveReason()"
|
||||
@keydown.escape="editing = false"
|
||||
class="border border-indigo-300 rounded px-2 py-1 text-xs focus:ring-1 focus:ring-indigo-400 outline-none w-48">
|
||||
<button @click="saveReason()" :disabled="saving"
|
||||
class="text-xs bg-indigo-600 text-white rounded px-2 py-1 hover:bg-indigo-700 disabled:opacity-50">
|
||||
<span x-text="saving ? '…' : '保存'"></span>
|
||||
</button>
|
||||
<button @click="editing = false"
|
||||
class="text-xs text-gray-400 hover:text-gray-600">取消</button>
|
||||
</div>
|
||||
</td>
|
||||
{{-- 时间 --}}
|
||||
<td class="px-4 py-3 text-gray-400 text-xs whitespace-nowrap">
|
||||
{{ $item->created_at?->format('Y-m-d H:i') ?? '-' }}
|
||||
</td>
|
||||
{{-- 操作 --}}
|
||||
<td class="px-4 py-3 text-center">
|
||||
<button @click="destroy()"
|
||||
class="text-xs text-red-600 hover:text-red-800 border border-red-200 hover:border-red-400 rounded px-3 py-1 transition">
|
||||
🗑 删除
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="4" class="py-16 text-center text-gray-400">
|
||||
<p class="text-3xl mb-2">🚫</p>
|
||||
<p class="font-bold">暂无禁用词</p>
|
||||
<p class="text-xs mt-1">使用左侧表单添加第一条禁用词</p>
|
||||
</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
{{-- 分页 --}}
|
||||
@if ($items->hasPages())
|
||||
<div class="mt-6">
|
||||
{{ $items->links() }}
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endsection
|
||||
@@ -101,6 +101,10 @@
|
||||
class="bg-orange-500 text-white text-xs px-1.5 py-0.5 rounded-full font-bold">{{ $pendingFeedback }}</span>
|
||||
@endif
|
||||
</a>
|
||||
<a href="{{ route('admin.forbidden-usernames.index') }}"
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.forbidden-usernames.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
🚫 禁用用户名
|
||||
</a>
|
||||
@endif
|
||||
@endif
|
||||
</nav>
|
||||
|
||||
@@ -261,5 +261,11 @@ Route::middleware(['chat.auth', 'chat.has_position'])->prefix('admin')->name('ad
|
||||
// 用户反馈管理
|
||||
Route::get('/feedback', [\App\Http\Controllers\Admin\FeedbackManagerController::class, 'index'])->name('feedback.index');
|
||||
Route::put('/feedback/{id}', [\App\Http\Controllers\Admin\FeedbackManagerController::class, 'update'])->name('feedback.update');
|
||||
|
||||
// 禁用用户名管理(永久禁止注册/改名的词语:领导人名称、攻击性词汇等)
|
||||
Route::get('/forbidden-usernames', [\App\Http\Controllers\Admin\ForbiddenUsernameController::class, 'index'])->name('forbidden-usernames.index');
|
||||
Route::post('/forbidden-usernames', [\App\Http\Controllers\Admin\ForbiddenUsernameController::class, 'store'])->name('forbidden-usernames.store');
|
||||
Route::put('/forbidden-usernames/{id}', [\App\Http\Controllers\Admin\ForbiddenUsernameController::class, 'update'])->name('forbidden-usernames.update');
|
||||
Route::delete('/forbidden-usernames/{id}', [\App\Http\Controllers\Admin\ForbiddenUsernameController::class, 'destroy'])->name('forbidden-usernames.destroy');
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user