更新地图组件,优化标记点数据处理逻辑,增加全局配置获取方式,提升代码可维护性和用户体验。同时,新增地图标记数据接口定义,确保数据结构一致性。
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { getGlobalConfig } from './utils.ts';
|
||||
import type { GlobalConfig } from '../share/types.ts';
|
||||
import { Spin } from 'antd';
|
||||
import './style_amap.css';
|
||||
import { MapMode, MarkerData } from '../share/types.ts';
|
||||
@@ -7,9 +9,9 @@ import { MapMode, MarkerData } from '../share/types.ts';
|
||||
// 在线地图配置
|
||||
export const AMAP_ONLINE_CONFIG = {
|
||||
// 高德地图 Web API 密钥
|
||||
API_KEY: window.CONFIG?.MAP_CONFIG?.KEY,
|
||||
API_KEY: getGlobalConfig('MAP_CONFIG')?.KEY || '',
|
||||
// 主JS文件路径
|
||||
MAIN_JS: 'https://webapi.amap.com/maps?v=2.0&key=' + window.CONFIG?.MAP_CONFIG?.KEY,
|
||||
MAIN_JS: 'https://webapi.amap.com/maps?v=2.0&key=' + (getGlobalConfig('MAP_CONFIG')?.KEY || ''),
|
||||
// 插件列表
|
||||
PLUGINS: ['AMap.MouseTool', 'AMap.RangingTool', 'AMap.Scale', 'AMap.ToolBar', 'AMap.MarkerCluster'],
|
||||
};
|
||||
@@ -82,6 +84,7 @@ export interface AMapInstance {
|
||||
declare global {
|
||||
interface Window {
|
||||
AMap: any;
|
||||
CONFIG?: GlobalConfig;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,7 +341,7 @@ const AMapComponent: React.FC<AMapProps> = ({
|
||||
height = '400px',
|
||||
center = TILE_CONFIG.DEFAULT_CENTER as [number, number],
|
||||
zoom = TILE_CONFIG.DEFAULT_ZOOM,
|
||||
mode = window.CONFIG?.MAP_CONFIG?.MAP_MODE || MapMode.ONLINE,
|
||||
mode = (getGlobalConfig('MAP_CONFIG')?.MAP_MODE as MapMode) || MapMode.ONLINE,
|
||||
onMarkerClick,
|
||||
onClick,
|
||||
markers = [],
|
||||
@@ -438,4 +441,4 @@ const AMapComponent: React.FC<AMapProps> = ({
|
||||
);
|
||||
};
|
||||
|
||||
export default AMapComponent;
|
||||
export default AMapComponent;
|
||||
|
||||
@@ -108,16 +108,18 @@ export const LoginMapPage = () => {
|
||||
|
||||
// 渲染地图标记点
|
||||
const renderMarkers = (locations: LoginLocation[]): MarkerData[] => {
|
||||
return locations.map(location => ({
|
||||
id: location.id,
|
||||
longitude: location.longitude,
|
||||
latitude: location.latitude,
|
||||
title: location.user.nickname || location.user.username,
|
||||
description: `登录时间: ${dayjs(location.loginTime).format('YYYY-MM-DD HH:mm:ss')}\nIP地址: ${location.ipAddress}`,
|
||||
status: 'online',
|
||||
type: 'login',
|
||||
extraData: location
|
||||
}));
|
||||
return locations
|
||||
.filter(location => location.longitude !== null && location.latitude !== null)
|
||||
.map(location => ({
|
||||
id: location.id?.toString() || '',
|
||||
longitude: location.longitude as number,
|
||||
latitude: location.latitude as number,
|
||||
title: location.user?.nickname || location.user?.username || '未知用户',
|
||||
description: `登录时间: ${dayjs(location.login_time).format('YYYY-MM-DD HH:mm:ss')}\nIP地址: ${location.ip_address}`,
|
||||
status: 'online',
|
||||
type: 'login',
|
||||
extraData: location
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -156,7 +158,9 @@ export const LoginMapPage = () => {
|
||||
<div style={{ height: '100%', minHeight: '500px' }}>
|
||||
<AMap
|
||||
markers={renderMarkers(locations)}
|
||||
center={locations[0] ? [locations[0].longitude, locations[0].latitude] : undefined}
|
||||
center={locations[0] && locations[0].longitude !== null && locations[0].latitude !== null
|
||||
? [locations[0].longitude, locations[0].latitude] as [number, number]
|
||||
: undefined}
|
||||
onMarkerClick={handleMarkerClick}
|
||||
height={'100%'}
|
||||
/>
|
||||
@@ -179,7 +183,7 @@ export const LoginMapPage = () => {
|
||||
) : markerDetail ? (
|
||||
<Descriptions column={1}>
|
||||
<Descriptions.Item label={<><UserOutlined /> 用户</>}>
|
||||
{markerDetail.user.nickname || markerDetail.user.username}
|
||||
{markerDetail.user?.nickname || markerDetail.user?.username || '未知用户'}
|
||||
</Descriptions.Item>
|
||||
<Descriptions.Item label={<><ClockCircleOutlined /> 登录时间</>}>
|
||||
{dayjs(markerDetail.login_time).format('YYYY-MM-DD HH:mm:ss')}
|
||||
@@ -208,4 +212,4 @@ export const LoginMapPage = () => {
|
||||
</Drawer>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -161,6 +161,37 @@ export enum MapMode {
|
||||
OFFLINE = 'offline'
|
||||
}
|
||||
|
||||
|
||||
// 地图标记数据接口 - 基础定义
|
||||
export interface MarkerData {
|
||||
/** 标记点经度 */
|
||||
longitude: number;
|
||||
|
||||
/** 标记点纬度 */
|
||||
latitude: number;
|
||||
|
||||
/** 标记点ID */
|
||||
id?: string | number;
|
||||
|
||||
/** 标记点标题 */
|
||||
title?: string;
|
||||
|
||||
/** 标记点描述 */
|
||||
description?: string;
|
||||
|
||||
/** 标记点图标URL */
|
||||
iconUrl?: string;
|
||||
|
||||
/** 标记点状态 */
|
||||
status?: string;
|
||||
|
||||
/** 标记点类型 */
|
||||
type?: string;
|
||||
|
||||
/** 标记点额外数据 */
|
||||
extraData?: Record<string, any>;
|
||||
}
|
||||
|
||||
// 审核状态枚举
|
||||
export enum AuditStatus {
|
||||
PENDING = 0, // 待审核
|
||||
@@ -424,44 +455,35 @@ export interface KnowInfo {
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
// 登录位置详细信息
|
||||
export interface LoginLocationDetail {
|
||||
/** 记录ID */
|
||||
// 登录位置相关类型定义
|
||||
export interface LoginLocation {
|
||||
id: number;
|
||||
/** 用户ID */
|
||||
user_id: number;
|
||||
/** 登录时间 */
|
||||
login_time: string;
|
||||
/** IP地址 */
|
||||
ip_address: string;
|
||||
/** 用户代理 */
|
||||
user_agent: string;
|
||||
/** 纬度 */
|
||||
latitude: number | null;
|
||||
/** 经度 */
|
||||
longitude: number | null;
|
||||
/** 位置名称 */
|
||||
loginTime: string;
|
||||
ipAddress: string;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
location_name?: string;
|
||||
/** 关联用户信息 */
|
||||
user?: {
|
||||
user: {
|
||||
id: number;
|
||||
username: string;
|
||||
nickname?: string;
|
||||
nickname: string;
|
||||
};
|
||||
}
|
||||
|
||||
// 登录位置信息
|
||||
export interface LoginLocation {
|
||||
/** 纬度 */
|
||||
latitude: number | null;
|
||||
/** 经度 */
|
||||
longitude: number | null;
|
||||
/** IP地址 */
|
||||
ip_address?: string;
|
||||
/** 用户代理 */
|
||||
user_agent?: string;
|
||||
/** 登录时间 */
|
||||
login_time?: string;
|
||||
export interface LoginLocationDetail {
|
||||
id: number;
|
||||
user_id: number;
|
||||
login_time: string;
|
||||
ip_address: string;
|
||||
longitude: number;
|
||||
latitude: number;
|
||||
location_name: string;
|
||||
user_agent: string;
|
||||
user: {
|
||||
id: number;
|
||||
username: string;
|
||||
nickname: string;
|
||||
};
|
||||
}
|
||||
|
||||
// 消息类型枚举
|
||||
|
||||
6
deno.lock
generated
6
deno.lock
generated
@@ -643,6 +643,10 @@
|
||||
"https://esm.d8d.fun/@deno/shim-deno-test@0.5.0?target=denonext": "503b73de1a14bd33782220e11fa2b33e9c87d574ac793e7addf1466c5436e66a",
|
||||
"https://esm.d8d.fun/@deno/shim-deno@0.18.2/denonext/shim-deno.mjs": "819d8ac34fdaf60658cf03d137f14adaff3f13a279ffd79cd8797d84a6ac46ab",
|
||||
"https://esm.d8d.fun/@deno/shim-deno@0.18.2?target=denonext": "ffa3ca347bb6b6530720158f307a2e31b16728fbb52e6432254a07d52fcbc404",
|
||||
"https://esm.d8d.fun/@heroicons/react@2.1.1/24/outline?deps=react@19.0.0,react-dom@19.0.0": "5e99f4d40ce60c55b5cf421c3cf3f13df1707cf53152e447b2332570412cd77a",
|
||||
"https://esm.d8d.fun/@heroicons/react@2.1.1/24/solid?deps=react@19.0.0,react-dom@19.0.0": "e3940182b574da537337b1e90a1b7f380e17050457423e13d5ac8c7bc88a3cc0",
|
||||
"https://esm.d8d.fun/@heroicons/react@2.1.1/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/24/outline.mjs": "640f934a0c987f682032049e5d4a455567db676de47bca0d44e76b72023661f7",
|
||||
"https://esm.d8d.fun/@heroicons/react@2.1.1/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/24/solid.mjs": "dcbd0c377d92857b6eb23c7dbb2ee6e650b12aa6ae1ef7fcc10dc1964df8ba47",
|
||||
"https://esm.d8d.fun/@socket.io/component-emitter@3.1.2/denonext/component-emitter.mjs": "3c6c5f2d64d4933b577a7117df1d8855c51ff01ab3dea8f42af1adcb1a5989e7",
|
||||
"https://esm.d8d.fun/@socket.io/component-emitter@3.1.2?target=denonext": "f6ff0f94ae3c9850a2c3a925cc2b236ec03a80fc2298d0ca48c2a90b10487db3",
|
||||
"https://esm.d8d.fun/@tanstack/query-core@5.67.1/denonext/query-core.mjs": "3001acc66d3efeab4900278cf630cb56ba23ac70cd77f7e0c413abb8a1f223f3",
|
||||
@@ -886,6 +890,8 @@
|
||||
"https://esm.d8d.fun/react-dom@19.0.0/client": "c972c16184c695fc5828dfa61d7f341edbc463d20d8108765c93a98027c24227",
|
||||
"https://esm.d8d.fun/react-dom@19.0.0/denonext/client.mjs": "af662fd134eea98f37fdcea6142accd0f8a7d2e13c1c3c9e98dc37a8c7aad46b",
|
||||
"https://esm.d8d.fun/react-dom@19.0.0/denonext/react-dom.mjs": "a2f7bc344e1d5b7ca47e68665291e206ae4db17ee84f234f3d3e2533b9119f63",
|
||||
"https://esm.d8d.fun/react-hook-form@7.55.0/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/react-hook-form.mjs": "788ec1a54e10051f539ba435aa513802c823bad03e11e2534b1b17df99189a87",
|
||||
"https://esm.d8d.fun/react-hook-form@7.55.0?deps=react@19.0.0,react-dom@19.0.0": "8ed376b3af6e11be43538b15e654692d5995232523a6dc16ce7f81263b1a3614",
|
||||
"https://esm.d8d.fun/react-router@7.3.0/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/dist/development/chunk-K6CSEXPM.mjs": "441898046ad7c4fd9a6b53e13a398c9c74c4412c519e942f82b8a77f7af9f9d6",
|
||||
"https://esm.d8d.fun/react-router@7.3.0/X-ZHJlYWN0LWRvbUAxOS4wLjAscmVhY3RAMTkuMC4w/denonext/react-router.mjs": "b0b05fcfc3a03c5f679cd0bc69ca19aa10abaa977395df00e86b3fb114e5e346",
|
||||
"https://esm.d8d.fun/react-router@7.3.0?deps=react@19.0.0,react-dom@19.0.0": "ad747718e32a45020d67eb4ff98f9734cb06a10ceb393baac0a965043e96cdf0",
|
||||
|
||||
Reference in New Issue
Block a user