feat(core): sgw-device-ui

This commit is contained in:
Tran Anh Tuan
2025-09-26 18:22:04 +07:00
parent 466e931537
commit 2707b92f7e
88 changed files with 19104 additions and 0 deletions

111
src/utils/fishRarity.ts Normal file
View File

@@ -0,0 +1,111 @@
export const fishRarities: API.FishRarity[] = [
{
id: 1,
code: 'common',
label: 'Phổ biến',
description: 'Loài không có nguy cơ bị đe dọa',
iucn_code: null,
cites_appendix: null,
vn_law: false,
},
{
id: 2,
code: 'near-threatened',
label: 'Gần bị đe dọa',
description: 'Có nguy cơ trong tương lai gần',
iucn_code: 'NT',
cites_appendix: null,
vn_law: false,
},
{
id: 3,
code: 'vulnerable',
label: 'Dễ bị tổn thương',
description: 'Loài có nguy cơ tuyệt chủng mức trung bình',
iucn_code: 'VU',
cites_appendix: null,
vn_law: false,
},
{
id: 4,
code: 'endangered',
label: 'Nguy cấp',
description: 'Nguy cơ tuyệt chủng cao',
iucn_code: 'EN',
cites_appendix: null,
vn_law: false,
},
{
id: 5,
code: 'critically-endangered',
label: 'Cực kỳ nguy cấp',
description: 'Nguy cơ tuyệt chủng rất cao',
iucn_code: 'CR',
cites_appendix: null,
vn_law: false,
},
{
id: 6,
code: 'cites-app-i',
label: 'CITES Phụ lục I',
description: 'Cấm hoàn toàn buôn bán quốc tế',
iucn_code: null,
cites_appendix: null,
vn_law: false,
},
{
id: 7,
code: 'cites-app-ii',
label: 'CITES Phụ lục II',
description: 'Kiểm soát buôn bán quốc tế',
iucn_code: null,
cites_appendix: null,
vn_law: false,
},
{
id: 8,
code: 'protected-vn',
label: 'Bảo vệ theo Luật VN',
description: 'Cấm đánh bắt hoặc hạn chế tại VN',
iucn_code: null,
cites_appendix: null,
vn_law: false,
},
];
export function getRarityById(id: number) {
const rarity = fishRarities.find((item) => item.id === id);
// Kiểm tra xem đối tượng có được tìm thấy hay không
if (rarity) {
// Nếu tìm thấy, trả về label và description
return {
rarityLabel: rarity.label,
rarityDescription: rarity.description,
};
}
// Nếu không tìm thấy, trả về null
return null;
}
export const getColorByRarityLevel = (level: number) => {
switch (level) {
case 2:
return '#FFCC00';
case 3:
return '#FFA500';
case 4:
return '#FF7F50';
case 5:
return '#FF6347';
case 6:
return '#FF4500';
case 7:
return '#FF0000';
case 8:
return '#8B0000';
default:
return 'B6F500';
}
};

21
src/utils/format.ts Normal file
View File

@@ -0,0 +1,21 @@
// 示例方法,没有实际意义
export function trim(str: string) {
return str.trim();
}
export const DURATION_POLLING = 15000; //15s
export const DURATION_CHART = 300000; //5m
export const DEFAULT_LIMIT = 200;
export const DATE_TIME_FORMAT = 'DD/MM/YY HH:mm:ss';
export const TIME_FORMAT = 'HH:mm:ss';
export const DATE_FORMAT = 'DD/MM/YYYY';
export const DURATION_DISCONNECTED = 300; //senconds
export const DURATION_POLLING_PRESENTATIONS = 120000; //miliseconds
export const DURATION_POLLING_CHART = 60000; //miliseconds
export const WAIT_DURATION = 1500;
export const WAIT_ACK_DURATION = 5000;
export const STATUS_NORMAL = 0;
export const STATUS_WARNING = 1;
export const STATUS_DANGEROUS = 2;
export const STATUS_SOS = 3;

View File

@@ -0,0 +1,13 @@
export function parseJwt(token: string) {
if (!token) return null;
const base64Url = token.split('.')[1];
const base64 = base64Url.replace(/-/g, '+').replace(/_/g, '/');
const jsonPayload = decodeURIComponent(
atob(base64)
.split('')
.map((c) => '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2))
.join(''),
);
return JSON.parse(jsonPayload);
}

View File

@@ -0,0 +1,13 @@
import { TOKEN } from '@/constants';
export function getToken(): string {
return localStorage.getItem(TOKEN) || '';
}
export function setToken(token: string) {
localStorage.setItem(TOKEN, token);
}
export function removeToken() {
localStorage.removeItem(TOKEN);
}

73
src/utils/mapUtils.ts Normal file
View File

@@ -0,0 +1,73 @@
import GeoJSON from 'ol/format/GeoJSON';
import VectorLayer from 'ol/layer/Vector';
import VectorSource from 'ol/source/Vector';
import Fill from 'ol/style/Fill';
import Stroke from 'ol/style/Stroke';
import Style from 'ol/style/Style';
import Text from 'ol/style/Text';
export const OL_PROJECTION = 'EPSG:3857';
export const createGeoJSONLayer = (options: any) => {
const { data, style = null, popupProperties = null } = options;
const source =
typeof data === 'string'
? new VectorSource({
url: data,
format: new GeoJSON(),
})
: new VectorSource({
features: new GeoJSON().readFeatures(data, {
dataProjection: 'EPSG:4326', // projection của dữ liệu
featureProjection: 'EPSG:3857', // projection bản đồ
}),
});
return new VectorLayer({
source,
style: style,
properties: {
popupProperties,
},
});
};
const createLabelStyle = (feature: any) => {
const tenTinh = feature.get('tenTinh');
return new Style({
stroke: new Stroke({
color: '#333',
width: 1,
}),
fill: new Fill({
color: 'rgba(0, 150, 255, 0.2)',
}),
text: new Text({
font: '14px Calibri,sans-serif',
fill: new Fill({ color: '#000' }),
stroke: new Stroke({ color: '#fff', width: 3 }),
text: tenTinh || '',
}),
});
};
export const createLabelAndFillStyle = (
fillColor = 'rgba(255,0,0,0.1)',
strokeColor = '#ff0000',
) => {
return (feature: any) => {
const tenTinh = feature.get('tenTinh');
return new Style({
stroke: new Stroke({ color: strokeColor, width: 1 }),
fill: new Fill({ color: fillColor }),
text: new Text({
font: '14px Calibri,sans-serif',
fill: new Fill({ color: '#000' }),
stroke: new Stroke({ color: '#fff', width: 3 }),
text: tenTinh || '',
}),
});
};
};

91
src/utils/sosUtil.ts Normal file
View File

@@ -0,0 +1,91 @@
/**
* Định nghĩa cấu trúc cho mỗi lý do cần hỗ trợ/SOS
*/
interface SosMessage {
ma: number; // Mã số thứ tự của lý do
moTa: string; // Mô tả ngắn gọn về sự cố
mucDoNghiemTrong: string;
chiTiet: string; // Chi tiết sự cố
}
/**
* Mảng 10 lý do phát tín hiệu SOS/Yêu cầu trợ giúp trên biển
* Sắp xếp từ nhẹ (yêu cầu hỗ trợ) đến nặng (SOS khẩn cấp)
*/
export const sosMessage: SosMessage[] = [
{
ma: 11,
moTa: 'Tình huống khẩn cấp, không kịp chọn !!!',
mucDoNghiemTrong: 'Nguy Hiem Can Ke (SOS)',
chiTiet:
'Tình huống nghiêm trọng nhất, đe dọa trực tiếp đến tính mạng tất cả người trên tàu.',
},
{
ma: 1,
moTa: 'Hỏng hóc động cơ không tự khắc phục được',
mucDoNghiemTrong: 'Nhe',
chiTiet: 'Tàu bị trôi hoặc mắc cạn nhẹ; cần tàu lai hoặc thợ máy.',
},
{
ma: 2,
moTa: 'Thiếu nhiên liệu/thực phẩm/nước uống nghiêm trọng',
mucDoNghiemTrong: 'Nhe',
chiTiet:
'Dự trữ thiết yếu cạn kiệt do hành trình kéo dài không lường trước được.',
},
{
ma: 3,
moTa: 'Sự cố y tế không nguy hiểm đến tính mạng',
mucDoNghiemTrong: 'Trung Binh',
chiTiet:
'Cần chăm sóc y tế chuyên nghiệp khẩn cấp (ví dụ: gãy xương, viêm ruột thừa).',
},
{
ma: 4,
moTa: 'Hỏng hóc thiết bị định vị/thông tin liên lạc chính',
mucDoNghiemTrong: 'Trung Binh',
chiTiet: 'Mất khả năng xác định vị trí hoặc liên lạc, tăng rủi ro bị lạc.',
},
{
ma: 5,
moTa: 'Thời tiết cực đoan sắp tới không kịp trú ẩn',
mucDoNghiemTrong: 'Trung Binh',
chiTiet:
'Tàu không kịp chạy vào nơi trú ẩn an toàn trước cơn bão lớn hoặc gió giật mạnh.',
},
{
ma: 6,
moTa: 'Va chạm gây hư hỏng cấu trúc',
mucDoNghiemTrong: 'Nang',
chiTiet:
'Tàu bị hư hại một phần do va chạm, cần kiểm tra và hỗ trợ lai dắt khẩn cấp.',
},
{
ma: 7,
moTa: 'Có cháy/hỏa hoạn trên tàu không kiểm soát được',
mucDoNghiemTrong: 'Nang',
chiTiet:
'Lửa bùng phát vượt quá khả năng chữa cháy của tàu, nguy cơ cháy lan.',
},
{
ma: 8,
moTa: 'Tàu bị thủng/nước vào không kiểm soát được',
mucDoNghiemTrong: 'Rat Nang',
chiTiet:
'Nước tràn vào khoang quá nhanh, vượt quá khả năng bơm tát, đe dọa tàu chìm.',
},
{
ma: 9,
moTa: 'Sự cố y tế nguy hiểm đến tính mạng (MEDEVAC)',
mucDoNghiemTrong: 'Rat Nang',
chiTiet:
'Thương tích/bệnh tật nghiêm trọng, cần sơ tán y tế (MEDEVAC) ngay lập tức bằng trực thăng/tàu cứu hộ.',
},
{
ma: 10,
moTa: 'Tàu bị chìm/lật úp hoàn toàn hoặc sắp xảy ra',
mucDoNghiemTrong: 'Nguy Hiem Can Ke (SOS)',
chiTiet:
'Tình huống nghiêm trọng nhất, đe dọa trực tiếp đến tính mạng tất cả người trên tàu.',
},
];