getAdcycleInsight($customerIds, $cycle, $startDateNumeric, $endDateNumeric); return $currentData; // 计算前一天的日期 // $previousStartDate = $startDate ? // (new DateTime($startDate))->modify('-1 day')->format('Ymd') : // null; // // $previousEndDate = $endDate ? // (new DateTime($endDate))->modify('-1 day')->format('Ymd') : // null; // 获取前一天周期的数据 // $lastData = $this->getAdcycleInsight($customerIds, $cycle, $previousStartDate, $previousEndDate); } public function getAdcycleInsight($customerIds, $cycle, $startDate = null, $endDate = null) { // 1. 查询全部数据集 $adcycleDataQuery = BpsAdInsight::alias('d'); //dump($customerIds); // 2. 客户 ID 过滤(如果提供了) if (!empty($customerIds)) { $adcycleDataQuery->whereIn('d.account_id', $customerIds); } else { return [ 'data' => [ 'meta' => [ 'meta_ads' => '-', 'roas' => '-', 'cpc' => '-', 'cpm' => '-', 'meta_purchases' => '-', 'web_purchases' => '-', 'purchases' => '-', 'meta_conversion_value' => '-', 'web_conversion_value' => '-', 'conversion_value' => '-', 'cpoc' => '-', 'ctr' => '-', 'revenue_per_link_click' => '-', 'cpa' => '-', ], 'google' => [ 'google_ads' => '-', 'conversion_value' => '-', 'roas' => '-', 'conversions' => '-', 'ctr' => '-', 'cpa' => '-', 'cpm' => '-', 'clicks' => '-', 'impressions' => '-', 'all_conversions_value' => '-', 'all_roas' => '-', 'all_conversions' => '-', 'all_cpa' => '-', ], 'tiktok' => [ 'tiktok_ads' => '-', 'roas' => '-', 'impressions' => '-', 'cpm' => '-', 'cpc' => '-', 'ctr' => '-', 'cpa' => '-', 'tiktok_shop_conversions' => '-', 'tiktok_shop_conversion_value' => '-', 'conversion_value' => '-', 'web_conversion_value' => '-', 'purchases' => '-', 'web_purchases' => '-', 'tiktok_gmv_max_ads' => '-', ] ] ]; } // 3. 时间范围筛选 if ($startDate && $endDate) { $adcycleDataQuery->whereBetween('d.date', [$startDate, $endDate]); } // 4. 获取数据并按平台和日期聚合 $adcycleData = $adcycleDataQuery->field( 'd.platform, COALESCE(SUM(d.assisted_purchases), 0) as assisted_purchases, COALESCE(SUM(d.last_clicked_purchases), 0) as last_clicked_purchases, COALESCE(SUM(d.clicks), 0) as clicks, COALESCE(SUM(d.spend) / 1000000, 0) as spend, COALESCE(SUM(d.impressions), 0) as impressions, COALESCE(SUM(d.adds_to_cart), 0) as adds_to_cart, COALESCE(SUM(d.purchases), 0) as purchases, COALESCE(SUM(d.purchases_all), 0) as purchases_all, COALESCE(SUM(d.platform_purchase), 0) as platform_purchase, COALESCE(SUM(d.purchases_value) / 1000000, 0) as purchases_value, COALESCE(SUM(d.platform_purchase_value) / 1000000, 0) as platform_purchase_value, COALESCE(SUM(d.revenue) / 1000000, 0) as revenue, COALESCE(SUM(d.total_cost) / 1000000, 0) as total_cost' ) ->group('d.platform') // 按平台和日期进行分组 ->select(); // dump(ThinkDb::getLastSql()); // 定义字段映射关系 $fieldMapping = [ 'meta' => [ 'meta_ads' => 'spend', // 示例映射 'roas' => 'roas', 'cpc' => 'cpc', 'cpm' => 'cpm', 'meta_purchases' => 'platform_purchase', 'web_purchases' => 'purchases', 'purchases' => 'purchases_all', 'meta_conversion_value' => 'platform_purchase_value', 'web_conversion_value' => 'purchases_value', 'conversion_value' => 'purchases_value', 'cpoc' => 'cpoc', 'ctr' => 'ctr', 'revenue_per_link_click' => 'revenue_per_link_click', 'cpa' => 'cpa', ], 'google' => [ 'google_ads' => 'spend', // 示例映射 'conversion_value' => 'platform_purchase_value', 'roas' => 'google_roas', 'conversions' => 'purchases', 'ctr' => 'ctr', 'cpa' => 'google_cpa', 'cpm' => 'cpm', 'clicks' => 'clicks', 'impressions' => 'impressions', 'all_conversions_value' => 'revenue', 'all_roas' => 'roas', 'all_conversions' => 'purchases', 'all_cpa' => 'cpa', ], 'tiktok' => [ 'tiktok_ads' => 'spend', // 示例映射 'roas' => 'roas', 'impressions' => 'impressions', 'cpm' => 'cpm', 'cpc' => 'cpc', 'ctr' => 'ctr', 'cpa' => 'cpa', 'tiktok_shop_conversions' => '', 'tiktok_shop_conversion_value' => '', 'conversion_value' => 'platform_purchase_value', 'web_conversion_value' => 'revenue', 'purchases' => 'platform_purchase', 'web_purchases' => 'purchases', 'tiktok_gmv_max_ads' => '', ], ]; // 初始化结果数组 $result = [ 'data' => [ 'meta' => array_fill_keys(array_keys($fieldMapping['meta']), '-'), 'google' => array_fill_keys(array_keys($fieldMapping['google']), '-'), 'tiktok' => array_fill_keys(array_keys($fieldMapping['tiktok']), '-'), ], ]; // 在 PHP 中计算指标 foreach ($adcycleData as $data) { $platform = $data['platform']; // 获取平台类型 $spend = (float)$data['spend']; $revenue = (float)$data['revenue']; $totalCost = (float)$data['total_cost']; $impressions = (int)$data['impressions']; $clicks = (int)$data['clicks']; $purchases = (int)$data['purchases']; $purchases_all = (int)$data['purchases_all']; $platform_purchase = (int)$data['platform_purchase']; $purchases_value = (float)$data['purchases_value']; $platform_purchase_value = (float)$data['platform_purchase_value']; // 计算指标 $roas = ($spend == 0) ? 0 : $revenue / $spend; $google_roas = ($spend == 0) ? 0 : $purchases_value / $spend; $ctr = ($impressions == 0) ? 0 : $clicks / $impressions; $cpoc = ($platform_purchase == 0) ? 0 : $platform_purchase_value / $platform_purchase; $cpa = ($purchases == 0) ? 0 : $spend / $purchases; $google_cpa = ($platform_purchase == 0) ? 0 : $spend / $platform_purchase; $cpm = ($impressions == 0) ? 0 : ($spend * 1000) / $impressions; $cpc = ($clicks == 0) ? 0 : $spend / $clicks; $conversionRate = ($clicks == 0) ? 0 : $purchases / $clicks; $revenuePerLinkClick = ($clicks == 0) ? 0 : $revenue / $clicks; // 根据平台类型映射数据 $platformKey = match ($platform) { 1 => 'meta', 2 => 'google', 3 => 'tiktok', default => null, }; if ($platformKey) { foreach ($fieldMapping[$platformKey] as $targetField => $sourceField) { $value = '-'; switch ($sourceField) { case 'spend': $value = '$' . number_format($spend, 2); break; case 'revenue': $value = '$' . number_format($revenue, 2); break; case 'total_cost': $value = '$' . number_format($totalCost, 2); break; case 'purchases_value': $value = '$' . number_format($purchases_value, 2); break; case 'platform_purchase_value': $value = '$' . number_format($platform_purchase_value, 2); break; case 'roas': $value = round($roas, 2) . 'x'; break; case 'google_roas': $value = round($google_roas, 2) . 'x'; break; case 'cpoc': $value = '$' . number_format($cpoc, 2); break; case 'ctr': $value = number_format($ctr * 100, 2) . '%'; break; case 'cpa': $value = '$' . number_format($cpa, 2); break; case 'google_cpa': $value = '$' . number_format($google_cpa, 2); break; case 'cpm': $value = '$' . number_format($cpm, 2); break; case 'cpc': $value = '$' . number_format($cpc, 2); break; case 'conversion_rate': $value = $conversionRate; break; case 'revenue_per_link_click': $value = '$' . number_format($revenuePerLinkClick, 2); break; case 'purchases': $value = $purchases; break; case 'purchases_all': $value = $purchases_all; break; case 'platform_purchase': $value = $platform_purchase; break; case 'clicks': $value = $clicks; break; case 'impressions': $value = $impressions; break; default: $value = '-'; break; } $result['data'][$platformKey][$targetField] = $value; } } } return $result; // dump(ThinkDb::getLastSql()); // 5. 处理数据,按照周期进行分组 // $processedData = $this->processDataByCycle($adcycleData->toArray(), $cycle); // 6. 返回处理后的数据 // return $adcycleData; } }