172 lines
7.0 KiB
PHP
172 lines
7.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace app\api\controller\system;
|
|
|
|
use app\api\controller\Base;
|
|
use app\api\CurrentMember;
|
|
use app\dao\system\FeedbackDao;
|
|
use core\exception\handler\UnauthorizedHttpException;
|
|
use core\tool\Json;
|
|
use madong\swagger\annotation\response\SimpleResponse;
|
|
use madong\swagger\attribute\AllowAnonymous;
|
|
use OpenApi\Attributes as OA;
|
|
use Webman\Http\Request;
|
|
use Webman\Http\Response;
|
|
|
|
#[OA\Tag(name: '问题反馈')]
|
|
final class FeedbackController extends Base
|
|
{
|
|
private FeedbackDao $dao;
|
|
|
|
public function __construct(FeedbackDao $dao, private readonly CurrentMember $currentMember)
|
|
{
|
|
$this->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());
|
|
}
|
|
}
|
|
}
|