--- a/application/p/logic/Analyse.php +++ b/application/p/logic/Analyse.php @@ -147,19 +147,16 @@ * 分析查看 * */ public function analyse($params) { - $readRes = $this->redisRead($params); - if($readRes){ - $data = $readRes; - }else{ - $tn_params = [ - 'start_date' => $params['start_date'], - 'end_date' => $params['end_date'], - 'staff_uuid' => $params['staff_uuid'], - 'norm_uuids' => explode(',',$params['norm_uuid_str']) - ]; - $data = $this->getNormDeviceData($tn_params); - $this->redisUpdate($params['staff_uuid'], $data); - } + // The legacy zset has no source timestamp/version, so it cannot + // guarantee the latest value across test, legacy and device sources. + // Read the indexed business tables directly for authoritative results. + $tn_params = [ + 'start_date' => $params['start_date'], + 'end_date' => $params['end_date'], + 'staff_uuid' => $params['staff_uuid'], + 'norm_uuids' => explode(',',$params['norm_uuid_str']) + ]; + $data = $this->getNormDeviceData($tn_params); //将基本数据组织为前端展示结构 $res = $this->analyseOrganize($data, $params['norm_uuid_str']); return $res; @@ -186,13 +183,36 @@ $staff_uuid_list = [$params['staff_uuid']]; } $where['b.norm_uuid'] = ['in',$params['norm_uuids']]; + $latest_candidates = array(); + $consider_candidate = function($row, $source_time, $source_rank, $source_id) use (&$latest_candidates) { + $norm_key = $row['test_date'].'_'.$row['staff_uuid'].'_'.$row['norm_uuid']; + $timestamp = strtotime((string)$source_time); + if ($timestamp === false) { + $timestamp = strtotime($row['test_date'].' 00:00:00'); + } + $candidate = array( + 'row' => $row, + 'timestamp' => (int)$timestamp, + 'source_rank' => (int)$source_rank, + 'source_id' => (int)$source_id, + ); + if (!isset($latest_candidates[$norm_key])) { + $latest_candidates[$norm_key] = $candidate; + return; + } + $current = $latest_candidates[$norm_key]; + if ($candidate['timestamp'] > $current['timestamp'] || + ($candidate['timestamp'] == $current['timestamp'] && $candidate['source_rank'] > $current['source_rank']) || + ($candidate['timestamp'] == $current['timestamp'] && $candidate['source_rank'] == $current['source_rank'] && $candidate['source_id'] > $current['source_id'])) { + $latest_candidates[$norm_key] = $candidate; + } + }; $data_value = $this->model ->alias("a") ->join('staff_test b','a.uuid = b.test_uuid','left') - ->field(["a.uuid uuid,a.test_date,a.type,b.create_time,b.norm_uuid, b.cate_uuid, b.staff_uuid, b.norm_value"]) + ->field(["a.uuid uuid,a.test_date,a.type,b.id staff_test_id,b.create_time,b.norm_uuid, b.cate_uuid, b.staff_uuid, b.norm_value"]) ->where($where) - ->group('b.staff_uuid,b.norm_uuid,a.test_date') - ->order(['a.test_date'=>'asc', 'b.create_time'=>'desc']) + ->order(['a.test_date'=>'asc', 'b.create_time'=>'desc', 'b.id'=>'desc']) ->select()->toArray(); //查询设备数据 $norm_uuids = $params['norm_uuids']; @@ -200,11 +220,14 @@ $data_list = []; if (!empty($data_value)) { foreach ($data_value as $value) { - $norm_key = $value['test_date'].'_'.$value['staff_uuid'].'_'.$value['norm_uuid']; - if ($value['norm_value'] != '') { + $consider_candidate($value, $value['create_time'], 20, $value['staff_test_id']); + } + foreach ($latest_candidates as $norm_key => $candidate) { + $value = $candidate['row']; + $data_list[$norm_key] = $value; + if (!is_null($value['norm_value']) && $value['norm_value'] !== '') { $exist_norm_data[$norm_key] = $value['norm_value']; } - $data_list[$norm_key] = $value; } } $absent_staff_uuids = []; @@ -248,23 +271,16 @@ foreach ($device_norm_data as $test_date => $staff_norms ) { foreach ($staff_norms as $staff_uuid => $norms) { foreach ($norms as $norm_uuid => $norm_value) { - $norm_key = $test_date.'_'.$staff_uuid.'_'.$norm_uuid; - if (!isset($data_list[$norm_key])) { - $data_list[$norm_key] = [ - 'uuid' => '', - 'test_date' => $test_date, - 'type' => '', - 'create_time' => '', - 'norm_uuid' => $norm_uuid, - 'norm_value' => $norm_value, - 'cate_uuid' => '', - 'staff_uuid' => $staff_uuid, - ]; - } else { - if ($data_list[$norm_key]['norm_value'] == '') { - $data_list[$norm_key]['norm_value'] = $norm_value; - } - } + $consider_candidate([ + 'uuid' => '', + 'test_date' => $test_date, + 'type' => '', + 'create_time' => $test_date.' 00:00:00', + 'norm_uuid' => $norm_uuid, + 'norm_value' => $norm_value, + 'cate_uuid' => '', + 'staff_uuid' => $staff_uuid, + ], $test_date.' 00:00:00', 15, 0); } } } @@ -300,28 +316,63 @@ ->join('equipment_result_extend b','a.id = b.equipment_result_id','left') ->where(['a.staff_uuid' => ['in', $params['staff_uuid']],'a.date' => ['between',[$params['start_date'],$params['end_date']]],'a.relation_type' => ['in',$device_id_arr]]) ->field('a.*,b.k21,b.k22,b.k23,b.k24,b.k25,b.k26,b.k27,b.k28,b.k29,b.k30,b.k31,b.k32,b.k33,b.k34,b.k35,b.k36,b.k37,b.k38,b.k39,b.k40,b.k41,b.k42,b.k43,b.k44,b.k45,b.k46,b.k47,b.k48,b.k49,b.k50,b.k51,b.k52,b.k53,b.k54,b.k55,b.k56,b.k57,b.k58,b.k59,b.k60') - ->order(['a.id' => 'desc']) + ->order(['a.record_time'=>'desc', 'a.update_time'=>'desc', 'a.create_time'=>'desc', 'a.id'=>'desc']) ->select(); foreach ($norm_res as $value){ $res_filed = isset($relation_k_v[$value['type']][$value['en_name']]) ? $relation_k_v[$value['type']][$value['en_name']] : ''; foreach ($staff_result as $k => $res_v){ - if ($value['device_id'] == $res_v['relation_type'] && isset($res_v[$res_filed]) && !empty($res_v[$res_filed])){ - //人员-日期-指标uuid=指标值 - $norm_key = $res_v['date'].'_'.$res_v['staff_uuid'].'_'.$value['uuid']; - $data_list[$norm_key] = [ + if ($value['device_id'] == $res_v['relation_type'] && + $res_filed !== '' && array_key_exists($res_filed, $res_v)){ + $source_time = $res_v['record_time'] ?: ($res_v['update_time'] ?: ($res_v['create_time'] ?: $res_v['date'].' 00:00:00')); + $consider_candidate([ 'uuid' => '', 'test_date' => $res_v['date'], 'type' => 7, - 'create_time' => '', + 'create_time' => $source_time, 'norm_uuid' => $value['uuid'], 'norm_value' => $res_v[$res_filed], 'cate_uuid' => '', 'staff_uuid' => $res_v['staff_uuid'], - ]; + ], $source_time, 30, $res_v['id']); } } } } + // Legacy functional values participate in the same latest-record + // selection instead of replacing or blindly appending current data. + $legacy_where = [ + 'a.staff_uuid' => ['in', $staff_uuid_list], + 'a.norm_uuid' => ['in', $norm_uuids], + 'a.is_del' => 0, + 'b.is_del' => 0, + ]; + if ($params['start_date'] == $params['end_date']) { + $legacy_where['a.test_date'] = $params['start_date']; + } else { + $legacy_where['a.test_date'] = ['between',[$params['start_date'],$params['end_date']]]; + } + $legacy_values = Db::name('test_value') + ->alias('a') + ->join('test_result_value b','a.id = b.value_id','left') + ->where($legacy_where) + ->field('a.*') + ->select(); + foreach ($legacy_values as $legacy_value) { + $consider_candidate([ + 'uuid' => '', + 'test_date' => $legacy_value['test_date'], + 'type' => 7, + 'create_time' => $legacy_value['create_time'], + 'norm_uuid' => $legacy_value['norm_uuid'], + 'norm_value' => $legacy_value['norm_value'], + 'cate_uuid' => '', + 'staff_uuid' => $legacy_value['staff_uuid'], + ], $legacy_value['create_time'], 10, $legacy_value['id']); + } + $data_list = array(); + foreach ($latest_candidates as $norm_key => $candidate) { + $data_list[$norm_key] = $candidate['row']; + } $data = array_values($data_list); return $data; } @@ -347,12 +398,15 @@ $date_arr = array(); $max_min_arr = array(); foreach ($params as $value){ + // DPS averages only actual values. Ignore missing values before + // building rows, extrema and statistics, while preserving zero. + if(is_null($value['norm_value']) || $value['norm_value'] === ''){ + continue; + } $norm_arr[$value['norm_uuid']][] = $value['norm_value']; $test_data[$value['test_date']][$value['norm_uuid']] = $value['norm_value']; $max_min_arr[$value['norm_uuid']][$value['norm_value']] = $value['test_date']; - if($value['norm_value']){//组织折线图数据 - $vertical_arr[$value['norm_uuid']][$value['test_date']] = $value['norm_value']; - } + $vertical_arr[$value['norm_uuid']][$value['test_date']] = $value['norm_value']; $date_arr[] = $value['test_date']; } //一个指标下的一组数据,根据指标大小进行日期排序 @@ -417,7 +471,7 @@ function getVariance($avg, $list){ $total_var = 0; foreach ($list as $lv){ - if (!empty($lv)) { + if (!is_null($lv) && $lv !== '') { $total_var += pow( ($lv - $avg), 2 ); } } @@ -1111,37 +1165,6 @@ foreach ($body_norms as $norm_uuid){ $body_avg_data[$value['staff_uuid']][$norm_uuid][] = $value[$norm_uuid]; $body_data[$value['staff_uuid']][$date][$norm_uuid] = $value[$norm_uuid]; - } - //记录人员+日期 - $date_arr[$value['staff_uuid']][] = $date; - } - } - } - //type=6 - //机能数据获取 - if($one_norm_arr){ - $one_norm_uuid_arr = array(); - foreach ($one_norm_arr as $norm_uuid_value){ - $one_norm_uuid_arr[] = $norm_uuid_value['uuid']; - } - $one_norm_uuid_arr = array_unique($one_norm_uuid_arr); - $tn_res = Db::name('test_value') - ->alias('a') - ->join('test_result_value b','a.id = b.value_id','left') - ->where(['b.is_del' => 0,'a.is_del' => 0]) - ->where(['a.staff_uuid' => ['in', $staff_uuid_str],'a.test_date'=>['between', "$start_date,$end_date"], 'a.norm_uuid' => ['in', $one_norm_uuid_arr]]) - ->field('a.*') - ->select(); - $tn_data = array(); - $tn_avg_data = array(); - foreach ($tn_res as $value){ - if(isset($value['norm_value']) && !is_null($value['norm_value']) && $value['norm_value'] != ''){ - $date = $value['test_date']; - foreach ($one_norm_uuid_arr as $norm_uuid){ - if($norm_uuid == $value['norm_uuid']){ - $tn_avg_data[$value['staff_uuid']][$norm_uuid][] = $value['norm_value']; - $tn_data[$value['staff_uuid']][$date][$norm_uuid] = $value['norm_value']; - } } //记录人员+日期 $date_arr[$value['staff_uuid']][] = $date;