fix: Fix edit entities on the map

This commit is contained in:
2025-06-09 19:16:30 +03:00
parent d8302e05b4
commit 27cb644242

View File

@ -22,6 +22,28 @@ interface ApiSight {
longitude: number; longitude: number;
} }
// Допуск для сравнения координат, чтобы избежать ошибок с точностью чисел.
const COORDINATE_PRECISION_TOLERANCE = 1e-9;
// Вспомогательная функция, обновленная для сравнения с допуском.
const arePathsEqual = (
path1: [number, number][],
path2: [number, number][]
): boolean => {
if (path1.length !== path2.length) {
return false;
}
for (let i = 0; i < path1.length; i++) {
if (
Math.abs(path1[i][0] - path2[i][0]) > COORDINATE_PRECISION_TOLERANCE ||
Math.abs(path1[i][1] - path2[i][1]) > COORDINATE_PRECISION_TOLERANCE
) {
return false;
}
}
return true;
};
class MapStore { class MapStore {
constructor() { constructor() {
makeAutoObservable(this); makeAutoObservable(this);
@ -33,25 +55,19 @@ class MapStore {
getRoutes = async () => { getRoutes = async () => {
const routes = await languageInstance("ru").get("/route"); const routes = await languageInstance("ru").get("/route");
const routedIds = routes.data.map((route: any) => route.id); const routedIds = routes.data.map((route: any) => route.id);
const mappedRoutes: ApiRoute[] = []; const mappedRoutes: ApiRoute[] = [];
for (const routeId of routedIds) { for (const routeId of routedIds) {
const responseSoloRoute = await languageInstance("ru").get( const responseSoloRoute = await languageInstance("ru").get(
`/route/${routeId}` `/route/${routeId}`
); );
const route = responseSoloRoute.data; const route = responseSoloRoute.data;
mappedRoutes.push({
const mappedRoute = {
id: route.id, id: route.id,
route_number: route.route_number, route_number: route.route_number,
path: route.path, path: route.path,
}; });
mappedRoutes.push(mappedRoute);
} }
this.routes = mappedRoutes.sort((a, b) => this.routes = mappedRoutes.sort((a, b) =>
a.route_number.localeCompare(b.route_number) a.route_number.localeCompare(b.route_number)
); );
@ -59,27 +75,23 @@ class MapStore {
getStations = async () => { getStations = async () => {
const stations = await languageInstance("ru").get("/station"); const stations = await languageInstance("ru").get("/station");
const mappedStations = stations.data.map((station: any) => ({ this.stations = stations.data.map((station: any) => ({
id: station.id, id: station.id,
name: station.name, name: station.name,
latitude: station.latitude, latitude: station.latitude,
longitude: station.longitude, longitude: station.longitude,
})); }));
this.stations = mappedStations;
}; };
getSights = async () => { getSights = async () => {
const sights = await languageInstance("ru").get("/sight"); const sights = await languageInstance("ru").get("/sight");
const mappedSights = sights.data.map((sight: any) => ({ this.sights = sights.data.map((sight: any) => ({
id: sight.id, id: sight.id,
name: sight.name, name: sight.name,
description: sight.description, description: sight.description,
latitude: sight.latitude, latitude: sight.latitude,
longitude: sight.longitude, longitude: sight.longitude,
})); }));
this.sights = mappedSights;
}; };
deleteRecourse = async (recourse: string, id: number) => { deleteRecourse = async (recourse: string, id: number) => {
@ -94,31 +106,98 @@ class MapStore {
}; };
handleSave = async (json: string) => { handleSave = async (json: string) => {
const sights: any[] = []; const newSights: any[] = [];
const routes: any[] = []; const newRoutes: any[] = [];
const stations: any[] = []; const newStations: any[] = [];
const updatedSights: any[] = [];
const updatedRoutes: any[] = [];
const updatedStations: any[] = [];
const parsedJSON = JSON.parse(json); const parsedJSON = JSON.parse(json);
console.log("Данные для сохранения (GeoJSON):", parsedJSON);
console.log(parsedJSON); for (const feature of parsedJSON.features) {
parsedJSON.features.forEach((feature: any) => {
const { geometry, properties, id } = feature; const { geometry, properties, id } = feature;
const idCanBeSplited = id.split("-"); const idParts = String(id).split("-");
if (!(idCanBeSplited.length > 1)) { if (idParts.length > 1) {
const featureType = idParts[0];
const numericId = parseInt(idParts[1], 10);
if (isNaN(numericId)) continue;
if (featureType === "station") {
const originalStation = this.stations.find((s) => s.id === numericId);
if (!originalStation) continue;
const currentStation = {
name: properties.name || "",
latitude: geometry.coordinates[1],
longitude: geometry.coordinates[0],
};
// ИЗМЕНЕНИЕ: Сравнение координат с допуском
if (
originalStation.name !== currentStation.name ||
Math.abs(originalStation.latitude - currentStation.latitude) >
COORDINATE_PRECISION_TOLERANCE ||
Math.abs(originalStation.longitude - currentStation.longitude) >
COORDINATE_PRECISION_TOLERANCE
) {
updatedStations.push({ id: numericId, ...currentStation });
}
} else if (featureType === "route") {
const originalRoute = this.routes.find((r) => r.id === numericId);
if (!originalRoute) continue;
const currentRoute = {
route_number: properties.name || "",
path: geometry.coordinates,
};
// ИЗМЕНЕНИЕ: Используется новая функция arePathsEqual с допуском
if (
originalRoute.route_number !== currentRoute.route_number ||
!arePathsEqual(originalRoute.path, currentRoute.path)
) {
updatedRoutes.push({ id: numericId, ...currentRoute });
}
} else if (featureType === "sight") {
const originalSight = this.sights.find((s) => s.id === numericId);
if (!originalSight) continue;
const currentSight = {
name: properties.name || "",
description: properties.description || "",
latitude: geometry.coordinates[1],
longitude: geometry.coordinates[0],
};
// ИЗМЕНЕНИЕ: Сравнение координат с допуском
if (
originalSight.name !== currentSight.name ||
originalSight.description !== currentSight.description ||
Math.abs(originalSight.latitude - currentSight.latitude) >
COORDINATE_PRECISION_TOLERANCE ||
Math.abs(originalSight.longitude - currentSight.longitude) >
COORDINATE_PRECISION_TOLERANCE
) {
updatedSights.push({ id: numericId, ...currentSight });
}
}
} else {
if (properties.featureType === "station") { if (properties.featureType === "station") {
stations.push({ newStations.push({
name: properties.name || "", name: properties.name || "",
latitude: geometry.coordinates[1], latitude: geometry.coordinates[1],
longitude: geometry.coordinates[0], longitude: geometry.coordinates[0],
}); });
} else if (properties.featureType === "route") { } else if (properties.featureType === "route") {
routes.push({ newRoutes.push({
route_number: properties.name || "", route_number: properties.name || "",
path: geometry.coordinates, path: geometry.coordinates,
}); });
} else if (properties.featureType === "sight") { } else if (properties.featureType === "sight") {
sights.push({ newSights.push({
name: properties.name || "", name: properties.name || "",
description: properties.description || "", description: properties.description || "",
latitude: geometry.coordinates[1], latitude: geometry.coordinates[1],
@ -126,16 +205,54 @@ class MapStore {
}); });
} }
} }
}); }
for (const station of stations) { const requests: Promise<any>[] = [];
await languageInstance("ru").post("/station", station);
console.log(
`К созданию: ${newStations.length} станций, ${newRoutes.length} маршрутов, ${newSights.length} достопримечательностей.`
);
console.log(
`К обновлению: ${updatedStations.length} станций, ${updatedRoutes.length} маршрутов, ${updatedSights.length} достопримечательностей.`
);
newStations.forEach((data) =>
requests.push(languageInstance("ru").post("/station", data))
);
newRoutes.forEach((data) =>
requests.push(languageInstance("ru").post("/route", data))
);
newSights.forEach((data) =>
requests.push(languageInstance("ru").post("/sight", data))
);
updatedStations.forEach(({ id, ...data }) =>
requests.push(languageInstance("ru").patch(`/station/${id}`, data))
);
updatedRoutes.forEach(({ id, ...data }) =>
requests.push(languageInstance("ru").patch(`/route/${id}`, data))
);
updatedSights.forEach(({ id, ...data }) =>
requests.push(languageInstance("ru").patch(`/sight/${id}`, data))
);
if (requests.length === 0) {
console.log("Нет изменений для сохранения.");
return;
} }
for (const route of routes) {
await languageInstance("ru").post("/route", route); try {
} await Promise.all(requests);
for (const sight of sights) { console.log("Все изменения успешно сохранены!");
await languageInstance("ru").post("/sight", sight);
await Promise.all([
this.getRoutes(),
this.getStations(),
this.getSights(),
]);
} catch (error) {
console.error("Ошибка при сохранении данных:", error);
throw error;
} }
}; };
} }