cache(false) // 强制不使用缓存 ->leftJoin('bps.bps_google_ads_ad_group g', 'a.ad_group_id = g.ad_group_id') // 关联广告组表 ->leftJoin('bps.bps_google_ads_campaign c', 'a.campaign_id = c.campaign_id'); // 关联广告系列表 // 动态拼接 LEFT JOIN 的 ON 条件 $onCondition = 'a.ad_id = d.ad_id'; if ($startDate && $endDate) { $onCondition .= " AND d.date BETWEEN '{$startDate}' AND '{$endDate}'"; } else { switch ($dateRange) { case 'Today': $onCondition .= " AND d.date = '" . date('Y-m-d') . "'"; break; case 'Yesterday': $onCondition .= " AND d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; break; case 'Last Week': $onCondition .= " AND d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; break; case 'Last Month': $onCondition .= " AND d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; break; case 'Last Year': $onCondition .= " AND d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; break; default: break; } } // 添加 LEFT JOIN 日数据表 $query->leftJoin('bps.bps_google_ad_day_data d', $onCondition); // 添加字段、分组和查询条件 $query->field('a.ad_id, -1 as ad_name, a.status as ad_status, a.customer_id, a.ad_group_id, g.ad_group_name as ad_group_name, a.campaign_id, c.campaign_name as campaign_name, COALESCE(SUM(d.clicks), -1) as clicks, COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, COALESCE(SUM(d.conversions), -1) as results, COALESCE(SUM(d.conversions_value), -1) as conversions_value, COALESCE(SUM(d.impressions), -1) as reach, -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') ->group('a.ad_id, a.ad_name, a.status, a.customer_id, a.ad_group_id, g.ad_group_name, a.campaign_id, c.campaign_name') ->where(function ($query) use ($keyword) { if ($keyword) { $query->where('a.ad_name', 'like', '%' . $keyword . '%'); } }); // 获取查询结果 $ads = $query->paginate($pageSize, false, ['page' => $page]); // 确保转换为数值 $result = array_map(function ($item) { $item['spend'] = (float)$item['spend']; $item['conversions_value'] = (float)$item['conversions_value']; return $item; }, $ads->items()); // dump($query->getLastSql()); // 返回分页和总数信息 return [ 'data' => $result, 'total' => $ads->total(), 'current_page' => $ads->currentPage(), 'last_page' => $ads->lastPage(), ]; } /** * 导出广告列表到 Excel * * @param string $keyword * @param string $dateRange * @return void */ public static function exportAdListToExcel($keyword, $dateRange, $startDate = null, $endDate = null) { // 基础查询:广告表和日数据表联接 $query = Ad::alias('a') ->cache(false) // 强制不使用缓存 ->leftJoin('bps.bps_google_ads_ad_group g', 'a.ad_group_id = g.ad_group_id') // 关联广告组表 ->leftJoin('bps.bps_google_ads_campaign c', 'a.campaign_id = c.campaign_id'); // 关联广告系列表 // 动态拼接 LEFT JOIN 的 ON 条件 $onCondition = 'a.ad_id = d.ad_id'; if ($startDate && $endDate) { $onCondition .= " AND d.date BETWEEN '{$startDate}' AND '{$endDate}'"; } else { switch ($dateRange) { case 'Today': $onCondition .= " AND d.date = '" . date('Y-m-d') . "'"; break; case 'Yesterday': $onCondition .= " AND d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; break; case 'Last Week': $onCondition .= " AND d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; break; case 'Last Month': $onCondition .= " AND d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; break; case 'Last Year': $onCondition .= " AND d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; break; default: break; } } // 添加 LEFT JOIN 日数据表 $query->leftJoin('bps.bps_google_ad_day_data d', $onCondition); // 添加字段、分组和查询条件 $query->field('a.ad_id, -1 as ad_name, a.status as ad_status, a.customer_id, a.ad_group_id, g.ad_group_name as ad_group_name, a.campaign_id, c.campaign_name as campaign_name, COALESCE(SUM(d.clicks), -1) as clicks, COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, COALESCE(SUM(d.conversions), -1) as results, COALESCE(SUM(d.conversions_value), -1) as conversions_value, COALESCE(SUM(d.impressions), -1) as reach, -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') ->group('a.ad_id, a.ad_name, a.status, a.customer_id, a.ad_group_id, g.ad_group_name, a.campaign_id, c.campaign_name') ->where(function ($query) use ($keyword) { if ($keyword) { $query->where('a.ad_name', 'like', '%' . $keyword . '%'); } }); // 获取所有广告数据 $ads = $query->select(); // 创建一个新的 Spreadsheet 对象 $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $ad_status = [ 0 => 'UNSPECIFIED', 1 => 'UNKNOWN', // UNKNOW 2 => 'ENABLED', // ENABLED 3 => 'PAUSED', // PAUSED 4 => 'REMOVED', // REMOVED ]; // 设置表头 $sheet->setCellValue('A1', 'Ad ID'); $sheet->setCellValue('B1', 'Ad Status'); $sheet->setCellValue('C1', 'Name'); $sheet->setCellValue('D1', 'Campaign'); $sheet->setCellValue('E1', 'Ad Set'); $sheet->setCellValue('F1', 'Delivery'); $sheet->setCellValue('G1', 'Results'); $sheet->setCellValue('H1', 'Reach'); $sheet->setCellValue('I1', 'Revenue'); $sheet->setCellValue('J1', 'ROAS'); $sheet->setCellValue('K1', 'beROAS'); $sheet->setCellValue('L1', 'Profit'); $sheet->setCellValue('M1', 'Spend'); // $sheet->setCellValue('N1', 'Customer ID'); // $sheet->setCellValue('E1', 'Clicks'); // $sheet->setCellValue('F1', 'Cost Micros'); // $sheet->setCellValue('G1', 'Conversions'); // $sheet->setCellValue('H1', 'Conversions Value'); // $sheet->setCellValue('I1', 'Impressions'); // 填充数据 $row = 2; // 从第二行开始 foreach ($ads as $ad) { $sheet->setCellValueExplicit('A' . $row, (string)$ad->ad_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); // 设置 ad_id 为文本 $sheet->setCellValue('B' . $row, $ad_status[$ad->ad_status]); $sheet->setCellValue('C' . $row, $ad->ad_name); // 直接设置 ad_name $sheet->setCellValue('D' . $row, $ad->campaign_name); // 直接设置 ad_name $sheet->setCellValue('E' . $row, $ad->ad_group_name); // 直接设置 ad_name $sheet->setCellValue('F' . $row, $ad->delivery); // 直接设置 ad_name $sheet->setCellValue('G' . $row, $ad->results); $sheet->setCellValue('H' . $row, $ad->reach); $sheet->setCellValue('I' . $row, $ad->revenue); $sheet->setCellValue('J' . $row, $ad->roas); $sheet->setCellValue('K' . $row, $ad->be_roas); $sheet->setCellValue('L' . $row, $ad->profit); $sheet->setCellValue('M' . $row, $ad->spend); // $sheet->setCellValueExplicit('N' . $row, (string)$ad->customer_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); // 设置 customer_id 为文本 $row++; } // 设置 Excel 文件名 $fileName = 'Ad_Report_' . $dateRange . '_' . date('Y-m-d_H-i-s') . '.xlsx'; // 创建 Excel 文件并保存 $writer = new Xlsx($spreadsheet); $filePath = public_path() . '/' . $fileName; try { $writer->save($filePath); return response()->download($filePath, $fileName); // return ['success' => true, 'file_path' => $filePath]; } catch (\Exception $e) { return ['' => false, 'message' => $e->getMessage()]; } } /** * 获取广告系列列表 */ public static function getCampaignList($page, $pageSize, $keyword, $dateRange, $startDate = null, $endDate = null) { // 动态构建日期条件 $dateCondition = ''; if ($startDate && $endDate) { $dateCondition = "d.date BETWEEN '{$startDate}' AND '{$endDate}'"; } else { switch ($dateRange) { case 'Today': $dateCondition = "d.date = '" . date('Y-m-d') . "'"; break; case 'Yesterday': $dateCondition = "d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; break; case 'Last Week': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; break; case 'Last Month': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; break; case 'Last Year': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; break; default: $dateCondition = "1=1"; // 无日期限制,默认条件始终为真 break; } } // 基础查询:广告活动和日数据表联接 $query = Campaign::alias('c') ->leftJoin('bps.bps_google_ad_day_data d', "c.campaign_id = d.campaign_id AND {$dateCondition}") // 将日期条件加入到 ON 子句中 ->field('c.campaign_id, c.status as campaign_status, c.campaign_name, c.customer_id, COALESCE(SUM(d.clicks), -1) as clicks, COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, COALESCE(SUM(d.conversions), -1) as results, COALESCE(SUM(d.conversions_value), -1) as conversions_value, COALESCE(SUM(d.impressions), -1) as reach, -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') ->group('c.campaign_id, c.status, c.customer_id, c.campaign_name') ->where(function ($query) use ($keyword) { if ($keyword) { $query->where('c.campaign_name', 'like', '%' . $keyword . '%'); } }); // 获取分页数据 $campaigns = $query->paginate($pageSize, false, ['page' => $page]); // 确保转换为数值 $result = array_map(function ($item) { $item['spend'] = (float)$item['spend']; $item['conversions_value'] = (float)$item['conversions_value']; return $item; }, $campaigns->items()); // 返回分页和总数信息 return [ 'data' => $campaigns->items(), 'total' => $campaigns->total(), 'current_page' => $campaigns->currentPage(), 'last_page' => $campaigns->lastPage(), ]; } /** * 导出广告系列数据到 Excel * * @param string $keyword * @param string $dateRange * @return void */ public static function exportCampaignsToExcel($keyword, $dateRange, $startDate = null, $endDate = null) { // 动态构建日期条件 $dateCondition = ''; if ($startDate && $endDate) { $dateCondition = "d.date BETWEEN '{$startDate}' AND '{$endDate}'"; } else { switch ($dateRange) { case 'Today': $dateCondition = "d.date = '" . date('Y-m-d') . "'"; break; case 'Yesterday': $dateCondition = "d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; break; case 'Last Week': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; break; case 'Last Month': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; break; case 'Last Year': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; break; default: $dateCondition = "1=1"; // 无日期限制,默认条件始终为真 break; } } // 基础查询:广告活动和日数据表联接 $query = Campaign::alias('c') ->leftJoin('bps.bps_google_ad_day_data d', "c.campaign_id = d.campaign_id AND {$dateCondition}") // 将日期条件加入到 ON 子句中 ->field('c.campaign_id, c.status as campaign_status, c.campaign_name, c.customer_id, COALESCE(SUM(d.clicks), -1) as clicks, COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, COALESCE(SUM(d.conversions), -1) as results, COALESCE(SUM(d.conversions_value), -1) as conversions_value, COALESCE(SUM(d.impressions), -1) as reach, -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') ->group('c.campaign_id, c.status, c.customer_id, c.campaign_name') ->where(function ($query) use ($keyword) { if ($keyword) { $query->where('c.campaign_name', 'like', '%' . $keyword . '%'); } }); // 获取所有广告系列数据 $campaigns = $query->select(); // 创建一个新的 Spreadsheet 对象 $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); $campaignsStatus = [ 0 => 'UNSPECIFIED', // UNSPECIFIED 1 => 'UNKNOWN', // UNKNOWN 2 => 'ENABLED', // ENABLED 3 => 'PAUSED', // PAUSED 4 => 'REMOVED', // REMOVED ]; // 设置表头 $sheet->setCellValue('A1', 'Campaign ID'); $sheet->setCellValue('B1', 'Status'); $sheet->setCellValue('C1', 'Name'); $sheet->setCellValue('D1', 'Delivery'); $sheet->setCellValue('E1', 'Results'); $sheet->setCellValue('F1', 'Reach'); $sheet->setCellValue('G1', 'Revenue'); $sheet->setCellValue('H1', 'ROAS'); $sheet->setCellValue('I1', 'beROAS'); $sheet->setCellValue('J1', 'Profit'); $sheet->setCellValue('K1', 'Spend'); // 填充数据 $row = 2; // 从第二行开始 foreach ($campaigns as $campaign) { //使用 setCellValueExplicit 显式设置为文本格式 $sheet->setCellValueExplicit('A' . $row, (string)$campaign->campaign_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); // 设置为文本格式 $sheet->setCellValue('B' . $row, $campaignsStatus[$campaign->campaign_status]); $sheet->setCellValue('C' . $row, $campaign->campaign_name); $sheet->setCellValue('D' . $row, $campaign->delivery); // 直接设置 ad_name $sheet->setCellValue('E' . $row, $campaign->results); $sheet->setCellValue('F' . $row, $campaign->reach); $sheet->setCellValue('G' . $row, $campaign->revenue); $sheet->setCellValue('H' . $row, $campaign->roas); $sheet->setCellValue('I' . $row, $campaign->be_roas); $sheet->setCellValue('J' . $row, $campaign->profit); $sheet->setCellValue('K' . $row, $campaign->spend); // $sheet->setCellValueExplicit('N' . $row, (string)$campaign->customer_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); // 设置为文本格式 $row++; } // 设置 Excel 文件名 $fileName = 'Campaign_Report_' . $dateRange . '_' . date('Y-m-d_H-i-s') . '.xlsx'; // 创建 Excel 文件并保存 $writer = new Xlsx($spreadsheet); $filePath = public_path() . '/' . $fileName; try { $writer->save($filePath); return response()->download($filePath, $fileName); // return ['success' => true, 'file_path' => $filePath]; } catch (\Exception $e) { return ['' => false, 'message' => $e->getMessage()]; } } /** * 获取广告系列列表 */ public static function getAdGroupList($page, $pageSize, $keyword, $dateRange, $startDate = null, $endDate = null) { // 动态构建日期条件 $dateCondition = ''; if ($startDate && $endDate) { $dateCondition = "d.date BETWEEN '{$startDate}' AND '{$endDate}'"; } else { switch ($dateRange) { case 'Today': $dateCondition = "d.date = '" . date('Y-m-d') . "'"; break; case 'Yesterday': $dateCondition = "d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; break; case 'Last Week': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; break; case 'Last Month': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; break; case 'Last Year': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; break; default: $dateCondition = "1=1"; // 默认无日期限制 break; } } // 初始化查询 $query = AdGroup::alias('ag') ->leftJoin("bps.bps_google_ad_day_data d", "ag.ad_group_id = d.ad_group_id AND {$dateCondition}") // 日期条件放入 ON 子句 ->leftJoin("bps.bps_google_ads_campaign c", "ag.campaign_id = c.campaign_id") // 关联广告系列表 ->field('ag.ad_group_id, ag.ad_group_name, ag.status as ad_group_status, ag.campaign_id, c.campaign_name, ag.customer_id, COALESCE(SUM(d.clicks), -1) as clicks, COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, COALESCE(SUM(d.conversions), -1) as results, COALESCE(SUM(d.conversions_value), -1) as conversions_value, COALESCE(SUM(d.impressions), -1) as reach, -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') ->group('ag.ad_group_id, ag.ad_group_name, ag.status, ag.campaign_id, c.campaign_name, ag.customer_id') ->where(function ($query) use ($keyword) { if ($keyword) { $query->where('ag.ad_group_name', 'like', '%' . $keyword . '%'); } }); // 获取分页数据 $adGroups = $query->paginate($pageSize, false, ['page' => $page]); // 确保转换为数值 $result = array_map(function ($item) { $item['spend'] = (float)$item['spend']; $item['conversions_value'] = (float)$item['conversions_value']; return $item; }, $adGroups->items()); // 返回分页和总数信息 return [ 'data' => $adGroups->items(), 'total' => $adGroups->total(), 'current_page' => $adGroups->currentPage(), 'last_page' => $adGroups->lastPage(), ]; } /** * 将广告组数据导出到 Excel 文件 */ public static function exportAdGroupsToExcel($keyword = '', $dateRange = 'Today', $startDate = null, $endDate = null) { // 动态构建日期条件 $dateCondition = ''; if ($startDate && $endDate) { $dateCondition = "d.date BETWEEN '{$startDate}' AND '{$endDate}'"; } else { switch ($dateRange) { case 'Today': $dateCondition = "d.date = '" . date('Y-m-d') . "'"; break; case 'Yesterday': $dateCondition = "d.date = '" . date('Y-m-d', strtotime('-1 day')) . "'"; break; case 'Last Week': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 week')) . "'"; break; case 'Last Month': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 month')) . "'"; break; case 'Last Year': $dateCondition = "d.date >= '" . date('Y-m-d', strtotime('-1 year')) . "'"; break; default: $dateCondition = "1=1"; // 默认无日期限制 break; } } // 初始化查询 $query = AdGroup::alias('ag') ->leftJoin("bps.bps_google_ad_day_data d", "ag.ad_group_id = d.ad_group_id AND {$dateCondition}") // 日期条件放入 ON 子句 ->leftJoin("bps.bps_google_ads_campaign c", "ag.campaign_id = c.campaign_id") // 关联广告系列表 ->field('ag.ad_group_id, ag.ad_group_name, ag.status as ad_group_status, ag.campaign_id, c.campaign_name, ag.customer_id, COALESCE(SUM(d.clicks), -1) as clicks, COALESCE(SUM(d.cost_micros) / 1000000, -1) as spend, COALESCE(SUM(d.conversions), -1) as results, COALESCE(SUM(d.conversions_value), -1) as conversions_value, COALESCE(SUM(d.impressions), -1) as reach, -1 as roas, -1 as be_roas, -1 as revenue, -1 as profit, -1 as delivery') ->group('ag.ad_group_id, ag.ad_group_name, ag.status, ag.campaign_id, c.campaign_name, ag.customer_id') ->where(function ($query) use ($keyword) { if ($keyword) { $query->where('ag.ad_group_name', 'like', '%' . $keyword . '%'); } }); // 获取所有广告组数据 $ad_groups = $query->select(); // 创建一个新的 Spreadsheet 对象 $spreadsheet = new Spreadsheet(); $sheet = $spreadsheet->getActiveSheet(); // 设置表头 $sheet->setCellValue('A1', 'Ad Group ID'); $sheet->setCellValue('B1', 'Status'); $sheet->setCellValue('C1', 'Name'); $sheet->setCellValue('D1', 'Campaign'); $sheet->setCellValue('E1', 'Delivery'); $sheet->setCellValue('F1', 'Results'); $sheet->setCellValue('G1', 'Reach'); $sheet->setCellValue('H1', 'Revenue'); $sheet->setCellValue('I1', 'ROAS'); $sheet->setCellValue('J1', 'beROAS'); $sheet->setCellValue('K1', 'Profit'); $sheet->setCellValue('L1', 'Spend'); $ad_groups_status = [ 0 => 'UNSPECIFIED', // UNSPECIFIED 1 => 'UNKNOWN', // UNKNOWN 2 => 'ENABLED', // ENABLED 3 => 'PAUSED', // PAUSED 4 => 'REMOVED', // REMOVED ]; // 填充数据 $row = 2; foreach ($ad_groups as $adGroup) { // 使用 setCellValueExplicit 显式设置为文本格式 $sheet->setCellValueExplicit('A' . $row, (string)$adGroup->ad_group_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); // 设置为文本格式 // $sheet->setCellValueExplicit('B' . $row, (string)$adGroup->campaign_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); $sheet->setCellValue('B' . $row, $ad_groups_status[$adGroup->ad_group_status]); $sheet->setCellValue('C' . $row, $adGroup->ad_group_name); $sheet->setCellValue('D' . $row, $adGroup->campaign_name); $sheet->setCellValue('E' . $row, $adGroup->delivery); // 直接设置 ad_name $sheet->setCellValue('F' . $row, $adGroup->results); $sheet->setCellValue('G' . $row, $adGroup->reach); $sheet->setCellValue('H' . $row, $adGroup->revenue); $sheet->setCellValue('I' . $row, $adGroup->roas); $sheet->setCellValue('J' . $row, $adGroup->be_roas); $sheet->setCellValue('K' . $row, $adGroup->profit); $sheet->setCellValue('L' . $row, $adGroup->spend); // $sheet->setCellValueExplicit('M' . $row, (string)$adGroup->customer_id, \PhpOffice\PhpSpreadsheet\Cell\DataType::TYPE_STRING); $row++; } // 自动调整所有列宽 foreach (range('A', 'H') as $column) { $spreadsheet->getActiveSheet()->getColumnDimension($column)->setAutoSize(true); } // 设置 Excel 文件名 $fileName = 'AdGroup_Report_' . $dateRange . '_' . date('Y-m-d_H-i-s') . '.xlsx'; // 创建 Excel 文件并保存 $writer = new Xlsx($spreadsheet); $filePath = public_path() . '/' . $fileName; try { $writer->save($filePath); return response()->download($filePath, $fileName); // return ['success' => true, 'file_path' => $filePath]; } catch (\Exception $e) { return ['' => false, 'message' => $e->getMessage()]; } } }