You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.0 KiB

<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Services\VenueImportService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
use Symfony\Component\HttpFoundation\StreamedResponse;
class VenueImportController extends Controller
{
public function __construct(
private VenueImportService $venueImportService
) {}
public function template(Request $request): StreamedResponse
{
$user = $request->user();
abort_unless($user?->isSuperAdmin(), 403, '仅超级管理员可下载导入模板');
$spreadsheet = $this->venueImportService->buildTemplateSpreadsheet();
$writer = new Xlsx($spreadsheet);
return response()->streamDownload(function () use ($writer) {
$writer->save('php://output');
}, '场馆导入模板.xlsx', [
'Content-Type' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
]);
}
public function preview(Request $request): JsonResponse
{
abort_unless($request->user()?->isSuperAdmin(), 403, '仅超级管理员可导入场馆');
$request->validate([
'file' => ['required', 'file', 'mimes:xlsx,xls', 'max:10240'],
]);
$path = $request->file('file')->getRealPath();
if ($path === false) {
return response()->json(['message' => '无法读取上传文件'], 422);
}
$result = $this->venueImportService->previewFromPath($path);
return response()->json($result);
}
public function confirm(Request $request): JsonResponse
{
$user = $request->user();
abort_unless($user?->isSuperAdmin(), 403, '仅超级管理员可导入场馆');
$data = $request->validate([
'rows' => ['required', 'array', 'min:1'],
'rows.*' => ['required', 'array'],
]);
$created = [];
$errors = [];
DB::beginTransaction();
try {
foreach ($data['rows'] as $index => $row) {
$errs = $this->venueImportService->validatePayload($row);
if ($errs !== []) {
$errors[] = ['index' => $index, 'errors' => $errs];
continue;
}
$clean = $this->venueImportService->stripInternalKeys($row);
$created[] = $this->venueImportService->createVenueFromPayload($clean, $user)->toArray();
}
if ($errors !== []) {
DB::rollBack();
return response()->json([
'message' => '部分数据校验失败,未写入任何场馆',
'failures' => $errors,
], 422);
}
DB::commit();
} catch (\Throwable $e) {
DB::rollBack();
throw $e;
}
return response()->json([
'created' => $created,
'count' => count($created),
], 201);
}
}