refactor(typings): Refactor user and profile models; update API response types
This commit is contained in:
@@ -1,185 +0,0 @@
|
|||||||
# ✅ Zone (Banzone) API Migration - Complete
|
|
||||||
|
|
||||||
## Migration Banzone/Zone API vào SGW Module
|
|
||||||
|
|
||||||
### Files Created
|
|
||||||
|
|
||||||
1. **ZoneController.ts** - `src/services/slave/sgw/ZoneController.ts`
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
✅ apiGetAllBanzones(body) - Get all banzones with pagination
|
|
||||||
✅ apiRemoveBanzone(id, groupID) - Remove a banzone
|
|
||||||
✅ apiGetZoneById(zoneId) - Get banzone by ID
|
|
||||||
✅ apiCreateBanzone(body) - Create new banzone
|
|
||||||
✅ apiUpdateBanzone(id, body) - Update banzone
|
|
||||||
```
|
|
||||||
|
|
||||||
2. **Type Definitions** - Added to `src/services/slave/sgw/sgw.typing.d.ts`
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
✅ Banzone
|
|
||||||
✅ Condition
|
|
||||||
✅ Geom
|
|
||||||
✅ ZoneResponse
|
|
||||||
✅ ZoneBodyRequest
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **Route Constants** - Added to `src/constants/slave/sgw/routes.ts`
|
|
||||||
```typescript
|
|
||||||
✅ SGW_ROUTE_BANZONES = '/api/sgw/banzones'
|
|
||||||
✅ SGW_ROUTE_BANZONES_LIST = '/api/sgw/banzones/list'
|
|
||||||
```
|
|
||||||
|
|
||||||
### Files Updated
|
|
||||||
|
|
||||||
- ✅ `src/pages/Slave/SGW/Map/components/ShipDetail.tsx`
|
|
||||||
- Updated import: `@/services/controller/ZoneController` → `@/services/slave/sgw/ZoneController`
|
|
||||||
- Updated types: `API.Thing` → `SgwModel.SgwThing`
|
|
||||||
- Updated types: `API.UserResponse` → `MasterModel.UserResponse`
|
|
||||||
- Updated types: `API.Geom` → `SgwModel.Geom`
|
|
||||||
|
|
||||||
### Migration Changes
|
|
||||||
|
|
||||||
**Before:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { apiGetZoneById } from '@/services/controller/ZoneController';
|
|
||||||
|
|
||||||
thing: API.Thing
|
|
||||||
const zone_geom: API.Geom = ...
|
|
||||||
```
|
|
||||||
|
|
||||||
**After:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { apiGetZoneById } from '@/services/slave/sgw/ZoneController';
|
|
||||||
|
|
||||||
thing: SgwModel.SgwThing
|
|
||||||
const zone_geom: SgwModel.Geom = ...
|
|
||||||
```
|
|
||||||
|
|
||||||
### Type Definitions
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
declare namespace SgwModel {
|
|
||||||
interface Banzone {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
province_code?: string;
|
|
||||||
type?: number;
|
|
||||||
conditions?: Condition[];
|
|
||||||
description?: string;
|
|
||||||
geometry?: string;
|
|
||||||
enabled?: boolean;
|
|
||||||
created_at?: Date;
|
|
||||||
updated_at?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Condition {
|
|
||||||
max?: number;
|
|
||||||
min?: number;
|
|
||||||
type?: 'length_limit' | 'month_range' | 'date_range';
|
|
||||||
to?: number;
|
|
||||||
from?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Geom {
|
|
||||||
geom_type?: number;
|
|
||||||
geom_poly?: string;
|
|
||||||
geom_lines?: string;
|
|
||||||
geom_point?: string;
|
|
||||||
geom_radius?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ZoneResponse {
|
|
||||||
total?: number;
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
banzones?: Banzone[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ZoneBodyRequest {
|
|
||||||
name?: string;
|
|
||||||
province_code?: string;
|
|
||||||
type?: number;
|
|
||||||
conditions?: Condition[];
|
|
||||||
description?: string;
|
|
||||||
geometry?: string;
|
|
||||||
enabled?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### API Usage Examples
|
|
||||||
|
|
||||||
**Get Zone by ID:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { apiGetZoneById } from '@/services/slave/sgw/ZoneController';
|
|
||||||
|
|
||||||
const zone = await apiGetZoneById('zone-123');
|
|
||||||
const geometry: SgwModel.Geom = JSON.parse(zone.geometry || '{}');
|
|
||||||
```
|
|
||||||
|
|
||||||
**Create Banzone:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { apiCreateBanzone } from '@/services/slave/sgw/ZoneController';
|
|
||||||
|
|
||||||
const zoneData: SgwModel.ZoneBodyRequest = {
|
|
||||||
name: 'Vùng cấm mùa sinh sản',
|
|
||||||
province_code: 'QN',
|
|
||||||
type: 1,
|
|
||||||
enabled: true,
|
|
||||||
conditions: [
|
|
||||||
{
|
|
||||||
type: 'month_range',
|
|
||||||
from: 4,
|
|
||||||
to: 8,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
geometry: JSON.stringify({
|
|
||||||
geom_type: 1,
|
|
||||||
geom_poly: 'POLYGON(...)',
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
await apiCreateBanzone(zoneData);
|
|
||||||
```
|
|
||||||
|
|
||||||
**Get All Banzones:**
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { apiGetAllBanzones } from '@/services/slave/sgw/ZoneController';
|
|
||||||
|
|
||||||
const response = await apiGetAllBanzones({
|
|
||||||
offset: 0,
|
|
||||||
limit: 20,
|
|
||||||
order: 'name',
|
|
||||||
dir: 'asc',
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Status: ✅ Complete
|
|
||||||
|
|
||||||
- ✅ 5 API functions migrated
|
|
||||||
- ✅ 5 type definitions added
|
|
||||||
- ✅ 2 route constants added
|
|
||||||
- ✅ 1 file updated (ShipDetail.tsx)
|
|
||||||
- ✅ 0 compilation errors
|
|
||||||
|
|
||||||
## Total SGW Migration Progress
|
|
||||||
|
|
||||||
| Module | APIs | Types | Status |
|
|
||||||
| --------- | ------ | ------- | ------ |
|
|
||||||
| Ship | 12 | 15+ | ✅ |
|
|
||||||
| Trip | 17 | 21+ | ✅ |
|
|
||||||
| Photo | 2 | 2 | ✅ |
|
|
||||||
| Zone | 5 | 5 | ✅ |
|
|
||||||
| **TOTAL** | **36** | **43+** | ✅ |
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Migration Date:** January 23, 2026
|
|
||||||
**Status:** ✅ Complete
|
|
||||||
**Ready for Testing:** YES
|
|
||||||
@@ -25,8 +25,8 @@ import {
|
|||||||
} from './utils/storage';
|
} from './utils/storage';
|
||||||
const isProdBuild = process.env.NODE_ENV === 'production';
|
const isProdBuild = process.env.NODE_ENV === 'production';
|
||||||
export type InitialStateResponse = {
|
export type InitialStateResponse = {
|
||||||
getUserProfile?: () => Promise<MasterModel.ProfileResponse | undefined>;
|
getUserProfile?: () => Promise<MasterModel.UserResponse | undefined>;
|
||||||
currentUserProfile?: MasterModel.ProfileResponse;
|
currentUserProfile?: MasterModel.UserResponse;
|
||||||
theme?: 'light' | 'dark';
|
theme?: 'light' | 'dark';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { Dropdown } from 'antd';
|
|||||||
export const AvatarDropdown = ({
|
export const AvatarDropdown = ({
|
||||||
currentUserProfile,
|
currentUserProfile,
|
||||||
}: {
|
}: {
|
||||||
currentUserProfile?: MasterModel.ProfileResponse;
|
currentUserProfile?: MasterModel.UserResponse;
|
||||||
}) => {
|
}) => {
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -6,10 +6,9 @@ import {
|
|||||||
WarningOutlined,
|
WarningOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import { useIntl } from '@umijs/max';
|
import { useIntl } from '@umijs/max';
|
||||||
import { Flex, Tag, Tooltip } from 'antd';
|
import { Flex, Tag, theme, Tooltip } from 'antd';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { TagStateCallbackPayload } from '../../pages/Slave/SGW/Map/type';
|
import { TagStateCallbackPayload } from '../../pages/Slave/SGW/Map/type';
|
||||||
import style from './index.less';
|
|
||||||
|
|
||||||
type TagStateProps = {
|
type TagStateProps = {
|
||||||
normalCount?: number;
|
normalCount?: number;
|
||||||
@@ -35,7 +34,59 @@ const TagState = ({
|
|||||||
sos: false,
|
sos: false,
|
||||||
disconnected: false,
|
disconnected: false,
|
||||||
});
|
});
|
||||||
|
const { token } = theme.useToken();
|
||||||
const intl = useIntl();
|
const intl = useIntl();
|
||||||
|
|
||||||
|
// Style variants using antd theme tokens for dark mode support
|
||||||
|
const getTagStyle = (
|
||||||
|
type: 'normal' | 'warning' | 'critical' | 'offline',
|
||||||
|
isActive: boolean,
|
||||||
|
) => {
|
||||||
|
const baseStyle = {
|
||||||
|
borderRadius: token.borderRadiusSM,
|
||||||
|
borderWidth: 1,
|
||||||
|
borderStyle: 'solid' as const,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (type === 'normal') {
|
||||||
|
return {
|
||||||
|
...baseStyle,
|
||||||
|
color: isActive ? token.colorSuccess : token.colorSuccess,
|
||||||
|
backgroundColor: isActive
|
||||||
|
? token.colorSuccessBg
|
||||||
|
: token.colorBgContainer,
|
||||||
|
borderColor: token.colorSuccessBorder,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (type === 'warning') {
|
||||||
|
return {
|
||||||
|
...baseStyle,
|
||||||
|
color: isActive ? token.colorWarning : token.colorWarning,
|
||||||
|
backgroundColor: isActive
|
||||||
|
? token.colorWarningBg
|
||||||
|
: token.colorBgContainer,
|
||||||
|
borderColor: token.colorWarningBorder,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (type === 'critical') {
|
||||||
|
return {
|
||||||
|
...baseStyle,
|
||||||
|
color: isActive ? token.colorError : token.colorError,
|
||||||
|
backgroundColor: isActive ? token.colorErrorBg : token.colorBgContainer,
|
||||||
|
borderColor: token.colorErrorBorder,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// offline
|
||||||
|
return {
|
||||||
|
...baseStyle,
|
||||||
|
color: token.colorTextSecondary,
|
||||||
|
backgroundColor: isActive
|
||||||
|
? token.colorFillSecondary
|
||||||
|
: token.colorBgContainer,
|
||||||
|
borderColor: token.colorBorder,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
const handleTagClick = (key: keyof typeof activeStates) => {
|
const handleTagClick = (key: keyof typeof activeStates) => {
|
||||||
const newStates = { ...activeStates, [key]: !activeStates[key] };
|
const newStates = { ...activeStates, [key]: !activeStates[key] };
|
||||||
setActiveStates(newStates);
|
setActiveStates(newStates);
|
||||||
@@ -45,39 +96,11 @@ const TagState = ({
|
|||||||
isWarning: newStates.warning,
|
isWarning: newStates.warning,
|
||||||
isCritical: newStates.critical,
|
isCritical: newStates.critical,
|
||||||
isSos: newStates.sos,
|
isSos: newStates.sos,
|
||||||
isDisconected: newStates.disconnected,
|
isDisconnected: newStates.disconnected,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// const tagStyles = {
|
|
||||||
// sos: activeStates.sos
|
|
||||||
// ? { background: '#ff4d4f', color: '#fff', borderColor: '#ff4d4f' }
|
|
||||||
// : { background: '#fff1f0', color: '#cf1322', borderColor: '#ffa39e' },
|
|
||||||
// normal: activeStates.normal
|
|
||||||
// ? { background: '#52c41a', color: '#fff', borderColor: '#52c41a' }
|
|
||||||
// : { background: '#f6ffed', color: '#389e0d', borderColor: '#b7eb8f' },
|
|
||||||
// warning: activeStates.warning
|
|
||||||
// ? {
|
|
||||||
// background: '#faad14',
|
|
||||||
// color: '#fff',
|
|
||||||
// borderColor: '#faad14',
|
|
||||||
// hoverColor: '#ffe58f',
|
|
||||||
// }
|
|
||||||
// : {
|
|
||||||
// background: '#fffbe6',
|
|
||||||
// color: '#d48806',
|
|
||||||
// borderColor: '#ffe58f',
|
|
||||||
// hoverColor: '#faad14',
|
|
||||||
// },
|
|
||||||
// critical: activeStates.critical
|
|
||||||
// ? { background: '#d4380d', color: '#fff', borderColor: '#d4380d' }
|
|
||||||
// : { background: '#fff2e8', color: '#d4380d', borderColor: '#ffd8bf' },
|
|
||||||
// disconnected: activeStates.disconnected
|
|
||||||
// ? { background: '#8c8c8c', color: '#fff', borderColor: '#8c8c8c' }
|
|
||||||
// : { background: '#f5f5f5', color: '#8c8c8c', borderColor: '#d9d9d9' },
|
|
||||||
// };
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
gap={1}
|
gap={1}
|
||||||
@@ -94,13 +117,12 @@ const TagState = ({
|
|||||||
{sosCount !== undefined && (
|
{sosCount !== undefined && (
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'thing.status.sos',
|
id: 'common.level.sos',
|
||||||
defaultMessage: 'SOS',
|
defaultMessage: 'SOS',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Tag.CheckableTag
|
<Tag.CheckableTag
|
||||||
className={activeStates.sos ? style.criticalActive : style.critical}
|
style={getTagStyle('critical', activeStates.sos)}
|
||||||
// style={tagStyles.sos}
|
|
||||||
icon={<AlertOutlined />}
|
icon={<AlertOutlined />}
|
||||||
checked={activeStates.sos}
|
checked={activeStates.sos}
|
||||||
onChange={() => handleTagClick('sos')}
|
onChange={() => handleTagClick('sos')}
|
||||||
@@ -113,13 +135,12 @@ const TagState = ({
|
|||||||
{/* {normalCount > 0 && ( */}
|
{/* {normalCount > 0 && ( */}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'thing.status.normal',
|
id: 'common.level.normal',
|
||||||
defaultMessage: 'Normal',
|
defaultMessage: 'Normal',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Tag.CheckableTag
|
<Tag.CheckableTag
|
||||||
className={activeStates.normal ? style.normalActive : style.normal}
|
style={getTagStyle('normal', activeStates.normal)}
|
||||||
// style={tagStyles.normal}
|
|
||||||
icon={<CheckOutlined />}
|
icon={<CheckOutlined />}
|
||||||
checked={activeStates.normal}
|
checked={activeStates.normal}
|
||||||
onChange={() => handleTagClick('normal')}
|
onChange={() => handleTagClick('normal')}
|
||||||
@@ -131,14 +152,13 @@ const TagState = ({
|
|||||||
{/* {warningCount > 0 && ( */}
|
{/* {warningCount > 0 && ( */}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'thing.status.warning',
|
id: 'common.level.warning',
|
||||||
defaultMessage: 'Warning',
|
defaultMessage: 'Warning',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Tag.CheckableTag
|
<Tag.CheckableTag
|
||||||
className={activeStates.warning ? style.warningActive : style.warning}
|
style={getTagStyle('warning', activeStates.warning)}
|
||||||
icon={<WarningOutlined />}
|
icon={<WarningOutlined />}
|
||||||
// style={tagStyles.warning}
|
|
||||||
checked={activeStates.warning}
|
checked={activeStates.warning}
|
||||||
onChange={() => handleTagClick('warning')}
|
onChange={() => handleTagClick('warning')}
|
||||||
>
|
>
|
||||||
@@ -149,16 +169,13 @@ const TagState = ({
|
|||||||
{/* {criticalCount > 0 && ( */}
|
{/* {criticalCount > 0 && ( */}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'thing.status.critical',
|
id: 'common.level.critical',
|
||||||
defaultMessage: 'Critical',
|
defaultMessage: 'Critical',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Tag.CheckableTag
|
<Tag.CheckableTag
|
||||||
className={
|
style={getTagStyle('critical', activeStates.critical)}
|
||||||
activeStates.critical ? style.criticalActive : style.critical
|
|
||||||
}
|
|
||||||
icon={<ExclamationOutlined />}
|
icon={<ExclamationOutlined />}
|
||||||
// style={tagStyles.critical}
|
|
||||||
checked={activeStates.critical}
|
checked={activeStates.critical}
|
||||||
onChange={() => handleTagClick('critical')}
|
onChange={() => handleTagClick('critical')}
|
||||||
>
|
>
|
||||||
@@ -169,16 +186,13 @@ const TagState = ({
|
|||||||
{/* {disconnectedCount > 0 && ( */}
|
{/* {disconnectedCount > 0 && ( */}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
title={intl.formatMessage({
|
title={intl.formatMessage({
|
||||||
id: 'thing.status.disconnected',
|
id: 'common.level.disconnected',
|
||||||
defaultMessage: 'Disconnected',
|
defaultMessage: 'Disconnected',
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
<Tag.CheckableTag
|
<Tag.CheckableTag
|
||||||
className={
|
style={getTagStyle('offline', activeStates.disconnected)}
|
||||||
activeStates.disconnected ? style.offlineActive : style.offline
|
|
||||||
}
|
|
||||||
icon={<DisconnectOutlined />}
|
icon={<DisconnectOutlined />}
|
||||||
// style={tagStyles.disconnected}
|
|
||||||
checked={activeStates.disconnected}
|
checked={activeStates.disconnected}
|
||||||
onChange={() => handleTagClick('disconnected')}
|
onChange={() => handleTagClick('disconnected')}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -5,18 +5,28 @@ import {
|
|||||||
STATUS_WARNING,
|
STATUS_WARNING,
|
||||||
} from '@/constants';
|
} from '@/constants';
|
||||||
import { Badge } from 'antd';
|
import { Badge } from 'antd';
|
||||||
|
import IconFont from '../IconFont';
|
||||||
|
|
||||||
export const getBadgeStatus = (status: number) => {
|
export const getBadgeStatus = (status: number) => {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case STATUS_NORMAL:
|
case STATUS_NORMAL:
|
||||||
return <Badge status="success" />;
|
return <Badge size="default" status="success" />;
|
||||||
case STATUS_WARNING:
|
case STATUS_WARNING:
|
||||||
return <Badge status="warning" />;
|
return <Badge size="default" status="warning" />;
|
||||||
case STATUS_DANGEROUS:
|
case STATUS_DANGEROUS:
|
||||||
return <Badge status="error" />;
|
return <Badge size="default" status="error" />;
|
||||||
case STATUS_SOS:
|
case STATUS_SOS:
|
||||||
return <Badge status="error" />;
|
return <Badge size="default" status="error" />;
|
||||||
default:
|
default:
|
||||||
return <Badge status="default" />;
|
return <Badge size="default" status="default" />;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getBadgeConnection = (online: boolean) => {
|
||||||
|
switch (online) {
|
||||||
|
case true:
|
||||||
|
return <Badge status="processing" />;
|
||||||
|
default:
|
||||||
|
return <IconFont type="icon-cloud-disconnect" />;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ export default {
|
|||||||
'common.type': 'Type',
|
'common.type': 'Type',
|
||||||
'common.type.placeholder': 'Select Type',
|
'common.type.placeholder': 'Select Type',
|
||||||
'common.status': 'Status',
|
'common.status': 'Status',
|
||||||
|
'common.connect': 'Connection',
|
||||||
'common.province': 'Province',
|
'common.province': 'Province',
|
||||||
'common.description': 'Description',
|
'common.description': 'Description',
|
||||||
'common.description.required': 'Description is required',
|
'common.description.required': 'Description is required',
|
||||||
@@ -48,6 +49,7 @@ export default {
|
|||||||
'common.updated_at': 'Updated At',
|
'common.updated_at': 'Updated At',
|
||||||
'common.undefined': 'Undefined',
|
'common.undefined': 'Undefined',
|
||||||
'common.not_empty': 'Cannot be empty!',
|
'common.not_empty': 'Cannot be empty!',
|
||||||
|
'common.level.disconnected': 'Disconnected',
|
||||||
'common.level.normal': 'Normal',
|
'common.level.normal': 'Normal',
|
||||||
'common.level.warning': 'Warning',
|
'common.level.warning': 'Warning',
|
||||||
'common.level.critical': 'Critical',
|
'common.level.critical': 'Critical',
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ export default {
|
|||||||
'common.type': 'Loại',
|
'common.type': 'Loại',
|
||||||
'common.type.placeholder': 'Chọn loại',
|
'common.type.placeholder': 'Chọn loại',
|
||||||
'common.status': 'Trạng thái',
|
'common.status': 'Trạng thái',
|
||||||
|
'common.connect': 'Kết nối',
|
||||||
'common.province': 'Tỉnh',
|
'common.province': 'Tỉnh',
|
||||||
'common.description': 'Mô tả',
|
'common.description': 'Mô tả',
|
||||||
'common.description.required': 'Mô tả không được để trống',
|
'common.description.required': 'Mô tả không được để trống',
|
||||||
@@ -49,6 +50,7 @@ export default {
|
|||||||
'common.updated_at': 'Ngày cập nhật',
|
'common.updated_at': 'Ngày cập nhật',
|
||||||
'common.undefined': 'Chưa xác định',
|
'common.undefined': 'Chưa xác định',
|
||||||
'common.not_empty': 'Không được để trống!',
|
'common.not_empty': 'Không được để trống!',
|
||||||
|
'common.level.disconnected': 'Mất kết nối',
|
||||||
'common.level.normal': 'Bình thường',
|
'common.level.normal': 'Bình thường',
|
||||||
'common.level.warning': 'Cảnh báo',
|
'common.level.warning': 'Cảnh báo',
|
||||||
'common.level.critical': 'Nguy hiểm',
|
'common.level.critical': 'Nguy hiểm',
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ const ManagerDevicePage = () => {
|
|||||||
const offset = current === 1 ? 0 : (current - 1) * size;
|
const offset = current === 1 ? 0 : (current - 1) * size;
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
|
|
||||||
const metadata: Partial<MasterModel.ThingMetadata> = {};
|
const metadata: Partial<MasterModel.SearchThingMetadata> = {};
|
||||||
if (external_id) metadata.external_id = external_id;
|
if (external_id) metadata.external_id = external_id;
|
||||||
|
|
||||||
// Add group filter if groups are selected
|
// Add group filter if groups are selected
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ const SystemLogs = () => {
|
|||||||
const tableRef = useRef<ActionType>();
|
const tableRef = useRef<ActionType>();
|
||||||
const { token } = theme.useToken();
|
const { token } = theme.useToken();
|
||||||
|
|
||||||
const queryUserSource = async (): Promise<MasterModel.ProfileResponse[]> => {
|
const queryUserSource = async (): Promise<MasterModel.UserResponse[]> => {
|
||||||
try {
|
try {
|
||||||
const body: MasterModel.SearchUserPaginationBody = {
|
const body: MasterModel.SearchUserPaginationBody = {
|
||||||
offset: 0,
|
offset: 0,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ enum AssignTabsKey {
|
|||||||
const AssignUserPage = () => {
|
const AssignUserPage = () => {
|
||||||
const { userId } = useParams<{ userId: string }>();
|
const { userId } = useParams<{ userId: string }>();
|
||||||
const [userProfile, setUserProfile] =
|
const [userProfile, setUserProfile] =
|
||||||
useState<MasterModel.ProfileResponse | null>(null);
|
useState<MasterModel.UserResponse | null>(null);
|
||||||
const [loading, setLoading] = useState<boolean>(false);
|
const [loading, setLoading] = useState<boolean>(false);
|
||||||
const [tabSelected, setTabSelected] = useState<AssignTabsKey>(
|
const [tabSelected, setTabSelected] = useState<AssignTabsKey>(
|
||||||
AssignTabsKey.group,
|
AssignTabsKey.group,
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ import {
|
|||||||
import { useRef, useState } from 'react';
|
import { useRef, useState } from 'react';
|
||||||
const { Text } = Typography;
|
const { Text } = Typography;
|
||||||
type AssignGroupProps = {
|
type AssignGroupProps = {
|
||||||
user: MasterModel.ProfileResponse | null;
|
user: MasterModel.UserResponse | null;
|
||||||
};
|
};
|
||||||
const AssignGroup = ({ user }: AssignGroupProps) => {
|
const AssignGroup = ({ user }: AssignGroupProps) => {
|
||||||
const groupActionRef = useRef<ActionType>();
|
const groupActionRef = useRef<ActionType>();
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ type PolicyShareDefault = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
type ShareThingProps = {
|
type ShareThingProps = {
|
||||||
user: MasterModel.ProfileResponse | null;
|
user: MasterModel.UserResponse | null;
|
||||||
};
|
};
|
||||||
const ShareThing = ({ user }: ShareThingProps) => {
|
const ShareThing = ({ user }: ShareThingProps) => {
|
||||||
const listActionRef = useRef<ActionType>();
|
const listActionRef = useRef<ActionType>();
|
||||||
|
|||||||
@@ -34,19 +34,19 @@ const ManagerUserPage = () => {
|
|||||||
const [isLoading, setIsLoading] = useState<boolean>(false);
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
const [messageApi, contextHolder] = message.useMessage();
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
const [selectedRowsState, setSelectedRowsState] = useState<
|
const [selectedRowsState, setSelectedRowsState] = useState<
|
||||||
MasterModel.ProfileResponse[]
|
MasterModel.UserResponse[]
|
||||||
>([]);
|
>([]);
|
||||||
|
|
||||||
const [groupCheckedKeys, setGroupCheckedKeys] = useState<
|
const [groupCheckedKeys, setGroupCheckedKeys] = useState<
|
||||||
string | string[] | null
|
string | string[] | null
|
||||||
>(null);
|
>(null);
|
||||||
|
|
||||||
const handleClickAssign = (user: MasterModel.ProfileResponse) => {
|
const handleClickAssign = (user: MasterModel.UserResponse) => {
|
||||||
const path = `${ROUTE_MANAGER_USERS}/${user.id}/${ROUTE_MANAGER_USERS_PERMISSIONS}`;
|
const path = `${ROUTE_MANAGER_USERS}/${user.id}/${ROUTE_MANAGER_USERS_PERMISSIONS}`;
|
||||||
history.push(path);
|
history.push(path);
|
||||||
};
|
};
|
||||||
|
|
||||||
const columns: ProColumns<MasterModel.ProfileResponse>[] = [
|
const columns: ProColumns<MasterModel.UserResponse>[] = [
|
||||||
{
|
{
|
||||||
key: 'email',
|
key: 'email',
|
||||||
title: (
|
title: (
|
||||||
@@ -136,7 +136,7 @@ const ManagerUserPage = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const handleRemove = async (selectedRows: MasterModel.ProfileResponse[]) => {
|
const handleRemove = async (selectedRows: MasterModel.UserResponse[]) => {
|
||||||
const key = 'remove_user';
|
const key = 'remove_user';
|
||||||
if (!selectedRows) return true;
|
if (!selectedRows) return true;
|
||||||
|
|
||||||
@@ -151,7 +151,7 @@ const ManagerUserPage = () => {
|
|||||||
key,
|
key,
|
||||||
});
|
});
|
||||||
const allDelete = selectedRows.map(
|
const allDelete = selectedRows.map(
|
||||||
async (row: MasterModel.ProfileResponse) => {
|
async (row: MasterModel.UserResponse) => {
|
||||||
await apiDeleteUser(row?.id || '');
|
await apiDeleteUser(row?.id || '');
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -196,7 +196,7 @@ const ManagerUserPage = () => {
|
|||||||
/>
|
/>
|
||||||
</ProCard>
|
</ProCard>
|
||||||
<ProCard colSpan={{ xs: 24, sm: 24, md: 18, lg: 18, xl: 18 }}>
|
<ProCard colSpan={{ xs: 24, sm: 24, md: 18, lg: 18, xl: 18 }}>
|
||||||
<ProTable<MasterModel.ProfileResponse>
|
<ProTable<MasterModel.UserResponse>
|
||||||
columns={columns}
|
columns={columns}
|
||||||
tableLayout="auto"
|
tableLayout="auto"
|
||||||
actionRef={actionRef}
|
actionRef={actionRef}
|
||||||
@@ -210,7 +210,7 @@ const ManagerUserPage = () => {
|
|||||||
selectedRowKeys: selectedRowsState.map((row) => row.id!),
|
selectedRowKeys: selectedRowsState.map((row) => row.id!),
|
||||||
onChange: (
|
onChange: (
|
||||||
_: React.Key[],
|
_: React.Key[],
|
||||||
selectedRows: MasterModel.ProfileResponse[],
|
selectedRows: MasterModel.UserResponse[],
|
||||||
) => {
|
) => {
|
||||||
setSelectedRowsState(selectedRows);
|
setSelectedRowsState(selectedRows);
|
||||||
},
|
},
|
||||||
@@ -249,12 +249,12 @@ const ManagerUserPage = () => {
|
|||||||
let users = userByGroupResponses.users || [];
|
let users = userByGroupResponses.users || [];
|
||||||
// Apply filters
|
// Apply filters
|
||||||
if (email) {
|
if (email) {
|
||||||
users = users.filter((user: MasterModel.ProfileResponse) =>
|
users = users.filter((user: MasterModel.UserResponse) =>
|
||||||
user.email?.includes(email),
|
user.email?.includes(email),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (phone_number) {
|
if (phone_number) {
|
||||||
users = users.filter((user: MasterModel.ProfileResponse) =>
|
users = users.filter((user: MasterModel.UserResponse) =>
|
||||||
user.metadata?.phone_number?.includes(phone_number),
|
user.metadata?.phone_number?.includes(phone_number),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -269,7 +269,7 @@ const ManagerUserPage = () => {
|
|||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Use regular queryUsers API
|
// Use regular queryUsers API
|
||||||
const metadata: Partial<MasterModel.ProfileMetadata> = {};
|
const metadata: Partial<MasterModel.UserMetadata> = {};
|
||||||
if (phone_number) metadata.phone_number = phone_number;
|
if (phone_number) metadata.phone_number = phone_number;
|
||||||
|
|
||||||
const query: MasterModel.SearchUserPaginationBody = {
|
const query: MasterModel.SearchUserPaginationBody = {
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const ChangeProfile = () => {
|
|||||||
}}
|
}}
|
||||||
onFinish={async (values) => {
|
onFinish={async (values) => {
|
||||||
try {
|
try {
|
||||||
const body: Partial<MasterModel.ProfileMetadata> = {
|
const body: Partial<MasterModel.UserMetadata> = {
|
||||||
full_name: values.full_name,
|
full_name: values.full_name,
|
||||||
phone_number: values.phone_number,
|
phone_number: values.phone_number,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -61,7 +61,7 @@ const ShipDetail = ({
|
|||||||
|
|
||||||
let shipOwner:
|
let shipOwner:
|
||||||
| MasterModel.UserResponse
|
| MasterModel.UserResponse
|
||||||
| MasterModel.ProfileResponse
|
| MasterModel.UserResponse
|
||||||
| null = null;
|
| null = null;
|
||||||
if (resp?.owner_id) {
|
if (resp?.owner_id) {
|
||||||
if (initialState?.currentUserProfile?.metadata?.user_type === 'admin') {
|
if (initialState?.currentUserProfile?.metadata?.user_type === 'admin') {
|
||||||
|
|||||||
@@ -206,7 +206,7 @@ const MapPage = () => {
|
|||||||
? ''
|
? ''
|
||||||
: [stateCriticalQuery, stateSosQuery].filter(Boolean).join(',');
|
: [stateCriticalQuery, stateSosQuery].filter(Boolean).join(',');
|
||||||
let metaFormQuery: Record<string, any> = {};
|
let metaFormQuery: Record<string, any> = {};
|
||||||
if (stateQuery?.isDisconected)
|
if (stateQuery?.isDisconnected)
|
||||||
metaFormQuery = { ...metaFormQuery, connected: false };
|
metaFormQuery = { ...metaFormQuery, connected: false };
|
||||||
const metaStateQuery =
|
const metaStateQuery =
|
||||||
stateQueryParams !== '' ? { state_level: stateQueryParams } : null;
|
stateQueryParams !== '' ? { state_level: stateQueryParams } : null;
|
||||||
@@ -252,7 +252,7 @@ const MapPage = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setThings(null);
|
setThings(null);
|
||||||
const resp = await apiSearchThings(metaQuery);
|
const resp = await apiSearchThings(metaQuery, 'sgw');
|
||||||
return resp;
|
return resp;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error when searchThings: ', error);
|
console.error('Error when searchThings: ', error);
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ export type TagStateCallbackPayload = {
|
|||||||
isWarning: boolean;
|
isWarning: boolean;
|
||||||
isCritical: boolean;
|
isCritical: boolean;
|
||||||
isSos: boolean;
|
isSos: boolean;
|
||||||
isDisconected: boolean; // giữ đúng theo yêu cầu (1 'n')
|
isDisconnected: boolean; // giữ đúng theo yêu cầu (1 'n')
|
||||||
};
|
};
|
||||||
|
|
||||||
export type PointData = {
|
export type PointData = {
|
||||||
@@ -82,7 +82,7 @@ export interface GPSParseResult {
|
|||||||
|
|
||||||
export interface ShipDetailData {
|
export interface ShipDetailData {
|
||||||
ship: SgwModel.ShipDetail;
|
ship: SgwModel.ShipDetail;
|
||||||
owner: MasterModel.ProfileResponse | null;
|
owner: MasterModel.UserResponse | null;
|
||||||
gps: GPSParseResult | null;
|
gps: GPSParseResult | null;
|
||||||
trip_id?: string;
|
trip_id?: string;
|
||||||
zone_entered_alarm_list: ZoneAlarmParse[];
|
zone_entered_alarm_list: ZoneAlarmParse[];
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ interface EditModalProps {
|
|||||||
onVisibleChange: (visible: boolean) => void;
|
onVisibleChange: (visible: boolean) => void;
|
||||||
onFinish: (
|
onFinish: (
|
||||||
values: Pick<MasterModel.Thing, 'name'> &
|
values: Pick<MasterModel.Thing, 'name'> &
|
||||||
Pick<MasterModel.ThingMetadata, 'address' | 'external_id'>,
|
Pick<MasterModel.ThingReponseMetadata, 'address' | 'external_id'>,
|
||||||
) => Promise<boolean>;
|
) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,18 @@ interface CreateTripProps {
|
|||||||
thing_id?: string;
|
thing_id?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface TripFormValues {
|
||||||
|
name: string;
|
||||||
|
departure_time: any; // dayjs object or string
|
||||||
|
departure_port_id: number;
|
||||||
|
arrival_time?: any; // dayjs object or string
|
||||||
|
arrival_port_id?: number;
|
||||||
|
fishing_ground_codes?: number[];
|
||||||
|
fishing_gear?: SgwModel.FishingGear[];
|
||||||
|
trip_cost?: SgwModel.TripCost[];
|
||||||
|
ship_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
const CreateTrip: React.FC<CreateTripProps> = ({ onSuccess, thing_id }) => {
|
const CreateTrip: React.FC<CreateTripProps> = ({ onSuccess, thing_id }) => {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [selectedThing, setSelectedThing] = useState<string | undefined>();
|
const [selectedThing, setSelectedThing] = useState<string | undefined>();
|
||||||
@@ -41,9 +53,9 @@ const CreateTrip: React.FC<CreateTripProps> = ({ onSuccess, thing_id }) => {
|
|||||||
const [loading, setLoading] = useState(false);
|
const [loading, setLoading] = useState(false);
|
||||||
const [lastTrip, setLastTrip] = useState<SgwModel.Trip | null>(null);
|
const [lastTrip, setLastTrip] = useState<SgwModel.Trip | null>(null);
|
||||||
const [initialFormValues, setInitialFormValues] = useState<
|
const [initialFormValues, setInitialFormValues] = useState<
|
||||||
Partial<SgwModel.TripFormValues>
|
Partial<TripFormValues>
|
||||||
>({});
|
>({});
|
||||||
const formRef = useRef<ProFormInstance<SgwModel.TripFormValues>>(null);
|
const formRef = useRef<ProFormInstance<TripFormValues>>(null);
|
||||||
const { homeports, getHomeportsByProvinceCode } = useModel(
|
const { homeports, getHomeportsByProvinceCode } = useModel(
|
||||||
'slave.sgw.useHomePorts',
|
'slave.sgw.useHomePorts',
|
||||||
);
|
);
|
||||||
@@ -125,7 +137,7 @@ const CreateTrip: React.FC<CreateTripProps> = ({ onSuccess, thing_id }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSubmit = async (values: SgwModel.TripFormValues) => {
|
const handleSubmit = async (values: TripFormValues) => {
|
||||||
try {
|
try {
|
||||||
if (!selectedShip) {
|
if (!selectedShip) {
|
||||||
message.error('Vui lòng chọn tàu!');
|
message.error('Vui lòng chọn tàu!');
|
||||||
@@ -155,7 +167,7 @@ const CreateTrip: React.FC<CreateTripProps> = ({ onSuccess, thing_id }) => {
|
|||||||
.filter((n: number) => !isNaN(n))
|
.filter((n: number) => !isNaN(n))
|
||||||
: [],
|
: [],
|
||||||
fishing_gears: values.fishing_gear,
|
fishing_gears: values.fishing_gear,
|
||||||
trip_cost: values.trip_cost,
|
trip_cost: values.trip_cost || [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const thingIdToUse = selectedShip.thing_id || selectedThing;
|
const thingIdToUse = selectedShip.thing_id || selectedThing;
|
||||||
@@ -211,7 +223,7 @@ const CreateTrip: React.FC<CreateTripProps> = ({ onSuccess, thing_id }) => {
|
|||||||
>
|
>
|
||||||
<StepsForm<SgwModel.TripCreateParams>
|
<StepsForm<SgwModel.TripCreateParams>
|
||||||
stepsProps={{ size: 'small' }}
|
stepsProps={{ size: 'small' }}
|
||||||
onFinish={handleSubmit}
|
onFinish={(values) => handleSubmit(values as TripFormValues)}
|
||||||
submitter={{
|
submitter={{
|
||||||
render: (_: SubmitterProps, dom) => dom,
|
render: (_: SubmitterProps, dom) => dom,
|
||||||
}}
|
}}
|
||||||
|
|||||||
@@ -1,9 +1,284 @@
|
|||||||
import React from 'react';
|
import TagState from '@/components/shared/TagState';
|
||||||
|
import {
|
||||||
|
getBadgeConnection,
|
||||||
|
getBadgeStatus,
|
||||||
|
} from '@/components/shared/ThingShared';
|
||||||
|
import TreeGroup from '@/components/shared/TreeGroup';
|
||||||
|
import { DEFAULT_PAGE_SIZE } from '@/constants';
|
||||||
|
import { apiSearchThings } from '@/services/master/ThingController';
|
||||||
|
import {
|
||||||
|
ActionType,
|
||||||
|
ProCard,
|
||||||
|
ProColumns,
|
||||||
|
ProTable,
|
||||||
|
} from '@ant-design/pro-components';
|
||||||
|
import { FormattedMessage, useIntl } from '@umijs/max';
|
||||||
|
import { Flex, Grid, theme, Typography } from 'antd';
|
||||||
|
import moment from 'moment';
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import { TagStateCallbackPayload } from '../../SGW/Map/type';
|
||||||
|
const { Text } = Typography;
|
||||||
const SpoleHome: React.FC = () => {
|
const SpoleHome: React.FC = () => {
|
||||||
|
const { useBreakpoint } = Grid;
|
||||||
|
const intl = useIntl();
|
||||||
|
const screens = useBreakpoint();
|
||||||
|
const { token } = theme.useToken();
|
||||||
|
const actionRef = useRef<ActionType | null>(null);
|
||||||
|
const [isLoading, setIsLoading] = useState<boolean>(false);
|
||||||
|
const [groupCheckedKeys, setGroupCheckedKeys] = useState<
|
||||||
|
string | string[] | null
|
||||||
|
>(null);
|
||||||
|
const [thing, setThing] = useState<
|
||||||
|
SpoleModel.SpoleThingsResponse | undefined
|
||||||
|
>(undefined);
|
||||||
|
const [stateQuery, setStateQuery] = useState<
|
||||||
|
TagStateCallbackPayload | undefined
|
||||||
|
>(undefined);
|
||||||
|
|
||||||
|
const columns: ProColumns<SpoleModel.SpoleThing>[] = [
|
||||||
|
{
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true,
|
||||||
|
title: (
|
||||||
|
<FormattedMessage id="master.devices.name" defaultMessage="Name" />
|
||||||
|
),
|
||||||
|
tip: intl.formatMessage({
|
||||||
|
id: 'master.devices.name.tip',
|
||||||
|
defaultMessage: 'The device name',
|
||||||
|
}),
|
||||||
|
dataIndex: 'name',
|
||||||
|
hideInSearch: true,
|
||||||
|
copyable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'connected',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
title: (
|
||||||
|
<FormattedMessage id="common.connect" defaultMessage="Connection" />
|
||||||
|
),
|
||||||
|
dataIndex: ['metadata', 'connected'],
|
||||||
|
filters: [
|
||||||
|
{ text: 'Connected', value: true },
|
||||||
|
{ text: 'Disconnected', value: false },
|
||||||
|
],
|
||||||
|
onFilter: (value: any, row) => row?.metadata?.connected === value,
|
||||||
|
render: (_, row) => {
|
||||||
|
const connectionDuration = row.metadata!.connected
|
||||||
|
? row.metadata!.uptime! * 1000
|
||||||
|
: (Math.round(new Date().getTime() / 1000) -
|
||||||
|
row.metadata!.updated_time!) *
|
||||||
|
1000;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex gap={5}>
|
||||||
|
{getBadgeConnection(row.metadata!.connected || false)}
|
||||||
|
<Text type={row.metadata?.connected ? undefined : 'secondary'}>
|
||||||
|
{connectionDuration > 0
|
||||||
|
? moment.duration(connectionDuration).humanize()
|
||||||
|
: ''}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: intl.formatMessage({
|
||||||
|
id: 'common.status',
|
||||||
|
defaultMessage: 'Status',
|
||||||
|
}),
|
||||||
|
dataIndex: ['metadata', 'state_level'],
|
||||||
|
key: 'state_level',
|
||||||
|
hideInSearch: true,
|
||||||
|
filters: true,
|
||||||
|
onFilter: true,
|
||||||
|
valueType: 'select',
|
||||||
|
valueEnum: {
|
||||||
|
0: {
|
||||||
|
text: intl.formatMessage({
|
||||||
|
id: 'common.level.normal',
|
||||||
|
defaultMessage: 'Normal',
|
||||||
|
}),
|
||||||
|
status: 'Normal',
|
||||||
|
},
|
||||||
|
1: {
|
||||||
|
text: intl.formatMessage({
|
||||||
|
id: 'common.level.warning',
|
||||||
|
defaultMessage: 'Warning',
|
||||||
|
}),
|
||||||
|
status: 'Warning',
|
||||||
|
},
|
||||||
|
2: {
|
||||||
|
text: intl.formatMessage({
|
||||||
|
id: 'common.level.critical',
|
||||||
|
defaultMessage: 'Critical',
|
||||||
|
}),
|
||||||
|
status: 'Critical',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
render: (_, row) => {
|
||||||
|
const alarm = JSON.parse(row?.metadata?.alarm_list || '{}');
|
||||||
|
const text = alarm?.map((a: any) => a?.name).join(', ');
|
||||||
|
return (
|
||||||
|
<Flex gap={5}>
|
||||||
|
{getBadgeStatus(Number(row?.metadata?.state_level ?? -1))}
|
||||||
|
<Text type={row.metadata?.connected ? undefined : 'secondary'}>
|
||||||
|
{text}
|
||||||
|
</Text>
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const handleTagStateChange = (payload: TagStateCallbackPayload) => {
|
||||||
|
setStateQuery(payload);
|
||||||
|
actionRef.current?.reload();
|
||||||
|
};
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<h1>Trang chủ (Spole)</h1>
|
<ProCard split={screens.md ? 'vertical' : 'horizontal'}>
|
||||||
|
<ProCard colSpan={{ xs: 24, sm: 24, md: 4, lg: 4, xl: 4 }}>
|
||||||
|
<TreeGroup
|
||||||
|
disable={isLoading}
|
||||||
|
multiple={true}
|
||||||
|
groupIds={groupCheckedKeys}
|
||||||
|
onSelected={(value: string | string[] | null) => {
|
||||||
|
setGroupCheckedKeys(value);
|
||||||
|
if (actionRef.current) {
|
||||||
|
actionRef.current.reload();
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ProCard>
|
||||||
|
<ProCard colSpan={{ xs: 24, sm: 24, md: 20, lg: 20, xl: 20 }}>
|
||||||
|
<ProTable<MasterModel.Thing>
|
||||||
|
bordered={true}
|
||||||
|
columns={columns}
|
||||||
|
tableLayout="auto"
|
||||||
|
actionRef={actionRef}
|
||||||
|
rowKey="id"
|
||||||
|
search={{
|
||||||
|
layout: 'vertical', // Hoặc 'vertical' để xếp dọc
|
||||||
|
defaultCollapsed: false, // Mặc định mở rộng
|
||||||
|
span: 12, // Chiếm 12 cột trên lưới (tổng 24 cột)
|
||||||
|
filterType: 'light', // Loại filter
|
||||||
|
labelWidth: 'auto', // Độ rộng nhãn
|
||||||
|
}}
|
||||||
|
size="large"
|
||||||
|
dateFormatter="string"
|
||||||
|
pagination={{
|
||||||
|
defaultPageSize: DEFAULT_PAGE_SIZE * 2,
|
||||||
|
showSizeChanger: true,
|
||||||
|
pageSizeOptions: ['10', '15', '20'],
|
||||||
|
showTotal: (total, range) =>
|
||||||
|
`${range[0]}-${range[1]}
|
||||||
|
${intl.formatMessage({
|
||||||
|
id: 'common.paginations.of',
|
||||||
|
defaultMessage: 'of',
|
||||||
|
})}
|
||||||
|
${total} ${intl.formatMessage({
|
||||||
|
id: 'master.devices.table.pagination',
|
||||||
|
defaultMessage: 'devices',
|
||||||
|
})}`,
|
||||||
|
}}
|
||||||
|
request={async (params = {}) => {
|
||||||
|
const {
|
||||||
|
current = 1,
|
||||||
|
pageSize,
|
||||||
|
name,
|
||||||
|
external_id,
|
||||||
|
keyword,
|
||||||
|
} = params;
|
||||||
|
const size = pageSize || DEFAULT_PAGE_SIZE * 2;
|
||||||
|
const offset = current === 1 ? 0 : (current - 1) * size;
|
||||||
|
setIsLoading(true);
|
||||||
|
const stateNormalQuery = stateQuery?.isNormal ? 'normal' : '';
|
||||||
|
const stateSosQuery = stateQuery?.isSos ? 'sos' : '';
|
||||||
|
const stateWarningQuery = stateQuery?.isWarning
|
||||||
|
? stateNormalQuery + ',warning'
|
||||||
|
: stateNormalQuery;
|
||||||
|
const stateCriticalQuery = stateQuery?.isCritical
|
||||||
|
? stateWarningQuery + ',critical'
|
||||||
|
: stateWarningQuery;
|
||||||
|
const stateQueryParams =
|
||||||
|
stateQuery?.isNormal &&
|
||||||
|
stateQuery?.isWarning &&
|
||||||
|
stateQuery?.isCritical &&
|
||||||
|
stateQuery?.isSos
|
||||||
|
? ''
|
||||||
|
: [stateCriticalQuery, stateSosQuery]
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(',');
|
||||||
|
let metaFormQuery: Record<string, any> = {};
|
||||||
|
if (stateQuery?.isDisconnected)
|
||||||
|
metaFormQuery = { ...metaFormQuery, connected: false };
|
||||||
|
const metaStateQuery =
|
||||||
|
stateQueryParams !== ''
|
||||||
|
? { state_level: stateQueryParams }
|
||||||
|
: null;
|
||||||
|
let metadata: Partial<MasterModel.SearchThingMetadata> = {};
|
||||||
|
if (external_id) metadata.external_id = external_id;
|
||||||
|
|
||||||
|
if (metaStateQuery) metadata = { ...metadata, ...metaStateQuery };
|
||||||
|
// Add group filter if groups are selected
|
||||||
|
if (groupCheckedKeys && groupCheckedKeys.length > 0) {
|
||||||
|
const groupId = Array.isArray(groupCheckedKeys)
|
||||||
|
? groupCheckedKeys.join(',')
|
||||||
|
: groupCheckedKeys;
|
||||||
|
metadata.group_id = groupId;
|
||||||
|
}
|
||||||
|
|
||||||
|
const query: MasterModel.SearchThingPaginationBody = {
|
||||||
|
offset: offset,
|
||||||
|
limit: size,
|
||||||
|
order: 'name',
|
||||||
|
dir: 'asc',
|
||||||
|
};
|
||||||
|
if (keyword) query.name = keyword;
|
||||||
|
if (Object.keys(metadata).length > 0) query.metadata = metadata;
|
||||||
|
try {
|
||||||
|
const response = await apiSearchThings(query, 'spole');
|
||||||
|
setIsLoading(false);
|
||||||
|
setThing(response);
|
||||||
|
return {
|
||||||
|
data: response.things || [],
|
||||||
|
success: true,
|
||||||
|
total: response.total || 0,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
setIsLoading(false);
|
||||||
|
return {
|
||||||
|
data: [],
|
||||||
|
success: false,
|
||||||
|
total: 0,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
options={{
|
||||||
|
search: true,
|
||||||
|
setting: false,
|
||||||
|
density: false,
|
||||||
|
reload: true,
|
||||||
|
}}
|
||||||
|
toolbar={{
|
||||||
|
actions: [
|
||||||
|
<TagState
|
||||||
|
key={'device-state-tag'}
|
||||||
|
normalCount={thing?.metadata?.total_state_level_0 || 0}
|
||||||
|
warningCount={thing?.metadata?.total_state_level_1 || 0}
|
||||||
|
criticalCount={thing?.metadata?.total_state_level_2 || 0}
|
||||||
|
sosCount={undefined}
|
||||||
|
disconnectedCount={
|
||||||
|
(thing?.metadata?.total_thing ?? 0) -
|
||||||
|
(thing?.metadata?.total_connected ?? 0) || 0
|
||||||
|
}
|
||||||
|
onTagPress={handleTagStateChange}
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</ProCard>
|
||||||
|
</ProCard>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -16,13 +16,13 @@ export async function apiLogin(body: MasterModel.LoginRequestBody) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export async function apiQueryProfile() {
|
export async function apiQueryProfile() {
|
||||||
return request<MasterModel.ProfileResponse>(API_PATH_GET_PROFILE);
|
return request<MasterModel.UserResponse>(API_PATH_GET_PROFILE);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiUpdateProfile(
|
export async function apiUpdateProfile(
|
||||||
body: Partial<MasterModel.ProfileMetadata>,
|
body: Partial<MasterModel.UserMetadata>,
|
||||||
) {
|
) {
|
||||||
return request<MasterModel.ProfileResponse>(API_USERS, {
|
return request<MasterModel.UserResponse>(API_USERS, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
data: {
|
data: {
|
||||||
metadata: body,
|
metadata: body,
|
||||||
|
|||||||
@@ -5,6 +5,19 @@ import {
|
|||||||
} from '@/constants/api';
|
} from '@/constants/api';
|
||||||
import { request } from '@umijs/max';
|
import { request } from '@umijs/max';
|
||||||
|
|
||||||
|
export async function apiSearchThings(
|
||||||
|
body: MasterModel.SearchPaginationBody,
|
||||||
|
domain: 'spole',
|
||||||
|
): Promise<SpoleModel.SpoleThingsResponse>;
|
||||||
|
export async function apiSearchThings(
|
||||||
|
body: MasterModel.SearchPaginationBody,
|
||||||
|
domain: 'sgw',
|
||||||
|
): Promise<SgwModel.SgwThingsResponse>;
|
||||||
|
export async function apiSearchThings(
|
||||||
|
body: MasterModel.SearchPaginationBody,
|
||||||
|
domain?: 'gms',
|
||||||
|
): Promise<GmsModel.GmsThingsResponse>;
|
||||||
|
|
||||||
export async function apiSearchThings(
|
export async function apiSearchThings(
|
||||||
body: MasterModel.SearchPaginationBody,
|
body: MasterModel.SearchPaginationBody,
|
||||||
domain: string = process.env.DOMAIN_ENV || 'gms',
|
domain: string = process.env.DOMAIN_ENV || 'gms',
|
||||||
|
|||||||
@@ -4,19 +4,21 @@ import { request } from '@umijs/max';
|
|||||||
export async function apiQueryUsers(
|
export async function apiQueryUsers(
|
||||||
params: MasterModel.SearchUserPaginationBody,
|
params: MasterModel.SearchUserPaginationBody,
|
||||||
) {
|
) {
|
||||||
return request<MasterModel.UserResponse>(API_USERS, {
|
return request<MasterModel.UserListResponse>(API_USERS, {
|
||||||
params: params,
|
params: params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiQueryUserById(userId: string) {
|
export async function apiQueryUserById(userId: string) {
|
||||||
return request<MasterModel.ProfileResponse>(`${API_USERS}/${userId}`);
|
return request<MasterModel.UserResponse>(`${API_USERS}/${userId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiQueryUsersByGroup(
|
export async function apiQueryUsersByGroup(
|
||||||
group_id: string,
|
group_id: string,
|
||||||
): Promise<MasterModel.UserResponse> {
|
): Promise<MasterModel.UserListResponse> {
|
||||||
return request<MasterModel.UserResponse>(`${API_USERS_BY_GROUP}/${group_id}`);
|
return request<MasterModel.UserListResponse>(
|
||||||
|
`${API_USERS_BY_GROUP}/${group_id}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function apiCreateUsers(body: MasterModel.CreateUserBodyRequest) {
|
export async function apiCreateUsers(body: MasterModel.CreateUserBodyRequest) {
|
||||||
|
|||||||
244
src/services/master/typings.d.ts
vendored
244
src/services/master/typings.d.ts
vendored
@@ -8,254 +8,12 @@ declare namespace MasterModel {
|
|||||||
limit?: number;
|
limit?: number;
|
||||||
dir?: 'asc' | 'desc';
|
dir?: 'asc' | 'desc';
|
||||||
}
|
}
|
||||||
interface SearchThingPaginationBody extends SearchPaginationBody {
|
|
||||||
order?: string;
|
|
||||||
metadata?: ThingMetadata;
|
|
||||||
}
|
|
||||||
interface ThingMetadata {
|
|
||||||
group_id?: string;
|
|
||||||
external_id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SearchAlarmPaginationBody extends SearchPaginationBody {
|
interface PaginationReponse {
|
||||||
order?: 'name' | undefined;
|
|
||||||
thing_name?: string;
|
|
||||||
thing_id?: string;
|
|
||||||
level?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface SearchUserPaginationBody extends SearchPaginationBody {
|
|
||||||
order?: 'email' | 'name' | undefined;
|
|
||||||
email?: string;
|
|
||||||
metadata?: Partial<ProfileMetadata>;
|
|
||||||
}
|
|
||||||
interface SearchLogPaginationBody extends SearchPaginationBody {
|
|
||||||
from?: number;
|
|
||||||
to?: number;
|
|
||||||
publisher?: string;
|
|
||||||
subtopic?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Auth
|
|
||||||
interface LoginRequestBody {
|
|
||||||
guid: string;
|
|
||||||
email: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface LoginResponse {
|
|
||||||
token?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ChangePasswordRequestBody {
|
|
||||||
old_password: string;
|
|
||||||
password: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProfileResponse {
|
|
||||||
id?: string;
|
|
||||||
email?: string;
|
|
||||||
metadata?: ProfileMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ProfileMetadata {
|
|
||||||
frontend_thing_id?: string;
|
|
||||||
frontend_thing_key?: string;
|
|
||||||
full_name?: string;
|
|
||||||
phone_number?: string;
|
|
||||||
telegram?: string;
|
|
||||||
user_type?: 'admin' | 'enduser' | 'sysadmin' | 'users';
|
|
||||||
}
|
|
||||||
|
|
||||||
// User
|
|
||||||
interface CreateUserMetadata extends ProfileMetadata {
|
|
||||||
group_id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CreateUserBodyRequest extends Partial<ProfileResponse> {
|
|
||||||
password: string;
|
|
||||||
full_name?: string;
|
|
||||||
metadata?: CreateUserMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface UserResponse {
|
|
||||||
total?: number;
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
users: ProfileResponse[];
|
|
||||||
}
|
|
||||||
interface AlarmsResponse {
|
|
||||||
total?: number;
|
|
||||||
limit?: number;
|
|
||||||
order?: string;
|
|
||||||
dir?: string;
|
|
||||||
alarms?: Alarm[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ConfirmAlarmRequest {
|
|
||||||
id?: string;
|
|
||||||
description?: string;
|
|
||||||
thing_id?: string;
|
|
||||||
time?: number;
|
|
||||||
}
|
|
||||||
// Alarm
|
|
||||||
interface Alarm {
|
|
||||||
name?: string;
|
|
||||||
time?: number;
|
|
||||||
level?: number;
|
|
||||||
id?: string;
|
|
||||||
confirmed?: boolean;
|
|
||||||
confirmed_email?: string;
|
|
||||||
confirmed_time?: number;
|
|
||||||
confirmed_desc?: string;
|
|
||||||
thing_id?: string;
|
|
||||||
thing_name?: string;
|
|
||||||
thing_type?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thing
|
|
||||||
interface ThingMetadata {
|
|
||||||
address?: string;
|
|
||||||
alarm_list?: string;
|
|
||||||
cfg_channel_id?: string;
|
|
||||||
connected?: boolean;
|
|
||||||
ctrl_channel_id?: string;
|
|
||||||
data_channel_id?: string;
|
|
||||||
enduser?: string;
|
|
||||||
external_id?: string;
|
|
||||||
group_id?: string;
|
|
||||||
req_channel_id?: string;
|
|
||||||
state?: string;
|
|
||||||
state_level?: number;
|
|
||||||
state_updated_time?: number;
|
|
||||||
type?: string;
|
|
||||||
updated_time?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ThingsResponse<T extends ThingMetadata = ThingMetadata> {
|
|
||||||
total?: number;
|
total?: number;
|
||||||
offset?: number;
|
offset?: number;
|
||||||
limit?: number;
|
limit?: number;
|
||||||
order?: string;
|
order?: string;
|
||||||
direction?: string;
|
direction?: string;
|
||||||
metadata?: ThingsResponseMetadata;
|
|
||||||
things?: Thing<T>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ThingsResponseMetadata {
|
|
||||||
total_connected?: number;
|
|
||||||
total_filter?: number;
|
|
||||||
total_sos?: number;
|
|
||||||
total_state_level_0?: number;
|
|
||||||
total_state_level_1?: number;
|
|
||||||
total_state_level_2?: number;
|
|
||||||
total_thing?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Thing<T extends ThingMetadata = ThingMetadata> {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
key?: string;
|
|
||||||
metadata?: T;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thing Policy
|
|
||||||
interface ThingPolicyResponse {
|
|
||||||
total?: number;
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
order?: string;
|
|
||||||
direction?: string;
|
|
||||||
metadata?: null;
|
|
||||||
things?: ThingPolicy[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ThingPolicy {
|
|
||||||
policies?: Policy[];
|
|
||||||
thing_id?: string;
|
|
||||||
thing_name?: string;
|
|
||||||
external_id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
type Policy = 'read' | 'delete' | 'write';
|
|
||||||
|
|
||||||
// Group
|
|
||||||
|
|
||||||
interface GroupBodyRequest {
|
|
||||||
id?: string;
|
|
||||||
name: string;
|
|
||||||
parent_id?: string;
|
|
||||||
description?: string;
|
|
||||||
metadata?: GroupMetadata;
|
|
||||||
}
|
|
||||||
interface AddGroupBodyResponse extends Partial<GroupBodyRequest> {
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GroupMetadata {
|
|
||||||
code?: string;
|
|
||||||
short_name?: string;
|
|
||||||
has_thing?: boolean;
|
|
||||||
[key: string]: unknown;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GroupResponse {
|
|
||||||
total?: number;
|
|
||||||
level?: number;
|
|
||||||
name?: string;
|
|
||||||
groups?: GroupNode[];
|
|
||||||
}
|
|
||||||
interface GroupNode {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
owner_id: string;
|
|
||||||
description: string;
|
|
||||||
metadata: GroupMetadata;
|
|
||||||
level: number;
|
|
||||||
path: string;
|
|
||||||
parent_id?: string;
|
|
||||||
created_at?: string;
|
|
||||||
updated_at?: string;
|
|
||||||
children?: GroupNode[]; // Đệ quy: mỗi node có thể có children là mảng GroupNode
|
|
||||||
[key: string]: any; // Nếu có thêm trường động
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GroupQueryParams {
|
|
||||||
level?: number;
|
|
||||||
tree?: boolean;
|
|
||||||
[key: string]: any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Log
|
|
||||||
|
|
||||||
type LogTypeRequest = 'user_logs' | undefined;
|
|
||||||
|
|
||||||
interface LogResponse {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
publisher?: string;
|
|
||||||
from?: number;
|
|
||||||
to?: number;
|
|
||||||
format?: string;
|
|
||||||
total?: number;
|
|
||||||
messages?: Message[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Message {
|
|
||||||
channel?: string;
|
|
||||||
subtopic?: string;
|
|
||||||
publisher?: string;
|
|
||||||
protocol?: string;
|
|
||||||
name?: string;
|
|
||||||
time?: number;
|
|
||||||
string_value?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// User
|
|
||||||
|
|
||||||
interface AssignMemberRequest {
|
|
||||||
group_id: string;
|
|
||||||
type: 'users' | 'admin' | 'things' | undefined;
|
|
||||||
members: string[];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
36
src/services/master/typings/alarm.d.ts
vendored
Normal file
36
src/services/master/typings/alarm.d.ts
vendored
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
declare namespace MasterModel {
|
||||||
|
interface SearchAlarmPaginationBody extends SearchPaginationBody {
|
||||||
|
order?: 'name' | undefined;
|
||||||
|
thing_name?: string;
|
||||||
|
thing_id?: string;
|
||||||
|
level?: number;
|
||||||
|
}
|
||||||
|
interface AlarmsResponse {
|
||||||
|
total?: number;
|
||||||
|
limit?: number;
|
||||||
|
order?: string;
|
||||||
|
dir?: string;
|
||||||
|
alarms?: Alarm[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ConfirmAlarmRequest {
|
||||||
|
id?: string;
|
||||||
|
description?: string;
|
||||||
|
thing_id?: string;
|
||||||
|
time?: number;
|
||||||
|
}
|
||||||
|
// Alarm
|
||||||
|
interface Alarm {
|
||||||
|
name?: string;
|
||||||
|
time?: number;
|
||||||
|
level?: number;
|
||||||
|
id?: string;
|
||||||
|
confirmed?: boolean;
|
||||||
|
confirmed_email?: string;
|
||||||
|
confirmed_time?: number;
|
||||||
|
confirmed_desc?: string;
|
||||||
|
thing_id?: string;
|
||||||
|
thing_name?: string;
|
||||||
|
thing_type?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/services/master/typings/auth.d.ts
vendored
Normal file
11
src/services/master/typings/auth.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
declare namespace MasterModel {
|
||||||
|
interface LoginRequestBody {
|
||||||
|
guid: string;
|
||||||
|
email: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface LoginResponse {
|
||||||
|
token?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/services/master/typings/group.d.ts
vendored
Normal file
52
src/services/master/typings/group.d.ts
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
declare namespace MasterModel {
|
||||||
|
interface GroupBodyRequest {
|
||||||
|
id?: string;
|
||||||
|
name: string;
|
||||||
|
parent_id?: string;
|
||||||
|
description?: string;
|
||||||
|
metadata?: GroupMetadata;
|
||||||
|
}
|
||||||
|
interface AddGroupBodyResponse extends Partial<GroupBodyRequest> {
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupMetadata {
|
||||||
|
code?: string;
|
||||||
|
short_name?: string;
|
||||||
|
has_thing?: boolean;
|
||||||
|
[key: string]: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupResponse {
|
||||||
|
total?: number;
|
||||||
|
level?: number;
|
||||||
|
name?: string;
|
||||||
|
groups?: GroupNode[];
|
||||||
|
}
|
||||||
|
interface GroupNode {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
owner_id: string;
|
||||||
|
description: string;
|
||||||
|
metadata: GroupMetadata;
|
||||||
|
level: number;
|
||||||
|
path: string;
|
||||||
|
parent_id?: string;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
children?: GroupNode[]; // Đệ quy: mỗi node có thể có children là mảng GroupNode
|
||||||
|
[key: string]: any; // Nếu có thêm trường động
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupQueryParams {
|
||||||
|
level?: number;
|
||||||
|
tree?: boolean;
|
||||||
|
[key: string]: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AssignMemberRequest {
|
||||||
|
group_id: string;
|
||||||
|
type: 'users' | 'admin' | 'things' | undefined;
|
||||||
|
members: string[];
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/services/master/typings/log.d.ts
vendored
Normal file
31
src/services/master/typings/log.d.ts
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
declare namespace MasterModel {
|
||||||
|
interface SearchLogPaginationBody extends SearchPaginationBody {
|
||||||
|
from?: number;
|
||||||
|
to?: number;
|
||||||
|
publisher?: string;
|
||||||
|
subtopic?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type LogTypeRequest = 'user_logs' | undefined;
|
||||||
|
|
||||||
|
interface LogResponse {
|
||||||
|
offset?: number;
|
||||||
|
limit?: number;
|
||||||
|
publisher?: string;
|
||||||
|
from?: number;
|
||||||
|
to?: number;
|
||||||
|
format?: string;
|
||||||
|
total?: number;
|
||||||
|
messages?: Message[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Message {
|
||||||
|
channel?: string;
|
||||||
|
subtopic?: string;
|
||||||
|
publisher?: string;
|
||||||
|
protocol?: string;
|
||||||
|
name?: string;
|
||||||
|
time?: number;
|
||||||
|
string_value?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
73
src/services/master/typings/thing.d.ts
vendored
Normal file
73
src/services/master/typings/thing.d.ts
vendored
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
declare namespace MasterModel {
|
||||||
|
interface SearchThingPaginationBody<T = SearchThingMetadata>
|
||||||
|
extends SearchPaginationBody {
|
||||||
|
order?: string;
|
||||||
|
metadata?: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SearchThingMetadata {
|
||||||
|
external_id?: string;
|
||||||
|
state_level?: string; // vd: "normal,warning,critical,sos"
|
||||||
|
/** kết nối */
|
||||||
|
connected?: boolean;
|
||||||
|
group_id?: string; // "id1,id2,id3"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thing
|
||||||
|
interface ThingReponseMetadata {
|
||||||
|
address?: string;
|
||||||
|
alarm_list?: string;
|
||||||
|
cfg_channel_id?: string;
|
||||||
|
connected?: boolean;
|
||||||
|
ctrl_channel_id?: string;
|
||||||
|
data_channel_id?: string;
|
||||||
|
enduser?: string;
|
||||||
|
external_id?: string;
|
||||||
|
group_id?: string;
|
||||||
|
req_channel_id?: string;
|
||||||
|
state?: string;
|
||||||
|
state_level?: number;
|
||||||
|
state_updated_time?: number;
|
||||||
|
type?: string;
|
||||||
|
updated_time?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThingsResponse<
|
||||||
|
T extends ThingReponseMetadata = ThingReponseMetadata,
|
||||||
|
> extends PaginationReponse {
|
||||||
|
metadata?: ThingsResponseMetadata;
|
||||||
|
things?: Thing<T>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThingsResponseMetadata {
|
||||||
|
total_connected?: number;
|
||||||
|
total_filter?: number;
|
||||||
|
total_sos?: number;
|
||||||
|
total_state_level_0?: number;
|
||||||
|
total_state_level_1?: number;
|
||||||
|
total_state_level_2?: number;
|
||||||
|
total_thing?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Thing<T extends ThingReponseMetadata = ThingReponseMetadata> {
|
||||||
|
id?: string;
|
||||||
|
name?: string;
|
||||||
|
key?: string;
|
||||||
|
metadata?: T;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Thing Policy
|
||||||
|
interface ThingPolicyResponse extends PaginationReponse {
|
||||||
|
metadata?: null;
|
||||||
|
things?: ThingPolicy[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ThingPolicy {
|
||||||
|
policies?: Policy[];
|
||||||
|
thing_id?: string;
|
||||||
|
thing_name?: string;
|
||||||
|
external_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Policy = 'read' | 'delete' | 'write';
|
||||||
|
}
|
||||||
44
src/services/master/typings/user.d.ts
vendored
Normal file
44
src/services/master/typings/user.d.ts
vendored
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
declare namespace MasterModel {
|
||||||
|
interface SearchUserPaginationBody extends SearchPaginationBody {
|
||||||
|
order?: 'email' | 'name' | undefined;
|
||||||
|
email?: string;
|
||||||
|
metadata?: Partial<UserMetadata>;
|
||||||
|
}
|
||||||
|
interface ChangePasswordRequestBody {
|
||||||
|
old_password: string;
|
||||||
|
password: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserResponse {
|
||||||
|
id?: string;
|
||||||
|
email?: string;
|
||||||
|
metadata?: UserMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserMetadata {
|
||||||
|
frontend_thing_id?: string;
|
||||||
|
frontend_thing_key?: string;
|
||||||
|
full_name?: string;
|
||||||
|
phone_number?: string;
|
||||||
|
telegram?: string;
|
||||||
|
user_type?: 'admin' | 'enduser' | 'sysadmin' | 'users';
|
||||||
|
}
|
||||||
|
|
||||||
|
// User
|
||||||
|
interface CreateUserMetadata extends UserMetadata {
|
||||||
|
group_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateUserBodyRequest extends Partial<UserResponse> {
|
||||||
|
password: string;
|
||||||
|
full_name?: string;
|
||||||
|
metadata?: CreateUserMetadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface UserListResponse {
|
||||||
|
total?: number;
|
||||||
|
offset?: number;
|
||||||
|
limit?: number;
|
||||||
|
users: UserResponse[];
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -42,7 +42,7 @@ export async function apiGetZoneById(
|
|||||||
* Create a new banzone
|
* Create a new banzone
|
||||||
* @param body Banzone data
|
* @param body Banzone data
|
||||||
*/
|
*/
|
||||||
export async function apiCreateBanzone(body: SgwModel.ZoneBodyRequest) {
|
export async function apiCreateBanzone(body: SgwModel.ZoneBasicInfo) {
|
||||||
return request(SGW_ROUTE_BANZONES, {
|
return request(SGW_ROUTE_BANZONES, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
data: body,
|
data: body,
|
||||||
@@ -56,7 +56,7 @@ export async function apiCreateBanzone(body: SgwModel.ZoneBodyRequest) {
|
|||||||
*/
|
*/
|
||||||
export async function apiUpdateBanzone(
|
export async function apiUpdateBanzone(
|
||||||
id: string,
|
id: string,
|
||||||
body: SgwModel.ZoneBodyRequest,
|
body: SgwModel.ZoneBasicInfo,
|
||||||
) {
|
) {
|
||||||
return request(`${SGW_ROUTE_BANZONES}/${id}`, {
|
return request(`${SGW_ROUTE_BANZONES}/${id}`, {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
|
|||||||
440
src/services/slave/sgw/sgw.typing.d.ts
vendored
440
src/services/slave/sgw/sgw.typing.d.ts
vendored
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
declare namespace SgwModel {
|
declare namespace SgwModel {
|
||||||
// Thing
|
// Thing
|
||||||
interface ThingMedata extends MasterModel.ThingMetadata {
|
interface ThingMedata extends MasterModel.ThingReponseMetadata {
|
||||||
gps?: string;
|
gps?: string;
|
||||||
gps_time?: string;
|
gps_time?: string;
|
||||||
ship_group_id?: string;
|
ship_group_id?: string;
|
||||||
@@ -23,442 +23,4 @@ declare namespace SgwModel {
|
|||||||
|
|
||||||
type SgwThingsResponse = MasterModel.ThingsResponse<SgwModel.ThingMedata>;
|
type SgwThingsResponse = MasterModel.ThingsResponse<SgwModel.ThingMedata>;
|
||||||
type SgwThing = MasterModel.Thing<SgwModel.ThingMedata>;
|
type SgwThing = MasterModel.Thing<SgwModel.ThingMedata>;
|
||||||
|
|
||||||
// Ship
|
|
||||||
interface ShipMetadata {
|
|
||||||
crew_count?: number;
|
|
||||||
home_port?: string;
|
|
||||||
home_port_point?: string;
|
|
||||||
ship_type?: string;
|
|
||||||
trip_arrival_port?: string;
|
|
||||||
trip_arrival_port_point?: string;
|
|
||||||
trip_arrival_time?: Date;
|
|
||||||
trip_depart_port?: string;
|
|
||||||
trip_depart_port_point?: string;
|
|
||||||
trip_departure_time?: Date;
|
|
||||||
trip_id?: string;
|
|
||||||
trip_name?: string;
|
|
||||||
trip_state?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipType {
|
|
||||||
id?: number;
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipDetail {
|
|
||||||
id?: string;
|
|
||||||
thing_id?: string;
|
|
||||||
owner_id?: string;
|
|
||||||
name?: string;
|
|
||||||
ship_type?: number;
|
|
||||||
home_port?: number;
|
|
||||||
ship_length?: number;
|
|
||||||
ship_power?: number;
|
|
||||||
reg_number?: string;
|
|
||||||
imo_number?: string;
|
|
||||||
mmsi_number?: string;
|
|
||||||
fishing_license_number?: string;
|
|
||||||
fishing_license_expiry_date?: Date | string;
|
|
||||||
province_code?: string;
|
|
||||||
ship_group_id?: string | null;
|
|
||||||
created_at?: Date | string;
|
|
||||||
updated_at?: Date | string;
|
|
||||||
metadata?: ShipMetadata;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipCreateParams {
|
|
||||||
thing_id?: string;
|
|
||||||
name?: string;
|
|
||||||
reg_number?: string;
|
|
||||||
ship_type?: number;
|
|
||||||
ship_length?: number;
|
|
||||||
ship_power?: number;
|
|
||||||
ship_group_id?: string;
|
|
||||||
home_port?: number;
|
|
||||||
fishing_license_number?: string;
|
|
||||||
fishing_license_expiry_date?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipUpdateParams {
|
|
||||||
name?: string;
|
|
||||||
reg_number?: string;
|
|
||||||
ship_type?: number;
|
|
||||||
ship_group_id?: string | null;
|
|
||||||
ship_length?: number;
|
|
||||||
ship_power?: number;
|
|
||||||
home_port?: number;
|
|
||||||
fishing_license_number?: string;
|
|
||||||
fishing_license_expiry_date?: string;
|
|
||||||
metadata?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipQueryParams {
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
order?: string;
|
|
||||||
dir?: 'asc' | 'desc';
|
|
||||||
name?: string;
|
|
||||||
registration_number?: string;
|
|
||||||
ship_type?: number;
|
|
||||||
ship_group_id?: string;
|
|
||||||
thing_id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipQueryResponse {
|
|
||||||
ships: ShipDetail[];
|
|
||||||
total: number;
|
|
||||||
offset: number;
|
|
||||||
limit: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipsResponse<T extends ShipMetadata = ShipMetadata> {
|
|
||||||
total?: number;
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
order?: string;
|
|
||||||
direction?: string;
|
|
||||||
Ship?: Ship<T>[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ship Group
|
|
||||||
interface ShipGroup {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
owner_id?: string;
|
|
||||||
description?: string;
|
|
||||||
created_at?: Date | string;
|
|
||||||
updated_at?: Date | string;
|
|
||||||
metadata?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface GroupShipResponse {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
owner_id?: string;
|
|
||||||
description?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipGroupCreateParams {
|
|
||||||
name: string;
|
|
||||||
description?: string;
|
|
||||||
metadata?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ShipGroupUpdateParams {
|
|
||||||
name?: string;
|
|
||||||
description?: string;
|
|
||||||
metadata?: Record<string, unknown>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Port
|
|
||||||
interface Port {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
type: string;
|
|
||||||
classification: string;
|
|
||||||
position_point: string;
|
|
||||||
has_origin_confirm: boolean;
|
|
||||||
province_code: string;
|
|
||||||
updated_at: string;
|
|
||||||
is_deleted: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PortQueryParams {
|
|
||||||
name?: string;
|
|
||||||
order?: string;
|
|
||||||
dir?: 'asc' | 'desc';
|
|
||||||
limit?: number;
|
|
||||||
offset?: number;
|
|
||||||
metadata?: {
|
|
||||||
province_code?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PortQueryResponse {
|
|
||||||
total: number;
|
|
||||||
offset: number;
|
|
||||||
limit: number;
|
|
||||||
ports: Port[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trip Management
|
|
||||||
interface FishingGear {
|
|
||||||
name: string;
|
|
||||||
number: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCost {
|
|
||||||
type: string;
|
|
||||||
unit: string;
|
|
||||||
amount: string;
|
|
||||||
total_cost: string;
|
|
||||||
cost_per_unit: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCrewPerson {
|
|
||||||
personal_id: string;
|
|
||||||
name: string;
|
|
||||||
phone: string;
|
|
||||||
email: string;
|
|
||||||
birth_date: Date;
|
|
||||||
note: string;
|
|
||||||
address: string;
|
|
||||||
created_at: Date;
|
|
||||||
updated_at: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCrews {
|
|
||||||
role: string;
|
|
||||||
joined_at: Date;
|
|
||||||
left_at: Date | null;
|
|
||||||
note: string | null;
|
|
||||||
Person: TripCrewPerson;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CrewCreateParams {
|
|
||||||
personal_id: string;
|
|
||||||
name: string;
|
|
||||||
phone?: string;
|
|
||||||
email?: string;
|
|
||||||
birth_date?: string;
|
|
||||||
address?: string;
|
|
||||||
note?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CrewUpdateParams {
|
|
||||||
name?: string;
|
|
||||||
phone?: string;
|
|
||||||
email?: string;
|
|
||||||
birth_date?: string;
|
|
||||||
address?: string;
|
|
||||||
note?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCrewCreateParams {
|
|
||||||
trip_id: string;
|
|
||||||
personal_id: string;
|
|
||||||
role: string;
|
|
||||||
note?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCrewUpdateParams {
|
|
||||||
trip_id: string;
|
|
||||||
personal_id: string;
|
|
||||||
role?: string;
|
|
||||||
note?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCrewQueryResponse {
|
|
||||||
trip_crews: TripCrews[];
|
|
||||||
total?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FishingLogInfo {
|
|
||||||
fish_species_id?: number;
|
|
||||||
fish_name?: string;
|
|
||||||
catch_number?: number;
|
|
||||||
catch_unit?: string;
|
|
||||||
fish_size?: number;
|
|
||||||
fish_rarity?: number;
|
|
||||||
fish_condition?: string;
|
|
||||||
gear_usage?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FishingLog {
|
|
||||||
fishing_log_id?: string;
|
|
||||||
trip_id: string;
|
|
||||||
start_at: Date;
|
|
||||||
end_at: Date;
|
|
||||||
start_lat: number;
|
|
||||||
start_lon: number;
|
|
||||||
haul_lat: number;
|
|
||||||
haul_lon: number;
|
|
||||||
status: number;
|
|
||||||
weather_description: string;
|
|
||||||
info?: FishingLogInfo[];
|
|
||||||
sync: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface NewFishingLogRequest {
|
|
||||||
trip_id: string;
|
|
||||||
start_at: Date;
|
|
||||||
start_lat: number;
|
|
||||||
start_lon: number;
|
|
||||||
weather_description: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FishSpecies {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
scientific_name?: string;
|
|
||||||
description?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface FishSpeciesResponse extends FishSpecies {}
|
|
||||||
|
|
||||||
interface Trip {
|
|
||||||
id: string;
|
|
||||||
ship_id: string;
|
|
||||||
ship_length: number;
|
|
||||||
vms_id: string;
|
|
||||||
name: string;
|
|
||||||
fishing_gears: FishingGear[];
|
|
||||||
crews?: TripCrews[];
|
|
||||||
departure_time: string;
|
|
||||||
departure_port_id: number;
|
|
||||||
arrival_time: string;
|
|
||||||
arrival_port_id: number;
|
|
||||||
fishing_ground_codes: number[];
|
|
||||||
total_catch_weight: number | null;
|
|
||||||
total_species_caught: number | null;
|
|
||||||
trip_cost: TripCost[];
|
|
||||||
trip_status: number;
|
|
||||||
approved_by: string;
|
|
||||||
notes: string | null;
|
|
||||||
fishing_logs: FishingLog[] | null;
|
|
||||||
sync: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripUpdateStateRequest {
|
|
||||||
status: number;
|
|
||||||
note?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripCreateParams {
|
|
||||||
name: string;
|
|
||||||
departure_time: string;
|
|
||||||
departure_port_id: number;
|
|
||||||
arrival_time?: string;
|
|
||||||
arrival_port_id?: number;
|
|
||||||
fishing_ground_codes?: number[];
|
|
||||||
fishing_gears?: FishingGear[];
|
|
||||||
crews?: TripCrews[];
|
|
||||||
trip_cost?: TripCost[];
|
|
||||||
notes?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripFormValues {
|
|
||||||
name: string;
|
|
||||||
departure_time: any; // dayjs object or string
|
|
||||||
departure_port_id: number;
|
|
||||||
arrival_time?: any; // dayjs object or string
|
|
||||||
arrival_port_id?: number;
|
|
||||||
fishing_ground_codes?: number[];
|
|
||||||
fishing_gear?: FishingGear[];
|
|
||||||
trip_cost?: TripCost[];
|
|
||||||
ship_id?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripQueryParams {
|
|
||||||
name?: string;
|
|
||||||
order?: string;
|
|
||||||
dir?: 'asc' | 'desc';
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
metadata?: {
|
|
||||||
from?: string;
|
|
||||||
to?: string;
|
|
||||||
ship_name?: string;
|
|
||||||
reg_number?: string;
|
|
||||||
province_code?: string;
|
|
||||||
owner_id?: string;
|
|
||||||
ship_id?: string;
|
|
||||||
status?: string;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripQueryResponse {
|
|
||||||
trips: Trip[];
|
|
||||||
total: number;
|
|
||||||
offset: number;
|
|
||||||
limit: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripUpdateParams {
|
|
||||||
name?: string;
|
|
||||||
departure_time?: string;
|
|
||||||
departure_port_id?: number;
|
|
||||||
arrival_time?: string;
|
|
||||||
arrival_port_id?: number;
|
|
||||||
fishing_ground_codes?: number[];
|
|
||||||
fishing_gears?: FishingGear[];
|
|
||||||
crews?: TripCrews[];
|
|
||||||
trip_cost?: TripCost[];
|
|
||||||
trip_status?: number;
|
|
||||||
notes?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface TripDeleteParams {
|
|
||||||
trip_ids: string[];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Photo Management
|
|
||||||
interface PhotoGetParams {
|
|
||||||
type: 'ship' | 'people';
|
|
||||||
id: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface PhotoUploadParams {
|
|
||||||
type: 'ship' | 'people';
|
|
||||||
id: string;
|
|
||||||
file: File;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Banzone Management
|
|
||||||
interface Banzone {
|
|
||||||
id?: string;
|
|
||||||
name?: string;
|
|
||||||
province_code?: string;
|
|
||||||
type?: number;
|
|
||||||
conditions?: Condition[];
|
|
||||||
description?: string;
|
|
||||||
geometry?: string;
|
|
||||||
enabled?: boolean;
|
|
||||||
created_at?: Date;
|
|
||||||
updated_at?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Condition {
|
|
||||||
max?: number;
|
|
||||||
min?: number;
|
|
||||||
type?: 'length_limit' | 'month_range' | 'date_range';
|
|
||||||
to?: number;
|
|
||||||
from?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Geom {
|
|
||||||
geom_type?: number;
|
|
||||||
geom_poly?: string;
|
|
||||||
geom_lines?: string;
|
|
||||||
geom_point?: string;
|
|
||||||
geom_radius?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ZoneResponse {
|
|
||||||
total?: number;
|
|
||||||
offset?: number;
|
|
||||||
limit?: number;
|
|
||||||
banzones?: Banzone[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ZoneBodyRequest {
|
|
||||||
name?: string;
|
|
||||||
province_code?: string;
|
|
||||||
type?: number;
|
|
||||||
conditions?: Condition[];
|
|
||||||
description?: string;
|
|
||||||
geometry?: string;
|
|
||||||
enabled?: boolean;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
declare namespace WsTypes {
|
|
||||||
interface WsThingResponse {
|
|
||||||
thing_id?: string;
|
|
||||||
key?: string;
|
|
||||||
data?: string;
|
|
||||||
time?: number;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
17
src/services/slave/sgw/typings/crew.d.ts
vendored
Normal file
17
src/services/slave/sgw/typings/crew.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface CrewBaseInfo {
|
||||||
|
name: string;
|
||||||
|
phone?: string;
|
||||||
|
email?: string;
|
||||||
|
birth_date?: string;
|
||||||
|
address?: string;
|
||||||
|
note?: string;
|
||||||
|
}
|
||||||
|
interface CrewCreateParams extends CrewBaseInfo {
|
||||||
|
personal_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CrewUpdateParams extends Partial<CrewBaseInfo> {
|
||||||
|
personal_id?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/services/slave/sgw/typings/fish.d.ts
vendored
Normal file
8
src/services/slave/sgw/typings/fish.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface FishSpeciesResponse {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
scientific_name?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/services/slave/sgw/typings/fishing_log.d.ts
vendored
Normal file
35
src/services/slave/sgw/typings/fishing_log.d.ts
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface FishingLogInfo {
|
||||||
|
fish_species_id?: number;
|
||||||
|
fish_name?: string;
|
||||||
|
catch_number?: number;
|
||||||
|
catch_unit?: string;
|
||||||
|
fish_size?: number;
|
||||||
|
fish_rarity?: number;
|
||||||
|
fish_condition?: string;
|
||||||
|
gear_usage?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface FishingLog {
|
||||||
|
fishing_log_id?: string;
|
||||||
|
trip_id: string;
|
||||||
|
start_at: Date;
|
||||||
|
end_at: Date;
|
||||||
|
start_lat: number;
|
||||||
|
start_lon: number;
|
||||||
|
haul_lat: number;
|
||||||
|
haul_lon: number;
|
||||||
|
status: number;
|
||||||
|
weather_description: string;
|
||||||
|
info?: FishingLogInfo[];
|
||||||
|
sync: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface NewFishingLogRequest {
|
||||||
|
trip_id: string;
|
||||||
|
start_at: Date;
|
||||||
|
start_lat: number;
|
||||||
|
start_lon: number;
|
||||||
|
weather_description: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
6
src/services/slave/sgw/typings/gear.d.ts
vendored
Normal file
6
src/services/slave/sgw/typings/gear.d.ts
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface FishingGear {
|
||||||
|
name: string;
|
||||||
|
number: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
17
src/services/slave/sgw/typings/photo.d.ts
vendored
Normal file
17
src/services/slave/sgw/typings/photo.d.ts
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
// interface PhotoBasicInfo {
|
||||||
|
// type: 'ship' | 'people';
|
||||||
|
// id: string;
|
||||||
|
// }
|
||||||
|
|
||||||
|
interface PhotoGetParams {
|
||||||
|
type: 'ship' | 'people';
|
||||||
|
id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PhotoUploadParams {
|
||||||
|
type: 'ship' | 'people';
|
||||||
|
id: string;
|
||||||
|
file: File;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/services/slave/sgw/typings/port.d.ts
vendored
Normal file
24
src/services/slave/sgw/typings/port.d.ts
vendored
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface Port {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
type: string;
|
||||||
|
classification: string;
|
||||||
|
position_point: string;
|
||||||
|
has_origin_confirm: boolean;
|
||||||
|
province_code: string;
|
||||||
|
updated_at: string;
|
||||||
|
is_deleted: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PortQueryParams extends MasterModel.SearchPaginationBody {
|
||||||
|
order?: string;
|
||||||
|
metadata?: {
|
||||||
|
province_code?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PortQueryResponse extends MasterModel.PaginationReponse {
|
||||||
|
ports: Port[];
|
||||||
|
}
|
||||||
|
}
|
||||||
89
src/services/slave/sgw/typings/ship.d.ts
vendored
Normal file
89
src/services/slave/sgw/typings/ship.d.ts
vendored
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface ShipBaseInfo {
|
||||||
|
name?: string;
|
||||||
|
reg_number?: string;
|
||||||
|
ship_type?: number;
|
||||||
|
ship_length?: number;
|
||||||
|
ship_power?: number;
|
||||||
|
home_port?: number;
|
||||||
|
fishing_license_number?: string;
|
||||||
|
fishing_license_expiry_date?: string;
|
||||||
|
ship_group_id?: string | null; // Lưu ý: Update có thể cần null để gỡ nhóm
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShipType {
|
||||||
|
id?: number;
|
||||||
|
name?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
interface ShipMetadata {
|
||||||
|
crew_count?: number;
|
||||||
|
home_port?: string;
|
||||||
|
home_port_point?: string;
|
||||||
|
ship_type?: string;
|
||||||
|
trip_arrival_port?: string;
|
||||||
|
trip_arrival_port_point?: string;
|
||||||
|
trip_arrival_time?: Date;
|
||||||
|
trip_depart_port?: string;
|
||||||
|
trip_depart_port_point?: string;
|
||||||
|
trip_departure_time?: Date;
|
||||||
|
trip_id?: string;
|
||||||
|
trip_name?: string;
|
||||||
|
trip_state?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShipDetail extends ShipBaseInfo {
|
||||||
|
id?: string;
|
||||||
|
thing_id?: string;
|
||||||
|
owner_id?: string;
|
||||||
|
imo_number?: string;
|
||||||
|
mmsi_number?: string;
|
||||||
|
province_code?: string;
|
||||||
|
created_at?: Date | string;
|
||||||
|
updated_at?: Date | string;
|
||||||
|
metadata?: ShipMetadata;
|
||||||
|
}
|
||||||
|
interface ShipCreateParams extends ShipBaseInfo {
|
||||||
|
thing_id?: string;
|
||||||
|
}
|
||||||
|
interface ShipUpdateParams {
|
||||||
|
metadata?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
interface ShipQueryParams extends MasterModel.SearchPaginationBody {
|
||||||
|
order?: string;
|
||||||
|
registration_number?: string;
|
||||||
|
ship_type?: number;
|
||||||
|
ship_group_id?: string;
|
||||||
|
thing_id?: string;
|
||||||
|
}
|
||||||
|
interface ShipQueryResponse extends MasterModel.PaginationReponse {
|
||||||
|
ships: ShipDetail[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ship Group
|
||||||
|
|
||||||
|
interface ShipGroupBaseInfo {
|
||||||
|
name: string;
|
||||||
|
owner_id?: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShipGroup extends ShipGroupBaseInfo {
|
||||||
|
id: string;
|
||||||
|
created_at?: Date | string;
|
||||||
|
updated_at?: Date | string;
|
||||||
|
metadata?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GroupShipResponse extends ShipGroupBaseInfo {
|
||||||
|
id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShipGroupCreateParams extends ShipGroupBaseInfo {
|
||||||
|
metadata?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ShipGroupUpdateParams extends ShipGroupBaseInfo {
|
||||||
|
metadata?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
}
|
||||||
111
src/services/slave/sgw/typings/trip.d.ts
vendored
Normal file
111
src/services/slave/sgw/typings/trip.d.ts
vendored
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
interface TripBasicInfo {
|
||||||
|
name: string;
|
||||||
|
departure_time: string;
|
||||||
|
arrival_time: string;
|
||||||
|
trip_status: number;
|
||||||
|
ship_name: string;
|
||||||
|
departure_port_id: number;
|
||||||
|
arrival_port_id: number;
|
||||||
|
fishing_ground_codes: number[];
|
||||||
|
trip_cost: TripCost[];
|
||||||
|
notes: string | null;
|
||||||
|
fishing_gears?: FishingGear[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Trip extends TripBasicInfo {
|
||||||
|
id: string;
|
||||||
|
ship_id: string;
|
||||||
|
ship_length: number;
|
||||||
|
vms_id: string;
|
||||||
|
crews?: TripCrews[];
|
||||||
|
total_catch_weight: number | null;
|
||||||
|
total_species_caught: number | null;
|
||||||
|
trip_status: number;
|
||||||
|
approved_by: string;
|
||||||
|
fishing_logs: FishingLog[] | null;
|
||||||
|
sync: boolean;
|
||||||
|
}
|
||||||
|
interface TripQueryParams extends MasterModel.SearchPaginationBody {
|
||||||
|
order?: string;
|
||||||
|
metadata?: {
|
||||||
|
from?: string;
|
||||||
|
to?: string;
|
||||||
|
ship_name?: string;
|
||||||
|
reg_number?: string;
|
||||||
|
province_code?: string;
|
||||||
|
owner_id?: string;
|
||||||
|
ship_id?: string;
|
||||||
|
status?: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripQueryResponse extends MasterModel.PaginationReponse {
|
||||||
|
trips: Trip[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripUpdateParams extends Partial<TripBasicInfo> {
|
||||||
|
crews?: TripCrews[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripDeleteParams {
|
||||||
|
trip_ids: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripUpdateStateRequest {
|
||||||
|
status: number;
|
||||||
|
note?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripCreateParams extends Partial<TripBasicInfo> {
|
||||||
|
crews?: TripCrews[];
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripCost {
|
||||||
|
type: string;
|
||||||
|
unit: string;
|
||||||
|
amount: string;
|
||||||
|
total_cost: string;
|
||||||
|
cost_per_unit: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trip Crews
|
||||||
|
|
||||||
|
interface TripCrewPerson {
|
||||||
|
personal_id: string;
|
||||||
|
name: string;
|
||||||
|
phone: string;
|
||||||
|
email: string;
|
||||||
|
birth_date: Date;
|
||||||
|
note: string;
|
||||||
|
address: string;
|
||||||
|
created_at: Date;
|
||||||
|
updated_at: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripCrews {
|
||||||
|
role: string;
|
||||||
|
joined_at: Date;
|
||||||
|
left_at: Date | null;
|
||||||
|
note: string | null;
|
||||||
|
Person: TripCrewPerson;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripCrewBasicInfo {
|
||||||
|
personal_id: string;
|
||||||
|
role: string;
|
||||||
|
note?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripCrewCreateParams extends Partial<TripCrewBasicInfo> {
|
||||||
|
trip_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface TripCrewUpdateParams extends Partial<TripCrewBasicInfo> {
|
||||||
|
trip_id: string;
|
||||||
|
}
|
||||||
|
interface TripCrewQueryResponse {
|
||||||
|
trip_crews: TripCrews[];
|
||||||
|
total?: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/services/slave/sgw/typings/ws.d.ts
vendored
Normal file
8
src/services/slave/sgw/typings/ws.d.ts
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
declare namespace WsTypes {
|
||||||
|
interface WsThingResponse {
|
||||||
|
thing_id?: string;
|
||||||
|
key?: string;
|
||||||
|
data?: string;
|
||||||
|
time?: number;
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/services/slave/sgw/typings/zone.d.ts
vendored
Normal file
38
src/services/slave/sgw/typings/zone.d.ts
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
declare namespace SgwModel {
|
||||||
|
// Banzone Management
|
||||||
|
interface ZoneBasicInfo {
|
||||||
|
name?: string;
|
||||||
|
province_code?: string;
|
||||||
|
type?: number;
|
||||||
|
conditions?: Condition[];
|
||||||
|
description?: string;
|
||||||
|
geometry?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Banzone extends ZoneBasicInfo {
|
||||||
|
id?: string;
|
||||||
|
created_at?: Date;
|
||||||
|
updated_at?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Condition {
|
||||||
|
max?: number;
|
||||||
|
min?: number;
|
||||||
|
type?: 'length_limit' | 'month_range' | 'date_range';
|
||||||
|
to?: number;
|
||||||
|
from?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Geom {
|
||||||
|
geom_type?: number;
|
||||||
|
geom_poly?: string;
|
||||||
|
geom_lines?: string;
|
||||||
|
geom_point?: string;
|
||||||
|
geom_radius?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface ZoneResponse extends Partial<MasterModel.PaginationResponse> {
|
||||||
|
banzones?: Banzone[];
|
||||||
|
}
|
||||||
|
}
|
||||||
11
src/services/slave/spole/spole.typings.d.ts
vendored
11
src/services/slave/spole/spole.typings.d.ts
vendored
@@ -2,8 +2,11 @@
|
|||||||
// 该文件由 OneAPI 自动生成,请勿手动修改!
|
// 该文件由 OneAPI 自动生成,请勿手动修改!
|
||||||
|
|
||||||
declare namespace SpoleModel {
|
declare namespace SpoleModel {
|
||||||
interface ThingMedata extends MasterModel.ThingMetadata {}
|
interface ThingMetdadata extends MasterModel.ThingReponseMetadata {
|
||||||
|
uptime?: number;
|
||||||
type SpoleThingsResponse = MasterModel.ThingsResponse<SpoleModel.ThingMedata>;
|
}
|
||||||
type SpoleThing = MasterModel.Thing<SpoleModel.ThingMedata>;
|
|
||||||
|
type SpoleThingsResponse =
|
||||||
|
MasterModel.ThingsResponse<SpoleModel.ThingMetdadata>;
|
||||||
|
type SpoleThing = MasterModel.Thing<SpoleModel.ThingMetdadata>;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user