dao = $dao; } #[OA\Get( path: '/feedback/mine', summary: '获取当前用户的问题反馈列表', tags: ['问题反馈'], parameters: [ new OA\Parameter(name: 'page', description: '页码', in: 'query', schema: new OA\Schema(type: 'integer', default: 1)), new OA\Parameter(name: 'limit', description: '每页数量', in: 'query', schema: new OA\Schema(type: 'integer', default: 10)), ], responses: [new OA\Response(response: 200, description: '获取成功')] )] #[SimpleResponse(schema: [], example: [])] #[AllowAnonymous(requireToken: true, requirePermission: false, description: '会员接口')] public function mine(Request $request): Response { try { $memberId = $this->currentMember->id(); if (!$memberId) { throw new UnauthorizedHttpException('请先登录后查看反馈记录'); } $page = max(1, (int)$request->get('page', 1)); $limit = min(50, max(1, (int)$request->get('limit', 10))); $where = ['created_by' => $memberId]; $total = $this->dao->getCount($where); $items = $this->dao->selectList($where, '*', $page, $limit, 'created_at desc')?->values()->all() ?? []; return Json::success('ok', [ 'items' => $items, 'total' => $total, 'page' => $page, 'limit' => $limit, ]); } catch (\Throwable $e) { return Json::fail($e->getMessage(), [], $e instanceof UnauthorizedHttpException ? 401 : 0); } } #[OA\Get( path: '/feedback/mine/{id}', summary: '获取当前用户的问题反馈详情', tags: ['问题反馈'], parameters: [new OA\Parameter(name: 'id', description: '反馈 ID', in: 'path', required: true, schema: new OA\Schema(type: 'string'))], responses: [new OA\Response(response: 200, description: '获取成功')] )] #[SimpleResponse(schema: [], example: [])] #[AllowAnonymous(requireToken: true, requirePermission: false, description: '会员接口')] public function mineShow(Request $request): Response { try { $memberId = $this->currentMember->id(); if (!$memberId) { throw new UnauthorizedHttpException('请先登录后查看反馈记录'); } $feedback = $this->dao->get([ 'id' => $request->route->param('id'), 'created_by' => $memberId, ]); if (!$feedback) { return Json::fail('反馈记录不存在或无权查看', [], 404); } $feedback->load('replyAdmin'); return Json::success('ok', $feedback->toArray()); } catch (\Throwable $e) { return Json::fail($e->getMessage(), [], $e instanceof UnauthorizedHttpException ? 401 : 0); } } #[OA\Post( path: '/feedback', summary: '提交问题反馈', tags: ['问题反馈'], requestBody: new OA\RequestBody( required: true, content: new OA\JsonContent( required: ['type', 'content', 'source'], properties: [ new OA\Property(property: 'type', description: '反馈类型:bug/suggestion/correction', type: 'string'), new OA\Property(property: 'content', description: '问题描述,最多2000个字符', type: 'string'), new OA\Property(property: 'contact', description: '联系方式,最多100个字符', type: 'string'), new OA\Property(property: 'images', description: '截图地址列表,最多3张', type: 'array', items: new OA\Items(type: 'string')), new OA\Property(property: 'source', description: '反馈来源:app/web', type: 'string'), ] ) ), responses: [ new OA\Response(response: 200, description: '提交成功'), new OA\Response(response: 400, description: '参数错误'), ] )] #[SimpleResponse(schema: [], example: [])] #[AllowAnonymous(requireToken: false, requirePermission: false, description: '公共接口')] public function store(Request $request): Response { try { $data = $request->post(); $data['content'] = trim((string)($data['content'] ?? '')); $data['contact'] = trim((string)($data['contact'] ?? '')); $data['source'] = (string)($data['source'] ?? 'app'); $data['images'] = $data['images'] ?? []; $validator = validator($data, [ 'type' => 'required|in:bug,suggestion,correction', 'content' => 'required|max:2000', 'contact' => 'nullable|max:100', 'images' => 'array|max:3', 'source' => 'required|in:app,web', ], [ 'type.required' => '请选择反馈类型', 'type.in' => '反馈类型不正确', 'content.required' => '请填写问题描述', 'content.max' => '问题描述不能超过2000个字符', 'contact.max' => '联系方式不能超过100个字符', 'images.array' => '截图附件格式不正确', 'images.max' => '截图附件最多上传3张', 'source.required' => '请选择反馈来源', 'source.in' => '反馈来源不正确', ]); if ($validator->fails()) { throw new \InvalidArgumentException($validator->errors()->first()); } $images = array_values(array_filter($data['images'], static fn ($image) => is_string($image) && $image !== '')); $type = $data['type']; $content = $data['content']; $contact = $data['contact']; $source = $data['source']; $memberId = $this->currentMember->id(); $model = $this->dao->save([ 'type' => $type, 'content' => $content, 'contact' => $contact, 'images' => $images, 'source' => $source, 'created_by' => $memberId ?: null, ]); return Json::success('提交成功', ['id' => $model->id]); } catch (\Throwable $e) { return Json::fail($e->getMessage()); } } }