新增每日签到与补签卡功能
This commit is contained in:
@@ -80,6 +80,10 @@
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.autoact.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
{!! '🎲 随机事件' !!}
|
||||
</a>
|
||||
<a href="{{ route('admin.sign-in-rules.index') }}"
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.sign-in-rules.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
{!! '✅ 签到奖励' !!}
|
||||
</a>
|
||||
<a href="{{ route('admin.vip.index') }}"
|
||||
class="block px-4 py-3 rounded-md transition {{ request()->routeIs('admin.vip.*') ? 'bg-indigo-600 font-bold' : 'hover:bg-white/10' }}">
|
||||
{!! '👑 VIP 会员等级' !!}
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
'one_time' => ['label' => '一次性道具', 'color' => 'bg-yellow-100 text-yellow-700'],
|
||||
'ring' => ['label' => '求婚戒指', 'color' => 'bg-rose-100 text-rose-700'],
|
||||
'auto_fishing' => ['label' => '自动钓鱼卡', 'color' => 'bg-emerald-100 text-emerald-700'],
|
||||
'sign_repair' => ['label' => '签到补签卡', 'color' => 'bg-teal-100 text-teal-700'],
|
||||
];
|
||||
$isSuperAdmin = Auth::id() === 1;
|
||||
@endphp
|
||||
@@ -283,6 +284,7 @@
|
||||
<option value="one_time">one_time — 一次性道具</option>
|
||||
<option value="ring">ring — 求婚戒指</option>
|
||||
<option value="auto_fishing">auto_fishing — 自动钓鱼卡</option>
|
||||
<option value="sign_repair">sign_repair — 签到补签卡</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
@extends('admin.layouts.app')
|
||||
|
||||
@section('title', '签到奖励管理')
|
||||
|
||||
@section('content')
|
||||
<div class="space-y-6">
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 p-6 flex justify-between items-center">
|
||||
<div>
|
||||
<h2 class="text-lg font-bold text-gray-800">✅ 签到奖励管理</h2>
|
||||
<p class="text-xs text-gray-500 mt-1">按连续签到天数配置金币、经验、魅力和专属身份。</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<table class="w-full text-sm">
|
||||
<thead class="bg-gray-50 border-b border-gray-100">
|
||||
<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-center 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>
|
||||
<th class="px-4 py-3 text-center 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>
|
||||
<th class="px-4 py-3 text-center text-xs font-bold text-gray-500 uppercase">状态</th>
|
||||
<th class="px-4 py-3 text-right text-xs font-bold text-gray-500 uppercase">操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-50">
|
||||
@forelse ($rules as $rule)
|
||||
<tr id="rule-row-{{ $rule->id }}" class="{{ $rule->is_enabled ? '' : 'opacity-50' }}">
|
||||
<td class="px-4 py-3 font-bold text-gray-800">第 {{ $rule->streak_days }} 天</td>
|
||||
<td class="px-4 py-3 text-center text-amber-600 font-mono">+{{ $rule->gold_reward }}</td>
|
||||
<td class="px-4 py-3 text-center text-emerald-600 font-mono">+{{ $rule->exp_reward }}</td>
|
||||
<td class="px-4 py-3 text-center text-pink-600 font-mono">+{{ $rule->charm_reward }}</td>
|
||||
<td class="px-4 py-3">
|
||||
@if ($rule->identity_badge_name)
|
||||
<span class="inline-flex items-center gap-1 rounded-full border px-2 py-1 text-xs font-bold"
|
||||
style="color: {{ $rule->identity_badge_color ?: '#0f766e' }}; border-color: #99f6e4; background: #f0fdfa;">
|
||||
<span>{{ $rule->identity_badge_icon ?: '✅' }}</span>
|
||||
<span>{{ $rule->identity_badge_name }}</span>
|
||||
</span>
|
||||
<div class="mt-1 text-[11px] text-gray-400">{{ $rule->identity_badge_code }}</div>
|
||||
@else
|
||||
<span class="text-xs text-gray-400">未配置身份</span>
|
||||
@endif
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center text-xs text-gray-600">
|
||||
{{ $rule->identity_duration_days > 0 ? $rule->identity_duration_days . ' 天' : '永久' }}
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<button onclick="toggleSignInRule({{ $rule->id }})" id="toggle-rule-{{ $rule->id }}"
|
||||
class="px-2 py-1 rounded-full text-xs font-bold transition {{ $rule->is_enabled ? 'bg-emerald-100 text-emerald-700 hover:bg-emerald-200' : 'bg-gray-100 text-gray-500 hover:bg-gray-200' }}">
|
||||
{{ $rule->is_enabled ? '启用' : '停用' }}
|
||||
</button>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-right">
|
||||
<button type="button" onclick="openEditRule({{ $rule->id }})"
|
||||
class="px-3 py-1 bg-indigo-50 text-indigo-700 rounded text-xs font-bold hover:bg-indigo-100 transition mr-1">
|
||||
编辑
|
||||
</button>
|
||||
<form action="{{ route('admin.sign-in-rules.destroy', $rule) }}" method="POST"
|
||||
class="inline" onsubmit="return confirm('确定删除第 {{ $rule->streak_days }} 天签到规则?')">
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button type="submit"
|
||||
class="px-3 py-1 bg-red-50 text-red-600 rounded text-xs font-bold hover:bg-red-100 transition">
|
||||
删除
|
||||
</button>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
@empty
|
||||
<tr>
|
||||
<td colspan="8" class="px-4 py-8 text-center text-sm text-gray-400">暂无签到奖励规则。</td>
|
||||
</tr>
|
||||
@endforelse
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<div class="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
|
||||
<div class="p-5 border-b border-gray-100 bg-gray-50">
|
||||
<h3 class="font-bold text-gray-700 text-sm">➕ 新增签到档位</h3>
|
||||
</div>
|
||||
<form action="{{ route('admin.sign-in-rules.store') }}" method="POST" class="p-5">
|
||||
@csrf
|
||||
@include('admin.sign-in-rules.partials.form-fields', ['rule' => null])
|
||||
<div class="mt-4 flex items-center gap-4">
|
||||
<button type="submit"
|
||||
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm shadow-sm">
|
||||
💾 添加规则
|
||||
</button>
|
||||
<label class="flex items-center gap-2 text-sm text-gray-600 cursor-pointer">
|
||||
<input type="checkbox" name="is_enabled" value="1" checked class="rounded">
|
||||
立即启用
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="edit-rule-modal" class="hidden fixed inset-0 bg-black/40 z-50 flex items-center justify-center p-4">
|
||||
<div class="bg-white rounded-xl w-full max-w-3xl shadow-2xl">
|
||||
<div class="p-5 border-b border-gray-100 flex justify-between items-center">
|
||||
<h3 class="font-bold text-gray-800">✏️ 编辑签到规则</h3>
|
||||
<button type="button" onclick="closeEditRule()" class="text-gray-400 hover:text-gray-600 text-xl">✕</button>
|
||||
</div>
|
||||
<form id="edit-rule-form" method="POST" class="p-5">
|
||||
@csrf
|
||||
@method('PUT')
|
||||
@include('admin.sign-in-rules.partials.form-fields', ['rule' => null, 'prefix' => 'edit-'])
|
||||
<div class="mt-5 flex items-center gap-4">
|
||||
<button type="submit"
|
||||
class="px-5 py-2 bg-indigo-600 text-white rounded-lg font-bold hover:bg-indigo-700 transition text-sm">
|
||||
💾 保存修改
|
||||
</button>
|
||||
<label class="flex items-center gap-2 text-sm text-gray-600 cursor-pointer">
|
||||
<input type="checkbox" name="is_enabled" id="edit-is-enabled" value="1" class="rounded">
|
||||
启用此规则
|
||||
</label>
|
||||
<button type="button" onclick="closeEditRule()"
|
||||
class="px-4 py-2 bg-gray-100 text-gray-700 rounded-lg font-bold hover:bg-gray-200 transition text-sm">
|
||||
取消
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
const signInRules = @json($rules->keyBy('id'));
|
||||
|
||||
function openEditRule(id) {
|
||||
const rule = signInRules[id];
|
||||
if (!rule) return;
|
||||
|
||||
document.getElementById('edit-rule-form').action = `/admin/sign-in-rules/${id}`;
|
||||
['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'
|
||||
].forEach((field) => {
|
||||
const input = document.getElementById(`edit-${field}`);
|
||||
if (input) input.value = rule[field] ?? '';
|
||||
});
|
||||
document.getElementById('edit-is-enabled').checked = Boolean(rule.is_enabled);
|
||||
document.getElementById('edit-rule-modal').classList.remove('hidden');
|
||||
}
|
||||
|
||||
function closeEditRule() {
|
||||
document.getElementById('edit-rule-modal').classList.add('hidden');
|
||||
}
|
||||
|
||||
async function toggleSignInRule(id) {
|
||||
const response = await fetch(`/admin/sign-in-rules/${id}/toggle`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
'Accept': 'application/json',
|
||||
},
|
||||
});
|
||||
const data = await response.json();
|
||||
if (!response.ok || !data.ok) {
|
||||
alert(data.message || '切换失败');
|
||||
return;
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
</script>
|
||||
@endsection
|
||||
@@ -0,0 +1,66 @@
|
||||
@php
|
||||
$prefix = $prefix ?? '';
|
||||
@endphp
|
||||
|
||||
<div class="grid grid-cols-2 md:grid-cols-4 gap-4">
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">连续天数</label>
|
||||
<input type="number" id="{{ $prefix }}streak_days" name="streak_days" min="1" required
|
||||
value="{{ old('streak_days') }}"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">金币奖励</label>
|
||||
<input type="number" id="{{ $prefix }}gold_reward" name="gold_reward" min="0" required
|
||||
value="{{ old('gold_reward', 0) }}"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">经验奖励</label>
|
||||
<input type="number" id="{{ $prefix }}exp_reward" name="exp_reward" min="0" required
|
||||
value="{{ old('exp_reward', 0) }}"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">魅力奖励</label>
|
||||
<input type="number" id="{{ $prefix }}charm_reward" name="charm_reward" min="0" required
|
||||
value="{{ old('charm_reward', 0) }}"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">身份编码</label>
|
||||
<input type="text" id="{{ $prefix }}identity_badge_code" name="identity_badge_code"
|
||||
value="{{ old('identity_badge_code') }}" placeholder="sign_in_7"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">身份名称</label>
|
||||
<input type="text" id="{{ $prefix }}identity_badge_name" name="identity_badge_name"
|
||||
value="{{ old('identity_badge_name') }}" placeholder="七日星辉"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">身份图标</label>
|
||||
<input type="text" id="{{ $prefix }}identity_badge_icon" name="identity_badge_icon"
|
||||
value="{{ old('identity_badge_icon') }}" placeholder="🔥"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">身份颜色</label>
|
||||
<input type="text" id="{{ $prefix }}identity_badge_color" name="identity_badge_color"
|
||||
value="{{ old('identity_badge_color', '#0f766e') }}" placeholder="#0f766e"
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">身份有效天数</label>
|
||||
<input type="number" id="{{ $prefix }}identity_duration_days" name="identity_duration_days" min="0"
|
||||
value="{{ old('identity_duration_days', 0) }}" required
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
<div>
|
||||
<label class="block text-xs font-bold text-gray-600 mb-1">排序</label>
|
||||
<input type="number" id="{{ $prefix }}sort_order" name="sort_order" min="0"
|
||||
value="{{ old('sort_order', 0) }}" required
|
||||
class="w-full border border-gray-300 rounded-lg p-2 text-sm focus:border-indigo-400">
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user