| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- <?php
- declare(strict_types=1);
- namespace plugin\saiadmin\app\service;
- use plugin\saiadmin\app\model\water\{WaterModel, WaterContent, WaterPackage};
- use plugin\saiadmin\app\service\content\{ContentInput, ContentPolicy};
- use plugin\saiadmin\exception\ApiException;
- /** Administrative content queries and simulated audience preview, not a public mobile API. */
- final class WaterContentDashboard
- {
- private readonly string $now;
- public function __construct(?\DateTimeImmutable $now = null)
- {
- $this->now = ($now ?? new \DateTimeImmutable())->setTimezone(new \DateTimeZone('Asia/Shanghai'))->format('Y-m-d H:i:s');
- }
- private function present(array $row): array
- {
- foreach (['id', 'sort', 'status'] as $field) $row[$field] = (int)$row[$field];
- $row['delivery_status'] = ContentPolicy::status($row, $this->now);
- $row['status_label'] = ContentPolicy::LABELS[$row['delivery_status']];
- return $row;
- }
- private function packages(): array
- {
- return WaterPackage::query()->alias('p')->join('sa_water_sku as s', 's.id', '=', 'p.sku_id')
- ->where('p.status', 1)->where('s.status', 1)->orderByDesc('p.id')->limit(3)
- ->get(['p.id', 'p.name', 'p.buckets', 'p.price_cents', 's.name as sku_name'])
- ->map(function ($row) {
- $data = $row->toArray();
- foreach (['id', 'buckets', 'price_cents'] as $field) $data[$field] = (int)$data[$field];
- return $data;
- })->all();
- }
- public function dashboard(array $input): array
- {
- $keyword = ContentInput::text($input, 'keyword', 120);
- $status = ContentInput::text($input, 'status', 20);
- if ($status !== '' && !isset(ContentPolicy::LABELS[$status])) throw new ApiException('投放状态不正确');
- $page = ContentInput::integer($input, 'page', 1, 1, 1000000);
- $limit = ContentInput::integer($input, 'limit', 8, 1, 100);
- return WaterModel::transaction(function () use ($keyword, $status, $page, $limit) {
- $query = ContentPolicy::filter(WaterContent::query(), $status, $this->now);
- if ($keyword !== '') $query->matching('title|region', '%'.$keyword.'%');
- $list = $query->orderByDesc('sort')->orderByDesc('id')->pageResult($page, $limit);
- $list['data'] = array_map($this->present(...), $list['data']);
- $summary = ['total' => WaterContent::query()->count()];
- foreach (ContentPolicy::LABELS as $key => $label) {
- $summary[$key] = ContentPolicy::filter(WaterContent::query(), $key, $this->now)->count();
- }
- return ['list' => $list, 'summary' => $summary, 'packages' => $this->packages(), 'updated_at' => $this->now];
- });
- }
- public function preview(array $input): array
- {
- $purchase = ContentInput::text($input, 'purchase_status', 20, 'new');
- if (!in_array($purchase, ['new', 'purchased'], true)) throw new ApiException('预览购水状态不正确');
- $admin = ContentInput::integer($input, 'is_enterprise_admin', 0, 0, 1);
- $region = ContentInput::text($input, 'region', 80);
- if ($region === '全国') $region = '';
- $audiences = ['all', $purchase];
- if ($admin) $audiences[] = 'enterprise_admin';
- return WaterModel::transaction(function () use ($purchase, $admin, $region, $audiences) {
- $query = ContentPolicy::filter(WaterContent::query(), 'active', $this->now)
- ->whereIn('audience', $audiences)
- ->where(fn ($q) => $q->whereNull('region')->orWhere('region', '')->orWhere('region', '全国')->orWhere('region', $region));
- $total = (clone $query)->count();
- $rows = $query->orderByDesc('sort')->orderByDesc('id')->limit(20)->get()->toArray();
- return ['banners' => array_map($this->present(...), $rows), 'total' => $total,
- 'packages' => $this->packages(), 'context' => ['purchase_status' => $purchase, 'is_enterprise_admin' => $admin, 'region' => $region],
- 'updated_at' => $this->now];
- });
- }
- }
|