mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-23 11:27:24 +08:00
exam add max user count
This commit is contained in:
@@ -49,22 +49,32 @@ class ExamResource extends Resource
|
||||
Forms\Components\Section::make(__('label.exam.section_base_info'))->schema([
|
||||
Forms\Components\TextInput::make('name')->required()->columnSpan(['sm' => 2])->label(__('label.name')),
|
||||
Forms\Components\Select::make('type')
|
||||
->required()->columnSpan(['sm' => 2])
|
||||
->required()
|
||||
->columnSpanFull()
|
||||
->label(__('exam.type'))
|
||||
->options(Exam::listTypeOptions())
|
||||
->helperText(__('exam.type_help'))
|
||||
->reactive()
|
||||
,
|
||||
Forms\Components\TextInput::make('success_reward_bonus')
|
||||
->columnSpanFull()
|
||||
->required()
|
||||
->label(__('exam.success_reward_bonus'))
|
||||
->hidden(fn (\Closure $get) => $get('type') != Exam::TYPE_TASK)
|
||||
,
|
||||
Forms\Components\TextInput::make('fail_deduct_bonus')
|
||||
->columnSpanFull()
|
||||
->required()
|
||||
->label(__('exam.fail_deduct_bonus'))
|
||||
->hidden(fn (\Closure $get) => $get('type') != Exam::TYPE_TASK)
|
||||
,
|
||||
Forms\Components\TextInput::make('max_user_count')
|
||||
->columnSpanFull()
|
||||
->required()
|
||||
->numeric()
|
||||
->label(__('exam.max_user_count'))
|
||||
->hidden(fn (\Closure $get) => $get('type') != Exam::TYPE_TASK)
|
||||
,
|
||||
|
||||
Forms\Components\Repeater::make('indexes')->schema([
|
||||
Forms\Components\Select::make('index')
|
||||
@@ -148,7 +158,7 @@ class ExamResource extends Resource
|
||||
Tables\Columns\TextColumn::make('end')->label(__('label.end')),
|
||||
Tables\Columns\TextColumn::make('durationText')->label(__('label.duration')),
|
||||
Tables\Columns\TextColumn::make('recurringText')->label(__('exam.recurring')),
|
||||
Tables\Columns\TextColumn::make('filterFormatted')->label(__('label.exam.filter_formatted'))->html(),
|
||||
Tables\Columns\TextColumn::make('filterFormatted')->label(__('label.exam.filter_formatted'))->html()->extraAttributes([]),
|
||||
Tables\Columns\BooleanColumn::make('is_discovered')->label(__('label.exam.is_discovered')),
|
||||
Tables\Columns\TextColumn::make('priority')->label(__('label.priority')),
|
||||
Tables\Columns\TextColumn::make('statusText')->label(__('label.status')),
|
||||
|
||||
+11
-1
@@ -11,7 +11,7 @@ class Exam extends NexusModel
|
||||
{
|
||||
protected $fillable = [
|
||||
'name', 'description', 'begin', 'end', 'duration', 'status', 'is_discovered', 'filters', 'indexes', 'priority',
|
||||
'recurring', 'type', 'success_reward_bonus', 'fail_deduct_bonus'
|
||||
'recurring', 'type', 'success_reward_bonus', 'fail_deduct_bonus', 'max_user_count'
|
||||
];
|
||||
|
||||
public $timestamps = true;
|
||||
@@ -294,4 +294,14 @@ class Exam extends NexusModel
|
||||
return $this->type == self::TYPE_TASK;
|
||||
}
|
||||
|
||||
public function users()
|
||||
{
|
||||
return $this->belongsToMany(User::class, "exam_users", "exam_id", "uid");
|
||||
}
|
||||
|
||||
public function OnGoingUsers()
|
||||
{
|
||||
return $this->users()->wherePivot("status", ExamUser::STATUS_NORMAL);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -368,6 +368,19 @@ class ExamRepository extends BaseRepository
|
||||
$locale = $user->locale;
|
||||
$authUserClass = get_user_class();
|
||||
$authUserId = get_user_id();
|
||||
$now = Carbon::now();
|
||||
if (!empty($exam->begin)) {
|
||||
$specificBegin = Carbon::parse($exam->begin);
|
||||
if ($specificBegin->isAfter($now)) {
|
||||
throw new NexusException(nexus_trans("exam.not_between_begin_end_time", [], $locale));
|
||||
}
|
||||
}
|
||||
if (!empty($exam->end)) {
|
||||
$specificEnd = Carbon::parse($exam->end);
|
||||
if ($specificEnd->isBefore($now)) {
|
||||
throw new NexusException(nexus_trans("exam.not_between_begin_end_time", [], $locale));
|
||||
}
|
||||
}
|
||||
if ($exam->isTypeExam()) {
|
||||
if ($authUserClass <= $user->class) {
|
||||
//exam only can assign by upper class admin
|
||||
@@ -378,6 +391,12 @@ class ExamRepository extends BaseRepository
|
||||
//task only can be claimed by self
|
||||
throw new NexusException(nexus_trans('exam.claim_by_yourself_only', [], $locale));
|
||||
}
|
||||
if ($exam->max_user_count > 0) {
|
||||
$claimUserCount = ExamUser::query()->where("exam_id", $examId)->count();
|
||||
if ($claimUserCount >= $exam->max_user_count) {
|
||||
throw new NexusException(nexus_trans('exam.reach_max_user_count', [], $locale));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!$this->isExamMatchUser($exam, $user)) {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('exams', function (Blueprint $table) {
|
||||
$table->integer("max_user_count")->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('exams', function (Blueprint $table) {
|
||||
$table->dropColumn("max_user_count");
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
defined('VERSION_NUMBER') || define('VERSION_NUMBER', '1.8.13');
|
||||
defined('RELEASE_DATE') || define('RELEASE_DATE', '2024-08-03');
|
||||
defined('RELEASE_DATE') || define('RELEASE_DATE', '2024-08-08');
|
||||
defined('IN_TRACKER') || define('IN_TRACKER', false);
|
||||
defined('PROJECTNAME') || define("PROJECTNAME","NexusPHP");
|
||||
defined('NEXUSPHPURL') || define("NEXUSPHPURL","https://nexusphp.org");
|
||||
|
||||
+17
-28
@@ -2,11 +2,14 @@
|
||||
require "../include/bittorrent.php";
|
||||
dbconn();
|
||||
loggedinorreturn();
|
||||
$query = \App\Models\Exam::query()->where('type', \App\Models\Exam::TYPE_TASK)->where("status", \App\Models\Exam::STATUS_ENABLED);
|
||||
$query = \App\Models\Exam::query()
|
||||
->where('type', \App\Models\Exam::TYPE_TASK)
|
||||
->where("status", \App\Models\Exam::STATUS_ENABLED)
|
||||
;
|
||||
$total = (clone $query)->count();
|
||||
$perPage = 20;
|
||||
list($paginationTop, $paginationBottom, $limit, $offset) = pager($perPage, $total, "?");
|
||||
$rows = (clone $query)->offset($offset)->take($perPage)->orderBy('id', 'desc')->get();
|
||||
$rows = (clone $query)->offset($offset)->take($perPage)->orderBy('id', 'desc')->withCount("users")->get();
|
||||
$title = nexus_trans('exam.type_task');
|
||||
$columnNameLabel = nexus_trans('label.name');
|
||||
$columnIndexLabel = nexus_trans('exam.index');
|
||||
@@ -20,6 +23,7 @@ $columnSuccessRewardLabel = nexus_trans('exam.success_reward_bonus');
|
||||
$columnFailDeductLabel = nexus_trans('exam.fail_deduct_bonus');
|
||||
$columnDescriptionDeductLabel = nexus_trans('label.description');
|
||||
$columnClaimLabel = nexus_trans('exam.action_claim_task');
|
||||
$columnClaimedUserCountLabel = nexus_trans('exam.claimed_user_count');
|
||||
|
||||
$header = '<h1 style="text-align: center">'.$title.'</h1>';
|
||||
stdhead($title);
|
||||
@@ -35,6 +39,7 @@ $table = <<<TABLE
|
||||
<td class="colhead">$columnTargetUserLabel</td>
|
||||
<td class="colhead">$columnSuccessRewardLabel</td>
|
||||
<td class="colhead">$columnFailDeductLabel</td>
|
||||
<td class="colhead">$columnClaimedUserCountLabel</td>
|
||||
<td class="colhead">$columnDescriptionDeductLabel</td>
|
||||
<td class="colhead">$columnClaimLabel</td>
|
||||
</tr>
|
||||
@@ -51,10 +56,10 @@ $userTasks = $userInfo->onGoingExamAndTasks()->where("type", \App\Models\Exam::T
|
||||
//dd(last_query());
|
||||
foreach ($rows as $row) {
|
||||
$claimDisabled = $claimClass = '';
|
||||
$claimBtnText = "认领";
|
||||
$claimBtnText = nexus_trans("exam.action_claim_task");
|
||||
if ($userTasks->has($row->id)) {
|
||||
$claimDisabled = " disabled";
|
||||
$claimBtnText = "已认领";
|
||||
$claimBtnText = nexus_trans("exam.claimed_already");
|
||||
} else {
|
||||
$claimClass = "claim";
|
||||
}
|
||||
@@ -64,12 +69,13 @@ foreach ($rows as $row) {
|
||||
);
|
||||
$columns = [];
|
||||
$columns[] = sprintf('<td class="nowrap"><strong>%s</strong></td>', $row->name);
|
||||
$columns[] = sprintf('<td>%s</td>', $row->indexFormatted);
|
||||
$columns[] = sprintf('<td class="nowrap">%s</td>', $row->indexFormatted);
|
||||
$columns[] = sprintf('<td>%s</td>', $row->getBeginForUser());
|
||||
$columns[] = sprintf('<td>%s</td>', $row->getEndForUser());
|
||||
$columns[] = sprintf('<td>%s</td>', $row->filterFormatted);
|
||||
$columns[] = sprintf('<td>%s</td>', number_format($row->success_reward_bonus));
|
||||
$columns[] = sprintf('<td>%s</td>', number_format($row->fail_deduct_bonus));
|
||||
$columns[] = sprintf('<td>%s</td>', sprintf("%s/%s",$row->users_count, $row->max_user_count ?: nexus_trans("label.infinite")));
|
||||
$columns[] = sprintf('<td>%s</td>', $row->description);
|
||||
$columns[] = sprintf('<td>%s</td>', $claimAction);
|
||||
$table .= sprintf('<tr>%s</tr>', implode("", $columns));
|
||||
@@ -83,35 +89,17 @@ $js = <<<JS
|
||||
jQuery('.claim').on('click', function (e) {
|
||||
let id = jQuery(this).attr('data-id')
|
||||
layer.confirm("{$confirmBuyMsg}", function (index) {
|
||||
layer.close(index)
|
||||
let params = {
|
||||
action: "claimTask",
|
||||
params: {exam_id: id}
|
||||
}
|
||||
console.log(params)
|
||||
jQuery('body').loading({
|
||||
stoppable: false
|
||||
});
|
||||
jQuery.post('ajax.php', params, function(response) {
|
||||
console.log(response)
|
||||
if (response.ret != 0) {
|
||||
layer.alert(response.msg)
|
||||
return
|
||||
}
|
||||
window.location.reload()
|
||||
}, 'json')
|
||||
})
|
||||
})
|
||||
jQuery('.gift').on('click', function (e) {
|
||||
let medalId = jQuery(this).attr('data-id')
|
||||
let uid = jQuery(this).prev().val()
|
||||
if (!uid) {
|
||||
layer.alert('Require UID')
|
||||
return
|
||||
}
|
||||
layer.confirm("{$confirmGiftMsg}" + uid + " ?", function (index) {
|
||||
let params = {
|
||||
action: "giftMedal",
|
||||
params: {medal_id: medalId, uid: uid}
|
||||
}
|
||||
console.log(params)
|
||||
jQuery.post('ajax.php', params, function(response) {
|
||||
jQuery('body').loading('stop');
|
||||
console.log(response)
|
||||
if (response.ret != 0) {
|
||||
layer.alert(response.msg)
|
||||
@@ -122,6 +110,7 @@ jQuery('.gift').on('click', function (e) {
|
||||
})
|
||||
})
|
||||
JS;
|
||||
\Nexus\Nexus::js('vendor/jquery-loading/jquery.loading.min.js', 'footer', true);
|
||||
\Nexus\Nexus::js($js, 'footer', false);
|
||||
stdfoot();
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ return [
|
||||
'type' => 'Type',
|
||||
'type_help' => 'Exam are regular exam and failing them will result in account banning. Tasks can be set to reward bonus or deduct bonus depending on whether they are completed or not',
|
||||
|
||||
'fail_deduct_bonus' => 'Deduct bonus for task failure',
|
||||
'success_reward_bonus' => 'Reward bonus for task completion',
|
||||
'fail_deduct_bonus' => 'Deduct bonus for failure',
|
||||
'success_reward_bonus' => 'Reward bonus for completion',
|
||||
|
||||
'action_claim_task' => 'Claim',
|
||||
'confirm_to_claim' => 'Sure you want to claim?' ,
|
||||
@@ -64,4 +64,8 @@ return [
|
||||
'not_match_target_user' => 'You are not a matching target user!' ,
|
||||
'has_other_on_the_way' => 'There is an other :type_text in progress!' ,
|
||||
'claimed_already' => 'Already claimed',
|
||||
'not_between_begin_end_time' => 'Not between begin & end time',
|
||||
'reach_max_user_count' => 'The number of claimed users has reached its maximum',
|
||||
'claimed_user_count' => 'Claimed',
|
||||
'max_user_count' => 'Max claim user count(0 means unlimited)',
|
||||
];
|
||||
|
||||
@@ -57,8 +57,8 @@ return [
|
||||
'type' => '类型',
|
||||
'type_help' => '考核是常规的考核,不通过会被封禁账号。任务可根据完成与否设置奖励魔力或扣除魔力',
|
||||
|
||||
'fail_deduct_bonus' => '任务失败扣除魔力',
|
||||
'success_reward_bonus' => '任务完成奖励魔力',
|
||||
'fail_deduct_bonus' => '失败扣除魔力',
|
||||
'success_reward_bonus' => '完成奖励魔力',
|
||||
|
||||
'action_claim_task' => '领取',
|
||||
'confirm_to_claim' => '确定要认领吗?',
|
||||
@@ -66,4 +66,8 @@ return [
|
||||
'not_match_target_user' => '你不是匹配的目标用户!',
|
||||
'has_other_on_the_way' => '有其他进行中的:type_text',
|
||||
'claimed_already' => '已经认领',
|
||||
'not_between_begin_end_time' => '不在开始结束时间范围内',
|
||||
'reach_max_user_count' => '认领人数已达上限',
|
||||
'claimed_user_count' => '认领人数',
|
||||
'max_user_count' => '最多认领人数(0表示无限制)',
|
||||
];
|
||||
|
||||
@@ -55,8 +55,8 @@ return [
|
||||
'type' => '类型',
|
||||
'type_help' => '考核是常规的考核,不通过会被封禁账号。任务可根据完成与否设置奖励魔力或扣除魔力',
|
||||
|
||||
'fail_deduct_bonus' => '任务失败扣除魔力',
|
||||
'success_reward_bonus' => '任务完成奖励魔力',
|
||||
'fail_deduct_bonus' => '失败扣除魔力',
|
||||
'success_reward_bonus' => '完成奖励魔力',
|
||||
|
||||
'action_claim_task' => '領取',
|
||||
'confirm_to_claim' => '確定要認領嗎?',
|
||||
@@ -64,4 +64,8 @@ return [
|
||||
'not_match_target_user' => '你不是匹配的目標用戶!',
|
||||
'has_other_on_the_way' => '有其他進行中的:type_text',
|
||||
'claimed_already' => '已經認領',
|
||||
'not_between_begin_end_time' => '不在開始結束時間範圍內',
|
||||
'reach_max_user_count' => '認領人數已達上限',
|
||||
'claimed_user_count' => '認領人數',
|
||||
'max_user_count' => '最多認領人數(0表示無限製)',
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user