['settings'], 'append' => ['status_text'] ]); } function getStatusTextAttr($v,$row){ return \app\enum\ServerStatus::tryFromValue($row['status']?:0)->getDescription(); } public static function onBeforeWrite(&$row) { if(!$row->settings){ $step_before_array = [ 'bootstrap' => rand(10,20), 'http_proxy' => rand(10,20), 'browser_env' => rand(10,20), 'enter_questionnaire' => rand(10,20), 'match_virtual_person' => rand(10,20), ]; //后置耗时 $step_after_array = [ 'submit_result' => rand(5,10), 'wait_submit_result' => rand(5,10), 'wait_settlement' => 0, ]; $answer_array=[]; /** @var Questionnaire $questionnaire */ $questionnaire = Questionnaire::where('id',$row->questionnaire_id)->find(); for ($i=0; $i < $questionnaire->total ; $i++) { $answer_array['answer_'.($i+1)] = 30; } $row->settings = array_merge($step_before_array,$answer_array,$step_after_array); } if(!$row->answer){ $answer = []; foreach($row->questionnaire->body as $k=>$vo){ $answer[$k]= rand(0,count($vo['answer'])-1); } $row->answer = $answer; } // if($row->start_time && !$row->end_time){ // $row->end_time = 0; // if(is_array($row->settings)){ // $end_time = $row->start_time + array_sum($row->settings); // $row->end_time = $end_time; // } // } //cp('onBeforeWrite'); } public function user() { return $this->belongsTo(User::class, 'user_id', 'id'); } public function product() { return $this->belongsTo(Product::class, 'product_id', 'id'); } public function questionnaire() { return $this->hasOne(Questionnaire::class, 'id', 'questionnaire_id'); } /** * 自动写入Settings字段 */ function setSettingsAttr($v='',$row=[]){ if(is_array($v)){ return json_encode($v); } return $v; } /** * Settings自动转为数组 */ public function getSettingsAttr($v='',$row=[]){ //cp('getSettingsAttr'); if(!$v){ return []; } if(!is_array($v)){ return json_decode($v,true); } return $v; } public function start(){ if($this->status != \app\enum\ServerStatus::WAITING->value){ return $this->error(__('Server could not start')); } $this->status = \app\enum\ServerStatus::WORKING->value; $this->start_time = time(); if(is_array($this->settings)){ $end_time = $this->start_time + array_sum($this->settings); $this->end_time = $end_time; } $this->save(); addJob(['server_id'=>$this->id,'action'=>'workcomplete'],'Questionnaire',$this->end_time-time()); } public function getStep(){ if ($this->status != \app\enum\ServerStatus::WORKING->value) { return [ 'step' => 0, 'msg' => \app\enum\ServerStatus::tryFromValue($this->status)->name, 'next_time' => null, 'remaining_seconds' => 0 ]; } $settings = $this->settings; //cp($settings); $start_time = $this->start_time; // 使用实际的开始时间 //$start_time = time(); $current_time = time(); //$current_time = $start_time+140;//time(); // 当前时间戳 if ($current_time < $start_time) { //根据时间判断未开始 return [ 'step' => 0, 'msg' => \app\enum\ServerStatus::tryFromValue($this->status)->name, 'next_time' => $start_time, 'remaining_seconds' => 0 ]; } // 计算已经过去的时间 $elapsed = $current_time - $start_time; // 初始化结果 $result = [ 'step' => 7, 'current' => __('bootstrap'), 'next_time' => null, 'msg' => __('anser'), 'remaining_seconds' => 0 ]; // 遍历所有阶段 $accumulated = 0; $found_current = false; $stepArr = [ 'bootstrap' => 1, 'http_proxy' => 2, 'browser_env' => 3, 'enter_questionnaire' => 4, 'match_virtual_person' => 5, 'submit_result' => 7, 'wait_submit_result' => 7, 'wait_settlement' => 7, ]; foreach ($settings as $name => $duration) { $accumulated += $duration; // 1. 找到当前阶段 if (!$found_current && $elapsed < $accumulated) { $found_current = true; if(substr($name,0,7) == 'answer_'){ $_name = explode('_',$name); $result['index'] = intval($_name[1]); $result['current'] = __($_name[0].'_%index%',['%index%'=>$result['index']]); $result['step'] = 6; $result['msg'] = 'AI Thinking'; }else{ $result['step'] = $stepArr[$name]; $result['msg'] = __($name); } // 当前阶段剩余时间 = 当前阶段结束时间 - 当前时间 $result['remaining_seconds'] = $accumulated - $elapsed; } // 2. 找到下一阶段开始时间 if ($elapsed < $accumulated) { $result['next_time'] = $start_time + $accumulated; break; } } // 如果已经超过所有阶段 if ($elapsed >= $accumulated) { return [ 'step' => 7, 'msg' => \app\enum\ServerStatus::tryFromValue(4)->name, 'next_time' => null, 'remaining_seconds' => 0 ]; } return $result; } }