save($data); if ($result === false) { throw new BusinessException($profile->getError() ?: '创建档案失败'); } Db::commit(); return $profile; } catch (\Throwable $e) { Db::rollback(); throw new BusinessException($e->getMessage()); } } /** * 更新身体档案 */ public static function updateProfile($profileId, $userId, $data) { $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } // 处理身体照片 if (isset($data['body_photos']) && is_array($data['body_photos'])) { $data['body_photos'] = json_encode($data['body_photos']); } Db::startTrans(); try { $result = $profile->save($data); if ($result === false) { throw new BusinessException($profile->getError() ?: '更新档案失败'); } Db::commit(); return $profile; } catch (\Throwable $e) { Db::rollback(); throw new BusinessException($e->getMessage()); } } /** * 删除身体档案 */ public static function deleteProfile($profileId, $userId) { $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } Db::startTrans(); try { // 删除相关数据 BodyMeasurements::where('profile_id', $profileId)->delete(); BodyTypeSelection::where('profile_id', $profileId)->delete(); BodyAiReport::where('profile_id', $profileId)->delete(); // 删除档案 $profile->delete(); Db::commit(); return true; } catch (\Throwable $e) { Db::rollback(); throw new BusinessException($e->getMessage()); } } /** * 获取用户档案列表 */ public static function getUserProfiles($userId) { $profiles = BodyProfile::where('user_id', $userId) ->with(['latestMeasurement', 'latestAiReport']) ->order('is_own DESC, id DESC') ->select(); $result = []; foreach ($profiles as $profile) { $data = $profile->toArray(); $data['bmi'] = $profile->calculateBMI(); $data['bmi_level'] = $profile->getBMILevel(); $result[] = $data; } return $result; } /** * 获取档案详情 */ public static function getProfileDetail($profileId, $userId) { $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } return $profile->getFullProfileData(); } /** * 添加测量数据 */ public static function addMeasurement($profileId, $userId, $measurementData) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } // 过滤测量数据字段 $gender = $profile->gender ?? 0; // 确保gender不为null $measurementFieldsMap = BodyMeasurements::getMeasurementFields($gender); if (!$measurementFieldsMap || !is_array($measurementFieldsMap)) { throw new BusinessException('无法获取测量字段配置'); } $measurementFields = array_keys($measurementFieldsMap); $filteredData = ['profile_id' => $profileId]; foreach ($measurementFields as $field) { if (isset($measurementData[$field]) && $measurementData[$field] !== '') { $filteredData[$field] = floatval($measurementData[$field]); } } // 设置测量日期 if (isset($measurementData['measurement_date']) && $measurementData['measurement_date']) { $filteredData['measurement_date'] = strtotime($measurementData['measurement_date']); } else { $filteredData['measurement_date'] = time(); } $measurement = new BodyMeasurements(); $result = $measurement->save($filteredData); if ($result === false) { throw new BusinessException($measurement->getError() ?: '添加测量数据失败'); } return $measurement; } /** * 获取测量历史 */ public static function getMeasurementHistory($profileId, $userId, $page = 1, $limit = 10) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } $list = BodyMeasurements::where('profile_id', $profileId) ->order('measurement_date DESC') ->paginate($limit, false, ['page' => $page]); return [ 'list' => $list->items(), 'total' => $list->total(), 'page' => $page, 'limit' => $limit ]; } /** * 保存体型选择 */ public static function saveBodyTypeSelection($profileId, $userId, $selections) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } $result = BodyTypeSelection::saveUserSelections($profileId, $selections); if (!$result) { throw new BusinessException('保存体型选择失败'); } return true; } /** * 生成AI测试报告 */ public static function generateAiReport($profileId, $userId, $reportType = 'comprehensive') { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } $report = BodyAiReport::generateReport($profileId, $reportType); if (!$report) { throw new BusinessException('生成报告失败,请确保已填写完整的身体数据'); } return $report; } /** * 获取AI报告详情 */ public static function getAiReport($reportId, $userId) { $report = BodyAiReport::with(['profile']) ->where('id', $reportId) ->find(); if (!$report || $report->profile->user_id != $userId) { throw new BusinessException('报告不存在'); } return $report; } /** * 获取AI报告列表 */ public static function getAiReportList($profileId, $userId, $page = 1, $limit = 10) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } $list = BodyAiReport::where('profile_id', $profileId) ->order('generated_time DESC') ->paginate($limit, false, ['page' => $page]); return [ 'list' => $list->items(), 'total' => $list->total(), 'page' => $page, 'limit' => $limit ]; } /** * 获取体型选择建议报告 */ public static function getSelectionReport($profileId, $userId) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } return BodyTypeService::generateSelectionReport($profileId); } /** * 保存测量数据和体型选择(合并业务逻辑) */ public static function saveMeasurementAndBodyType($profileId, $userId, $measurementData = [], $bodyTypeSelections = [], $profileUpdateData = []) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } $result = [ 'measurement_saved' => false, 'body_type_saved' => false, 'measurement_id' => null, 'profile_updated' => false ]; Db::startTrans(); try { // 保存测量数据 if (!empty($measurementData)) { $measurement = self::addMeasurement($profileId, $userId, $measurementData); $result['measurement_saved'] = true; $result['measurement_id'] = $measurement->id; } // 保存体型选择 if (!empty($bodyTypeSelections)) { $selectionResult = self::saveBodyTypeSelection($profileId, $userId, $bodyTypeSelections); $result['body_type_saved'] = $selectionResult; } // 更新档案信息(身高体重) if (!empty($profileUpdateData)) { $updateResult = $profile->save($profileUpdateData); if ($updateResult === false) { throw new BusinessException($profile->getError() ?: '更新档案信息失败'); } $result['profile_updated'] = true; } Db::commit(); return $result; } catch (\Throwable $e) { Db::rollback(); throw new BusinessException($e->getMessage()); } } /** * 更新测量数据和体型选择(合并业务逻辑) */ public static function updateMeasurementAndBodyType($profileId, $userId, $measurementData = [], $bodyTypeSelections = [], $profileUpdateData = []) { // 验证档案归属 $profile = BodyProfile::where('id', $profileId) ->where('user_id', $userId) ->find(); if (!$profile) { throw new BusinessException('档案不存在'); } $result = [ 'measurement_updated' => false, 'body_type_updated' => false, 'profile_updated' => false, 'measurement_id' => null ]; Db::startTrans(); try { // 更新测量数据(创建新的测量记录) if (!empty($measurementData)) { $measurement = self::addMeasurement($profileId, $userId, $measurementData); $result['measurement_updated'] = true; $result['measurement_id'] = $measurement->id; } // 更新体型选择(覆盖现有选择) if (!empty($bodyTypeSelections)) { $selectionResult = self::saveBodyTypeSelection($profileId, $userId, $bodyTypeSelections); $result['body_type_updated'] = $selectionResult; } // 更新档案信息(身高体重) if (!empty($profileUpdateData)) { $updateResult = $profile->save($profileUpdateData); if ($updateResult === false) { throw new BusinessException($profile->getError() ?: '更新档案信息失败'); } $result['profile_updated'] = true; } Db::commit(); return $result; } catch (\Throwable $e) { Db::rollback(); throw new BusinessException($e->getMessage()); } } }