mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-23 19:37:23 +08:00
[admin] torrent add more bulk action
This commit is contained in:
@@ -15,4 +15,12 @@ trait OptionsTrait
|
||||
$disableValue => __('label.disabled'),
|
||||
];
|
||||
}
|
||||
|
||||
private static function getYesNoOptions($yesValue = 1, $noValue = 0): array
|
||||
{
|
||||
return [
|
||||
$yesValue => 'Yes',
|
||||
$noValue => 'No',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,7 @@ class SeedBoxRecordResource extends Resource
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('id'),
|
||||
Tables\Columns\TextColumn::make('typeText')->label(__('label.seed_box_record.type')),
|
||||
Tables\Columns\TextColumn::make('uid')->searchable(),
|
||||
Tables\Columns\TextColumn::make('user.username')->label(__('label.username'))->searchable(),
|
||||
Tables\Columns\TextColumn::make('operator')->label(__('label.seed_box_record.operator'))->searchable(),
|
||||
Tables\Columns\TextColumn::make('bandwidth')->label(__('label.seed_box_record.bandwidth')),
|
||||
|
||||
@@ -112,6 +112,7 @@ class EditSetting extends Page implements Forms\Contracts\HasForms
|
||||
Forms\Components\TextInput::make('seed_box.not_seed_box_max_speed')->label(__('label.setting.seed_box.not_seed_box_max_speed'))->helperText(__('label.setting.seed_box.not_seed_box_max_speed_help'))->integer(),
|
||||
Forms\Components\Radio::make('seed_box.no_promotion')->options(self::$yesOrNo)->inline(true)->label(__('label.setting.seed_box.no_promotion'))->helperText(__('label.setting.seed_box.no_promotion_help')),
|
||||
Forms\Components\TextInput::make('seed_box.max_uploaded')->label(__('label.setting.seed_box.max_uploaded'))->helperText(__('label.setting.seed_box.max_uploaded_help'))->integer(),
|
||||
Forms\Components\TextInput::make('seed_box.max_uploaded_duration')->label(__('label.setting.seed_box.max_uploaded_duration'))->helperText(__('label.setting.seed_box.max_uploaded_duration_help'))->integer(),
|
||||
])->columns(2);
|
||||
|
||||
$tabs[] = Forms\Components\Tabs\Tab::make(__('label.setting.system.tab_header'))
|
||||
|
||||
@@ -9,6 +9,7 @@ use App\Models\Setting;
|
||||
use App\Models\Tag;
|
||||
use App\Models\Torrent;
|
||||
use App\Models\TorrentTag;
|
||||
use App\Models\User;
|
||||
use App\Repositories\TagRepository;
|
||||
use App\Repositories\TorrentRepository;
|
||||
use Filament\Facades\Filament;
|
||||
@@ -24,6 +25,7 @@ use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\HtmlString;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class TorrentResource extends Resource
|
||||
{
|
||||
@@ -83,10 +85,16 @@ class TorrentResource extends Resource
|
||||
})->label(__('label.name'))->searchable(),
|
||||
Tables\Columns\TextColumn::make('posStateText')->label(__('label.torrent.pos_state')),
|
||||
Tables\Columns\TextColumn::make('spStateText')->label(__('label.torrent.sp_state')),
|
||||
Tables\Columns\TextColumn::make('pickInfoText')
|
||||
->label(__('label.torrent.picktype'))
|
||||
->formatStateUsing(fn ($record) => $record->pickInfo['text'])
|
||||
,
|
||||
Tables\Columns\BooleanColumn::make('hr')
|
||||
->label(__('label.torrent.hr'))
|
||||
,
|
||||
Tables\Columns\TextColumn::make('size')->label(__('label.torrent.size'))->formatStateUsing(fn ($state) => mksize($state)),
|
||||
Tables\Columns\TextColumn::make('seeders')->label(__('label.torrent.seeders')),
|
||||
Tables\Columns\TextColumn::make('leechers')->label(__('label.torrent.leechers')),
|
||||
// Tables\Columns\TextColumn::make('times_completed')->label(__('label.torrent.times_completed')),
|
||||
Tables\Columns\BadgeColumn::make('approval_status')
|
||||
->visible($showApproval)
|
||||
->label(__('label.torrent.approval_status'))
|
||||
@@ -113,10 +121,18 @@ class TorrentResource extends Resource
|
||||
->options(Torrent::listPromotionTypes(true))
|
||||
->label(__('label.torrent.sp_state')),
|
||||
|
||||
Tables\Filters\SelectFilter::make('picktype')
|
||||
->options(Torrent::listPickInfo(true))
|
||||
->label(__('label.torrent.picktype')),
|
||||
|
||||
Tables\Filters\SelectFilter::make('approval_status')
|
||||
->options(Torrent::listApprovalStatus(true))
|
||||
->visible($showApproval)
|
||||
->label(__('label.torrent.approval_status')),
|
||||
|
||||
Tables\Filters\SelectFilter::make('hr')
|
||||
->options(self::getYesNoOptions())
|
||||
->label(__('label.torrent.hr')),
|
||||
])
|
||||
->actions(self::getActions())
|
||||
->bulkActions(self::getBulkActions());
|
||||
@@ -146,6 +162,7 @@ class TorrentResource extends Resource
|
||||
|
||||
private static function getBulkActions(): array
|
||||
{
|
||||
$user = Auth::user();
|
||||
$actions = [];
|
||||
if (user_can('torrentsticky')) {
|
||||
$actions[] = Tables\Actions\BulkAction::make('posState')
|
||||
@@ -174,6 +191,66 @@ class TorrentResource extends Resource
|
||||
->deselectRecordsAfterCompletion();
|
||||
}
|
||||
|
||||
if (user_can('torrentonpromotion')) {
|
||||
$actions[] = Tables\Actions\BulkAction::make('sp_state')
|
||||
->label(__('admin.resources.torrent.bulk_action_sp_state'))
|
||||
->form([
|
||||
Forms\Components\Select::make('sp_state')
|
||||
->label(__('label.torrent.sp_state'))
|
||||
->options(Torrent::listPromotionTypes(true))
|
||||
->required()
|
||||
,
|
||||
Forms\Components\Select::make('promotion_time_type')
|
||||
->label(__('label.torrent.promotion_time_type'))
|
||||
->options(Torrent::listPromotionTimeTypes(true))
|
||||
->required()
|
||||
,
|
||||
Forms\Components\DateTimePicker::make('promotion_until')
|
||||
->label(__('label.deadline'))
|
||||
,
|
||||
])
|
||||
->icon('heroicon-o-speakerphone')
|
||||
->action(function (Collection $records, array $data) {
|
||||
$idArr = $records->pluck('id')->toArray();
|
||||
try {
|
||||
$torrentRep = new TorrentRepository();
|
||||
$torrentRep->setSpState($idArr, $data['sp_state'], $data['promotion_time_type'], $data['promotion_until']);
|
||||
} catch (\Exception $exception) {
|
||||
do_log($exception->getMessage() . $exception->getTraceAsString(), 'error');
|
||||
Filament::notify('danger', $exception->getMessage());
|
||||
}
|
||||
})
|
||||
->deselectRecordsAfterCompletion();
|
||||
}
|
||||
|
||||
if (user_can('torrentmanage') && ($user->picker == 'yes' || $user->class >= User::CLASS_SYSOP)) {
|
||||
$actions[] = Tables\Actions\BulkAction::make('recommend')
|
||||
->label(__('admin.resources.torrent.bulk_action_recommend'))
|
||||
->form([
|
||||
Forms\Components\Radio::make('picktype')
|
||||
->label(__('admin.resources.torrent.bulk_action_recommend'))
|
||||
->inline()
|
||||
->options(Torrent::listPickInfo(true))
|
||||
->required(),
|
||||
|
||||
])
|
||||
->icon('heroicon-o-fire')
|
||||
->action(function (Collection $records, array $data) {
|
||||
if (empty($data['picktype'])) {
|
||||
return;
|
||||
}
|
||||
$idArr = $records->pluck('id')->toArray();
|
||||
try {
|
||||
$torrentRep = new TorrentRepository();
|
||||
$torrentRep->setPickType($idArr, $data['picktype']);
|
||||
} catch (\Exception $exception) {
|
||||
do_log($exception->getMessage() . $exception->getTraceAsString(), 'error');
|
||||
Filament::notify('danger', class_basename($exception));
|
||||
}
|
||||
})
|
||||
->deselectRecordsAfterCompletion();
|
||||
}
|
||||
|
||||
if (user_can('torrentmanage')) {
|
||||
$actions[] = Tables\Actions\BulkAction::make('remove_tag')
|
||||
->label(__('admin.resources.torrent.bulk_action_remove_tag'))
|
||||
@@ -217,6 +294,38 @@ class TorrentResource extends Resource
|
||||
}
|
||||
})
|
||||
->deselectRecordsAfterCompletion();
|
||||
|
||||
$actions[] = Tables\Actions\BulkAction::make('hr')
|
||||
->label(__('admin.resources.torrent.bulk_action_hr'))
|
||||
->form([
|
||||
Forms\Components\Radio::make('hr')
|
||||
->label(__('admin.resources.torrent.bulk_action_hr'))
|
||||
->inline()
|
||||
->options(self::getYesNoOptions())
|
||||
->required(),
|
||||
|
||||
])
|
||||
->icon('heroicon-o-sparkles')
|
||||
->action(function (Collection $records, array $data) {
|
||||
if (empty($data['hr'])) {
|
||||
return;
|
||||
}
|
||||
$idArr = $records->pluck('id')->toArray();
|
||||
try {
|
||||
$torrentRep = new TorrentRepository();
|
||||
$torrentRep->setHr($idArr, $data['hr']);
|
||||
} catch (\Exception $exception) {
|
||||
do_log($exception->getMessage() . $exception->getTraceAsString(), 'error');
|
||||
Filament::notify('danger', class_basename($exception));
|
||||
}
|
||||
})
|
||||
->deselectRecordsAfterCompletion();
|
||||
}
|
||||
|
||||
if (user_can('torrent-delete')) {
|
||||
$actions[] = Tables\Actions\DeleteBulkAction::make('bulk-delete')->using(function (Collection $records) {
|
||||
deletetorrent($records->pluck('id')->toArray());
|
||||
});
|
||||
}
|
||||
|
||||
return $actions;
|
||||
@@ -248,7 +357,7 @@ class TorrentResource extends Resource
|
||||
});
|
||||
|
||||
}
|
||||
if (user_can('torrentmanage')) {
|
||||
if (user_can('torrent-delete')) {
|
||||
$actions[] = Tables\Actions\DeleteAction::make('delete')->using(function ($record) {
|
||||
deletetorrent($record->id);
|
||||
});
|
||||
|
||||
@@ -51,4 +51,19 @@ class NexusModel extends Model
|
||||
return sprintf('%s: %s', nexus_trans('label.deadline'), $raw);
|
||||
}
|
||||
|
||||
public static function listStaticProps($dataSource, $textTransPrefix, $onlyKeyValue = false, $valueField = 'text'): array
|
||||
{
|
||||
$result = $dataSource;
|
||||
$keyValue = [];
|
||||
foreach ($result as $key => &$info) {
|
||||
$text = $textTransPrefix ? nexus_trans("$textTransPrefix.$key") : $info['text'];
|
||||
$info['text'] = $text;
|
||||
$keyValue[$key] = $info[$valueField];
|
||||
}
|
||||
if ($onlyKeyValue) {
|
||||
return $keyValue;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,6 +48,14 @@ class Tag extends NexusModel
|
||||
],
|
||||
];
|
||||
|
||||
public static function listSpecial(): array
|
||||
{
|
||||
return array_filter([
|
||||
Setting::get('system.official_tag'),
|
||||
Setting::get('system.zero_bonus_tag'),
|
||||
]);
|
||||
}
|
||||
|
||||
public function torrents(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Torrent::class, 'torrent_tags', 'tag_id', 'torrent_id');
|
||||
|
||||
@@ -130,6 +130,16 @@ class Torrent extends NexusModel
|
||||
self::PICK_RECOMMENDED => ['text' => self::PICK_RECOMMENDED, 'color' => '#820084'],
|
||||
];
|
||||
|
||||
const PROMOTION_TIME_TYPE_GLOBAL = 0;
|
||||
const PROMOTION_TIME_TYPE_PERMANENT = 1;
|
||||
const PROMOTION_TIME_TYPE_DEADLINE = 2;
|
||||
|
||||
public static array $promotionTimeTypes = [
|
||||
self::PROMOTION_TIME_TYPE_GLOBAL => ['text' => 'Global'],
|
||||
self::PROMOTION_TIME_TYPE_PERMANENT => ['text' => 'Permanent'],
|
||||
self::PROMOTION_TIME_TYPE_DEADLINE => ['text' => 'Until'],
|
||||
];
|
||||
|
||||
const BONUS_REWARD_VALUES = [50, 100, 200, 500, 1000];
|
||||
|
||||
const APPROVAL_STATUS_NONE = 0;
|
||||
@@ -272,6 +282,11 @@ class Torrent extends NexusModel
|
||||
return $result;
|
||||
}
|
||||
|
||||
public static function listPromotionTimeTypes($onlyKeyValue = false, $valueField = 'text'): array
|
||||
{
|
||||
return self::listStaticProps(self::$promotionTimeTypes, 'torrent.promotion_time_types', $onlyKeyValue, $valueField);
|
||||
}
|
||||
|
||||
public static function listPickInfo($onlyKeyValue = false, $valueField = 'text'): array
|
||||
{
|
||||
$result = self::$pickTypes;
|
||||
|
||||
@@ -50,10 +50,14 @@ class TagRepository extends BaseRepository
|
||||
return Tag::query()->orderBy('priority', 'desc')->orderBy('id', 'desc');
|
||||
}
|
||||
|
||||
public function renderCheckbox(array $checked = []): string
|
||||
public function renderCheckbox(array $checked = [], $ignorePermission = false): string
|
||||
{
|
||||
$html = '';
|
||||
$results = $this->createBasicQuery()->get();
|
||||
$results = $this->listAll();
|
||||
if (!$ignorePermission && !user_can('torrent-set-special-tag')) {
|
||||
$specialTags = Tag::listSpecial();
|
||||
$results = $results->filter(fn ($item) => !in_array($item->id, $specialTags));
|
||||
}
|
||||
foreach ($results as $value) {
|
||||
$html .= sprintf(
|
||||
'<label><input type="checkbox" name="tags[]" value="%s"%s />%s</label>',
|
||||
@@ -65,11 +69,8 @@ class TagRepository extends BaseRepository
|
||||
|
||||
public function renderSpan(array $renderIdArr = [], $withFilterLink = false): string
|
||||
{
|
||||
if (empty(self::$allTags)) {
|
||||
self::$allTags = self::createBasicQuery()->get();
|
||||
}
|
||||
$html = '';
|
||||
foreach (self::$allTags as $value) {
|
||||
foreach ($this->listAll() as $value) {
|
||||
if (in_array($value->id, $renderIdArr) || (isset($renderIdArr[0]) && $renderIdArr[0] == '*')) {
|
||||
$tagId = $value->id;
|
||||
if ($value) {
|
||||
@@ -150,7 +151,9 @@ class TagRepository extends BaseRepository
|
||||
|
||||
public function listAll()
|
||||
{
|
||||
self::$allTags = self::createBasicQuery()->get();
|
||||
if (empty(self::$allTags)) {
|
||||
self::$allTags = self::createBasicQuery()->get();
|
||||
}
|
||||
return self::$allTags;
|
||||
}
|
||||
|
||||
|
||||
@@ -616,6 +616,56 @@ class TorrentRepository extends BaseRepository
|
||||
return Torrent::query()->whereIn('id', $idArr)->update($update);
|
||||
}
|
||||
|
||||
public function setPickType($id, $pickType): int
|
||||
{
|
||||
user_can('torrentmanage', true);
|
||||
if (!isset(Torrent::$pickTypes[$pickType])) {
|
||||
throw new \InvalidArgumentException("Invalid pickType: $pickType");
|
||||
}
|
||||
$update = [
|
||||
'picktype' => $pickType,
|
||||
'picktime' => now(),
|
||||
];
|
||||
$idArr = Arr::wrap($id);
|
||||
return Torrent::query()->whereIn('id', $idArr)->update($update);
|
||||
}
|
||||
|
||||
public function setHr($id, $hrStatus): int
|
||||
{
|
||||
user_can('torrentmanage', true);
|
||||
if (!isset(Torrent::$hrStatus[$hrStatus])) {
|
||||
throw new \InvalidArgumentException("Invalid hrStatus: $hrStatus");
|
||||
}
|
||||
$update = [
|
||||
'hr' => $hrStatus,
|
||||
];
|
||||
$idArr = Arr::wrap($id);
|
||||
return Torrent::query()->whereIn('id', $idArr)->update($update);
|
||||
}
|
||||
|
||||
public function setSpState($id, $spState, $promotionTimeType, $promotionUntil = null): int
|
||||
{
|
||||
user_can('torrentonpromotion', true);
|
||||
if (!isset(Torrent::$promotionTypes[$spState])) {
|
||||
throw new \InvalidArgumentException("Invalid spState: $spState");
|
||||
}
|
||||
if (!isset(Torrent::$promotionTimeTypes[$promotionTimeType])) {
|
||||
throw new \InvalidArgumentException("Invalid promotionTimeType: $promotionTimeType");
|
||||
}
|
||||
if (in_array($promotionTimeType, [Torrent::PROMOTION_TIME_TYPE_GLOBAL, Torrent::PROMOTION_TIME_TYPE_PERMANENT])) {
|
||||
$promotionUntil = null;
|
||||
} elseif (!$promotionUntil || Carbon::parse($promotionUntil)->lte(now())) {
|
||||
throw new \InvalidArgumentException("Invalid promotionUntil: $promotionUntil");
|
||||
}
|
||||
$update = [
|
||||
'sp_state' => $spState,
|
||||
'promotion_time_type' => $promotionTimeType,
|
||||
'promotion_until' => $promotionUntil,
|
||||
];
|
||||
$idArr = Arr::wrap($id);
|
||||
return Torrent::query()->whereIn('id', $idArr)->update($update);
|
||||
}
|
||||
|
||||
public function buildUploadFieldInput($name, $value, $noteText, $btnText): string
|
||||
{
|
||||
$btn = $note = '';
|
||||
|
||||
Reference in New Issue
Block a user