diff --git a/resources/js/admin/sign-in-rules.js b/resources/js/admin/sign-in-rules.js new file mode 100644 index 0000000..eaf8a7f --- /dev/null +++ b/resources/js/admin/sign-in-rules.js @@ -0,0 +1,177 @@ +// 签到奖励规则后台管理页事件代理,替代 Blade 内联编辑、删除确认和启停函数。 + +let adminSignInRulesControlsBound = false; +let signInRulesCache = null; + +const SIGN_IN_RULE_FIELDS = [ + "streak_days", + "gold_reward", + "exp_reward", + "charm_reward", + "identity_badge_code", + "identity_badge_name", + "identity_badge_icon", + "identity_badge_color", + "identity_duration_days", + "sort_order", +]; + +/** + * 读取后台 layout 注入的 CSRF token。 + * + * @returns {string} + */ +function getCsrfToken() { + return document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") || ""; +} + +/** + * 读取 Blade 注入的签到规则快照。 + * + * @returns {Record>} + */ +function getSignInRules() { + if (signInRulesCache !== null) { + return signInRulesCache; + } + + const dataNode = document.getElementById("admin-sign-in-rules-data"); + if (!dataNode?.textContent) { + signInRulesCache = {}; + return signInRulesCache; + } + + try { + signInRulesCache = JSON.parse(dataNode.textContent); + } catch (error) { + // 数据块异常时不影响新增和删除表单,编辑弹窗会自然不可打开。 + signInRulesCache = {}; + } + + return signInRulesCache; +} + +/** + * 打开签到规则编辑弹窗并填充表单。 + * + * @param {string} ruleId 规则 ID + * @returns {void} + */ +function openSignInRuleModal(ruleId) { + const rule = getSignInRules()[ruleId]; + const form = document.getElementById("edit-rule-form"); + const modal = document.getElementById("edit-rule-modal"); + + if (!rule || !(form instanceof HTMLFormElement) || !modal) { + return; + } + + form.action = String(rule.update_url || ""); + SIGN_IN_RULE_FIELDS.forEach((field) => { + const input = document.getElementById(`edit-${field}`); + if (input instanceof HTMLInputElement) { + input.value = String(rule[field] ?? ""); + } + }); + + const enabledInput = document.getElementById("edit-is-enabled"); + if (enabledInput instanceof HTMLInputElement) { + enabledInput.checked = Boolean(rule.is_enabled); + } + + modal.classList.remove("hidden"); +} + +/** + * 关闭签到规则编辑弹窗。 + * + * @returns {void} + */ +function closeSignInRuleModal() { + document.getElementById("edit-rule-modal")?.classList.add("hidden"); +} + +/** + * 切换签到规则启停状态,低风险沿用旧逻辑:成功后刷新页面。 + * + * @param {HTMLButtonElement} button 启停按钮 + * @returns {Promise} + */ +async function toggleSignInRule(button) { + const toggleUrl = button.getAttribute("data-sign-in-rule-toggle-url") || ""; + + if (!toggleUrl || button.disabled) { + return; + } + + button.disabled = true; + + try { + const response = await fetch(toggleUrl, { + method: "POST", + headers: { + "X-CSRF-TOKEN": getCsrfToken(), + "Accept": "application/json", + }, + }); + const data = await response.json(); + + if (!response.ok || !data?.ok) { + window.alert(data?.message || "切换失败"); + return; + } + + window.location.reload(); + } finally { + button.disabled = false; + } +} + +/** + * 绑定签到奖励规则管理页操作按钮。 + * + * @returns {void} + */ +export function bindAdminSignInRulesControls() { + if (adminSignInRulesControlsBound || typeof document === "undefined") { + return; + } + + adminSignInRulesControlsBound = true; + document.addEventListener("click", (event) => { + if (!(event.target instanceof Element)) { + return; + } + + const editButton = event.target.closest("[data-sign-in-rule-edit-id]"); + if (editButton) { + event.preventDefault(); + openSignInRuleModal(editButton.getAttribute("data-sign-in-rule-edit-id") || ""); + return; + } + + const closeButton = event.target.closest("[data-sign-in-rule-close]"); + if (closeButton) { + event.preventDefault(); + closeSignInRuleModal(); + return; + } + + const toggleButton = event.target.closest("[data-sign-in-rule-toggle-url]"); + if (toggleButton instanceof HTMLButtonElement) { + event.preventDefault(); + void toggleSignInRule(toggleButton); + } + }); + + document.addEventListener("submit", (event) => { + if (!(event.target instanceof HTMLFormElement)) { + return; + } + + const confirmMessage = event.target.getAttribute("data-sign-in-rule-delete-confirm"); + if (confirmMessage && !window.confirm(confirmMessage)) { + event.preventDefault(); + } + }); +} diff --git a/resources/js/app.js b/resources/js/app.js index 0e26c4c..a7fcbdc 100644 --- a/resources/js/app.js +++ b/resources/js/app.js @@ -1,7 +1,9 @@ import './bootstrap'; import { bindAdminAutoactControls } from './admin/autoact.js'; import { bindAdminFishingEventsControls } from './admin/fishing-events.js'; +import { bindAdminSignInRulesControls } from './admin/sign-in-rules.js'; // 后台共用入口只注册轻量事件代理,具体页面通过 data-* 属性决定是否响应。 bindAdminAutoactControls(); bindAdminFishingEventsControls(); +bindAdminSignInRulesControls(); diff --git a/resources/views/admin/sign-in-rules/index.blade.php b/resources/views/admin/sign-in-rules/index.blade.php index a7ccdf9..c8afa6b 100644 --- a/resources/views/admin/sign-in-rules/index.blade.php +++ b/resources/views/admin/sign-in-rules/index.blade.php @@ -3,6 +3,30 @@ @section('title', '签到奖励管理') @section('content') + @php + $signInRulePayload = $rules->mapWithKeys( + fn($rule) => [ + (string) $rule->id => [ + 'id' => $rule->id, + 'streak_days' => $rule->streak_days, + 'gold_reward' => $rule->gold_reward, + 'exp_reward' => $rule->exp_reward, + 'charm_reward' => $rule->charm_reward, + 'identity_badge_code' => $rule->identity_badge_code, + 'identity_badge_name' => $rule->identity_badge_name, + 'identity_badge_icon' => $rule->identity_badge_icon, + 'identity_badge_color' => $rule->identity_badge_color, + 'identity_duration_days' => $rule->identity_duration_days, + 'sort_order' => $rule->sort_order, + 'is_enabled' => (bool) $rule->is_enabled, + 'update_url' => route('admin.sign-in-rules.update', $rule), + ], + ], + ); + @endphp + + +
@@ -48,18 +72,19 @@ {{ $rule->identity_duration_days > 0 ? $rule->identity_duration_days . ' 天' : '永久' }} - -
+ class="inline" data-sign-in-rule-delete-confirm="确定删除第 {{ $rule->streak_days }} 天签到规则?"> @csrf @method('DELETE') +
@csrf @@ -118,7 +143,7 @@ 启用此规则 - @@ -126,44 +151,4 @@
- - @endsection