feat(sgw): Add new services and utilities for ship, trip, and photo management
This commit is contained in:
113
src/utils/slave/sgw/geomUtils.ts
Normal file
113
src/utils/slave/sgw/geomUtils.ts
Normal file
@@ -0,0 +1,113 @@
|
||||
import { ZoneData } from '@/pages/Slave/SGW/Map/type';
|
||||
|
||||
export const convertWKTPointToLatLng = (
|
||||
wktString: string,
|
||||
): [number, number] | null => {
|
||||
if (
|
||||
!wktString ||
|
||||
typeof wktString !== 'string' ||
|
||||
!wktString.startsWith('POINT')
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const matched = wktString.match(/POINT\s*\(([-\d.]+)\s+([-\d.]+)\)/);
|
||||
if (!matched) return null;
|
||||
|
||||
const lng = parseFloat(matched[1]);
|
||||
const lat = parseFloat(matched[2]);
|
||||
|
||||
return [lng, lat]; // [longitude, latitude]
|
||||
};
|
||||
export const convertWKTLineStringToLatLngArray = (wktString: string) => {
|
||||
if (
|
||||
!wktString ||
|
||||
typeof wktString !== 'string' ||
|
||||
!wktString.startsWith('LINESTRING')
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const matched = wktString.match(/LINESTRING\s*\((.*)\)/);
|
||||
if (!matched) return [];
|
||||
|
||||
const coordinates = matched[1].split(',').map((coordStr) => {
|
||||
const [x, y] = coordStr.trim().split(' ').map(Number);
|
||||
return [x, y]; // [lng, lat]
|
||||
});
|
||||
|
||||
return coordinates;
|
||||
};
|
||||
|
||||
export const convertWKTtoLatLngString = (wktString: string) => {
|
||||
if (
|
||||
!wktString ||
|
||||
typeof wktString !== 'string' ||
|
||||
!wktString.startsWith('MULTIPOLYGON')
|
||||
) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const matched = wktString.match(/MULTIPOLYGON\s*\(\(\((.*)\)\)\)/);
|
||||
if (!matched) return [];
|
||||
|
||||
const polygons = matched[1]
|
||||
.split(')),((') // chia các polygon
|
||||
.map((polygonStr) =>
|
||||
polygonStr
|
||||
.trim()
|
||||
.split(',')
|
||||
.map((coordStr) => {
|
||||
const [x, y] = coordStr.trim().split(' ').map(Number);
|
||||
return [x, y];
|
||||
}),
|
||||
);
|
||||
|
||||
return polygons;
|
||||
};
|
||||
|
||||
export const getBanzoneNameByType = (type: number) => {
|
||||
switch (type) {
|
||||
case 1:
|
||||
return 'Cấm đánh bắt';
|
||||
case 2:
|
||||
return 'Cấm di chuyển';
|
||||
case 3:
|
||||
return 'Vùng an toàn';
|
||||
default:
|
||||
return 'Chưa có';
|
||||
}
|
||||
};
|
||||
|
||||
const PI = 3.1416;
|
||||
/**
|
||||
* Hàm tính bán kính từ diện tích (hecta) để hiển thị trên bản đồ
|
||||
* @param areaInHa - Diện tích tính bằng hecta
|
||||
* @returns Bán kính tính bằng mét
|
||||
*/
|
||||
export const getCircleRadius = (areaInHa: number) => {
|
||||
const areaInSquareMeters = areaInHa * 10000;
|
||||
const radius = Math.sqrt(areaInSquareMeters / PI);
|
||||
return Math.round(radius); // Trả về số nguyên (mét)
|
||||
};
|
||||
/**
|
||||
* Hàm tính diện tích (hecta) từ bán kính (mét)
|
||||
* @param radiusInMeters - Bán kính tính bằng mét
|
||||
* @returns Diện tích tính bằng hecta (ha), làm tròn số nguyên
|
||||
*/
|
||||
export const getAreaFromRadius = (radiusInMeters: number) => {
|
||||
const areaInSquareMeters = PI * Math.pow(radiusInMeters, 2);
|
||||
const areaInHa = areaInSquareMeters / 10000;
|
||||
return Math.round(areaInHa); // Trả về số nguyên (ha)
|
||||
};
|
||||
|
||||
export const getAlarmTypeName = (type: number): ZoneData['type'] => {
|
||||
switch (type) {
|
||||
case 1:
|
||||
return 'warning';
|
||||
case 2:
|
||||
return 'alarm';
|
||||
default:
|
||||
return 'default';
|
||||
}
|
||||
};
|
||||
33
src/utils/slave/sgw/mapUtils.ts
Normal file
33
src/utils/slave/sgw/mapUtils.ts
Normal file
@@ -0,0 +1,33 @@
|
||||
import {
|
||||
GEOSERVER_URL,
|
||||
WORKSPACE,
|
||||
} from '@/pages/Slave/SGW/Map/config/MapConfig';
|
||||
import ImageLayer from 'ol/layer/Image';
|
||||
import { ImageWMS } from 'ol/source';
|
||||
|
||||
/**
|
||||
* Tạo một WMS tile layer.
|
||||
*/
|
||||
export function createWmsLayer(layerName: string) {
|
||||
// return new TileLayer({
|
||||
// visible: true,
|
||||
// source: new TileWMS({
|
||||
// url: `${GEOSERVER_URL}/${WORKSPACE}/wms`,
|
||||
// params: {
|
||||
// LAYERS: `${WORKSPACE}:${layerName}`,
|
||||
// TILED: true,
|
||||
// FORMAT: "image/png",
|
||||
// TRANSPARENT: true,
|
||||
// },
|
||||
// serverType: "geoserver",
|
||||
// crossOrigin: "anonymous",
|
||||
// }),
|
||||
// ...options,
|
||||
// });
|
||||
return new ImageLayer({
|
||||
source: new ImageWMS({
|
||||
url: `${GEOSERVER_URL}/${WORKSPACE}/wms`,
|
||||
params: { LAYERS: `${WORKSPACE}:${layerName}` },
|
||||
}),
|
||||
});
|
||||
}
|
||||
25
src/utils/slave/sgw/timeUtils.ts
Normal file
25
src/utils/slave/sgw/timeUtils.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
export const formatDate = (dateString: string | number | Date) => {
|
||||
return new Date(dateString).toLocaleDateString('vi-VN', {
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Chuyển đổi unix time (string hoặc int) sang định dạng DD/MM/YY HH:mm:ss
|
||||
* @param unixTime Unix time (giây hoặc mili giây, dạng string hoặc int)
|
||||
* @returns Chuỗi thời gian định dạng DD/MM/YY HH:mm:ss
|
||||
*/
|
||||
export function formatUnixTime(unixTime: string | number): string {
|
||||
let ts = typeof unixTime === 'string' ? parseInt(unixTime, 10) : unixTime;
|
||||
if (ts < 1e12) ts *= 1000; // Nếu là giây, chuyển sang mili giây
|
||||
const d = new Date(ts);
|
||||
const pad = (n: number) => n.toString().padStart(2, '0');
|
||||
return `${pad(d.getDate())}/${pad(d.getMonth() + 1)}/${d
|
||||
.getFullYear()
|
||||
.toString()
|
||||
.slice(-2)} ${pad(d.getHours())}:${pad(d.getMinutes())}:${pad(
|
||||
d.getSeconds(),
|
||||
)}`;
|
||||
}
|
||||
18
src/utils/slave/sgw/tripUtils.tsx
Normal file
18
src/utils/slave/sgw/tripUtils.tsx
Normal file
@@ -0,0 +1,18 @@
|
||||
export const getTripState = (type: number | undefined) => {
|
||||
switch (type) {
|
||||
case 0:
|
||||
return 'Chưa phê duyệt, đang tạo';
|
||||
case 1:
|
||||
return 'Đang chờ phê duyệt';
|
||||
case 2:
|
||||
return 'Đã phê duyệt';
|
||||
case 3:
|
||||
return 'Đã xuất bến';
|
||||
case 4:
|
||||
return 'Đã hoàn thành';
|
||||
case 5:
|
||||
return 'Đã huỷ';
|
||||
default:
|
||||
return '-';
|
||||
}
|
||||
};
|
||||
70
src/utils/slave/sgw/wsClient.ts
Normal file
70
src/utils/slave/sgw/wsClient.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import ReconnectingWebSocket from 'reconnecting-websocket';
|
||||
import { getToken } from '../../storage';
|
||||
|
||||
type MessageHandler = (data: any) => void;
|
||||
|
||||
class WSClient {
|
||||
private ws: ReconnectingWebSocket | null = null;
|
||||
private handler = new Set<MessageHandler>();
|
||||
|
||||
/**
|
||||
* Kết nối tới WebSocket server.
|
||||
* @param url Địa chỉ WebSocket server
|
||||
* @param isAuthenticated Có sử dụng token xác thực hay không
|
||||
*/
|
||||
connect(url: string, isAuthenticated: boolean) {
|
||||
if (this.ws) return;
|
||||
let token = '';
|
||||
if (isAuthenticated) {
|
||||
token = getToken();
|
||||
}
|
||||
const wsUrl = isAuthenticated ? `${url}?token=${token}` : url;
|
||||
this.ws = new ReconnectingWebSocket(wsUrl, [], {
|
||||
maxRetries: 10,
|
||||
maxReconnectionDelay: 10000,
|
||||
});
|
||||
this.ws.onmessage = (event) => {
|
||||
try {
|
||||
const data = JSON.parse(event.data);
|
||||
this.handler.forEach((fn) => fn(data));
|
||||
} catch (error) {
|
||||
console.error('WS Parse Error: ', error);
|
||||
}
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Ngắt kết nối WebSocket và giải phóng tài nguyên.
|
||||
*/
|
||||
disconnect() {
|
||||
this.ws?.close();
|
||||
this.ws = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gửi dữ liệu qua WebSocket.
|
||||
* @param data Dữ liệu cần gửi (sẽ được stringify)
|
||||
*/
|
||||
send(data: any) {
|
||||
this.ws?.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Đăng ký callback để nhận dữ liệu từ WebSocket.
|
||||
* @param cb Hàm callback xử lý dữ liệu nhận được
|
||||
* @returns Hàm hủy đăng ký callback
|
||||
*/
|
||||
subscribe(cb: MessageHandler) {
|
||||
this.handler.add(cb);
|
||||
return () => this.handler.delete(cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Kiểm tra trạng thái kết nối WebSocket.
|
||||
* @returns true nếu đã kết nối, ngược lại là false
|
||||
*/
|
||||
isConnected() {
|
||||
return this.ws?.readyState === WebSocket.OPEN;
|
||||
}
|
||||
}
|
||||
|
||||
export const wsClient = new WSClient();
|
||||
Reference in New Issue
Block a user