chore: init saasshop repo + sql migrations runner + gitee go
This commit is contained in:
228
app/Http/Controllers/SiteAdmin/MerchantController.php
Normal file
228
app/Http/Controllers/SiteAdmin/MerchantController.php
Normal file
@@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\SiteAdmin;
|
||||
|
||||
use App\Http\Controllers\Concerns\ResolvesSiteContext;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Merchant;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\View\View;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class MerchantController extends Controller
|
||||
{
|
||||
use ResolvesSiteContext;
|
||||
|
||||
public function index(Request $request): View
|
||||
{
|
||||
$site = $this->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 => '最近激活优先',
|
||||
};
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user