WaterContentDashboard.php 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. <?php
  2. declare(strict_types=1);
  3. namespace plugin\saiadmin\app\service;
  4. use plugin\saiadmin\app\model\water\{WaterModel, WaterContent, WaterPackage};
  5. use plugin\saiadmin\app\service\content\{ContentInput, ContentPolicy};
  6. use plugin\saiadmin\exception\ApiException;
  7. /** Administrative content queries and simulated audience preview, not a public mobile API. */
  8. final class WaterContentDashboard
  9. {
  10. private readonly string $now;
  11. public function __construct(?\DateTimeImmutable $now = null)
  12. {
  13. $this->now = ($now ?? new \DateTimeImmutable())->setTimezone(new \DateTimeZone('Asia/Shanghai'))->format('Y-m-d H:i:s');
  14. }
  15. private function present(array $row): array
  16. {
  17. foreach (['id', 'sort', 'status'] as $field) $row[$field] = (int)$row[$field];
  18. $row['delivery_status'] = ContentPolicy::status($row, $this->now);
  19. $row['status_label'] = ContentPolicy::LABELS[$row['delivery_status']];
  20. return $row;
  21. }
  22. private function packages(): array
  23. {
  24. return WaterPackage::query()->alias('p')->join('sa_water_sku as s', 's.id', '=', 'p.sku_id')
  25. ->where('p.status', 1)->where('s.status', 1)->orderByDesc('p.id')->limit(3)
  26. ->get(['p.id', 'p.name', 'p.buckets', 'p.price_cents', 's.name as sku_name'])
  27. ->map(function ($row) {
  28. $data = $row->toArray();
  29. foreach (['id', 'buckets', 'price_cents'] as $field) $data[$field] = (int)$data[$field];
  30. return $data;
  31. })->all();
  32. }
  33. public function dashboard(array $input): array
  34. {
  35. $keyword = ContentInput::text($input, 'keyword', 120);
  36. $status = ContentInput::text($input, 'status', 20);
  37. if ($status !== '' && !isset(ContentPolicy::LABELS[$status])) throw new ApiException('投放状态不正确');
  38. $page = ContentInput::integer($input, 'page', 1, 1, 1000000);
  39. $limit = ContentInput::integer($input, 'limit', 8, 1, 100);
  40. return WaterModel::transaction(function () use ($keyword, $status, $page, $limit) {
  41. $query = ContentPolicy::filter(WaterContent::query(), $status, $this->now);
  42. if ($keyword !== '') $query->matching('title|region', '%'.$keyword.'%');
  43. $list = $query->orderByDesc('sort')->orderByDesc('id')->pageResult($page, $limit);
  44. $list['data'] = array_map($this->present(...), $list['data']);
  45. $summary = ['total' => WaterContent::query()->count()];
  46. foreach (ContentPolicy::LABELS as $key => $label) {
  47. $summary[$key] = ContentPolicy::filter(WaterContent::query(), $key, $this->now)->count();
  48. }
  49. return ['list' => $list, 'summary' => $summary, 'packages' => $this->packages(), 'updated_at' => $this->now];
  50. });
  51. }
  52. public function preview(array $input): array
  53. {
  54. $purchase = ContentInput::text($input, 'purchase_status', 20, 'new');
  55. if (!in_array($purchase, ['new', 'purchased'], true)) throw new ApiException('预览购水状态不正确');
  56. $admin = ContentInput::integer($input, 'is_enterprise_admin', 0, 0, 1);
  57. $region = ContentInput::text($input, 'region', 80);
  58. if ($region === '全国') $region = '';
  59. $audiences = ['all', $purchase];
  60. if ($admin) $audiences[] = 'enterprise_admin';
  61. return WaterModel::transaction(function () use ($purchase, $admin, $region, $audiences) {
  62. $query = ContentPolicy::filter(WaterContent::query(), 'active', $this->now)
  63. ->whereIn('audience', $audiences)
  64. ->where(fn ($q) => $q->whereNull('region')->orWhere('region', '')->orWhere('region', '全国')->orWhere('region', $region));
  65. $total = (clone $query)->count();
  66. $rows = $query->orderByDesc('sort')->orderByDesc('id')->limit(20)->get()->toArray();
  67. return ['banners' => array_map($this->present(...), $rows), 'total' => $total,
  68. 'packages' => $this->packages(), 'context' => ['purchase_status' => $purchase, 'is_enterprise_admin' => $admin, 'region' => $region],
  69. 'updated_at' => $this->now];
  70. });
  71. }
  72. }