CollectionService.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. namespace App\Services;
  3. use App\Models\Collection;
  4. use App\Http\Api\AuthApi;
  5. use App\Http\Api\StudioApi;
  6. use App\Http\Api\ShareApi;
  7. use Illuminate\Http\Request;
  8. use App\Http\Resources\CollectionResource;
  9. use Illuminate\Support\Facades\Log;
  10. class CollectionService
  11. {
  12. protected $indexCol = [
  13. 'uid',
  14. 'title',
  15. 'subtitle',
  16. 'summary',
  17. 'article_list',
  18. 'owner',
  19. 'status',
  20. 'default_channel',
  21. 'lang',
  22. 'updated_at',
  23. 'created_at',
  24. ];
  25. /**
  26. * 判断用户是否有编辑权限
  27. */
  28. public function userCanEdit(string $user_uid, Collection $collection): bool
  29. {
  30. if ($collection->owner === $user_uid) {
  31. return true;
  32. }
  33. return ShareApi::getResPower($user_uid, $collection->uid) >= 20;
  34. }
  35. /**
  36. * 判断用户是否有读取权限
  37. */
  38. public function userCanRead(string $user_uid, Collection $collection): bool
  39. {
  40. if ($collection->owner === $user_uid) {
  41. return true;
  42. }
  43. return ShareApi::getResPower($user_uid, $collection->uid) >= 10;
  44. }
  45. /**
  46. * 获取当前 studio 下我的数量与协作数量
  47. */
  48. public function getMyNumber(Request $request): array
  49. {
  50. $user = AuthApi::current($request);
  51. if (!$user) {
  52. return ['error' => __('auth.failed'), 'code' => 403];
  53. }
  54. $studioId = StudioApi::getIdByName($request->get('studio'));
  55. if ($user['user_uid'] !== $studioId) {
  56. return ['error' => __('auth.failed'), 'code' => 403];
  57. }
  58. $my = Collection::where('owner', $studioId)->count();
  59. $resList = ShareApi::getResList($studioId, 4);
  60. $resId = array_column($resList, 'res_id');
  61. $collaboration = Collection::whereIn('uid', $resId)
  62. ->where('owner', '<>', $studioId)
  63. ->count();
  64. return ['data' => ['my' => $my, 'collaboration' => $collaboration]];
  65. }
  66. /**
  67. * 构建 index 查询,根据 view 参数分发不同逻辑
  68. */
  69. public function buildIndexQuery(Request $request): array
  70. {
  71. $table = match ($request->get('view')) {
  72. 'studio_list' => $this->buildStudioListQuery($this->indexCol),
  73. 'studio' => $this->buildStudioQuery($request, $this->indexCol),
  74. 'public' => $this->buildPublicQuery($request, $this->indexCol),
  75. default => null,
  76. };
  77. if ($table === null) {
  78. return ['error' => '无法识别的view参数'];
  79. }
  80. // 如果是鉴权失败从 studio 分支返回的错误
  81. if (isset($table['error'])) {
  82. return $table;
  83. }
  84. // 搜索
  85. if ($request->filled('search')) {
  86. $table = $table->where('title', 'like', '%' . $request->get('search') . '%');
  87. }
  88. $count = $table->count();
  89. // 排序
  90. if ($request->has('order') && $request->has('dir')) {
  91. $table = $table->orderBy($request->get('order'), $request->get('dir'));
  92. } else {
  93. $orderCol = $request->get('view') === 'studio_list' ? 'count' : 'updated_at';
  94. $table = $table->orderBy($orderCol, 'desc');
  95. }
  96. $result = $table
  97. ->skip($request->get('offset', 0))
  98. ->take($request->get('limit', 1000))
  99. ->get();
  100. return ['data' => $result, 'count' => $count];
  101. }
  102. // -------------------------------------------------------------------------
  103. // 私有:各 view 的查询构建
  104. // -------------------------------------------------------------------------
  105. private function buildStudioListQuery(array $indexCol)
  106. {
  107. return Collection::select(['owner'])
  108. ->selectRaw('count(*) as count')
  109. ->where('status', 30)
  110. ->groupBy('owner');
  111. }
  112. private function buildStudioQuery(Request $request, array $indexCol): array|\Illuminate\Database\Eloquent\Builder
  113. {
  114. $user = AuthApi::current($request);
  115. if (!$user) {
  116. return ['error' => __('auth.failed'), 'code' => 403];
  117. }
  118. $studioId = StudioApi::getIdByName($request->get('name'));
  119. if ($user['user_uid'] !== $studioId) {
  120. return ['error' => __('auth.failed'), 'code' => 403];
  121. }
  122. $table = Collection::select($indexCol);
  123. if ($request->get('view2', 'my') === 'my') {
  124. return $table->where('owner', $studioId);
  125. }
  126. // 协作
  127. $resList = ShareApi::getResList($studioId, 4);
  128. $resId = array_column($resList, 'res_id');
  129. return $table->whereIn('uid', $resId)->where('owner', '<>', $studioId);
  130. }
  131. private function buildPublicQuery(Request $request, array $indexCol)
  132. {
  133. $table = Collection::select($indexCol)->where('status', 30);
  134. if ($request->has('studio')) {
  135. $studioId = StudioApi::getIdByName($request->get('studio'));
  136. $table = $table->where('owner', $studioId);
  137. }
  138. return $table;
  139. }
  140. public function getPublicList(int $pageSize, int $currPage): array
  141. {
  142. $table = Collection::select($this->indexCol)->where('status', 30);
  143. $count = $table->count();
  144. $result = $table
  145. ->orderBy('updated_at', 'desc')
  146. ->skip(($currPage - 1) * $pageSize)
  147. ->take($pageSize)
  148. ->get();
  149. return ['data' => CollectionResource::collection($result), 'total' => $count];
  150. }
  151. public function getCollection(string $id): array
  152. {
  153. $result = Collection::where('uid', $id)->first();
  154. if (!$result) {
  155. Log::warning("没有查询到数据 id={$id}");
  156. return ['error' => "没有查询到数据 id={$id}", 'code' => 404];
  157. }
  158. $result->fullArticleList = true;
  159. return ['data' => new CollectionResource($result)];
  160. }
  161. }