新增人员定位页面
parent
31b679162d
commit
65fb990d7c
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 122 KiB |
@ -0,0 +1,4 @@
|
||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.5633 10.5654C10.8511 10.2501 9.77943 9.43494 8.21372 9.15469C8.61417 8.72587 8.90992 8.05633 9.2207 7.2628C9.40139 6.80308 9.3653 6.41118 9.3653 5.85227C9.3653 5.44032 9.44266 4.7791 9.33952 4.41556C8.99501 3.18709 8.12092 2.84875 7.09964 2.84875C6.07702 2.84875 5.2036 3.18906 4.8589 4.41834C4.75853 4.78288 4.83564 5.44171 4.83564 5.85227C4.83564 6.41217 4.80537 6.80584 4.98646 7.26579C5.29963 8.06347 5.59888 8.73226 5.99675 9.15967C4.44474 9.44328 3.44071 10.2535 2.73305 10.5678C1.26871 11.2219 1.30477 11.9379 1.30477 11.9379V13.1513L13.0724 13.1491V11.9379C13.0724 11.9379 13.0336 11.2191 11.5633 10.5654ZM11.035 3.1224H15.6894V4.14106H11.035V3.1224ZM11.035 5.3529H13.8804V6.38911H11.035V5.3529Z" fill="white" fill-opacity="0.45"/>
|
||||
<path d="M11.0312 7.58337H15.106V8.61959H11.0312V7.58337Z" fill="white" fill-opacity="0.45"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 950 B |
@ -0,0 +1,4 @@
|
||||
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M11.5633 10.5654C10.8511 10.2501 9.77943 9.43494 8.21372 9.15469C8.61417 8.72587 8.90992 8.05633 9.2207 7.2628C9.40139 6.80308 9.3653 6.41118 9.3653 5.85227C9.3653 5.44032 9.44266 4.7791 9.33952 4.41556C8.99501 3.18709 8.12092 2.84875 7.09964 2.84875C6.07702 2.84875 5.2036 3.18906 4.8589 4.41834C4.75853 4.78288 4.83564 5.44171 4.83564 5.85227C4.83564 6.41217 4.80537 6.80584 4.98646 7.26579C5.29963 8.06347 5.59888 8.73226 5.99675 9.15967C4.44474 9.44328 3.44071 10.2535 2.73305 10.5678C1.26871 11.2219 1.30477 11.9379 1.30477 11.9379V13.1513L13.0724 13.1491V11.9379C13.0724 11.9379 13.0336 11.2191 11.5633 10.5654ZM11.035 3.1224H15.6894V4.14106H11.035V3.1224ZM11.035 5.3529H13.8804V6.38911H11.035V5.3529Z" fill="white"/>
|
||||
<path d="M11.0312 7.58337H15.106V8.61959H11.0312V7.58337Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 910 B |
@ -0,0 +1,486 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { Button, Card, Row, Col, Input, Select, Space, Tag, Divider } from 'antd';
|
||||
import { SearchOutlined, FilterOutlined, ExportOutlined, LocateOutlined, UserOutlined, ClockCircleOutlined, EnvironmentOutlined }
|
||||
from '@ant-design/icons';
|
||||
import StandardTable from '@/components/StandardTable';
|
||||
import styles from './PersonnelLocation.less';
|
||||
import datadictionary from "@/utils/dataDictionary";
|
||||
import gisTemp from '@/assets/img/gisTemp.svg';
|
||||
|
||||
const { Option } = Select;
|
||||
const { Search } = Input;
|
||||
|
||||
// 模拟数据
|
||||
const mockLocationData = {
|
||||
list: [
|
||||
{
|
||||
id: '001',
|
||||
name: '张三',
|
||||
empId: '10001',
|
||||
position: '管理人员',
|
||||
department: '安全部',
|
||||
location: 'A区安控室',
|
||||
time: '2025-09-03 21:32',
|
||||
status: '正常'
|
||||
},
|
||||
{
|
||||
id: '002',
|
||||
name: '李四',
|
||||
empId: '10002',
|
||||
position: '管理人员',
|
||||
department: '设备部',
|
||||
location: 'A区发电室',
|
||||
time: '2025-09-03 21:30',
|
||||
status: '预警'
|
||||
},
|
||||
{
|
||||
id: '003',
|
||||
name: '王五',
|
||||
empId: '10003',
|
||||
position: '管理人员',
|
||||
department: '设备部',
|
||||
location: 'A区发电室',
|
||||
time: '2025-09-03 21:29',
|
||||
status: '预警'
|
||||
},
|
||||
{
|
||||
id: '004',
|
||||
name: '赵六',
|
||||
empId: '10004',
|
||||
position: '管理人员',
|
||||
department: '设备部',
|
||||
location: 'A区发电室',
|
||||
time: '2025-09-03 21:28',
|
||||
status: '告警'
|
||||
},
|
||||
{
|
||||
id: '005',
|
||||
name: '孙七',
|
||||
empId: '10005',
|
||||
position: '管理人员',
|
||||
department: '设备部',
|
||||
location: 'A区发电室',
|
||||
time: '2025-09-03 21:27',
|
||||
status: '正常'
|
||||
},
|
||||
],
|
||||
pagination: {
|
||||
total: 120,
|
||||
current: 1,
|
||||
pageSize: 5,
|
||||
},
|
||||
};
|
||||
|
||||
// 历史轨迹数据
|
||||
const historyTrailData = [
|
||||
{
|
||||
title: '进入危险区域管理',
|
||||
time: '2025-09-03 20:30',
|
||||
location: 'A区发电室'
|
||||
},
|
||||
{
|
||||
title: '长时间停留',
|
||||
time: '2025-09-03 20:15',
|
||||
location: 'A区发电室'
|
||||
},
|
||||
{
|
||||
title: '异常行为',
|
||||
time: '2025-09-03 19:45',
|
||||
location: 'A区发电室'
|
||||
},
|
||||
{
|
||||
title: '工作开始',
|
||||
time: '2025-09-03 08:00',
|
||||
location: 'A区发电室'
|
||||
},
|
||||
];
|
||||
|
||||
// 人员警告信息数据
|
||||
const personnelWarningData = [
|
||||
{
|
||||
title: '电池低电量',
|
||||
time: '2025-09-03 21:35',
|
||||
location: 'A区发电室',
|
||||
level: 'warning'
|
||||
},
|
||||
{
|
||||
title: '信号丢失',
|
||||
time: '2025-09-03 21:30',
|
||||
location: 'B区地下室',
|
||||
level: 'error'
|
||||
},
|
||||
{
|
||||
title: '超过活动范围',
|
||||
time: '2025-09-03 21:25',
|
||||
location: 'C区仓库',
|
||||
level: 'warning'
|
||||
},
|
||||
{
|
||||
title: '静止时间过长',
|
||||
time: '2025-09-03 21:20',
|
||||
location: 'D区会议室',
|
||||
level: 'warning'
|
||||
},
|
||||
];
|
||||
|
||||
class PersonnelLocation extends PureComponent {
|
||||
state = {
|
||||
selectedRows: [],
|
||||
formValues: {},
|
||||
selectedPerson: null,
|
||||
};
|
||||
|
||||
// 表格列定义
|
||||
columns = [
|
||||
{
|
||||
title: '姓名',
|
||||
dataIndex: 'name',
|
||||
key: 'name',
|
||||
width: 100,
|
||||
render: (text) => (
|
||||
<span style={{ fontSize: '12px' }}>{text}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '工号',
|
||||
dataIndex: 'empId',
|
||||
key: 'empId',
|
||||
width: 100,
|
||||
render: (text) => (
|
||||
<span style={{ fontSize: '12px' }}>{text}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '岗位',
|
||||
dataIndex: 'position',
|
||||
key: 'position',
|
||||
width: 120,
|
||||
render: (text) => (
|
||||
<span style={{ fontSize: '12px' }}>{text}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '所属部门',
|
||||
dataIndex: 'department',
|
||||
key: 'department',
|
||||
width: 120,
|
||||
render: (text) => (
|
||||
<span style={{ fontSize: '12px' }}>{text}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '当前位置',
|
||||
dataIndex: 'location',
|
||||
key: 'location',
|
||||
width: 150,
|
||||
render: (text) => (
|
||||
<span style={{ fontSize: '12px' }}>{text}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '时间',
|
||||
dataIndex: 'time',
|
||||
key: 'time',
|
||||
width: 150,
|
||||
render: (text) => (
|
||||
<span style={{ fontSize: '12px' }}>{text}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: '状态',
|
||||
dataIndex: 'status',
|
||||
key: 'status',
|
||||
width: 80,
|
||||
render: (text) => {
|
||||
if (text === '正常') {
|
||||
return <Tag className={styles['status-tag'] + ' ' + styles['status-normal']}>{text}</Tag>;
|
||||
} else if (text === '预警') {
|
||||
return <Tag className={styles['status-tag'] + ' ' + styles['status-warning']}>{text}</Tag>;
|
||||
} else {
|
||||
return <Tag className={styles['status-tag'] + ' ' + styles['status-error']}>{text}</Tag>;
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
title: '操作',
|
||||
key: 'action',
|
||||
width: 80,
|
||||
fixed: 'right',
|
||||
render: (_, record) => (
|
||||
<a
|
||||
style={{
|
||||
color: 'rgba(36, 114, 214, 1)',
|
||||
fontSize: '12px'
|
||||
}}
|
||||
onClick={() => this.handleLocate(record)}
|
||||
>
|
||||
定位
|
||||
</a>
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
// 获取地图配置选项
|
||||
getMapChartOption = () => {
|
||||
return {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: '{b}'
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '人员分布',
|
||||
type: 'scatter',
|
||||
coordinateSystem: 'geo',
|
||||
symbolSize: 20,
|
||||
data: [
|
||||
{ name: '张三', value: [116.404, 39.915], itemStyle: { color: '#52C41A' } },
|
||||
{ name: '李四', value: [116.414, 39.925], itemStyle: { color: '#FAAD14' } },
|
||||
{ name: '王五', value: [116.424, 39.935], itemStyle: { color: '#FAAD14' } },
|
||||
{ name: '赵六', value: [116.434, 39.945], itemStyle: { color: '#FF4D4F' } },
|
||||
{ name: '孙七', value: [116.444, 39.955], itemStyle: { color: '#52C41A' } },
|
||||
],
|
||||
emphasis: {
|
||||
focus: 'series',
|
||||
itemStyle: {
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
geo: {
|
||||
map: 'beijing',
|
||||
label: {
|
||||
show: true
|
||||
},
|
||||
roam: true,
|
||||
itemStyle: {
|
||||
areaColor: '#f0f2f5',
|
||||
borderColor: '#999'
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
areaColor: '#e6f7ff'
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// 处理表格变化
|
||||
handleTableChange = (pagination, sorter) => {
|
||||
const { dispatch } = this.props;
|
||||
const { formValues } = this.state;
|
||||
|
||||
const params = {
|
||||
currentPage: pagination.current,
|
||||
pageSize: pagination.pageSize,
|
||||
...formValues
|
||||
};
|
||||
|
||||
sorter.field && (params.sorter = `${sorter.field}_${sorter.order}`);
|
||||
};
|
||||
|
||||
// 处理行选择
|
||||
handleSelectRows = rows => {
|
||||
this.setState({
|
||||
selectedRows: rows
|
||||
});
|
||||
};
|
||||
|
||||
// 处理搜索
|
||||
handleSearch = values => {
|
||||
this.setState({
|
||||
formValues: values
|
||||
});
|
||||
};
|
||||
|
||||
// 处理定位
|
||||
handleLocate = (record) => {
|
||||
this.setState({
|
||||
selectedPerson: record
|
||||
});
|
||||
// 这里可以添加地图定位的逻辑
|
||||
console.log('定位人员:', record);
|
||||
};
|
||||
|
||||
render() {
|
||||
const {
|
||||
selectedRows,
|
||||
selectedPerson
|
||||
} = this.state;
|
||||
|
||||
return (
|
||||
<Card bordered={false} className={styles['card-container']}>
|
||||
{/* 主要内容区域 - 地图、历史轨迹和人员警告在同一行 */}
|
||||
<Row gutter={16} style={{ marginBottom: 15 }}>
|
||||
{/* 左侧:地图显示(占一半宽度) */}
|
||||
<Col span={12}>
|
||||
<Card title="人员定位管理" className={styles['map-card']}>
|
||||
<div className={styles['map-container']}>
|
||||
{/* 由于缺少实际地图组件,这里使用模拟的地图容器 */}
|
||||
<div className={styles['mock-map']}>
|
||||
<div className={styles['map-legend']}>
|
||||
<div className={styles['legend-item']}>
|
||||
<div className={styles['legend-dot']} style={{ backgroundColor: '#52C41A' }}></div>
|
||||
<span>正常 (45)</span>
|
||||
</div>
|
||||
<div className={styles['legend-item']}>
|
||||
<div className={styles['legend-dot']} style={{ backgroundColor: '#FAAD14' }}></div>
|
||||
<span>预警 (32)</span>
|
||||
</div>
|
||||
<div className={styles['legend-item']}>
|
||||
<div className={styles['legend-dot']} style={{ backgroundColor: '#FF4D4F' }}></div>
|
||||
<span>告警 (12)</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className={styles['map-content']}>
|
||||
<img
|
||||
src={gisTemp}
|
||||
alt="GIS地图"
|
||||
className={styles['map-image']}
|
||||
/>
|
||||
{/* 地图上的标记点 */}
|
||||
<div className={styles['map-marker']} style={{ top: '15%', left: '25%', backgroundColor: '#52C41A' }}>
|
||||
<span className={styles['marker-tooltip']}>张三 - A区安控室</span>
|
||||
</div>
|
||||
<div className={styles['map-marker']} style={{ top: '30%', left: '40%', backgroundColor: '#FAAD14' }}>
|
||||
<span className={styles['marker-tooltip']}>李四 - A区发电室</span>
|
||||
</div>
|
||||
<div className={styles['map-marker']} style={{ top: '45%', left: '55%', backgroundColor: '#FAAD14' }}>
|
||||
<span className={styles['marker-tooltip']}>王五 - A区发电室</span>
|
||||
</div>
|
||||
<div className={styles['map-marker']} style={{ top: '60%', left: '70%', backgroundColor: '#FF4D4F' }}>
|
||||
<span className={styles['marker-tooltip']}>赵六 - A区发电室</span>
|
||||
</div>
|
||||
<div className={styles['map-marker']} style={{ top: '75%', left: '85%', backgroundColor: '#52C41A' }}>
|
||||
<span className={styles['marker-tooltip']}>孙七 - A区发电室</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/* 筛选栏 - 移至地图卡片内部 */}
|
||||
<Divider style={{ margin: '16px 0' }} />
|
||||
<div className={styles['table-toolbar-container']}>
|
||||
<Row justify="space-between" align="middle">
|
||||
<Col>
|
||||
<Space>
|
||||
<Search
|
||||
placeholder="搜索姓名、工号..."
|
||||
className={styles['search-input']}
|
||||
onSearch={this.handleSearch}
|
||||
/>
|
||||
<span style={{ marginLeft: 20 }}>安全区域</span>
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
className={styles['filter-select']}
|
||||
defaultValue="all"
|
||||
>
|
||||
<Option value="all">全部区域</Option>
|
||||
<Option value="high">高风险</Option>
|
||||
<Option value="medium">中风险</Option>
|
||||
<Option value="low">低风险</Option>
|
||||
</Select>
|
||||
<span style={{ marginLeft: 20 }}>人员类型</span>
|
||||
<Select
|
||||
placeholder="请选择"
|
||||
className={styles['filter-select']}
|
||||
defaultValue="all"
|
||||
>
|
||||
<Option value="all">全部人员</Option>
|
||||
<Option value="safety">安全人员</Option>
|
||||
<Option value="manager">管理人员</Option>
|
||||
<Option value="operator">操作维护人员</Option>
|
||||
<Option value="other">其他人员</Option>
|
||||
</Select>
|
||||
</Space>
|
||||
</Col>
|
||||
<Col>
|
||||
<Space>
|
||||
<Button
|
||||
icon={<FilterOutlined />}
|
||||
className={styles['button-style']}
|
||||
>
|
||||
筛选
|
||||
</Button>
|
||||
<Button
|
||||
icon={<ExportOutlined />}
|
||||
className={styles['button-style']}
|
||||
>
|
||||
导出
|
||||
</Button>
|
||||
</Space>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
{/* 中间:历史轨迹(占四分之一宽度) */}
|
||||
<Col span={6}>
|
||||
<Card title="历史轨迹追踪" className={styles['trail-card']}>
|
||||
<div className={styles['trail-list']}>
|
||||
{historyTrailData.map((item, index) => (
|
||||
<div key={index} className={styles['trail-item']}>
|
||||
<div className={styles['trail-icon']}>
|
||||
<ClockCircleOutlined />
|
||||
</div>
|
||||
<div className={styles['trail-content']}>
|
||||
<div className={styles['trail-title']}>{item.title}</div>
|
||||
<div className={styles['trail-info']}>
|
||||
<span>{item.time}</span>
|
||||
<span>{item.location}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
|
||||
{/* 右侧:人员警告信息(占四分之一宽度) */}
|
||||
<Col span={6}>
|
||||
<Card title="人员警告信息" className={styles['warning-card']}>
|
||||
<div className={styles['warning-list']}>
|
||||
{personnelWarningData.map((item, index) => (
|
||||
<div key={index} className={styles['warning-item'] + ' ' + styles[`warning-${item.level}`]}>
|
||||
<div className={styles['warning-icon']}>
|
||||
{item.level === 'error' ? <Tag color="error">严重</Tag> : <Tag color="warning">警告</Tag>}
|
||||
</div>
|
||||
<div className={styles['warning-content']}>
|
||||
<div className={styles['warning-title']}>{item.title}</div>
|
||||
<div className={styles['warning-info']}>
|
||||
<span>{item.time}</span>
|
||||
<span>{item.location}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</Card>
|
||||
</Col>
|
||||
</Row>
|
||||
|
||||
{/* 底部表格区域 */}
|
||||
<div className={styles['table-container']}>
|
||||
<Card title="人员实时位置信息" className={styles['location-table-card']}>
|
||||
<StandardTable
|
||||
rowKey={'id'}
|
||||
selectedRows={selectedRows}
|
||||
loading={false}
|
||||
data={mockLocationData}
|
||||
columns={this.columns}
|
||||
onSelectRow={this.handleSelectRows}
|
||||
onChange={this.handleTableChange}
|
||||
scroll={{ x: 1200 }}
|
||||
showTotal={(total, range) => `共 ${total} 条`}
|
||||
/>
|
||||
</Card>
|
||||
</div>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default PersonnelLocation;
|
||||
@ -0,0 +1,452 @@
|
||||
// Ant Design 5.x不再需要导入less主题文件
|
||||
// 直接定义我们需要的主题变量
|
||||
@primary-color: rgba(36, 114, 214, 1); // 与全局样式保持一致
|
||||
@success-color: #52c41a;
|
||||
@warning-color: #faad14;
|
||||
@error-color: #ff4d4f;
|
||||
@bg-color: #f7f8fa;
|
||||
@card-bg: #ffffff;
|
||||
@border-color: #e8e8e8;
|
||||
@text-primary: #333333;
|
||||
@text-secondary: #666666;
|
||||
@text-tertiary: #999999;
|
||||
|
||||
// 阴影效果
|
||||
@shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
@shadow-md: 0 4px 12px rgba(0, 0, 0, 0.08);
|
||||
@shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.12);
|
||||
|
||||
// 动画效果
|
||||
@transition-base: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
@transition-hover: all 0.2s ease-in-out;
|
||||
|
||||
.card-container {
|
||||
padding: 16px;
|
||||
background-color: @bg-color;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
// 顶部工具栏样式
|
||||
.table-toolbar-container {
|
||||
padding: 12px 16px;
|
||||
background-color: @card-bg;
|
||||
border-radius: 8px;
|
||||
box-shadow: @shadow-sm;
|
||||
}
|
||||
|
||||
// 搜索和筛选控件样式
|
||||
.search-input {
|
||||
width: 240px;
|
||||
height: 36px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
transition: @transition-hover;
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.2);
|
||||
}
|
||||
}
|
||||
|
||||
.filter-select {
|
||||
width: 140px;
|
||||
height: 36px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
transition: @transition-hover;
|
||||
}
|
||||
|
||||
// 按钮样式
|
||||
.button-style {
|
||||
margin-left: 12px;
|
||||
height: 36px;
|
||||
padding: 0 16px;
|
||||
border-radius: 6px;
|
||||
font-size: 14px;
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
transform: translateY(-1px);
|
||||
box-shadow: @shadow-md;
|
||||
}
|
||||
}
|
||||
|
||||
// 地图卡片样式
|
||||
.map-card {
|
||||
width: 100%;
|
||||
min-height: 400px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: @shadow-md;
|
||||
transition: @transition-hover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&:hover {
|
||||
box-shadow: @shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.map-container {
|
||||
height: calc(100% - 120px);
|
||||
}
|
||||
|
||||
.mock-map {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
background: linear-gradient(135deg, #f0f2f5 0%, #e6f7ff 100%);
|
||||
border-radius: 0 0 8px 8px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// 地图图例样式
|
||||
.map-legend {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 16px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
padding: 12px 16px;
|
||||
border-radius: 8px;
|
||||
box-shadow: @shadow-md;
|
||||
z-index: 10;
|
||||
backdrop-filter: blur(4px);
|
||||
}
|
||||
|
||||
.legend-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 6px;
|
||||
font-size: 13px;
|
||||
color: @text-secondary;
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.legend-dot {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
border-radius: 50%;
|
||||
margin-right: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
// 地图内容样式
|
||||
.map-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.map-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
border-radius: 0 0 8px 8px;
|
||||
}
|
||||
|
||||
// 地图标记点样式
|
||||
.map-marker {
|
||||
position: absolute;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 50%;
|
||||
cursor: pointer;
|
||||
transform: translate(-50%, -50%);
|
||||
box-shadow: 0 0 0 4px rgba(255, 255, 255, 0.9);
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
transform: translate(-50%, -50%) scale(1.2);
|
||||
box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.95);
|
||||
z-index: 20;
|
||||
}
|
||||
}
|
||||
|
||||
// 标记点提示样式
|
||||
.marker-tooltip {
|
||||
position: absolute;
|
||||
top: -32px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: rgba(0, 0, 0, 0.8);
|
||||
color: white;
|
||||
padding: 6px 12px;
|
||||
border-radius: 6px;
|
||||
font-size: 13px;
|
||||
white-space: nowrap;
|
||||
display: none;
|
||||
animation: fadeIn 0.2s ease-in-out;
|
||||
}
|
||||
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateX(-50%) translateY(5px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.map-marker:hover .marker-tooltip {
|
||||
display: block;
|
||||
}
|
||||
|
||||
// 统计卡片样式
|
||||
.stats-card {
|
||||
margin-bottom: 16px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: @shadow-md;
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
box-shadow: @shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
// 历史轨迹卡片样式
|
||||
.trail-card {
|
||||
height: 100%;
|
||||
min-height: 240px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: @shadow-md;
|
||||
transition: @transition-hover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&:hover {
|
||||
box-shadow: @shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
// 人员警告卡片样式
|
||||
.warning-card {
|
||||
height: 100%;
|
||||
min-height: 240px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: @shadow-md;
|
||||
transition: @transition-hover;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
&:hover {
|
||||
box-shadow: @shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
.trail-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
// 轨迹项样式
|
||||
.trail-item {
|
||||
display: flex;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
background-color: #fafafa;
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid @primary-color;
|
||||
}
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.trail-icon {
|
||||
margin-right: 12px;
|
||||
color: @primary-color;
|
||||
font-size: 16px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.trail-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.trail-title {
|
||||
font-size: 14px;
|
||||
color: @text-primary;
|
||||
margin-bottom: 6px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.trail-info {
|
||||
font-size: 12px;
|
||||
color: @text-tertiary;
|
||||
}
|
||||
|
||||
.trail-info span {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
// 表格容器样式
|
||||
.table-container {
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
// 位置表格卡片样式
|
||||
.location-table-card {
|
||||
min-height: 400px;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: @shadow-md;
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
box-shadow: @shadow-lg;
|
||||
}
|
||||
}
|
||||
|
||||
// 滚动条样式优化
|
||||
.trail-list::-webkit-scrollbar,
|
||||
.warning-list::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.trail-list::-webkit-scrollbar-track,
|
||||
.warning-list::-webkit-scrollbar-track {
|
||||
background: #f5f5f5;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.trail-list::-webkit-scrollbar-thumb,
|
||||
.warning-list::-webkit-scrollbar-thumb {
|
||||
background: #d9d9d9;
|
||||
border-radius: 3px;
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
background: #bfbfbf;
|
||||
}
|
||||
}
|
||||
|
||||
// Ant Design 表格样式覆盖
|
||||
.ant-table {
|
||||
.ant-table-thead > tr > th {
|
||||
background-color: #fafafa;
|
||||
font-weight: 500;
|
||||
border-bottom: 1px solid #e8e8e8;
|
||||
}
|
||||
.ant-table-tbody > tr:hover > td {
|
||||
background-color: #f5f8ff !important;
|
||||
}
|
||||
.ant-table-pagination {
|
||||
margin-top: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
// 状态标签样式
|
||||
.status-tag {
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
&.status-normal {
|
||||
background-color: #f6ffed;
|
||||
color: @success-color;
|
||||
border: 1px solid #b7eb8f;
|
||||
}
|
||||
&.status-warning {
|
||||
background-color: #fff7e6;
|
||||
color: @warning-color;
|
||||
border: 1px solid #ffd591;
|
||||
}
|
||||
&.status-error {
|
||||
background-color: #fff1f0;
|
||||
color: @error-color;
|
||||
border: 1px solid #ffccc7;
|
||||
}
|
||||
}
|
||||
|
||||
// 人员警告列表样式
|
||||
.warning-list {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
// 警告项样式
|
||||
.warning-item {
|
||||
display: flex;
|
||||
padding: 12px 0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
transition: @transition-hover;
|
||||
&:hover {
|
||||
background-color: #fafafa;
|
||||
padding-left: 8px;
|
||||
border-left: 3px solid @primary-color;
|
||||
}
|
||||
&:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
&.warning-warning {
|
||||
border-left: 3px solid @warning-color;
|
||||
}
|
||||
&.warning-error {
|
||||
border-left: 3px solid @error-color;
|
||||
}
|
||||
}
|
||||
|
||||
.warning-icon {
|
||||
margin-right: 12px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.warning-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.warning-title {
|
||||
font-size: 14px;
|
||||
color: @text-primary;
|
||||
margin-bottom: 6px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.warning-info {
|
||||
font-size: 12px;
|
||||
color: @text-tertiary;
|
||||
}
|
||||
|
||||
.warning-info span {
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
// 响应式布局适配
|
||||
@media (max-width: 1200px) {
|
||||
.search-input {
|
||||
width: 200px;
|
||||
}
|
||||
.filter-select {
|
||||
width: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.card-container {
|
||||
padding: 8px;
|
||||
}
|
||||
.table-toolbar-container {
|
||||
padding: 12px 8px;
|
||||
}
|
||||
.search-input {
|
||||
width: 100%;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.filter-select {
|
||||
width: 100%;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.button-style {
|
||||
margin-left: 0;
|
||||
margin-right: 8px;
|
||||
}
|
||||
.map-card {
|
||||
min-height: 300px;
|
||||
}
|
||||
.trail-card {
|
||||
height: auto;
|
||||
min-height: 200px;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue