PointsController.php 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. <?php
  2. namespace App\Http\Controllers\Points;
  3. use App\Facade\Site;
  4. use App\Libs\ApiResponse;
  5. use App\Libs\Utils;
  6. use App\Services\PointsService;
  7. use App\Transformer\Points\PointsTransformer;
  8. use Illuminate\Http\Request;
  9. use Illuminate\Routing\Controller as BaseController;
  10. use Illuminate\Support\Facades\Validator;
  11. class PointsController extends BaseController
  12. {
  13. use ApiResponse;
  14. protected $pointsService;
  15. public function __construct(PointsService $pointsService)
  16. {
  17. $this->pointsService = $pointsService;
  18. }
  19. /**
  20. * 积分流水列表(前端查看积分明细)
  21. *
  22. * @param Request $request
  23. * @return mixed
  24. */
  25. public function records(Request $request)
  26. {
  27. $result = $this->pointsService->getUserPointsRecords($request->all());
  28. $transformer = new PointsTransformer();
  29. return $this->success([
  30. 'summary' => $result['summary'],
  31. 'meta' => getMeta($result['records']),
  32. 'list' => $transformer->newEachPointsRecord($result['records']),
  33. ]);
  34. }
  35. /**
  36. * 积分明细导出 CSV(筛选条件与列表一致:uid/type/start_date/end_date)
  37. *
  38. * @param Request $request
  39. * @return void
  40. */
  41. public function exportRecords(Request $request)
  42. {
  43. $this->pointsService->exportPointsRecords($request->all());
  44. }
  45. /**
  46. * 获取系统当前全部积分规则(文生文/图片/视频)
  47. *
  48. * 供前端积分规则管理页展示:
  49. * - chat:文生文(对话)扣分规则(默认10,支持按模型配置)
  50. * - image_models:图片模型计费规则
  51. * - video_models:视频模型计费规则
  52. *
  53. * @param Request $request
  54. * @return mixed
  55. */
  56. public function rules(Request $request)
  57. {
  58. $this->checkSuperadmin();
  59. return $this->success($this->pointsService->getPointsRules());
  60. }
  61. /**
  62. * 编辑积分规则(文生文/图片/视频)
  63. *
  64. * 入参三个区块均可选传,单次至少传一个:
  65. * - text_rules:文生文规则列表 [{model?, charge_type?, price_json?}],model 可不传,不传时更新全部文生文模型
  66. * - image_rules:图片规则列表 [{model, charge_type?, price_json?}]
  67. * - video_rules:视频规则列表 [{model, charge_type?, price_json?}]
  68. * 图片/视频规则 model 必填;每条规则 charge_type / price_json 至少传一个(未传字段保留原值)。
  69. *
  70. * @param Request $request
  71. * @return mixed
  72. */
  73. public function editRules(Request $request)
  74. {
  75. $this->checkSuperadmin();
  76. $data = $request->all();
  77. $validator = Validator::make($data, [
  78. 'text_rules' => 'nullable|array',
  79. 'image_rules' => 'nullable|array',
  80. 'video_rules' => 'nullable|array',
  81. ], [
  82. 'text_rules.array' => 'text_rules必须为数组',
  83. 'image_rules.array' => 'image_rules必须为数组',
  84. 'video_rules.array' => 'video_rules必须为数组',
  85. ]);
  86. if ($validator->fails()) {
  87. Utils::throwError('1002:' . $validator->errors()->first());
  88. }
  89. $hasText = isset($data['text_rules']) && !empty($data['text_rules']);
  90. $hasImage = isset($data['image_rules']) && !empty($data['image_rules']);
  91. $hasVideo = isset($data['video_rules']) && !empty($data['video_rules']);
  92. if (!$hasText && !$hasImage && !$hasVideo) {
  93. Utils::throwError('1002:请至少传入text_rules、image_rules或video_rules之一');
  94. }
  95. $updated = $this->pointsService->updatePointsRules($data);
  96. return $this->success([
  97. 'updated' => $updated,
  98. 'remark' => '计费规则已更新,后续生成任务按新规则扣费',
  99. ]);
  100. }
  101. /**
  102. * 发放/回收积分(平台↔组织 / 组织↔同公司组员,支持批量)
  103. *
  104. * 入参:
  105. * - uid:目标用户ID(必填,支持多个ID用英文逗号隔开,如 142857,142858)
  106. * - points:发放积分数(必填,大于0)
  107. * - action:操作类型 grant-发放(默认)/ revoke-回收(可选)
  108. * - remark:备注文案(可选,回收时校验目标积分充足)
  109. *
  110. * @param Request $request
  111. * @return mixed
  112. */
  113. public function grantPoints(Request $request)
  114. {
  115. $data = $request->all();
  116. $validator = Validator::make($data, [
  117. 'uid' => ['required', 'regex:/^[\d\s,]+$/'],
  118. 'points' => 'required|integer|gt:0',
  119. // 'action' => 'nullable|string|in:grant,revoke',
  120. 'remark' => 'nullable|string|max:200',
  121. ], [
  122. 'uid.required' => '请传入目标用户uid',
  123. 'uid.regex' => 'uid格式不正确,多个用户ID请用英文逗号隔开,如 142857,142858',
  124. 'points.required' => '请传入发放积分数',
  125. 'points.integer' => '发放积分数必须为整数',
  126. 'points.gt' => '发放积分数必须大于0',
  127. // 'action.in' => 'action仅支持grant(发放)或revoke(回收)',
  128. 'remark.max' => '备注不能超过200个字符',
  129. ]);
  130. if ($validator->fails()) {
  131. Utils::throwError('1002:' . $validator->errors()->first());
  132. }
  133. $result = $this->pointsService->grantPoints($data);
  134. return $this->success($result);
  135. }
  136. /**
  137. * 获取可发放积分的用户列表
  138. *
  139. * 同一接口按当前角色返回:
  140. * - 平台(superadmin):所有组织
  141. * - 组织(admin):同公司组员
  142. *
  143. * @param Request $request
  144. * @return mixed
  145. */
  146. public function grantUsers(Request $request)
  147. {
  148. return $this->success([
  149. 'list' => $this->pointsService->getGrantUserList(),
  150. ]);
  151. }
  152. /**
  153. * 校验当前用户是否为平台
  154. *
  155. * @return void
  156. */
  157. private function checkSuperadmin(): void
  158. {
  159. if (Site::getRole() !== 'superadmin') {
  160. Utils::throwError('1005:仅平台可操作积分规则');
  161. }
  162. }
  163. }