mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-14 12:30:49 +08:00
[exam] schedule
This commit is contained in:
@@ -42,7 +42,7 @@
|
|||||||
</el-menu>
|
</el-menu>
|
||||||
</el-aside>
|
</el-aside>
|
||||||
<el-container class="content">
|
<el-container class="content">
|
||||||
<Header />
|
<Header :router-name="state.routerName"/>
|
||||||
<div class="main">
|
<div class="main">
|
||||||
<router-view />
|
<router-view />
|
||||||
</div>
|
</div>
|
||||||
@@ -56,7 +56,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { reactive } from 'vue'
|
import { reactive, onMounted } from 'vue'
|
||||||
import Header from './components/Header.vue'
|
import Header from './components/Header.vue'
|
||||||
import Footer from './components/Footer.vue'
|
import Footer from './components/Footer.vue'
|
||||||
import { useRouter } from 'vue-router'
|
import { useRouter } from 'vue-router'
|
||||||
@@ -76,7 +76,11 @@ export default {
|
|||||||
currentPath: '/dashboard',
|
currentPath: '/dashboard',
|
||||||
count: {
|
count: {
|
||||||
number: 1
|
number: 1
|
||||||
}
|
},
|
||||||
|
routerName: router.name
|
||||||
|
})
|
||||||
|
onMounted(() => {
|
||||||
|
console.log(router)
|
||||||
})
|
})
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
console.log("App beforeEach to", to)
|
console.log("App beforeEach to", to)
|
||||||
|
|||||||
@@ -31,38 +31,42 @@
|
|||||||
<script>
|
<script>
|
||||||
import {computed, onMounted, reactive, toRefs, watch} from 'vue'
|
import {computed, onMounted, reactive, toRefs, watch} from 'vue'
|
||||||
import { useRouter, useRoute } from 'vue-router'
|
import { useRouter, useRoute } from 'vue-router'
|
||||||
import { localRemove, pathMap } from '../utils'
|
import {localGet, localSet, localRemove, pathMap} from '../utils'
|
||||||
import api from "../utils/api";
|
import api from "../utils/api";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Header',
|
name: 'Header',
|
||||||
|
props: {
|
||||||
|
userInfo: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
|
},
|
||||||
setup(props, context) {
|
setup(props, context) {
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const userInfoKey = 'userInfo'
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
name: 'dashboard',
|
name: 'dashboard',
|
||||||
userInfo: null,
|
userInfo: null,
|
||||||
hasBack: false
|
hasBack: false
|
||||||
})
|
})
|
||||||
onMounted(() => {
|
onMounted(async () => {
|
||||||
console.log("Head onMounted!")
|
console.log("Head onMounted!")
|
||||||
console.log(props, context)
|
console.log(props)
|
||||||
|
// let userInfo = localGet(userInfoKey);
|
||||||
|
// if (userInfo) {
|
||||||
|
// state.userInfo = userInfo;
|
||||||
|
// } else {
|
||||||
|
// let res = await api.getUserBase()
|
||||||
|
// state.userInfo = res.data
|
||||||
|
// localSet(userInfoKey, res.data)
|
||||||
|
// }
|
||||||
})
|
})
|
||||||
watch(
|
|
||||||
() => route,
|
|
||||||
(newValue, oldValue) => {
|
|
||||||
console.log(newValue, 'new')
|
|
||||||
console.log(oldValue, 'old')
|
|
||||||
}
|
|
||||||
)
|
|
||||||
const getUserInfo = async () => {
|
|
||||||
const userInfo = await api.getUserBase()
|
|
||||||
console.log(userInfo)
|
|
||||||
state.userInfo = userInfo.data
|
|
||||||
}
|
|
||||||
const logout = () => {
|
const logout = () => {
|
||||||
api.logout().then(() => {
|
api.logout().then(() => {
|
||||||
localRemove('token')
|
localRemove('token')
|
||||||
|
localRemove(userInfoKey)
|
||||||
router.push({ name: 'login' })
|
router.push({ name: 'login' })
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
51
app/Console/Commands/ExamAssign.php
Normal file
51
app/Console/Commands/ExamAssign.php
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Repositories\ExamRepository;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class ExamAssign extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'exam:assign {--uid=} {--exam_id=} {--begin=} {--end=}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Assign exam to user, options: --uid, --exam_id, --begin, --end';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$examRep = new ExamRepository();
|
||||||
|
$uid = $this->option('uid');
|
||||||
|
$examId = $this->option('exam_id');
|
||||||
|
$begin = $this->option('begin');
|
||||||
|
$end = $this->option('end');
|
||||||
|
$this->info(sprintf('uid: %s, examId: %s, begin: %s, end: %s', $uid, $examId, $begin, $end));
|
||||||
|
$result = $examRep->assignToUser($uid, $examId, $begin, $end);
|
||||||
|
$this->info(sprintf('%s, [assignToUser], result: %s, request_id: %s', __METHOD__, var_export($result, true), REQUEST_ID));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
46
app/Console/Commands/ExamAssignCronjob.php
Normal file
46
app/Console/Commands/ExamAssignCronjob.php
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Repositories\ExamRepository;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class ExamAssignCronjob extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'exam:assign_cronjob';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Assign exam cronjob';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$examRep = new ExamRepository();
|
||||||
|
$result = $examRep->cronjonAssign();
|
||||||
|
$this->info(sprintf('%s, [cronjonAssign], result: %s, request_id: %s', __METHOD__, var_export($result, true), REQUEST_ID));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
48
app/Console/Commands/ExamCheckoutCronjob.php
Normal file
48
app/Console/Commands/ExamCheckoutCronjob.php
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Repositories\ExamRepository;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
|
||||||
|
class ExamCheckoutCronjob extends Command
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'exam:checkout_cronjob {--ignore-time-range}';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Checkout exam cronjob, options: --ignore-time-range';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new command instance.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*
|
||||||
|
* @return int
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$examRep = new ExamRepository();
|
||||||
|
$ignoreTimeRange = $this->option('ignore-time-range');
|
||||||
|
$this->info('ignore-time-range: ' . var_export($ignoreTimeRange, true));
|
||||||
|
$result = $examRep->cronjobCheckout($ignoreTimeRange);
|
||||||
|
$this->info(sprintf('%s, [cronjobCheckout], result: %s, request_id: %s', __METHOD__, var_export($result, true), REQUEST_ID));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -44,12 +44,19 @@ class Test extends Command
|
|||||||
*/
|
*/
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
|
$user = User::query()->findOrFail(1);
|
||||||
|
dd(nexus_trans('exam.checkout_pass_message_content', ['exam_name' => '年中考核', 'begin' => 1, 'end' => 2]));
|
||||||
$rep = new ExamRepository();
|
$rep = new ExamRepository();
|
||||||
// $r = $rep->assignToUser(1, 1);
|
// $r = $rep->assignToUser(1, 1);
|
||||||
// $r = $rep->addProgress(27, 4, 1025, 1);
|
$r = $rep->addProgress(3, 1, [
|
||||||
// dd($r);
|
1 => 25*1024*1024*1024,
|
||||||
|
2 => 55*3600,
|
||||||
|
3 => 100*1024*1024*1024,
|
||||||
|
4 => 1252
|
||||||
|
]);
|
||||||
|
dd($r);
|
||||||
// $rep->assignCronjob();
|
// $rep->assignCronjob();
|
||||||
$rep->cronjobCheckout();
|
// $rep->cronjobCheckout();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ class Kernel extends ConsoleKernel
|
|||||||
*/
|
*/
|
||||||
protected function schedule(Schedule $schedule)
|
protected function schedule(Schedule $schedule)
|
||||||
{
|
{
|
||||||
// $schedule->command('inspire')->hourly();
|
$schedule->command('exam:assign_cronjob')->everyMinute();
|
||||||
|
$schedule->command('exam:checkout_cronjob')->everyMinute();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -29,6 +29,17 @@ class ExamUser extends NexusModel
|
|||||||
return self::$status[$this->status]['text'] ?? '';
|
return self::$status[$this->status]['text'] ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getBeginAttribute()
|
||||||
|
{
|
||||||
|
return $this->begin ?? $this->exam->begin;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEndAttribute()
|
||||||
|
{
|
||||||
|
return $this->end ?? $this->exam->end;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function exam(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
public function exam(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Exam::class, 'exam_id');
|
return $this->belongsTo(Exam::class, 'exam_id');
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Http\Middleware\Locale;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
@@ -117,6 +118,11 @@ class User extends Authenticatable
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getLocaleAttribute()
|
||||||
|
{
|
||||||
|
return Locale::$languageMaps[$this->language->site_lang_folder] ?? 'en';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public function exams()
|
public function exams()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class ExamRepository extends BaseRepository
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($added < $registerTimeBegin) {
|
if ($added < $registerTimeBegin) {
|
||||||
do_log("$logPrefix, added: $added not after: " . $registerTimeBegin);
|
do_log("$logPrefix, user added: $added not after: " . $registerTimeBegin);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ class ExamRepository extends BaseRepository
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ($added > $registerTimeEnd) {
|
if ($added > $registerTimeEnd) {
|
||||||
do_log("$logPrefix, added: $added not before: " . $registerTimeEnd);
|
do_log("$logPrefix, user added: $added not before: " . $registerTimeEnd);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -186,17 +186,20 @@ class ExamRepository extends BaseRepository
|
|||||||
if ($examId > 0) {
|
if ($examId > 0) {
|
||||||
$exam = Exam::query()->find($examId);
|
$exam = Exam::query()->find($examId);
|
||||||
} else {
|
} else {
|
||||||
$exams = $this->listMatchExam($uid);
|
$exams = $this->listValid();
|
||||||
|
if ($exams->isEmpty()) {
|
||||||
|
throw new NexusException("No valid exam.");
|
||||||
|
}
|
||||||
if ($exams->count() > 1) {
|
if ($exams->count() > 1) {
|
||||||
do_log(last_query());
|
do_log(last_query());
|
||||||
throw new NexusException("Match exam more than 1.");
|
throw new NexusException("valid exam more than 1.");
|
||||||
}
|
}
|
||||||
$exam = $exams->first();
|
$exam = $exams->first();
|
||||||
}
|
}
|
||||||
if (!$exam) {
|
|
||||||
throw new NexusException("No valid exam.");
|
|
||||||
}
|
|
||||||
$user = User::query()->findOrFail($uid);
|
$user = User::query()->findOrFail($uid);
|
||||||
|
if (!$this->isExamMatchUser($exam, $user)) {
|
||||||
|
throw new NexusException("Exam: {$exam->id} no match this user.");
|
||||||
|
}
|
||||||
if ($user->exams()->where('status', ExamUser::STATUS_NORMAL)->exists()) {
|
if ($user->exams()->where('status', ExamUser::STATUS_NORMAL)->exists()) {
|
||||||
throw new NexusException("User: $uid already has exam on the way.");
|
throw new NexusException("User: $uid already has exam on the way.");
|
||||||
}
|
}
|
||||||
@@ -404,7 +407,7 @@ class ExamRepository extends BaseRepository
|
|||||||
$requireValueAtomic = $requireValue * 1024 * 1024 * 1024;
|
$requireValueAtomic = $requireValue * 1024 * 1024 * 1024;
|
||||||
break;
|
break;
|
||||||
case Exam::INDEX_SEED_TIME_AVERAGE:
|
case Exam::INDEX_SEED_TIME_AVERAGE:
|
||||||
$currentValueFormatted = mkprettytime($currentValue);
|
$currentValueFormatted = number_format($currentValue / 3600, 2) . " {$index['unit']}";
|
||||||
$requireValueAtomic = $requireValue * 3600;
|
$requireValueAtomic = $requireValue * 3600;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -437,7 +440,7 @@ class ExamRepository extends BaseRepository
|
|||||||
$exams = $this->listValid();
|
$exams = $this->listValid();
|
||||||
if ($exams->isEmpty()) {
|
if ($exams->isEmpty()) {
|
||||||
do_log("No valid exam.");
|
do_log("No valid exam.");
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
if ($exams->count() > 1) {
|
if ($exams->count() > 1) {
|
||||||
do_log("Valid exam more than 1.", "warning");
|
do_log("Valid exam more than 1.", "warning");
|
||||||
@@ -446,103 +449,118 @@ class ExamRepository extends BaseRepository
|
|||||||
$exam = $exams->first();
|
$exam = $exams->first();
|
||||||
$userTable = (new User())->getTable();
|
$userTable = (new User())->getTable();
|
||||||
$examUserTable = (new ExamUser())->getTable();
|
$examUserTable = (new ExamUser())->getTable();
|
||||||
User::query()
|
$baseQuery = User::query()
|
||||||
->leftJoin($examUserTable, function (JoinClause $join) use ($examUserTable, $userTable) {
|
->leftJoin($examUserTable, function (JoinClause $join) use ($examUserTable, $userTable) {
|
||||||
$join->on("$userTable.id", "=", "$examUserTable.uid")
|
$join->on("$userTable.id", "=", "$examUserTable.uid")
|
||||||
->on("$examUserTable.status", "=", DB::raw(ExamUser::STATUS_NORMAL));
|
->on("$examUserTable.status", "=", DB::raw(ExamUser::STATUS_NORMAL));
|
||||||
})
|
})
|
||||||
->whereRaw("$examUserTable.id is null")
|
->whereRaw("$examUserTable.id is null")
|
||||||
->selectRaw("$userTable.*")
|
->selectRaw("$userTable.*")
|
||||||
->chunk(100, function ($users) use ($exam) {
|
->orderBy("$userTable.id", "asc");
|
||||||
do_log("user count: " . $users->count() . last_query());
|
$size = 100;
|
||||||
$insert = [];
|
$minId = 0;
|
||||||
$now = Carbon::now()->toDateTimeString();
|
$result = 0;
|
||||||
foreach ($users as $user) {
|
while (true) {
|
||||||
$logPrefix = sprintf('[assignCronjob] user: %s, exam: %s', $user->id, $exam->id);
|
$logPrefix = sprintf('[%s], exam: %s, size: %s', __FUNCTION__, $exam->id , $size);
|
||||||
if (!$this->isExamMatchUser($exam, $user)) {
|
$users = (clone $baseQuery)->where("$userTable.id", ">", $minId)->limit($size)->get();
|
||||||
do_log("$logPrefix, exam not match user.");
|
if ($users->isEmpty()) {
|
||||||
continue;
|
do_log("$logPrefix, no more data..." . last_query());
|
||||||
}
|
break;
|
||||||
$insert[] = [
|
}
|
||||||
'uid' => $user->id,
|
$insert = [];
|
||||||
'exam_id' => $exam->id,
|
$now = Carbon::now()->toDateTimeString();
|
||||||
'created_at' => $now,
|
foreach ($users as $user) {
|
||||||
'updated_at' => $now,
|
$minId = $user->id;
|
||||||
];
|
$currentLogPrefix = sprintf("$logPrefix, user: %s", $user->id);
|
||||||
do_log("$logPrefix, exam assign to user.");
|
if (!$this->isExamMatchUser($exam, $user)) {
|
||||||
|
do_log("$currentLogPrefix, exam not match this user.");
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
$insert[] = [
|
||||||
|
'uid' => $user->id,
|
||||||
|
'exam_id' => $exam->id,
|
||||||
|
'created_at' => $now,
|
||||||
|
'updated_at' => $now,
|
||||||
|
];
|
||||||
|
do_log("$currentLogPrefix, exam will be assigned to this user.");
|
||||||
|
}
|
||||||
|
if (!empty($insert)) {
|
||||||
|
$result += count($insert);
|
||||||
ExamUser::query()->insert($insert);
|
ExamUser::query()->insert($insert);
|
||||||
});
|
}
|
||||||
return true;
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function cronjobCheckout()
|
public function cronjobCheckout($ignoreTimeRange = false)
|
||||||
{
|
{
|
||||||
$now = Carbon::now()->toDateTimeString();
|
$now = Carbon::now()->toDateTimeString();
|
||||||
$examUserTable = (new ExamUser())->getTable();
|
$examUserTable = (new ExamUser())->getTable();
|
||||||
$examTable = (new Exam())->getTable();
|
$examTable = (new Exam())->getTable();
|
||||||
$perPage = 100;
|
$baseQuery = ExamUser::query()
|
||||||
$page = 1;
|
|
||||||
$query = ExamUser::query()
|
|
||||||
->join($examTable, "$examUserTable.exam_id", "=", "$examTable.id")
|
->join($examTable, "$examUserTable.exam_id", "=", "$examTable.id")
|
||||||
->where("$examUserTable.status", ExamUser::STATUS_NORMAL)
|
->where("$examUserTable.status", ExamUser::STATUS_NORMAL)
|
||||||
->whereRaw("if($examUserTable.begin is not null, $examUserTable.begin <= '$now', $examTable.begin <= '$now')")
|
|
||||||
->whereRaw("if($examUserTable.end is not null, $examUserTable.end >= '$now', $examTable.end >= '$now')")
|
|
||||||
->selectRaw("$examUserTable.*")
|
->selectRaw("$examUserTable.*")
|
||||||
->with(['exam', 'user', 'user.language'])
|
->with(['exam', 'user', 'user.language'])
|
||||||
->orderBy("$examUserTable.id", "asc");
|
->orderBy("$examUserTable.id", "asc");
|
||||||
|
if (!$ignoreTimeRange) {
|
||||||
|
$baseQuery->whereRaw("if($examUserTable.end is not null, $examUserTable.end < '$now', $examTable.end < '$now')");
|
||||||
|
}
|
||||||
|
|
||||||
|
$size = 100;
|
||||||
|
$minId = 0;
|
||||||
|
$result = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
$logPrefix = sprintf('[%s], page: %s', __FUNCTION__, $page);
|
$logPrefix = sprintf('[%s], size: %s', __FUNCTION__, $size);
|
||||||
$examUsers = $query->forPage($page, $perPage)->get("$examUserTable.*");
|
$examUsers = (clone $baseQuery)->where("$examUserTable.id", ">", $minId)->limit($size)->get();
|
||||||
if ($examUsers->isEmpty()) {
|
if ($examUsers->isEmpty()) {
|
||||||
do_log("$logPrefix, no more data..." . last_query());
|
do_log("$logPrefix, no more data..." . last_query());
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
do_log("$logPrefix, fetch exam users: {$examUsers->count()}, " . last_query());
|
do_log("$logPrefix, fetch exam users: {$examUsers->count()}");
|
||||||
}
|
}
|
||||||
|
$result += $examUsers->count();
|
||||||
$now = Carbon::now()->toDateTimeString();
|
$now = Carbon::now()->toDateTimeString();
|
||||||
$idArr = $uidToDisable = $messageToSend = [];
|
$examUserIdArr = $uidToDisable = $messageToSend = [];
|
||||||
foreach ($examUsers as $examUser) {
|
foreach ($examUsers as $examUser) {
|
||||||
$idArr[] = $examUser->id;
|
$minId = $examUser->id;
|
||||||
|
$examUserIdArr[] = $examUser->id;
|
||||||
$uid = $examUser->uid;
|
$uid = $examUser->uid;
|
||||||
$currentLogPrefix = sprintf("$logPrefix, user: %s, exam: %s, examUser: %s", $uid, $examUser->exam_id, $examUser->id);
|
$currentLogPrefix = sprintf("$logPrefix, user: %s, exam: %s, examUser: %s", $uid, $examUser->exam_id, $examUser->id);
|
||||||
|
$locale = $examUser->user->locale;
|
||||||
if ($examUser->is_done) {
|
if ($examUser->is_done) {
|
||||||
do_log("$currentLogPrefix, [is_done]");
|
do_log("$currentLogPrefix, [is_done]");
|
||||||
$messageToSend[] = [
|
$subjectTransKey = 'exam.checkout_pass_message_subject';
|
||||||
'receiver' => $uid,
|
$msgTransKey = 'exam.checkout_pass_message_content';
|
||||||
'added' => $now,
|
|
||||||
'subject' => 'Exam passed!',
|
|
||||||
'msg' => sprintf(
|
|
||||||
'Congratulations! You have complete the exam: %s in time(%s ~ %s)!',
|
|
||||||
$examUser->exam->name, $examUser->begin ?? $examUser->exam->begin, $examUser->end ?? $examUser->exam->end
|
|
||||||
),
|
|
||||||
];
|
|
||||||
} else {
|
} else {
|
||||||
do_log("$currentLogPrefix, [will be banned]");
|
do_log("$currentLogPrefix, [will be banned]");
|
||||||
|
$subjectTransKey = 'exam.checkout_not_pass_message_subject';
|
||||||
|
$msgTransKey = 'exam.checkout_not_pass_message_content';
|
||||||
//ban user
|
//ban user
|
||||||
$uidToDisable[] = $uid;
|
$uidToDisable[] = $uid;
|
||||||
$messageToSend[] = [
|
|
||||||
'receiver' => $uid,
|
|
||||||
'added' => $now,
|
|
||||||
'subject' => 'Exam not passed! And your account is banned!',
|
|
||||||
'msg' => sprintf(
|
|
||||||
'You did not complete the exam: %s in time(%s ~ %s), so your account has been banned!',
|
|
||||||
$examUser->exam->name, $examUser->begin ?? $examUser->exam->begin, $examUser->end ?? $examUser->exam->end
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
$subject = nexus_trans($subjectTransKey, [], $locale);
|
||||||
|
$msg = nexus_trans($msgTransKey, [
|
||||||
|
'exam_name' => $examUser->exam->name,
|
||||||
|
'begin' => $examUser->begin,
|
||||||
|
'end' => $examUser->end
|
||||||
|
], $locale);
|
||||||
|
$messageToSend[] = [
|
||||||
|
'receiver' => $uid,
|
||||||
|
'added' => $now,
|
||||||
|
'subject' => $subject,
|
||||||
|
'msg' => $msg
|
||||||
|
];
|
||||||
}
|
}
|
||||||
DB::transaction(function () use ($uidToDisable, $messageToSend, $idArr) {
|
DB::transaction(function () use ($uidToDisable, $messageToSend, $examUserIdArr) {
|
||||||
ExamUser::query()->whereIn('id', $idArr)->update(['status' => ExamUser::STATUS_FINISHED]);
|
ExamUser::query()->whereIn('id', $examUserIdArr)->update(['status' => ExamUser::STATUS_FINISHED]);
|
||||||
Message::query()->insert($messageToSend);
|
Message::query()->insert($messageToSend);
|
||||||
if (!empty($uidToDisable)) {
|
if (!empty($uidToDisable)) {
|
||||||
User::query()->whereIn('id', $uidToDisable)->update(['enabled' => User::ENABLED_NO]);
|
User::query()->whereIn('id', $uidToDisable)->update(['enabled' => User::ENABLED_NO]);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$page++;
|
|
||||||
}
|
}
|
||||||
return true;
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -540,17 +540,32 @@ function nexus_trans($key, $replace = [], $locale = null)
|
|||||||
return trans($key, $replace, $locale);
|
return trans($key, $replace, $locale);
|
||||||
}
|
}
|
||||||
static $translations;
|
static $translations;
|
||||||
if (is_null($translations)) {
|
if (!$locale) {
|
||||||
$lang = get_langfolder_cookie();
|
$lang = get_langfolder_cookie();
|
||||||
$lang = \App\Http\Middleware\Locale::$languageMaps[$lang] ?? 'en';
|
$locale = \App\Http\Middleware\Locale::$languageMaps[$lang] ?? 'en';
|
||||||
$dir = ROOT_PATH . 'resources/lang/' . $lang;
|
}
|
||||||
$files = glob($dir . '/*.php');
|
if (is_null($translations)) {
|
||||||
|
$langDir = ROOT_PATH . 'resources/lang/';
|
||||||
|
$files = glob($langDir . '*/*');
|
||||||
foreach ($files as $file) {
|
foreach ($files as $file) {
|
||||||
$basename = basename($file);
|
|
||||||
$values = require $file;
|
$values = require $file;
|
||||||
$key = strstr($basename, '.php', true);
|
$setKey = substr($file, strlen($langDir));
|
||||||
arr_set($translations, $key, $values);
|
if (substr($setKey, -4) == '.php') {
|
||||||
|
$setKey = substr($setKey, 0, -4);
|
||||||
|
}
|
||||||
|
$setKey = str_replace('/', '.', $setKey);
|
||||||
|
arr_set($translations, $setKey, $values);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return arr_get($translations, $key);
|
$getKey = $locale . "." . $key;
|
||||||
|
$result = arr_get($translations, $getKey);
|
||||||
|
if (empty($result) && $locale != 'en') {
|
||||||
|
$getKey = "en.$key";
|
||||||
|
$result = arr_get($translations, $getKey);
|
||||||
|
}
|
||||||
|
if (!empty($replace)) {
|
||||||
|
$search = array_map(function ($value) {return ":$value";}, array_keys($replace));
|
||||||
|
$result = str_replace($search, array_values($replace), $result);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,4 +13,8 @@ return [
|
|||||||
'result' => 'Result',
|
'result' => 'Result',
|
||||||
'result_pass' => 'Pass!',
|
'result_pass' => 'Pass!',
|
||||||
'result_not_pass' => '<bold color="red">Not pass!</bold>',
|
'result_not_pass' => '<bold color="red">Not pass!</bold>',
|
||||||
|
'checkout_pass_message_subject' => 'Exam pass!',
|
||||||
|
'checkout_pass_message_content' => 'Congratulation! You have complete the exam: :exam_name in time(:begin ~ :end)',
|
||||||
|
'checkout_not_pass_message_subject' => 'Exam not pass, and account is banned!',
|
||||||
|
'checkout_not_pass_message_content' => 'You did not complete the exam: :exam_name in time(:begin ~ :end), and your account has be banned!',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,4 +13,8 @@ return [
|
|||||||
'result' => '结果',
|
'result' => '结果',
|
||||||
'result_pass' => '通过!',
|
'result_pass' => '通过!',
|
||||||
'result_not_pass' => '<bold color="red">未通过!</bold>',
|
'result_not_pass' => '<bold color="red">未通过!</bold>',
|
||||||
|
'checkout_pass_message_subject' => '考核通过!',
|
||||||
|
'checkout_pass_message_content' => '恭喜!你在规定时间内(:begin ~ :end)顺利完成了考核::exam_name。',
|
||||||
|
'checkout_not_pass_message_subject' => '考核未通过,账号被禁用!',
|
||||||
|
'checkout_not_pass_message_content' => '你在规定时间内(:begin ~ :end)未完成考核::exam_name,账号已被禁用。',
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,4 +13,8 @@ return [
|
|||||||
'result' => '結果',
|
'result' => '結果',
|
||||||
'result_pass' => '通過!',
|
'result_pass' => '通過!',
|
||||||
'result_not_pass' => '<bold color="red">未通過!</bold>',
|
'result_not_pass' => '<bold color="red">未通過!</bold>',
|
||||||
|
'checkout_pass_message_subject' => '考核通過!',
|
||||||
|
'checkout_pass_message_content' => '恭喜!你在規定時間內(:begin ~ :end)順利完成了考核::exam_name。',
|
||||||
|
'checkout_not_pass_message_subject' => '考核未通過,賬號被禁用!',
|
||||||
|
'checkout_not_pass_message_content' => '你在規定時間內(:begin ~ :end)未完成考核::exam_name,賬號已被禁用。',
|
||||||
];
|
];
|
||||||
|
|||||||
Reference in New Issue
Block a user