2
0

DiscussionResource.php 4.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. <?php
  2. namespace App\Http\Resources\V3;
  3. use App\Http\Resources\Concerns\ResolvesActor;
  4. use App\Models\Discussion;
  5. use App\Services\V3\DiscussionService;
  6. use Illuminate\Http\Request;
  7. /**
  8. * 一条评论:话题(parent_id 为 null)或回复;或一条批注(note / commentary)。
  9. *
  10. * 批注带锚点(pos_start / pos_end / quote_*),指明它挂在句子文本的哪一段;
  11. * 评论线程的这几个字段恒为 null。
  12. *
  13. * 删除了但还挂着回复的话题以「墓碑」出现:deleted_at 有值,title / content 为 null,
  14. * 回复照常可读(与 Google Drive 的 comments.deleted、GitHub 的 deletedAt 同一做法)。
  15. *
  16. * editor 是对内容负责的人;AI 凭人类授权代写时,co_editor 是那个模型(仿 git 的
  17. * Co-Authored-By)。存量数据里 AI 写的行没有 co_editor,editor 直接是模型。
  18. *
  19. * **本类不查库。** 编辑者从预加载的 `user` / `aiModel` / `coEditor` 关系上取;权限与正文渲染
  20. * 由 {@see DiscussionService} 算好挂在模型的 `abilities` / `rendered` 属性上。
  21. *
  22. * 字段名改了两处(v2 → v3):res_type / res_id → target_type / target_id,
  23. * parent → parent_id;children_count → reply_count(只有话题有)。
  24. *
  25. * @mixin Discussion
  26. */
  27. class DiscussionResource extends BaseResource
  28. {
  29. use ResolvesActor;
  30. /**
  31. * @param Request $request
  32. * @return array{
  33. * id: string,
  34. * target_type: string,
  35. * target_id: string,
  36. * parent_id: string|null,
  37. * type: string,
  38. * severity: string|null,
  39. * status: string,
  40. * title: string|null,
  41. * content: string|null,
  42. * content_type: string,
  43. * html?: string,
  44. * summary?: string,
  45. * tpl_id: string|null,
  46. * pos_start: int|null,
  47. * pos_end: int|null,
  48. * quote_exact: string|null,
  49. * quote_prefix: string|null,
  50. * quote_suffix: string|null,
  51. * reply_count?: int,
  52. * editor: array{id: string, nickName: string, userName: string, realName: string, sn: int, avatar: string|null, roles: array|null}|null,
  53. * co_editor: array{id: string, nickName: string, userName: string, realName: string, sn: int, avatar: string|null, roles: array|null}|null,
  54. * abilities: array{update: bool, delete: bool, close: bool, reply: bool},
  55. * created_at: string,
  56. * updated_at: string,
  57. * deleted_at: string|null
  58. * }
  59. */
  60. public function toArray($request): array
  61. {
  62. $tombstone = $this->trashed();
  63. return [
  64. 'id' => (string) $this->id,
  65. 'target_type' => $this->res_type,
  66. 'target_id' => $this->res_id,
  67. 'parent_id' => $this->parent,
  68. 'type' => $this->type,
  69. 'severity' => $this->severity,
  70. 'status' => $this->status,
  71. 'title' => $tombstone ? null : $this->title,
  72. 'content' => $tombstone ? null : $this->content,
  73. 'content_type' => $this->content_type,
  74. 'html' => $this->when($this->rendered !== null, fn () => $this->rendered['html']),
  75. 'summary' => $this->when($this->rendered !== null, fn () => $this->rendered['summary']),
  76. 'tpl_id' => $this->tpl_id,
  77. 'pos_start' => $this->pos_start,
  78. 'pos_end' => $this->pos_end,
  79. 'quote_exact' => $tombstone ? null : $this->quote_exact,
  80. 'quote_prefix' => $tombstone ? null : $this->quote_prefix,
  81. 'quote_suffix' => $tombstone ? null : $this->quote_suffix,
  82. 'reply_count' => $this->when($this->parent === null, fn () => (int) $this->reply_count),
  83. 'editor' => $this->actor($this->user, $this->aiModel),
  84. // AI 代写时的模型;人类自己写的、存量数据都为 null
  85. 'co_editor' => $this->coEditor ? $this->actor(null, $this->coEditor) : null,
  86. 'abilities' => $this->abilities ?? ['update' => false, 'delete' => false, 'close' => false, 'reply' => false],
  87. 'created_at' => $this->created_at,
  88. 'updated_at' => $this->updated_at,
  89. 'deleted_at' => $this->deleted_at,
  90. ];
  91. }
  92. }