user medal add more bulk actions

This commit is contained in:
xiaomlove
2025-07-15 01:33:59 +07:00
parent 3ffdec1f4a
commit d64243fe6a
9 changed files with 239 additions and 3 deletions
@@ -2,11 +2,14 @@
namespace App\Filament\Resources\User;
use App\Filament\OptionsTrait;
use App\Filament\Resources\User\UserMedalResource\Pages;
use App\Filament\Resources\User\UserMedalResource\RelationManagers;
use App\Models\Medal;
use App\Models\NexusModel;
use App\Models\UserMedal;
use App\Repositories\MedalRepository;
use Carbon\Carbon;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
@@ -14,10 +17,13 @@ use Filament\Tables\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Collection;
use Illuminate\Support\HtmlString;
class UserMedalResource extends Resource
{
use OptionsTrait;
protected static ?string $model = UserMedal::class;
protected static ?string $navigationIcon = 'heroicon-o-flag';
@@ -57,8 +63,10 @@ class UserMedalResource extends Resource
,
Tables\Columns\TextColumn::make('medal.name')->label(__('label.medal.label'))->searchable(),
Tables\Columns\ImageColumn::make('medal.image_large')->label(__('label.image')),
Tables\Columns\TextColumn::make('expire_at')->label(__('label.expire_at'))->dateTime(),
Tables\Columns\TextColumn::make('expire_at')->label(__('label.expire_at')),
Tables\Columns\TextColumn::make('bonus_addition_expire_at')->label(__('medal.bonus_addition_expire_at')),
Tables\Columns\TextColumn::make('wearingStatusText')->label(__('label.status')),
Tables\Columns\TextColumn::make('created_at')->label(__('label.created_at')),
])
->defaultSort('id', 'desc')
->filters([
@@ -76,6 +84,42 @@ class UserMedalResource extends Resource
->options(Medal::query()->pluck('name', 'id')->toArray())
->label(__('medal.label'))
,
Tables\Filters\SelectFilter::make('is_expired')
->options(self::getYesNoOptions())
->label(__('medal.is_expired'))
->query(function (Builder $query, array $data) {
if (isset($data['value']) && $data['value'] === "0") {
//未过期,为 null 或大于当前时间
$query->where(function ($query) {
$query->whereNull('expire_at')->orWhere('expire_at', '>', now());
});
}
if (isset($data['value']) && $data['value'] === "1") {
//已过期, 不为 null 且小于当前时间
$query->whereNotNull('expire_at')->where("expire_at", "<", now());
}
})
,
Tables\Filters\SelectFilter::make('is_bonus_addition_expired')
->options(self::getYesNoOptions())
->label(__('medal.is_bonus_addition_expired'))
->query(function (Builder $query, array $data) {
if (isset($data['value']) && $data['value'] === "0") {
//未过期,为 null 或大于当前时间
$query->where(function ($query) {
$query->whereNull('bonus_addition_expire_at')->orWhere('bonus_addition_expire_at', '>', now());
});
}
if (isset($data['value']) && $data['value'] === "1") {
//已过期, 不为 null 且小于当前时间
$query->whereNotNull('bonus_addition_expire_at')->where("bonus_addition_expire_at", "<", now());
}
})
,
Tables\Filters\SelectFilter::make('status')
->options(UserMedal::listWearingStatusLabels())
->label(__('label.status'))
,
])
->actions([
Tables\Actions\DeleteAction::make()->using(function (NexusModel $record) {
@@ -84,8 +128,89 @@ class UserMedalResource extends Resource
})
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
self::buildBulkActionIncreaseExpireAt('expire_at'),
self::buildBulkActionUpdateExpireAt('expire_at'),
self::buildBulkActionCancelExpireAt('expire_at'),
])->label(sprintf("%s-%s", __('label.bulk'), __('label.expire_at'))),
Tables\Actions\BulkActionGroup::make([
self::buildBulkActionIncreaseExpireAt('bonus_addition_expire_at'),
self::buildBulkActionUpdateExpireAt('bonus_addition_expire_at'),
self::buildBulkActionCancelExpireAt('bonus_addition_expire_at'),
])->label(sprintf("%s-%s", __('label.bulk'), __('medal.bonus_addition_expire_at'))),
Tables\Actions\DeleteBulkAction::make(),
])
->selectCurrentPageOnly()
;
}
]);
private static function buildBulkActionIncreaseExpireAt(string $filed): Tables\Actions\BulkAction
{
return Tables\Actions\BulkAction::make("bulkActionIncrease$filed")
->label(__('medal.bulk_action_increase'))
->modalHeading(__('medal.bulk_action_increase_' . $filed))
->form([
Forms\Components\TextInput::make('increase_duration')
->label(__('medal.increase_duration'))
->helperText(__('medal.increase_duration_help'))
->integer()
->required(),
])
->action(function (Collection $collection, array $data) use ($filed) {
try {
$rep = new MedalRepository();
$rep->increaseExpireAt($collection, $filed, $data['increase_duration']);
send_admin_success_notification();
} catch (\Exception $e) {
send_admin_fail_notification($e->getMessage());
}
})
->deselectRecordsAfterCompletion()
;
}
private static function buildBulkActionUpdateExpireAt(string $filed): Tables\Actions\BulkAction
{
return Tables\Actions\BulkAction::make("bulkActionUpdate$filed")
->label(__('medal.bulk_action_update'))
->modalHeading(__('medal.bulk_action_update_' . $filed))
->form([
Forms\Components\DateTimePicker::make('update_expire_at')
->label(__('medal.update_expire_at'))
->helperText(__('medal.update_expire_at_help'))
->required(),
])
->action(function (Collection $collection, array $data) use ($filed) {
try {
$expireAt = Carbon::parse($data['update_expire_at']);
$rep = new MedalRepository();
$rep->updateExpireAt($collection, $filed, $expireAt);
send_admin_success_notification();
} catch (\Exception $e) {
send_admin_fail_notification($e->getMessage());
}
})
->deselectRecordsAfterCompletion()
;
}
private static function buildBulkActionCancelExpireAt(string $filed): Tables\Actions\BulkAction
{
return Tables\Actions\BulkAction::make("bulkActionCancel$filed")
->label(__('medal.bulk_action_cancel'))
->modalHeading(__('medal.bulk_action_cancel_' . $filed))
->requiresConfirmation()
->action(function (Collection $collection) use ($filed) {
try {
$rep = new MedalRepository();
$rep->cancelExpireAt($collection, $filed);
send_admin_success_notification();
} catch (\Exception $e) {
send_admin_fail_notification($e->getMessage());
}
})
->deselectRecordsAfterCompletion()
;
}
public static function getEloquentQuery(): Builder
+9 -1
View File
@@ -9,11 +9,19 @@ class UserMedal extends NexusModel
const STATUS_NOT_WEARING = 0;
const STATUS_WEARING = 1;
public function getWearingStatusTextAttribute()
public function getWearingStatusTextAttribute(): string
{
return nexus_trans("medal.wearing_status_text." . $this->status);
}
public static function listWearingStatusLabels(): array
{
return [
self::STATUS_WEARING => nexus_trans("medal.wearing_status_text." . self::STATUS_WEARING),
self::STATUS_NOT_WEARING => nexus_trans("medal.wearing_status_text." . self::STATUS_NOT_WEARING),
];
}
public function medal()
{
return $this->belongsTo(Medal::class, 'medal_id');
+48
View File
@@ -7,6 +7,7 @@ use App\Models\Setting;
use App\Models\User;
use App\Models\UserMedal;
use Carbon\Carbon;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Nexus\Database\NexusDB;
@@ -148,4 +149,51 @@ class MedalRepository extends BaseRepository
return NexusDB::statement($sql);
}
public function increaseExpireAt(Collection $collection, string $field, int $duration): void
{
$this->checkExpireField($field);
$idArr = $collection->pluck('id')->toArray();
$result = NexusDB::table("user_medals")
->whereIn('id', $idArr)
->whereNotNull($field)
->update([$field => NexusDB::raw("`$field` + INTERVAL $duration DAY")]);
do_log(sprintf(
"operator: %s, increase records: %s $field + $duration day, result: %s",
get_pure_username(), implode(', ', $idArr), $result
));
}
public function updateExpireAt(Collection $collection, string $field, Carbon $expireAt): void
{
$this->checkExpireField($field);
$idArr = $collection->pluck('id')->toArray();
$result = NexusDB::table("user_medals")
->whereIn('id', $idArr)
->update([$field => $expireAt]);
do_log(sprintf(
"operator: %s, update records: %s $field $expireAt, result: %s",
get_pure_username(), implode(', ', $idArr), $result
));
}
public function cancelExpireAt(Collection $collection, string $field): void
{
$this->checkExpireField($field);
$idArr = $collection->pluck('id')->toArray();
$result = NexusDB::table("user_medals")
->whereIn('id', $idArr)
->update([$field => NexusDB::raw("null")]);
do_log(sprintf(
"operator: %s, update records: %s $field null, result: %s",
get_pure_username(), implode(', ', $idArr), $result
));
}
private function checkExpireField(string $field): void
{
if (!in_array($field, ['expire_at', 'bonus_addition_expire_at'])) {
throw new \InvalidArgumentException("invalid field: $field");
}
}
}
+1
View File
@@ -49,6 +49,7 @@ return [
'language' => 'Language',
'content' => 'Content',
'is_default' => 'Is default',
'bulk' => 'Bulk',
'setting' => [
'nav_text' => 'Setting',
'backup' => [
+18
View File
@@ -50,4 +50,22 @@ return [
0 => 'Wearing',
1 => 'Not wearing'
],
'bonus_addition_expire_at' => 'Bonus addition Expiration Time',
'is_expired' => 'Is Expired',
'is_bonus_addition_expired' => 'Is Bonus addition expired',
'is_wearing' => 'Is Wearing',
'increase_duration' => 'Increase Duration',
'increase_duration_help' => 'Unit: days. Uniformly extend the expiration time from the original value',
'update_expire_at' => 'Set expiration time',
'update_expire_at_help' => 'Uniformly set the expiration time to a specified value',
'bulk_action_increase' => 'Increase',
'bulk_action_update' => 'Update',
'bulk_action_cancel' => 'Cancel',
'bulk_action_increase_expire_at' => 'Bulk increase expiration time',
'bulk_action_update_expire_at' => 'Bulk update expiration time',
'bulk_action_cancel_expire_at' => 'Bulk cancel expiration time',
'bulk_action_increase_bonus_addition_expire_at' => 'Bulk extend bonus addition expiration time',
'bulk_action_update_bonus_addition_expire_at' => 'Bulk update bonus expiration time',
'bulk_action_cancel_bonus_addition_expire_at' => 'Bulk cancel bonus expiration time',
];
+1
View File
@@ -49,6 +49,7 @@ return [
'language' => '语言',
'content' => '内容',
'is_default' => '是否默认',
'bulk' => '批量',
'setting' => [
'nav_text' => '设置',
'backup' => [
+17
View File
@@ -50,4 +50,21 @@ return [
0 => '未佩戴',
1 => '已佩戴'
],
'bonus_addition_expire_at' => '魔力加成过期时间',
'is_expired' => '是否过期',
'is_bonus_addition_expired' => '是否魔力加成过期',
'is_wearing' => '是否佩戴',
'increase_duration' => '延长时长',
'increase_duration_help' => '单位:天。将过期时间在原基础上统一延长',
'update_expire_at' => '设置过期时间',
'update_expire_at_help' => '将过期时间统一设置为指定值',
'bulk_action_increase' => '延长',
'bulk_action_update' => '设置',
'bulk_action_cancel' => '取消',
'bulk_action_increase_expire_at' => '批量延长过期时间',
'bulk_action_update_expire_at' => '批量设置过期时间',
'bulk_action_cancel_expire_at' => '批量取消过期时间',
'bulk_action_increase_bonus_addition_expire_at' => '批量延长魔力加成过期时间',
'bulk_action_update_bonus_addition_expire_at' => '批量设置魔力加成过期时间',
'bulk_action_cancel_bonus_addition_expire_at' => '批量取消魔力加成过期时间',
];
+1
View File
@@ -49,6 +49,7 @@ return [
'language' => '語言',
'content' => '內容',
'is_default' => '是否默認',
'bulk' => '批量',
'setting' => [
'nav_text' => '設置',
'backup' => [
+17
View File
@@ -50,4 +50,21 @@ return [
0 => '未佩戴',
1 => '已佩戴'
],
'bonus_addition_expire_at' => '魔力加成過期時間',
'is_expired' => '是否過期',
'is_bonus_addition_expired' => '是否魔力加成過期',
'is_wearing' => '是否佩戴',
'increase_duration' => '延長時長',
'increase_duration_help' => '單位:天。將過期時間在原基礎上統一延長',
'update_expire_at' => '設置過期時間',
'update_expire_at_help' => '將過期時間統一設置爲指定值',
'bulk_action_increase' => '延長',
'bulk_action_update' => '設置',
'bulk_action_cancel' => '取消',
'bulk_action_increase_expire_at' => '批量延長過期時間',
'bulk_action_update_expire_at' => '批量設置過期時間',
'bulk_action_cancel_expire_at' => '批量取消過期時間',
'bulk_action_increase_bonus_addition_expire_at' => '批量延長魔力加成過期時間',
'bulk_action_update_bonus_addition_expire_at' => '批量設置魔力加成過期時間',
'bulk_action_cancel_bonus_addition_expire_at' => '批量取消魔力加成過期時間',
];