siteId($request); $site = $this->site($request); $filters = $this->filters($request); $statusStatsFilters = $filters; $statusStatsFilters['status'] = ''; if ($filters['has_validation_error'] ?? false) { return view('site_admin.products.index', [ 'site' => $site, 'products' => Product::query()->whereRaw('1 = 0')->paginate(10)->withQueryString(), 'summaryStats' => $this->emptySummaryStats(), 'statusStats' => $this->emptyStatusStats(), 'activeFilterSummary' => $this->buildActiveFilterSummary($filters), 'operationsFocus' => $this->buildOperationsFocus($siteId, $this->emptySummaryStats(), $filters), 'workbenchLinks' => $this->workbenchLinks(), 'filters' => $filters, 'statusLabels' => $this->statusLabels(), 'filterOptions' => [ 'statuses' => $this->statusOptions, 'sortOptions' => [ 'latest' => '最新创建', 'price_asc' => '价格从低到高', 'price_desc' => '价格从高到低', 'stock_asc' => '库存从低到高', 'stock_desc' => '库存从高到低', ], ], 'categories' => ProductCategory::query()->forMerchant($siteId)->orderBy('sort')->orderBy('id')->get(), ]); } $summaryStats = $this->buildSummaryStats( $this->applyFilters(Product::query()->forMerchant($siteId), $statusStatsFilters) ); return view('site_admin.products.index', [ 'site' => $site, 'products' => $this->applySorting( $this->applyFilters(Product::query()->with('category')->forMerchant($siteId), $filters), $filters )->paginate(10)->withQueryString(), 'summaryStats' => $summaryStats, 'statusStats' => $this->buildStatusStats( $this->applyFilters(Product::query()->forMerchant($siteId), $statusStatsFilters) ), 'activeFilterSummary' => $this->buildActiveFilterSummary($filters), 'operationsFocus' => $this->buildOperationsFocus($siteId, $summaryStats, $filters), 'workbenchLinks' => $this->workbenchLinks(), 'filters' => $filters, 'statusLabels' => $this->statusLabels(), 'filterOptions' => [ 'statuses' => $this->statusOptions, 'sortOptions' => [ 'latest' => '最新创建', 'price_asc' => '价格从低到高', 'price_desc' => '价格从高到低', 'stock_asc' => '库存从低到高', 'stock_desc' => '库存从高到低', ], ], 'categories' => ProductCategory::query()->forMerchant($siteId)->orderBy('sort')->orderBy('id')->get(), ]); } public function export(Request $request): StreamedResponse|RedirectResponse { $siteId = $this->siteId($request); $filters = $this->filters($request); if ($filters['has_validation_error'] ?? false) { return redirect('/site-admin/products?' . http_build_query($this->exportableFilters($filters))) ->withErrors($filters['validation_errors'] ?? ['商品筛选条件不合法,请先修正后再导出。']); } $fileName = 'site_' . $siteId . '_products_' . now()->format('Ymd_His') . '.csv'; $exportSummary = $this->buildSummaryStats( $this->applyFilters(Product::query()->forMerchant($siteId), $filters) ); return response()->streamDownload(function () use ($siteId, $filters, $exportSummary) { $handle = fopen('php://output', 'w'); fwrite($handle, "\xEF\xBB\xBF"); fputcsv($handle, ['导出信息', '站点商品导出']); fputcsv($handle, ['站点ID', $siteId]); fputcsv($handle, ['关键词', $filters['keyword'] !== '' ? $filters['keyword'] : '全部']); fputcsv($handle, ['状态', $this->statusLabel($filters['status'] ?? '')]); fputcsv($handle, ['分类', $this->categoryLabel($filters['category_id'] ?? '')]); fputcsv($handle, ['最低价格', $filters['min_price'] !== '' && is_numeric($filters['min_price']) ? ('¥' . number_format((float) $filters['min_price'], 2, '.', '')) : '全部']); fputcsv($handle, ['最高价格', $filters['max_price'] !== '' && is_numeric($filters['max_price']) ? ('¥' . number_format((float) $filters['max_price'], 2, '.', '')) : '全部']); fputcsv($handle, ['最低库存', $filters['min_stock'] !== '' ? ($filters['min_stock'] . ' 件') : '全部']); fputcsv($handle, ['最高库存', $filters['max_stock'] !== '' ? ($filters['max_stock'] . ' 件') : '全部']); fputcsv($handle, ['排序', $this->sortLabel($filters['sort'] ?? 'latest')]); fputcsv($handle, ['导出商品数', $exportSummary['total_products'] ?? 0]); fputcsv($handle, ['导出总库存', $exportSummary['total_stock'] ?? 0]); fputcsv($handle, ['导出总货值', number_format((float) ($exportSummary['total_stock_value'] ?? 0), 2, '.', '')]); fputcsv($handle, ['导出平均售价', number_format((float) ($exportSummary['average_price'] ?? 0), 2, '.', '')]); fputcsv($handle, []); fputcsv($handle, [ 'ID', '分类ID', '分类名称', '商品标题', '商品Slug', 'SKU', '售价', '划线价', '库存', '状态', '商品简介', '创建时间', '更新时间', ]); foreach ($this->applySorting($this->applyFilters(Product::query()->with('category')->forMerchant($siteId), $filters), $filters)->cursor() as $product) { fputcsv($handle, [ $product->id, $product->category_id, $product->category?->name ?? '', $product->title, $product->slug, $product->sku, number_format((float) $product->price, 2, '.', ''), number_format((float) $product->original_price, 2, '.', ''), $product->stock, $this->statusLabel($product->status), $product->summary, optional($product->created_at)?->format('Y-m-d H:i:s'), optional($product->updated_at)?->format('Y-m-d H:i:s'), ]); } fclose($handle); }, $fileName, [ 'Content-Type' => 'text/csv; charset=UTF-8', ]); } protected function filters(Request $request): array { $minPrice = trim((string) $request->string('min_price')); $maxPrice = trim((string) $request->string('max_price')); $minStock = trim((string) $request->string('min_stock')); $maxStock = trim((string) $request->string('max_stock')); $validationErrors = []; if ($minPrice !== '' && ! is_numeric($minPrice)) { $validationErrors[] = '最低价格必须为数字。'; } if ($maxPrice !== '' && ! is_numeric($maxPrice)) { $validationErrors[] = '最高价格必须为数字。'; } if ($minPrice !== '' && $maxPrice !== '' && is_numeric($minPrice) && is_numeric($maxPrice) && (float) $minPrice > (float) $maxPrice) { $validationErrors[] = '最低价格不能大于最高价格。'; } if ($minStock !== '' && filter_var($minStock, FILTER_VALIDATE_INT) === false) { $validationErrors[] = '最低库存必须为整数。'; } if ($maxStock !== '' && filter_var($maxStock, FILTER_VALIDATE_INT) === false) { $validationErrors[] = '最高库存必须为整数。'; } if ($minStock !== '' && $maxStock !== '' && filter_var($minStock, FILTER_VALIDATE_INT) !== false && filter_var($maxStock, FILTER_VALIDATE_INT) !== false && (int) $minStock > (int) $maxStock) { $validationErrors[] = '最低库存不能大于最高库存。'; } return [ 'keyword' => trim((string) $request->string('keyword')), 'status' => trim((string) $request->string('status')), 'category_id' => trim((string) $request->string('category_id')), 'min_price' => $minPrice, 'max_price' => $maxPrice, 'min_stock' => $minStock, 'max_stock' => $maxStock, 'sort' => trim((string) $request->string('sort', 'latest')), 'validation_errors' => $validationErrors, 'has_validation_error' => ! empty($validationErrors), ]; } protected function applyFilters(Builder $query, array $filters): Builder { return $query ->when(($filters['keyword'] ?? '') !== '', fn ($builder) => $builder->where(function ($subQuery) use ($filters) { $subQuery->where('title', 'like', '%' . $filters['keyword'] . '%') ->orWhere('sku', 'like', '%' . $filters['keyword'] . '%') ->orWhere('slug', 'like', '%' . $filters['keyword'] . '%'); })) ->when(($filters['status'] ?? '') !== '', fn ($builder) => $builder->where('status', $filters['status'])) ->when(($filters['category_id'] ?? '') !== '', fn ($builder) => $builder->where('category_id', $filters['category_id'])) ->when(($filters['min_price'] ?? '') !== '' && is_numeric($filters['min_price']), fn ($builder) => $builder->where('price', '>=', $filters['min_price'])) ->when(($filters['max_price'] ?? '') !== '' && is_numeric($filters['max_price']), fn ($builder) => $builder->where('price', '<=', $filters['max_price'])) ->when(($filters['min_stock'] ?? '') !== '' && filter_var($filters['min_stock'], FILTER_VALIDATE_INT) !== false, fn ($builder) => $builder->where('stock', '>=', (int) $filters['min_stock'])) ->when(($filters['max_stock'] ?? '') !== '' && filter_var($filters['max_stock'], FILTER_VALIDATE_INT) !== false, fn ($builder) => $builder->where('stock', '<=', (int) $filters['max_stock'])); } protected function applySorting(Builder $query, array $filters): Builder { return match ($filters['sort'] ?? 'latest') { 'price_asc' => $query->orderBy('price')->orderByDesc('id'), 'price_desc' => $query->orderByDesc('price')->orderByDesc('id'), 'stock_asc' => $query->orderBy('stock')->orderByDesc('id'), 'stock_desc' => $query->orderByDesc('stock')->orderByDesc('id'), default => $query->latest(), }; } protected function buildSummaryStats(Builder $query): array { $summary = (clone $query) ->selectRaw('COUNT(*) as total_products') ->selectRaw('COALESCE(SUM(stock), 0) as total_stock') ->selectRaw('COALESCE(SUM(price * stock), 0) as total_stock_value') ->selectRaw('COALESCE(AVG(price), 0) as average_price') ->first(); return [ 'total_products' => (int) ($summary->total_products ?? 0), 'total_stock' => (int) ($summary->total_stock ?? 0), 'total_stock_value' => (float) ($summary->total_stock_value ?? 0), 'average_price' => (float) ($summary->average_price ?? 0), ]; } protected function buildStatusStats(Builder $query): array { $counts = (clone $query) ->selectRaw('status, COUNT(*) as aggregate') ->groupBy('status') ->pluck('aggregate', 'status'); $stats = ['all' => (int) $counts->sum()]; foreach ($this->statusOptions as $status) { $stats[$status] = (int) ($counts[$status] ?? 0); } return $stats; } protected function emptySummaryStats(): array { return [ 'total_products' => 0, 'total_stock' => 0, 'total_stock_value' => 0, 'average_price' => 0, ]; } protected function emptyStatusStats(): array { $stats = ['all' => 0]; foreach ($this->statusOptions as $status) { $stats[$status] = 0; } return $stats; } protected function exportableFilters(array $filters): array { return [ 'keyword' => $filters['keyword'] ?? '', 'status' => $filters['status'] ?? '', 'category_id' => $filters['category_id'] ?? '', 'min_price' => $filters['min_price'] ?? '', 'max_price' => $filters['max_price'] ?? '', 'min_stock' => $filters['min_stock'] ?? '', 'max_stock' => $filters['max_stock'] ?? '', 'sort' => $filters['sort'] ?? 'latest', ]; } protected function buildActiveFilterSummary(array $filters): array { return [ '关键词' => $this->displayTextValue($filters['keyword'] ?? '', '全部'), '状态' => $this->statusLabel($filters['status'] ?? ''), '分类' => $this->categoryLabel($filters['category_id'] ?? ''), '价格区间' => $this->formatMoneyRange($filters['min_price'] ?? '', $filters['max_price'] ?? ''), '库存区间' => $this->formatStockRange($filters['min_stock'] ?? '', $filters['max_stock'] ?? ''), '排序' => $this->sortLabel($filters['sort'] ?? 'latest'), ]; } protected function statusLabels(): array { return [ 'draft' => '草稿', 'published' => '已上架', 'offline' => '已下架', ]; } protected function statusLabel(string $status): string { return $this->statusLabels()[$status] ?? '全部'; } protected function categoryLabel(string $categoryId): string { if ($categoryId === '') { return '全部'; } $category = ProductCategory::query()->find($categoryId); return $category?->name ?? ('分类 #' . $categoryId); } protected function formatMoneyRange(string $min, string $max): string { if ($min === '' && $max === '') { return '全部'; } $minLabel = $min !== '' && is_numeric($min) ? ('¥' . number_format((float) $min, 2, '.', '')) : '不限'; $maxLabel = $max !== '' && is_numeric($max) ? ('¥' . number_format((float) $max, 2, '.', '')) : '不限'; return $minLabel . ' ~ ' . $maxLabel; } protected function formatStockRange(string $min, string $max): string { if ($min === '' && $max === '') { return '全部'; } $minLabel = $min !== '' ? $min : '不限'; $maxLabel = $max !== '' ? $max : '不限'; return $minLabel . ' ~ ' . $maxLabel . ' 件'; } protected function sortLabel(string $sort): string { return match ($sort) { 'price_asc' => '价格从低到高', 'price_desc' => '价格从高到低', 'stock_asc' => '库存从低到高', 'stock_desc' => '库存从高到低', default => '最新创建', }; } protected function displayTextValue(string $value, string $default = '未设置'): string { return $value === '' ? $default : $value; } protected function displayMoneyValue(string $value): string { if ($value === '') { return '全部'; } return is_numeric($value) ? ('¥' . number_format((float) $value, 2, '.', '')) : $value; } protected function displayStockValue(string $value): string { return $value === '' ? '全部' : ($value . ' 件'); } protected function workbenchLinks(): array { return [ 'published_stock_desc' => '/site-admin/products?sort=stock_desc&status=published', 'published_stock_asc' => '/site-admin/products?sort=stock_asc&status=published', 'latest' => '/site-admin/products?sort=latest', 'draft' => '/site-admin/products?status=draft&sort=latest', 'current' => '/site-admin/products', ]; } protected function hasCategoryFilter(array $filters): bool { return ($filters['category_id'] ?? '') !== ''; } protected function hasKeywordFilter(array $filters): bool { return ($filters['keyword'] ?? '') !== ''; } protected function hasPriceRangeFilter(array $filters): bool { return (($filters['min_price'] ?? '') !== '') || (($filters['max_price'] ?? '') !== ''); } protected function hasPublishedStockFocus(array $filters): bool { return ($filters['status'] ?? '') === 'published' && ((($filters['max_stock'] ?? '') !== '') || ((($filters['min_stock'] ?? '') !== '') && is_numeric($filters['min_stock']) && (int) $filters['min_stock'] <= 20)); } protected function buildOperationsFocusResponse(string $headline, array $actions, array $workbench, array $signals): array { return [ 'headline' => $headline, 'actions' => $actions, 'workbench' => $workbench, 'signals' => $signals, ]; } protected function buildOperationsFocus(int $siteId, array $summaryStats, array $filters): array { $publishedCount = (int) Product::query()->forMerchant($siteId)->where('status', 'published')->count(); $lowStockCount = (int) Product::query()->forMerchant($siteId)->where('status', 'published')->where('stock', '<=', 20)->count(); $categoryCount = (int) ProductCategory::query()->forMerchant($siteId)->count(); $links = $this->workbenchLinks(); $currentQuery = http_build_query(array_filter($this->exportableFilters($filters), fn ($value) => $value !== null && $value !== '')); $currentUrl = $links['current'] . ($currentQuery !== '' ? ('?' . $currentQuery) : ''); $workbench = [ '高库存已上架' => $links['published_stock_desc'], '低库存补货' => $links['published_stock_asc'], '最近新增' => $links['latest'], '草稿待整理' => $links['draft'], '返回当前筛选视图' => $currentUrl, ]; $signals = [ '已上架商品' => $publishedCount, '低库存商品' => $lowStockCount, '分类覆盖数' => $categoryCount, ]; $isPublished = ($filters['status'] ?? '') === 'published'; $hasCategoryFilter = $this->hasCategoryFilter($filters); $hasKeywordFilter = $this->hasKeywordFilter($filters); $hasPriceRangeFilter = $this->hasPriceRangeFilter($filters); $categoryLabel = $hasCategoryFilter ? $this->categoryLabel((string) ($filters['category_id'] ?? '')) : ''; $keyword = (string) ($filters['keyword'] ?? ''); $priceRange = $hasPriceRangeFilter ? $this->formatMoneyRange((string) ($filters['min_price'] ?? ''), (string) ($filters['max_price'] ?? '')) : ''; $categoryUrl = $links['current'] . '?category_id=' . ($filters['category_id'] ?? ''); $categoryKeywordUrl = $categoryUrl . '&keyword=' . urlencode($keyword); $publishedCategoryUrl = $links['current'] . '?status=published&category_id=' . ($filters['category_id'] ?? ''); $publishedKeywordUrl = $links['current'] . '?status=published&keyword=' . urlencode($keyword); $publishedCategoryKeywordUrl = $publishedCategoryUrl . '&keyword=' . urlencode($keyword); if (($filters['status'] ?? '') === 'draft') { return $this->buildOperationsFocusResponse( '当前正在查看草稿商品,建议优先补齐标题、分类、价格与库存后再安排上架。', [ ['label' => '继续查看当前草稿', 'url' => $currentUrl], ['label' => '去看已上架商品', 'url' => $links['published_stock_desc']], ], $workbench, $signals, ); } if ($this->hasPublishedStockFocus($filters)) { return $this->buildOperationsFocusResponse( '当前筛选已聚焦已上架库存视角,建议优先确认低库存补货节奏,并同步观察高库存结构是否健康。', [ ['label' => '继续查看当前库存视角', 'url' => $currentUrl], ['label' => '去看高库存商品', 'url' => $links['published_stock_desc']], ], $workbench, $signals, ); } if ($isPublished && $hasCategoryFilter && $hasKeywordFilter && $hasPriceRangeFilter) { return [ 'headline' => '当前筛选已聚焦已上架的“' . $categoryLabel . '”分类下关键词“' . $keyword . '”命中的价格带 ' . $priceRange . ' 商品,建议优先核对在售商品命名、分类承接、价格梯度与搜索结果是否一致,并同步观察库存结构是否健康。', 'actions' => [ ['label' => '继续查看当前已上架分类关键词价格带商品', 'url' => $currentUrl], ['label' => '去看当前已上架分类关键词商品', 'url' => $publishedCategoryKeywordUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($isPublished && $hasCategoryFilter && $hasKeywordFilter) { return [ 'headline' => '当前筛选已聚焦已上架的“' . $categoryLabel . '”分类下关键词“' . $keyword . '”命中的商品,建议优先核对在售商品命名、分类承接与搜索结果是否一致,并同步观察价格带与库存结构是否健康。', 'actions' => [ ['label' => '继续查看当前已上架分类关键词商品', 'url' => $currentUrl], ['label' => '去看当前已上架分类商品', 'url' => $publishedCategoryUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($isPublished && $hasCategoryFilter && $hasPriceRangeFilter) { return [ 'headline' => '当前筛选已聚焦已上架的“' . $categoryLabel . '”分类下价格带 ' . $priceRange . ' 商品,建议优先核对该分类在售商品的价格结构、库存分布与承接效率是否协调。', 'actions' => [ ['label' => '继续查看当前已上架分类价格带商品', 'url' => $currentUrl], ['label' => '去看当前已上架分类商品', 'url' => $publishedCategoryUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($isPublished && $hasKeywordFilter && $hasPriceRangeFilter) { return [ 'headline' => '当前筛选已聚焦已上架商品中关键词“' . $keyword . '”命中的价格带 ' . $priceRange . ' 结果,建议优先核对在售商品命名、卖点表达与价格梯度是否一致,并同步观察库存结构与搜索承接是否健康。', 'actions' => [ ['label' => '继续查看当前已上架关键词价格带商品', 'url' => $currentUrl], ['label' => '去看当前已上架关键词商品', 'url' => $publishedKeywordUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($isPublished && $hasKeywordFilter) { return [ 'headline' => '当前筛选已聚焦已上架商品中关键词“' . $keyword . '”命中的结果,建议优先核对在售商品命名、卖点表达与搜索承接是否一致,并同步观察价格带与库存结构是否健康。', 'actions' => [ ['label' => '继续查看当前已上架关键词商品', 'url' => $currentUrl], ['label' => '去看全部已上架商品', 'url' => $links['published_stock_desc']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($hasCategoryFilter && $hasKeywordFilter && $hasPriceRangeFilter) { return [ 'headline' => '当前筛选已聚焦“' . $categoryLabel . '”分类下关键词“' . $keyword . '”命中的价格带 ' . $priceRange . ' 商品,建议优先核对分类承接、命名卖点与价格梯度是否一致,并同步观察库存结构与搜索承接是否健康。', 'actions' => [ ['label' => '继续查看当前分类关键词价格带商品', 'url' => $currentUrl], ['label' => '去看当前分类关键词商品', 'url' => $categoryKeywordUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($hasCategoryFilter && $hasKeywordFilter) { return [ 'headline' => '当前筛选已聚焦“' . $categoryLabel . '”分类下关键词“' . $keyword . '”命中的商品,建议优先核对分类承接、命名卖点与搜索结果是否一致,并同步观察相关商品的价格带与库存结构。', 'actions' => [ ['label' => '继续查看当前分类关键词商品', 'url' => $currentUrl], ['label' => '去看当前分类商品', 'url' => $categoryUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($hasCategoryFilter && $hasPriceRangeFilter) { return [ 'headline' => '当前筛选已聚焦“' . $categoryLabel . '”分类下价格带 ' . $priceRange . ' 商品,建议优先核对该分类价格结构是否连贯,并同步观察库存分布与承接效率是否健康。', 'actions' => [ ['label' => '继续查看当前分类价格带商品', 'url' => $currentUrl], ['label' => '去看当前分类商品', 'url' => $categoryUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($isPublished && $hasCategoryFilter) { return [ 'headline' => '当前筛选已聚焦已上架的“' . $categoryLabel . '”分类商品,建议优先核对该分类在售商品的价格带、库存结构与承接质量是否均衡。', 'actions' => [ ['label' => '继续查看当前已上架分类商品', 'url' => $currentUrl], ['label' => '去看当前分类商品', 'url' => $categoryUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($hasCategoryFilter) { return [ 'headline' => '当前筛选已聚焦“' . $categoryLabel . '”分类商品,建议优先核对分类承接是否准确,并同步观察价格带与库存结构是否均衡。', 'actions' => [ ['label' => '继续查看当前分类商品', 'url' => $currentUrl], ['label' => '去看低库存商品', 'url' => $links['published_stock_asc']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($hasKeywordFilter) { return [ 'headline' => '当前筛选已聚焦关键词“' . $keyword . '”命中的商品,建议优先核对命名、卖点与搜索承接是否一致,并同步观察相关商品的价格带与库存结构。', 'actions' => [ ['label' => '继续查看当前关键词商品', 'url' => $currentUrl], ['label' => '去看最近新增商品', 'url' => $links['latest']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($hasPriceRangeFilter) { return [ 'headline' => '当前筛选已聚焦价格带 ' . $priceRange . ' 商品,建议优先核对定价梯度是否连贯,并同步观察库存结构与转化表现是否匹配。', 'actions' => [ ['label' => '继续查看当前价格带商品', 'url' => $currentUrl], ['label' => '去看最近新增商品', 'url' => $links['latest']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if ($isPublished) { return [ 'headline' => '当前正在查看已上架商品,建议优先关注库存结构、价格带与分类覆盖是否均衡。', 'actions' => [ ['label' => '去看低库存商品', 'url' => $links['published_stock_asc']], ['label' => '继续查看已上架商品', 'url' => $currentUrl], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if (($summaryStats['total_products'] ?? 0) <= 0) { return [ 'headline' => '当前站点暂无商品,建议先补齐基础商品数据,再开始做上架与库存运营。', 'actions' => [ ['label' => '先看商品空白情况', 'url' => $links['latest']], ['label' => '查看草稿商品', 'url' => $links['draft']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } if (($summaryStats['total_products'] ?? 0) < 3) { return [ 'headline' => '当前站点商品仍较少,建议优先查看最近新增与已上架商品,确认基础信息是否完整。', 'actions' => [ ['label' => '去看最近新增商品', 'url' => $links['latest']], ['label' => '去看已上架商品', 'url' => $links['published_stock_desc']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } return [ 'headline' => $lowStockCount > 0 ? '当前站点商品已形成基础规模,建议优先巡检低库存商品,并同步关注高库存结构是否均衡。' : '当前站点商品已形成基础规模,建议优先关注高库存结构与最近新增商品质量。', 'actions' => $lowStockCount > 0 ? [ ['label' => '去看低库存商品', 'url' => $links['published_stock_asc']], ['label' => '去看高库存商品', 'url' => $links['published_stock_desc']], ] : [ ['label' => '去看高库存商品', 'url' => $links['published_stock_desc']], ['label' => '去看最近新增商品', 'url' => $links['latest']], ], 'workbench' => $workbench, 'signals' => $signals, ]; } }