site($request); $filters = $this->filters($request); $query = $this->applySorting( $this->applyFilters( Merchant::query() ->withCount(['admins', 'users', 'products', 'orders', 'categories']) ->whereKey($site->id), $filters ), $filters ); $merchants = $query->get(); $summaryStats = $this->buildSummaryStats($site); return view('site_admin.merchants.index', [ 'site' => $site, 'merchants' => $merchants, 'filters' => $filters, 'activeFilterSummary' => $this->buildActiveFilterSummary($filters), 'summaryStats' => $summaryStats, 'statusLabels' => $this->statusLabels(), 'planLabels' => $this->planLabels(), 'filterOptions' => [ 'statuses' => array_keys($this->statusLabels()), 'plans' => array_keys($this->planLabels()), 'sortOptions' => [ 'latest' => '最近激活优先', 'name_asc' => '名称 A-Z', 'name_desc' => '名称 Z-A', ], ], ]); } public function export(Request $request): StreamedResponse { $site = $this->site($request); $filters = $this->filters($request); $merchants = $this->applySorting( $this->applyFilters( Merchant::query() ->withCount(['admins', 'users', 'products', 'orders', 'categories']) ->whereKey($site->id), $filters ), $filters )->get(); $summaryStats = $this->buildSummaryStats($site); $fileName = 'site_' . $site->id . '_merchants_' . now()->format('Ymd_His') . '.csv'; return response()->streamDownload(function () use ($site, $filters, $merchants, $summaryStats) { $handle = fopen('php://output', 'w'); fwrite($handle, "\xEF\xBB\xBF"); fputcsv($handle, ['导出信息', '站点商家导出']); fputcsv($handle, ['站点ID', $site->id]); fputcsv($handle, ['站点名称', $site->name]); fputcsv($handle, ['关键词', ($filters['keyword'] ?? '') !== '' ? $filters['keyword'] : '全部']); fputcsv($handle, ['状态', $this->statusLabel($filters['status'] ?? '')]); fputcsv($handle, ['套餐', $this->planLabel($filters['plan'] ?? '')]); fputcsv($handle, ['排序', $this->sortLabel($filters['sort'] ?? 'latest')]); fputcsv($handle, ['承接站点数', $summaryStats['site_count'] ?? 0]); fputcsv($handle, ['启用中站点', $summaryStats['active_site_count'] ?? 0]); fputcsv($handle, ['站点管理员数', $summaryStats['admin_count'] ?? 0]); fputcsv($handle, ['站点用户数', $summaryStats['user_count'] ?? 0]); fputcsv($handle, ['站点商品数', $summaryStats['product_count'] ?? 0]); fputcsv($handle, ['站点订单数', $summaryStats['order_count'] ?? 0]); fputcsv($handle, ['商品分类数', $summaryStats['category_count'] ?? 0]); fputcsv($handle, []); fputcsv($handle, ['当前站点资料', '']); fputcsv($handle, ['站点标识', $site->slug]); fputcsv($handle, ['当前状态', $this->statusLabel((string) $site->status)]); fputcsv($handle, ['当前套餐', $this->planLabel((string) $site->plan)]); fputcsv($handle, ['联系人', $site->contact_name ?: '未设置']); fputcsv($handle, ['联系电话', $site->contact_phone ?: '未设置']); fputcsv($handle, ['联系邮箱', $site->contact_email ?: '未设置']); fputcsv($handle, ['激活时间', $site->activated_at?->format('Y-m-d H:i:s') ?? '未激活']); fputcsv($handle, []); fputcsv($handle, ['ID', '名称', 'Slug', '状态', '套餐', '联系人', '联系电话', '联系邮箱', '管理员数', '用户数', '商品数', '订单数', '商品分类数', '激活时间']); foreach ($merchants as $merchant) { fputcsv($handle, [ $merchant->id, $merchant->name, $merchant->slug, $this->statusLabel((string) $merchant->status), $this->planLabel((string) $merchant->plan), $merchant->contact_name ?: '未设置', $merchant->contact_phone ?: '未设置', $merchant->contact_email ?: '未设置', $merchant->admins_count ?? 0, $merchant->users_count ?? 0, $merchant->products_count ?? 0, $merchant->orders_count ?? 0, $merchant->categories_count ?? 0, $merchant->activated_at?->format('Y-m-d H:i:s') ?? '未激活', ]); } fclose($handle); }, $fileName, [ 'Content-Type' => 'text/csv; charset=UTF-8', ]); } protected function filters(Request $request): array { return [ 'keyword' => trim((string) $request->string('keyword')), 'status' => trim((string) $request->string('status')), 'plan' => trim((string) $request->string('plan')), 'sort' => trim((string) $request->string('sort', 'latest')), ]; } protected function applyFilters(Builder $query, array $filters): Builder { return $query ->when(($filters['status'] ?? '') !== '', fn ($builder) => $builder->where('status', $filters['status'])) ->when(($filters['plan'] ?? '') !== '', fn ($builder) => $builder->where('plan', $filters['plan'])) ->when(($filters['keyword'] ?? '') !== '', function ($builder) use ($filters) { $keyword = $filters['keyword']; $builder->where(function ($subQuery) use ($keyword) { $subQuery->where('name', 'like', '%' . $keyword . '%') ->orWhere('slug', 'like', '%' . $keyword . '%') ->orWhere('contact_name', 'like', '%' . $keyword . '%') ->orWhere('contact_phone', 'like', '%' . $keyword . '%') ->orWhere('contact_email', 'like', '%' . $keyword . '%'); }); }); } protected function applySorting(Builder $query, array $filters): Builder { return match ($filters['sort'] ?? 'latest') { 'name_asc' => $query->orderBy('name')->orderBy('id'), 'name_desc' => $query->orderByDesc('name')->orderByDesc('id'), default => $query->orderByDesc('activated_at')->orderByDesc('id'), }; } protected function buildSummaryStats(Merchant $site): array { $site->loadCount(['admins', 'users', 'products', 'orders', 'categories']); return [ 'site_count' => 1, 'active_site_count' => $site->status === 'active' ? 1 : 0, 'admin_count' => (int) ($site->admins_count ?? 0), 'user_count' => (int) ($site->users_count ?? 0), 'product_count' => (int) ($site->products_count ?? 0), 'order_count' => (int) ($site->orders_count ?? 0), 'category_count' => (int) ($site->categories_count ?? 0), ]; } protected function buildActiveFilterSummary(array $filters): array { return [ '关键词' => ($filters['keyword'] ?? '') !== '' ? $filters['keyword'] : '全部', '状态' => $this->statusLabel($filters['status'] ?? ''), '套餐' => $this->planLabel($filters['plan'] ?? ''), '排序' => $this->sortLabel($filters['sort'] ?? 'latest'), ]; } protected function statusLabels(): array { return [ 'active' => '启用中', 'inactive' => '未启用', 'suspended' => '已停用', ]; } protected function statusLabel(string $status): string { return $this->statusLabels()[$status] ?? '全部'; } protected function planLabels(): array { return [ 'basic' => '基础版', 'pro' => '专业版', 'enterprise' => '企业版', ]; } protected function planLabel(string $plan): string { return $this->planLabels()[$plan] ?? (($plan === '') ? '全部' : $plan); } protected function sortLabel(string $sort): string { return match ($sort) { 'name_asc' => '名称 A-Z', 'name_desc' => '名称 Z-A', default => '最近激活优先', }; } }