diff --git a/app/Filament/Resources/System/MedalResource.php b/app/Filament/Resources/System/MedalResource.php index 92fdf0aa..f282a316 100644 --- a/app/Filament/Resources/System/MedalResource.php +++ b/app/Filament/Resources/System/MedalResource.php @@ -75,6 +75,14 @@ class MedalResource extends Resource ->label(__('medal.fields.bonus_addition_factor')) ->helperText(__('medal.fields.bonus_addition_factor_help')) ->numeric() + ->minValue(0) + ->default(0) + , + Forms\Components\TextInput::make('bonus_addition_duration') + ->label(__('medal.fields.bonus_addition_duration')) + ->helperText(__('medal.fields.bonus_addition_duration_help')) + ->numeric() + ->minValue(0) ->default(0) , Forms\Components\TextInput::make('gift_fee_factor') @@ -109,6 +117,7 @@ class MedalResource extends Resource ->formatStateUsing(fn ($record) => new HtmlString(sprintf('%s ~
%s', $record->sale_begin_time ?? nexus_trans('nexus.no_limit'), $record->sale_end_time ?? nexus_trans('nexus.no_limit')))) , Tables\Columns\TextColumn::make('bonus_addition_factor')->label(__('medal.fields.bonus_addition_factor')), + Tables\Columns\TextColumn::make('bonus_addition_duration')->label(__('medal.fields.bonus_addition_duration')), Tables\Columns\TextColumn::make('gift_fee_factor')->label(__('medal.fields.gift_fee_factor')), Tables\Columns\TextColumn::make('price')->label(__('label.price'))->formatStateUsing(fn ($state) => number_format($state)), diff --git a/app/Models/Medal.php b/app/Models/Medal.php index d41078f0..f6ba2866 100644 --- a/app/Models/Medal.php +++ b/app/Models/Medal.php @@ -18,7 +18,7 @@ class Medal extends NexusModel protected $fillable = [ 'name', 'description', 'image_large', 'image_small', 'price', 'duration', 'get_type', 'display_on_medal_page', 'sale_begin_time', 'sale_end_time', 'inventory', 'bonus_addition_factor', - 'gift_fee_factor', 'priority' + 'gift_fee_factor', 'priority', 'bonus_addition_duration' ]; public $timestamps = true; diff --git a/app/Models/UserMedal.php b/app/Models/UserMedal.php index cb7e3035..d41a6e07 100644 --- a/app/Models/UserMedal.php +++ b/app/Models/UserMedal.php @@ -4,7 +4,7 @@ namespace App\Models; class UserMedal extends NexusModel { - protected $fillable = ['uid', 'medal_id', 'expire_at', 'status']; + protected $fillable = ['uid', 'medal_id', 'expire_at', 'status', 'bonus_addition_expire_at']; const STATUS_NOT_WEARING = 0; const STATUS_WEARING = 1; diff --git a/app/Repositories/BonusRepository.php b/app/Repositories/BonusRepository.php index 81c89c1f..5be08792 100644 --- a/app/Repositories/BonusRepository.php +++ b/app/Repositories/BonusRepository.php @@ -70,11 +70,8 @@ class BonusRepository extends BaseRepository ], $user->locale); do_log("comment: $comment"); $this->consumeUserBonus($user, $requireBonus, BonusLogs::BUSINESS_TYPE_BUY_MEDAL, "$comment(medal ID: {$medal->id})"); - $expireAt = null; - if ($medal->duration > 0) { - $expireAt = Carbon::now()->addDays((int)$medal->duration)->toDateTimeString(); - } - $user->medals()->attach([$medal->id => ['expire_at' => $expireAt, 'status' => UserMedal::STATUS_NOT_WEARING]]); + $medalRep = new MedalRepository(); + $medalRep->userAttachMedal($user, $medal); if ($medal->inventory !== null) { $affectedRows = NexusDB::table('medals') ->where('id', $medal->id) diff --git a/app/Repositories/MedalRepository.php b/app/Repositories/MedalRepository.php index 96e36c36..837e085f 100644 --- a/app/Repositories/MedalRepository.php +++ b/app/Repositories/MedalRepository.php @@ -68,12 +68,27 @@ class MedalRepository extends BaseRepository if ($exists) { throw new \LogicException("user: $uid already own this medal: $medalId."); } + $this->userAttachMedal($user, $medal); + } + + public function userAttachMedal(User $user, Medal $medal): void + { $expireAt = null; - if ($duration > 0) { - $expireAt = Carbon::now()->addDays(intval($duration))->toDateTimeString(); + $bonusAdditionExpireAt = null; + if ($medal->duration > 0) { + $expireAt = Carbon::now()->addDays((int)$medal->duration)->toDateTimeString(); } - clear_user_cache($uid); - return $user->medals()->attach([$medal->id => ['expire_at' => $expireAt, 'status' => UserMedal::STATUS_NOT_WEARING]]); + if ($medal->bonus_addition_duration > 0) { + $bonusAdditionExpireAt = Carbon::now()->addDays((int)$medal->bonus_addition_duration)->toDateTimeString(); + } + $user->medals()->attach([ + $medal->id => [ + 'expire_at' => $expireAt, + 'bonus_addition_expire_at' => $bonusAdditionExpireAt, + 'status' => UserMedal::STATUS_NOT_WEARING, + ] + ]); + clear_user_cache($user->id); } public function toggleUserMedalStatus($id, $userId) diff --git a/database/migrations/2025_07_13_232240_add_bonus_addition_duration_to_medals.php b/database/migrations/2025_07_13_232240_add_bonus_addition_duration_to_medals.php new file mode 100644 index 00000000..66d9a811 --- /dev/null +++ b/database/migrations/2025_07_13_232240_add_bonus_addition_duration_to_medals.php @@ -0,0 +1,34 @@ +integer('bonus_addition_duration')->default(0)->after('bonus_addition_factor')->comment('魔力加成有效天数,0 永久有效'); + }); + Schema::table('user_medals', function (Blueprint $table) { + $table->dateTime('bonus_addition_expire_at')->nullable()->after('expire_at')->comment('魔力加成过期时间,null 永不过期'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('medals', function (Blueprint $table) { + $table->dropColumn('bonus_addition_duration'); + }); + Schema::table('user_medals', function (Blueprint $table) { + $table->dropColumn('bonus_addition_expire_at'); + }); + } +}; diff --git a/include/constants.php b/include/constants.php index eab90622..b286ef0f 100644 --- a/include/constants.php +++ b/include/constants.php @@ -1,6 +1,6 @@ '$nowStr'))"); + $userMedalResult = \Nexus\Database\NexusDB::select("select sum(bonus_addition_factor) as factor from medals where id in (select medal_id from user_medals where uid = $uid and (expire_at is null or expire_at > '$nowStr') and (bonus_addition_expire_at is null or bonus_addition_expire_at > '$nowStr'))"); $medalAdditionalFactor = floatval($userMedalResult[0]['factor'] ?? 0); do_log("$logPrefix, sql: $sql, count: " . count($torrentResult) . ", officialTag: $officialTag, officialAdditionalFactor: $officialAdditionalFactor, zeroBonusTag: $zeroBonusTag, zeroBonusFactor: $zeroBonusFactor, medalAdditionalFactor: $medalAdditionalFactor"); $last_action = ""; @@ -6350,7 +6350,7 @@ function build_bonus_table(array $user, array $bonusResult = [], array $options $baseBonusFactor, number_format($baseBonus,3), $rowSpan, - $totalBonus + number_format($totalBonus, 3) ); if ($hasMedalAddition) { $table .= sprintf( @@ -6360,7 +6360,7 @@ function build_bonus_table(array $user, array $bonusResult = [], array $options mksize($bonusResult['size']), number_format($bonusResult['A'], 3), number_format($bonusResult['medal_bonus'], 3), - $bonusResult['medal_additional_factor'], + number_format($bonusResult['medal_additional_factor'], 3), number_format($bonusResult['medal_bonus'] * $bonusResult['medal_additional_factor'], 3) ); } @@ -6373,7 +6373,7 @@ function build_bonus_table(array $user, array $bonusResult = [], array $options mksize($bonusResult['official_size']), number_format($bonusResult['official_a'], 3), number_format($bonusResult['official_bonus'], 3), - $officialAdditionalFactor, + number_format($officialAdditionalFactor, 3), number_format($bonusResult['official_bonus'] * $officialAdditionalFactor, 3) ); } @@ -6386,7 +6386,7 @@ function build_bonus_table(array $user, array $bonusResult = [], array $options '--', '--', number_format($haremAddition, 3), - $haremFactor, + number_format($haremFactor, 3), number_format($haremAddition * $haremFactor, 3) ); } diff --git a/resources/lang/en/medal.php b/resources/lang/en/medal.php index acba2b11..50e89efa 100644 --- a/resources/lang/en/medal.php +++ b/resources/lang/en/medal.php @@ -32,6 +32,8 @@ return [ 'gift_fee_factor' => 'Gift fee factor', 'gift_fee' => 'Gift fee', 'gift_fee_factor_help' => 'The additional fee charged for gifts to other users is equal to the price multiplied by this factor', + 'bonus_addition_duration' => 'Bonus addition duration', + 'bonus_addition_duration_help' => 'Unit: days. Set to 0 for permanent effect. Counts from the time of acquisition, regardless of whether it is equipped or not', ], 'buy_already' => 'Already buy', 'buy_btn' => 'Buy', diff --git a/resources/lang/zh_CN/medal.php b/resources/lang/zh_CN/medal.php index c8ad8659..21aa6e5d 100644 --- a/resources/lang/zh_CN/medal.php +++ b/resources/lang/zh_CN/medal.php @@ -32,6 +32,8 @@ return [ 'gift_fee_factor' => '赠送手续费系数', 'gift_fee' => '手续费', 'gift_fee_factor_help' => '赠送给其他用户时额外收取手续费等于价格乘以此系数', + 'bonus_addition_duration' => '魔力加成有效时长', + 'bonus_addition_duration_help' => '单位:天,设置为 0 表示永久有效。从获得时开始算,无论是否佩戴', ], 'buy_already' => '已经购买', 'buy_btn' => '购买', diff --git a/resources/lang/zh_TW/medal.php b/resources/lang/zh_TW/medal.php index 7aa5f434..577a15fa 100644 --- a/resources/lang/zh_TW/medal.php +++ b/resources/lang/zh_TW/medal.php @@ -32,6 +32,8 @@ return [ 'gift_fee_factor' => '贈送手續費系數', 'gift_fee' => '手續費', 'gift_fee_factor_help' => '贈送給其他用戶時額外收取手續費等於價格乘以此系數', + 'bonus_addition_duration' => '魔力加成有效時長', + 'bonus_addition_duration_help' => '單位:天,設置爲 0 表示永久有效。從獲得時開始算,無論是否佩戴', ], 'buy_already' => '已經購買', 'buy_btn' => '購買',