重构:将后台编辑用户 AJAX 提交方法移入 Alpine data 组件内部,彻底解决作用域和数据获取问题

This commit is contained in:
2026-02-27 16:47:03 +08:00
parent 2c5d4cedea
commit aa9a9318f5
+32 -25
View File
@@ -8,7 +8,7 @@
// 管理员级别 = 最高等级 + 1,后台编辑最高可设到管理员级别 // 管理员级别 = 最高等级 + 1,后台编辑最高可设到管理员级别
$adminLevel = (int) \App\Models\Sysparam::getValue('maxlevel', '15') + 1; $adminLevel = (int) \App\Models\Sysparam::getValue('maxlevel', '15') + 1;
@endphp @endphp
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden mb-6" x-data="{ showEditModal: false, editingUser: {}, adminLevel: {{ $adminLevel }}, editToast: false, editToastOk: true, editToastMsg: '', editSaving: false }"> <div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden mb-6" x-data="userEditor()">
<div class="p-6 border-b border-gray-100 bg-gray-50 flex items-center justify-between"> <div class="p-6 border-b border-gray-100 bg-gray-50 flex items-center justify-between">
<form action="{{ route('admin.users.index') }}" method="GET" class="flex gap-2"> <form action="{{ route('admin.users.index') }}" method="GET" class="flex gap-2">
<input type="text" name="username" value="{{ request('username') }}" placeholder="搜索用户名..." <input type="text" name="username" value="{{ request('username') }}" placeholder="搜索用户名..."
@@ -168,7 +168,7 @@
class="mb-4 px-4 py-2 border-l-4 rounded text-sm font-bold" x-text="editToastMsg"> class="mb-4 px-4 py-2 border-l-4 rounded text-sm font-bold" x-text="editToastMsg">
</div> </div>
<form @submit.prevent="submitEditUser($el, $data)" method="POST"> <form @submit.prevent="submitEditUser($el)" method="POST">
@csrf @method('PUT') @csrf @method('PUT')
<div class="grid grid-cols-2 gap-4"> <div class="grid grid-cols-2 gap-4">
@@ -281,50 +281,57 @@
</div> </div>
<script> <script>
/** document.addEventListener('alpine:init', () => {
* 用户编辑弹窗 AJAX 提交 Alpine.data('userEditor', () => ({
* 避免传统表单导致 302 重定向,改为 fetch 就地显示结果 showEditModal: false,
* @param {HTMLFormElement} form Alpine $el(表单元素) editingUser: {},
* @param {object} data Alpine $data(组件数据,直接传入避免 querySelector 查找失败) adminLevel: {{ $adminLevel }},
*/ editToast: false,
async function submitEditUser(form, data) { editToastOk: true,
data.editSaving = true; editToastMsg: '',
data.editToast = false; editSaving: false,
async submitEditUser(formEl) {
this.editSaving = true;
this.editToast = false;
const formEl = form.querySelector('form') ?? form;
const formData = new FormData(formEl); const formData = new FormData(formEl);
// Laravel 路由为 PUTfetch 需通过 _method 伪造方法 formData.append('_method', 'PUT'); // 必须带有伪造方法给 Laravel
formData.append('_method', 'PUT');
try { try {
const res = await fetch(data.editingUser.requestUrl, { const res = await fetch(this.editingUser.requestUrl, {
method: 'POST', method: 'POST',
headers: { headers: {
'Accept': 'application/json', 'Accept': 'application/json',
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content, 'X-CSRF-TOKEN': document.querySelector(
'meta[name="csrf-token"]')
.content,
}, },
body: formData, body: formData,
}); });
const json = await res.json(); const json = await res.json();
data.editToastOk = json.status === 'success'; this.editToastOk = json.status === 'success';
data.editToastMsg = json.message || (json.status === 'success' ? '保存成功!' : '保存失败'); this.editToastMsg = json.message || (json.status === 'success' ? '保存成功!' :
data.editToast = true; '保存失败');
this.editToast = true;
// 成功后 1.5 秒关闭弹窗
if (json.status === 'success') { if (json.status === 'success') {
setTimeout(() => { setTimeout(() => {
data.showEditModal = false; this.showEditModal = false;
}, 1500); }, 1500);
} }
} catch (e) { } catch (e) {
data.editToastOk = false; this.editToastOk = false;
data.editToastMsg = '网络异常,请检查连接后重试。'; this.editToastMsg = '网络请求异常,请检查连接后重试。';
data.editToast = true; this.editToast = true;
console.error('Edit User Request Failed:', e); // 输出详细报错方便调试
} }
data.editSaving = false; this.editSaving = false;
} }
}));
});
</script> </script>
@endsection @endsection