From 0700fcd58408b3777d5f7cd135c51499b98e1d8b Mon Sep 17 00:00:00 2001 From: Mikhail Chusavitin Date: Thu, 22 Jan 2026 11:41:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A3=D0=BB=D1=83=D1=87=D1=88=D0=B5=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BE=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=B0?= =?UTF-8?q?=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BE=D0=BA=20API?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Бэкенд: - Добавлен try-catch для insert, update, delete, delete-batch - Ошибки возвращаются как JSON с полем message Фронтенд: - Улучшена функция api() для парсинга JSON ошибок - Извлечение понятного сообщения из ответа сервера Co-Authored-By: Claude Opus 4.5 --- public/app.js | 29 ++++++++++-- public/index.php | 112 ++++++++++++++++++++++++++++------------------- 2 files changed, 94 insertions(+), 47 deletions(-) diff --git a/public/app.js b/public/app.js index d2bb473..95274a3 100644 --- a/public/app.js +++ b/public/app.js @@ -18,11 +18,34 @@ async function api(url, method = 'GET', body) { if (body) opts.body = JSON.stringify(body); const res = await fetch(url, opts); - if (!res.ok) { + + // Пытаемся распарсить как JSON + const contentType = res.headers.get('content-type'); + let data; + + if (contentType && contentType.includes('application/json')) { + data = await res.json(); + } else { const txt = await res.text(); - throw new Error(`HTTP ${res.status}: ${txt}`); + // Пытаемся извлечь сообщение из HTML ошибки Slim + const msgMatch = txt.match(/Message:<\/strong>\s*([^<]+)/); + if (msgMatch) { + throw new Error(msgMatch[1].trim()); + } + throw new Error(`Ошибка сервера: ${res.status}`); } - return res.json(); + + if (!res.ok) { + // Сервер вернул JSON с ошибкой + throw new Error(data.message || data.error || 'Неизвестная ошибка'); + } + + // Проверяем на ошибку в успешном ответе + if (data.error) { + throw new Error(data.message || 'Ошибка'); + } + + return data; } function updateSelectionCounter() { diff --git a/public/index.php b/public/index.php index 31d3bdf..946b91b 100644 --- a/public/index.php +++ b/public/index.php @@ -123,51 +123,69 @@ $app->post('/api/table/data', function (Request $request, Response $response) us // API: insert / update / delete $app->post('/api/table/insert', function (Request $request, Response $response) use ($container) { - $payload = json_decode((string)$request->getBody(), true); - $pdo = $container->get('db'); - $meta = new \App\MetaService($pdo); - $ds = new \App\DataService($pdo); + try { + $payload = json_decode((string)$request->getBody(), true); + $pdo = $container->get('db'); + $meta = new \App\MetaService($pdo); + $ds = new \App\DataService($pdo); - $schema = $payload['schema']; - $table = $payload['table']; - $row = $payload['row']; - $metaArr = $meta->getTableMeta($schema, $table); + $schema = $payload['schema']; + $table = $payload['table']; + $row = $payload['row']; + $metaArr = $meta->getTableMeta($schema, $table); - $result = $ds->insertRow($schema, $table, $row, $metaArr['columns']); - $response->getBody()->write(json_encode($result)); - return $response->withHeader('Content-Type', 'application/json'); + $result = $ds->insertRow($schema, $table, $row, $metaArr['columns']); + $response->getBody()->write(json_encode($result)); + return $response->withHeader('Content-Type', 'application/json'); + } catch (\Exception $e) { + $error = ['error' => true, 'message' => $e->getMessage()]; + $response->getBody()->write(json_encode($error)); + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } }); $app->post('/api/table/update', function (Request $request, Response $response) use ($container) { - $payload = json_decode((string)$request->getBody(), true); - $pdo = $container->get('db'); - $meta = new \App\MetaService($pdo); - $ds = new \App\DataService($pdo); + try { + $payload = json_decode((string)$request->getBody(), true); + $pdo = $container->get('db'); + $meta = new \App\MetaService($pdo); + $ds = new \App\DataService($pdo); - $schema = $payload['schema']; - $table = $payload['table']; - $row = $payload['row']; - $metaArr = $meta->getTableMeta($schema, $table); + $schema = $payload['schema']; + $table = $payload['table']; + $row = $payload['row']; + $metaArr = $meta->getTableMeta($schema, $table); - $result = $ds->updateRow($schema, $table, $row, $metaArr['columns'], $metaArr['primaryKey']); - $response->getBody()->write(json_encode($result)); - return $response->withHeader('Content-Type', 'application/json'); + $result = $ds->updateRow($schema, $table, $row, $metaArr['columns'], $metaArr['primaryKey']); + $response->getBody()->write(json_encode($result)); + return $response->withHeader('Content-Type', 'application/json'); + } catch (\Exception $e) { + $error = ['error' => true, 'message' => $e->getMessage()]; + $response->getBody()->write(json_encode($error)); + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } }); $app->post('/api/table/delete', function (Request $request, Response $response) use ($container) { - $payload = json_decode((string)$request->getBody(), true); - $pdo = $container->get('db'); - $meta = new \App\MetaService($pdo); - $ds = new \App\DataService($pdo); + try { + $payload = json_decode((string)$request->getBody(), true); + $pdo = $container->get('db'); + $meta = new \App\MetaService($pdo); + $ds = new \App\DataService($pdo); - $schema = $payload['schema']; - $table = $payload['table']; - $row = $payload['row']; - $metaArr = $meta->getTableMeta($schema, $table); + $schema = $payload['schema']; + $table = $payload['table']; + $row = $payload['row']; + $metaArr = $meta->getTableMeta($schema, $table); - $result = $ds->deleteRow($schema, $table, $row, $metaArr['primaryKey']); - $response->getBody()->write(json_encode($result)); - return $response->withHeader('Content-Type', 'application/json'); + $result = $ds->deleteRow($schema, $table, $row, $metaArr['primaryKey']); + $response->getBody()->write(json_encode($result)); + return $response->withHeader('Content-Type', 'application/json'); + } catch (\Exception $e) { + $error = ['error' => true, 'message' => $e->getMessage()]; + $response->getBody()->write(json_encode($error)); + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } }); // API: импорт CSV (массовая вставка) @@ -315,19 +333,25 @@ $app->get('/api/fk-values', function (Request $request, Response $response) use // API: массовое удаление строк (batch delete) $app->post('/api/table/delete-batch', function (Request $request, Response $response) use ($container) { - $payload = json_decode((string)$request->getBody(), true); - $pdo = $container->get('db'); - $meta = new \App\MetaService($pdo); - $ds = new \App\DataService($pdo); + try { + $payload = json_decode((string)$request->getBody(), true); + $pdo = $container->get('db'); + $meta = new \App\MetaService($pdo); + $ds = new \App\DataService($pdo); - $schema = $payload['schema']; - $table = $payload['table']; - $rows = $payload['rows'] ?? []; // Массив строк для удаления - $metaArr = $meta->getTableMeta($schema, $table); + $schema = $payload['schema']; + $table = $payload['table']; + $rows = $payload['rows'] ?? []; // Массив строк для удаления + $metaArr = $meta->getTableMeta($schema, $table); - $result = $ds->deleteMultipleRows($schema, $table, $rows, $metaArr['primaryKey']); - $response->getBody()->write(json_encode($result)); - return $response->withHeader('Content-Type', 'application/json'); + $result = $ds->deleteMultipleRows($schema, $table, $rows, $metaArr['primaryKey']); + $response->getBody()->write(json_encode($result)); + return $response->withHeader('Content-Type', 'application/json'); + } catch (\Exception $e) { + $error = ['error' => true, 'message' => $e->getMessage()]; + $response->getBody()->write(json_encode($error)); + return $response->withHeader('Content-Type', 'application/json')->withStatus(400); + } });