pointsService = $pointsService; } /** * 积分流水列表(前端查看积分明细) * * @param Request $request * @return mixed */ public function records(Request $request) { $result = $this->pointsService->getUserPointsRecords($request->all()); $transformer = new PointsTransformer(); return $this->success([ 'summary' => $result['summary'], 'meta' => getMeta($result['records']), 'list' => $transformer->newEachPointsRecord($result['records']), ]); } /** * 积分明细导出 CSV(筛选条件与列表一致:uid/type/start_date/end_date) * * @param Request $request * @return void */ public function exportRecords(Request $request) { $this->pointsService->exportPointsRecords($request->all()); } /** * 获取系统当前全部积分规则(文生文/图片/视频) * * 供前端积分规则管理页展示: * - chat:文生文(对话)扣分规则(默认10,支持按模型配置) * - image_models:图片模型计费规则 * - video_models:视频模型计费规则 * * @param Request $request * @return mixed */ public function rules(Request $request) { $this->checkSuperadmin(); return $this->success($this->pointsService->getPointsRules()); } /** * 编辑积分规则(文生文/图片/视频) * * 入参三个区块均可选传,单次至少传一个: * - text_rules:文生文规则列表 [{model?, charge_type?, price_json?}],model 可不传,不传时更新全部文生文模型 * - image_rules:图片规则列表 [{model, charge_type?, price_json?}] * - video_rules:视频规则列表 [{model, charge_type?, price_json?}] * 图片/视频规则 model 必填;每条规则 charge_type / price_json 至少传一个(未传字段保留原值)。 * * @param Request $request * @return mixed */ public function editRules(Request $request) { $this->checkSuperadmin(); $data = $request->all(); $validator = Validator::make($data, [ 'text_rules' => 'nullable|array', 'image_rules' => 'nullable|array', 'video_rules' => 'nullable|array', ], [ 'text_rules.array' => 'text_rules必须为数组', 'image_rules.array' => 'image_rules必须为数组', 'video_rules.array' => 'video_rules必须为数组', ]); if ($validator->fails()) { Utils::throwError('1002:' . $validator->errors()->first()); } $hasText = isset($data['text_rules']) && !empty($data['text_rules']); $hasImage = isset($data['image_rules']) && !empty($data['image_rules']); $hasVideo = isset($data['video_rules']) && !empty($data['video_rules']); if (!$hasText && !$hasImage && !$hasVideo) { Utils::throwError('1002:请至少传入text_rules、image_rules或video_rules之一'); } $updated = $this->pointsService->updatePointsRules($data); return $this->success([ 'updated' => $updated, 'remark' => '计费规则已更新,后续生成任务按新规则扣费', ]); } /** * 发放/回收积分(平台↔组织 / 组织↔同公司组员,支持批量) * * 入参: * - uid:目标用户ID(必填,支持多个ID用英文逗号隔开,如 142857,142858) * - points:发放积分数(必填,大于0) * - action:操作类型 grant-发放(默认)/ revoke-回收(可选) * - remark:备注文案(可选,回收时校验目标积分充足) * * @param Request $request * @return mixed */ public function grantPoints(Request $request) { $data = $request->all(); $validator = Validator::make($data, [ 'uid' => ['required', 'regex:/^[\d\s,]+$/'], 'points' => 'required|integer|gt:0', // 'action' => 'nullable|string|in:grant,revoke', 'remark' => 'nullable|string|max:200', ], [ 'uid.required' => '请传入目标用户uid', 'uid.regex' => 'uid格式不正确,多个用户ID请用英文逗号隔开,如 142857,142858', 'points.required' => '请传入发放积分数', 'points.integer' => '发放积分数必须为整数', 'points.gt' => '发放积分数必须大于0', // 'action.in' => 'action仅支持grant(发放)或revoke(回收)', 'remark.max' => '备注不能超过200个字符', ]); if ($validator->fails()) { Utils::throwError('1002:' . $validator->errors()->first()); } $result = $this->pointsService->grantPoints($data); return $this->success($result); } /** * 获取可发放积分的用户列表 * * 同一接口按当前角色返回: * - 平台(superadmin):所有组织 * - 组织(admin):同公司组员 * * @param Request $request * @return mixed */ public function grantUsers(Request $request) { return $this->success([ 'list' => $this->pointsService->getGrantUserList(), ]); } /** * 校验当前用户是否为平台 * * @return void */ private function checkSuperadmin(): void { if (Site::getRole() !== 'superadmin') { Utils::throwError('1005:仅平台可操作积分规则'); } } }