diff --git a/src/pages/business_emergencyDuty/components/DutyLog.js b/src/pages/business_emergencyDuty/components/DutyLog.js
index 981d610..65eadb5 100644
--- a/src/pages/business_emergencyDuty/components/DutyLog.js
+++ b/src/pages/business_emergencyDuty/components/DutyLog.js
@@ -1,122 +1,144 @@
import React, { useState } from 'react';
-import { Input, Button, Select, message, Modal, DatePicker } from 'antd';
-import { SearchOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
+import { Input, Button, Select, message, Modal, Tag } from 'antd';
+import { SearchOutlined, PlusOutlined } from '@ant-design/icons';
import StandardTable from '@/components/StandardTable';
import styles from './DutyLog.less';
-import iconsc from '@/assets/yjzygl/iconsc.svg';
const { Option } = Select;
-const { RangePicker } = DatePicker;
const DutyLog = () => {
const [loading, setLoading] = useState(false);
const [selectedRowKeys, setSelectedRowKeys] = useState([]);
const [searchValue, setSearchValue] = useState('');
+ const [eventType, setEventType] = useState('');
+ const [eventStatus, setEventStatus] = useState('');
const [pagination, setPagination] = useState({
- current: 1,
- pageSize: 10,
- total: 15,
- showSizeChanger: true,
+ current: 3,
+ pageSize: 5,
+ total: 48,
+ showSizeChanger: false,
showQuickJumper: true,
- showTotal: (total, range) => `共${total}条`,
+ showTotal: (total) => `共${total}条`,
});
// 模拟数据
const [dataSource, setDataSource] = useState([
{
key: '1',
- number: '01',
- logDate: '2025-10-28 08:00',
- dutyPerson: '张三',
- dutyType: '白班',
- logContent: '正常巡检,未发现异常情况',
- weather: '晴',
- temperature: '18°C',
- recorder: '张三',
- status: '已提交',
+ time: '2025-10-19 15:35:27',
+ location: '义宾南区16号楼',
+ eventType: '交通事故',
+ description: '主干道发生交通事故,造成交通拥堵',
+ status: '已解决',
},
{
key: '2',
- number: '02',
- logDate: '2025-10-28 20:00',
- dutyPerson: '李四',
- dutyType: '夜班',
- logContent: '夜间巡检,设备运行正常',
- weather: '晴',
- temperature: '12°C',
- recorder: '李四',
- status: '已提交',
+ time: '2025-10-15 13:44:41',
+ location: '中山南大街甲1号楼-1-5号附近',
+ eventType: '自然灾害',
+ description: '强风导致广告牌松动,存在安全隐患',
+ status: '待处理',
},
{
key: '3',
- number: '03',
- logDate: '2025-10-27 08:00',
- dutyPerson: '王五',
- dutyType: '白班',
- logContent: '发现A区域照明设备故障,已报修',
- weather: '多云',
- temperature: '16°C',
- recorder: '王五',
- status: '已处理',
+ time: '2025-10-15 00:29:03',
+ location: '西辛南区66号(卧龙环岛东南角)',
+ eventType: '社会安全',
+ description: '商场内发生顾客纠纷,可能引发冲突',
+ status: '已解决',
},
- ]);
-
- // 表格列配置
- const columns = [
{
- title: '编号',
- dataIndex: 'number',
- key: 'number',
- width: 80,
+ key: '4',
+ time: '2025-10-14 17:21:38',
+ location: '怡馨家园5号楼',
+ eventType: '自然灾害',
+ description: '强风导致广告牌松动,存在安全隐患',
+ status: '已解决',
},
{
- title: '记录时间',
- dataIndex: 'logDate',
- key: 'logDate',
- width: 150,
+ key: '5',
+ time: '2025-10-15 02:30:41',
+ location: '站前南街',
+ eventType: '社会安全',
+ description: '商场内发生顾客纠纷,可能引发冲突',
+ status: '已解决',
},
+ ]);
+
+ // 最近值班日志数据
+ const recentLogs = [
{
- title: '值班人员',
- dataIndex: 'dutyPerson',
- key: 'dutyPerson',
- width: 120,
+ title: '设备故障报告',
+ time: '2023-04-17 14:45',
+ location: '3号机房',
+ description: '服务器温度异常升高,已启动备用设备..',
+ status: '预警',
},
{
- title: '值班类型',
- dataIndex: 'dutyType',
- key: 'dutyType',
- width: 100,
+ title: '网络中断处理',
+ time: '2023-04-17 14:45',
+ location: '3号机房',
+ description: '主办公楼网络中断,已联系维修人员处理..',
+ status: '紧急',
},
{
- title: '日志内容',
- dataIndex: 'logContent',
- key: 'logContent',
- width: 250,
- ellipsis: true,
+ title: '日常巡检记录',
+ time: '2023-04-17 14:45',
+ location: '83号机房',
+ description: '完成日常安全巡检,所有设备运行正常...',
+ status: '常规',
+ },
+ ];
+
+ // 事件类型分布数据
+ const eventTypeData = [
+ { name: '交通事故', value: 10, color: '#52C41A' },
+ { name: '自然灾害', value: 15, color: '#FAAD14' },
+ { name: '社会安全', value: 8, color: '#FF7A45' },
+ { name: '电力故障', value: 5, color: '#F5222D' },
+ { name: '火灾隐患', value: 3, color: '#CF1322' },
+ { name: '设施故障', value: 7, color: '#1890FF' },
+ ];
+
+ // 表格列配置
+ const columns = [
+ {
+ title: '时间',
+ dataIndex: 'time',
+ key: 'time',
+ width: 180,
},
{
- title: '天气',
- dataIndex: 'weather',
- key: 'weather',
- width: 80,
+ title: '地点',
+ dataIndex: 'location',
+ key: 'location',
+ width: 200,
},
{
- title: '温度',
- dataIndex: 'temperature',
- key: 'temperature',
- width: 80,
+ title: '事件类型',
+ dataIndex: 'eventType',
+ key: 'eventType',
+ width: 120,
},
{
- title: '记录人',
- dataIndex: 'recorder',
- key: 'recorder',
- width: 100,
+ title: '事件描述',
+ dataIndex: 'description',
+ key: 'description',
+ ellipsis: true,
},
{
title: '状态',
dataIndex: 'status',
key: 'status',
width: 100,
+ render: (status) => {
+ const colorMap = {
+ '已解决': 'success',
+ '待处理': 'warning',
+ '已处理': 'processing',
+ };
+ return {status};
+ },
},
{
title: '操作',
@@ -128,21 +150,16 @@ const DutyLog = () => {
type="link"
size="small"
onClick={() => handleView(record)}
+ style={{ color: '#1890FF', padding: 0 }}
>
查看
-
@@ -167,29 +184,7 @@ const DutyLog = () => {
// 查看处理
const handleView = (record) => {
- message.info(`查看日志详情:${record.logContent}`);
- };
-
- // 批量删除处理
- const handleBatchDelete = () => {
- if (selectedRowKeys.length === 0) {
- message.warning('请选择要删除的数据');
- return;
- }
- Modal.confirm({
- title: '确认删除',
- content: `确定要删除选中的 ${selectedRowKeys.length} 条数据吗?`,
- onOk() {
- setDataSource(dataSource.filter(item => !selectedRowKeys.includes(item.key)));
- setSelectedRowKeys([]);
- message.success('删除成功');
- },
- });
- };
-
- // 编辑处理
- const handleEdit = (record) => {
- message.info(`编辑日志记录`);
+ message.info(`查看日志详情:${record.description}`);
};
// 删除处理
@@ -209,79 +204,223 @@ const DutyLog = () => {
setPagination(pagination);
};
- return (
-
- {/* 页面标题 */}
-
-
-
值班日志记录
+ // 渲染状态标签
+ const renderStatusTag = (status) => {
+ const statusConfig = {
+ '预警': { color: '#FF7A45', bg: '#FFF7E6' },
+ '紧急': { color: '#F5222D', bg: '#FFF1F0' },
+ '常规': { color: '#1890FF', bg: '#E6F7FF' },
+ };
+ const config = statusConfig[status] || { color: '#666', bg: '#F5F5F5' };
+ return (
+
+ {status}
+
+ );
+ };
+
+ // 渲染饼图(简化版)
+ const renderPieChart = () => {
+ const total = eventTypeData.reduce((sum, item) => sum + item.value, 0);
+ let currentAngle = 0;
+
+ return (
+
+
+
+ {eventTypeData.map((item, index) => (
+
+
+ {item.name}
+
+ ))}
+
+ );
+ };
- {/* 搜索和操作区域 */}
-
-
-
-
-
}
- onClick={handleSearch}
- loading={loading}
- className={styles.customButton}
- >
- 查询
-
+ return (
+
+ {/* A块:顶部统计卡片 */}
+
+
-
-
}
- onClick={handleAdd}
- className={styles.customButton}
- >
- 新增
-
-
}
- onClick={handleBatchDelete}
- >
- 删除
-
+
+
+
- {/* 数据表格 */}
-
-
+ {/* B块:主要内容区域 */}
+
+ {/* 左块 */}
+
+ {/* 上部分:事件类型分布 */}
+
+
事件类型分布
+
+ {renderPieChart()}
+
+
+ {/* 下部分:最近值班日志 */}
+
+
最近值班日志
+
+ {recentLogs.map((log, index) => (
+
+
{log.title}
+
+ {log.time}
+ {log.location}
+
+
{log.description}
+
+ {renderStatusTag(log.status)}
+
+
+ ))}
+
+
+
+
+ {/* 右块:值班日志列表 */}
+
+
值班日志列表
+ {/* 搜索和操作区域 */}
+
+ }
+ className={styles.searchInput}
+ style={{ borderRadius: '2px' }}
+ />
+
+
+ }
+ onClick={handleAdd}
+ className={styles.addButton}
+ style={{ borderRadius: '2px' }}
+ >
+ 新增日志
+
+
+ {/* 数据表格 */}
+
+
+
+
);
};
export default DutyLog;
-
diff --git a/src/pages/business_emergencyDuty/components/DutyLog.less b/src/pages/business_emergencyDuty/components/DutyLog.less
index 1c6a136..decbbc8 100644
--- a/src/pages/business_emergencyDuty/components/DutyLog.less
+++ b/src/pages/business_emergencyDuty/components/DutyLog.less
@@ -1,127 +1,412 @@
.container {
padding: 20px;
- background: #fff;
+ background: #F5F5F5;
height: 100vh;
-}
-
-.header {
display: flex;
- align-items: center;
- margin-bottom: 15px;
-
- .titleBar {
- width: 3px;
- height: 16px;
- background: #2E4CD4;
- margin-right: 12px;
- }
-
- .title {
- margin: 0;
- font-size: 14px;
- font-weight: 500;
- color: #333;
- }
-}
+ flex-direction: column;
+ overflow: hidden;
-.searchBar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- margin-bottom: 10px;
- padding: 5px;
-
- .searchLeft {
+ // A块:顶部统计卡片区域
+ .blockA {
+ width: 100%;
+ height: 20%;
display: flex;
- align-items: center;
- gap: 12px;
- }
-
- .searchRight {
- display: flex;
- align-items: center;
- gap: 12px;
- }
-}
+ gap: 16px;
+ margin-bottom: 16px;
+ background: linear-gradient(135deg, #E6F4FF 0%, #BAE0FF 100%);
+ border-radius: 2px;
+ padding: 16px;
-// 自定义按钮样式
-.customButton {
- background-color: #2E4CD4 !important;
- border-color: #2E4CD4 !important;
- border-radius: 2px !important;
- height: 30px !important;
- width: 75px;
- display: flex !important;
- align-items: center !important;
- justify-content: center !important;
-
- &:hover {
- background-color: #1e3bb8 !important;
- border-color: #1e3bb8 !important;
- }
-
- &:focus {
- background-color: #2E4CD4 !important;
- border-color: #2E4CD4 !important;
- }
-}
+ .statCard {
+ flex: 1;
+ height: 100%;
+ background: #FFFFFF;
+ border-radius: 2px;
+ padding: 20px;
+ display: flex;
+ align-items: center;
+ gap: 16px;
-.tableContainer {
- background: #fff;
- border-radius: 0px;
- overflow: hidden;
-
- .actionButtons {
- display: flex;
- gap: 8px;
- font-size: 10px;
- justify-content: center;
-
- .ant-btn-link {
- padding: 0;
- height: auto;
- font-size: 10px;
+ .statIcon {
+ width: 48px;
+ height: 48px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ .cubeIcon {
+ width: 32px;
+ height: 32px;
+ background: #1890FF;
+ border-radius: 4px;
+ }
+
+ .warningIcon {
+ width: 0;
+ height: 0;
+ border-left: 16px solid transparent;
+ border-right: 16px solid transparent;
+ border-bottom: 28px solid #1890FF;
+ position: relative;
+
+ &::after {
+ content: '!';
+ position: absolute;
+ top: 8px;
+ left: -6px;
+ color: #fff;
+ font-weight: bold;
+ font-size: 16px;
+ }
+ }
+
+ .successIcon {
+ width: 32px;
+ height: 32px;
+ background: #1890FF;
+ border-radius: 2px;
+ position: relative;
+
+ &::after {
+ content: '✓';
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: #fff;
+ font-weight: bold;
+ font-size: 18px;
+ }
+ }
+
+ .clockIcon {
+ width: 32px;
+ height: 32px;
+ background: #1890FF;
+ border-radius: 2px;
+ position: relative;
+
+ &::after {
+ content: 'L';
+ position: absolute;
+ top: 50%;
+ left: 50%;
+ transform: translate(-50%, -50%);
+ color: #fff;
+ font-weight: bold;
+ font-size: 18px;
+ }
+ }
+ }
+
+ .statContent {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+
+ .statNumber {
+ font-size: 32px;
+ font-weight: 600;
+ color: #333333;
+ line-height: 1;
+ margin-bottom: 8px;
+ }
+
+ .statLabel {
+ font-size: 14px;
+ color: #666666;
+ }
+ }
}
}
-}
-// 表格样式优化
-.tableContainer {
- :global {
- .ant-table-thead > tr > th {
- background: #F5F5FA;
- font-weight: 500;
- color: #333333;
- font-size: 14px;
- text-align: center;
- }
-
- .ant-table-tbody > tr > td {
- color: #666666;
- font-size: 13px;
- text-align: center;
- }
-
- .ant-table-tbody > tr:hover > td {
- background: #f5f5f5;
- }
-
- .ant-pagination {
- margin-top: 10px;
- text-align: right;
- }
-
- .ant-btn.ant-btn-sm {
- font-size: 13px !important;
- height: 20px !important;
- padding: 0px 4px !important;
+ // B块:主要内容区域
+ .blockB {
+ width: 100%;
+ flex: 1;
+ display: flex;
+ gap: 16px;
+ overflow: hidden;
+
+ // 左块
+ .blockBLeft {
+ width: 400px;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+
+ // 上部分:事件类型分布
+ .leftTop {
+ flex: 1;
+ background: #FFFFFF;
+ border-radius: 2px;
+ padding: 16px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .sectionTitle {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333333;
+ margin-bottom: 16px;
+ }
+
+ .chartWrapper {
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .pieChartContainer {
+ display: flex;
+ align-items: center;
+ gap: 24px;
+ width: 100%;
+
+ .pieSvg {
+ width: 160px;
+ height: 160px;
+ flex-shrink: 0;
+ }
+
+ .pieLegend {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+
+ .legendItem {
+ display: flex;
+ align-items: center;
+ gap: 8px;
+
+ .legendColor {
+ width: 12px;
+ height: 12px;
+ border-radius: 2px;
+ flex-shrink: 0;
+ }
+
+ .legendText {
+ font-size: 14px;
+ color: #666666;
+ }
+ }
+ }
+ }
+ }
+
+ // 下部分:最近值班日志
+ .leftBottom {
+ flex: 1;
+ background: #FFFFFF;
+ border-radius: 2px;
+ padding: 16px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .sectionTitle {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333333;
+ margin-bottom: 16px;
+ }
+
+ .recentLogsList {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+ overflow-y: auto;
+
+ .logCard {
+ background: #F5F5F5;
+ border-radius: 2px;
+ padding: 12px;
+
+ .logTitle {
+ font-size: 14px;
+ font-weight: 500;
+ color: #333333;
+ margin-bottom: 8px;
+ }
+
+ .logInfo {
+ font-size: 12px;
+ color: #999999;
+ margin-bottom: 8px;
+ display: flex;
+ gap: 8px;
+
+ .logLocation {
+ margin-left: 8px;
+ }
+ }
+
+ .logDescription {
+ font-size: 13px;
+ color: #666666;
+ line-height: 1.5;
+ margin-bottom: 8px;
+ display: -webkit-box;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+ overflow: hidden;
+ }
+
+ .logFooter {
+ display: flex;
+ justify-content: flex-end;
+
+ .statusTag {
+ padding: 2px 8px;
+ border-radius: 12px;
+ font-size: 12px;
+ border: 1px solid;
+ }
+ }
+ }
+ }
+ }
}
-
- .ant-btn-link.ant-btn-sm {
- font-size: 13px !important;
- height: auto !important;
- padding: 0 !important;
+
+ // 右块:值班日志列表
+ .blockBRight {
+ flex: 1;
+ background: #FFFFFF;
+ border-radius: 2px;
+ padding: 16px;
+ display: flex;
+ flex-direction: column;
+ overflow: hidden;
+
+ .sectionTitle {
+ font-size: 16px;
+ font-weight: 600;
+ color: #333333;
+ margin-bottom: 16px;
+ }
+
+ .searchBar {
+ display: flex;
+ gap: 12px;
+ margin-bottom: 16px;
+ align-items: center;
+
+ .searchInput {
+ flex: 1;
+ max-width: 300px;
+ }
+
+ .filterSelect {
+ width: 120px;
+ }
+
+ .addButton {
+ background: #1890FF;
+ border-color: #1890FF;
+ color: #FFFFFF;
+ border-radius: 2px;
+ height: 32px;
+ padding: 0 16px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ &:hover {
+ background: #40A9FF;
+ border-color: #40A9FF;
+ }
+ }
+ }
+
+ .tableContainer {
+ flex: 1;
+ overflow: hidden;
+ display: flex;
+ flex-direction: column;
+
+ :global {
+ .ant-table-wrapper {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .ant-spin-nested-loading {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .ant-spin-container {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .ant-table {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .ant-table-container {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+
+ .ant-table-body {
+ flex: 1;
+ overflow-y: auto;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ .ant-table-thead > tr > th {
+ background: #F5F5FA;
+ font-weight: 500;
+ color: #333333;
+ font-size: 14px;
+ text-align: center;
+ border-radius: 0;
+ }
+
+ .ant-table-tbody > tr > td {
+ color: #666666;
+ font-size: 13px;
+ text-align: center;
+ }
+
+ .ant-table-tbody > tr:hover > td {
+ background: #F5F5F5;
+ }
+
+ .ant-pagination {
+ margin-top: 16px;
+ display: flex;
+ justify-content: flex-end;
+ align-items: center;
+ padding: 0;
+ }
+ }
+
+ .actionButtons {
+ display: flex;
+ gap: 8px;
+ justify-content: center;
+ align-items: center;
+
+ .ant-btn-link {
+ padding: 0;
+ height: auto;
+ font-size: 13px;
+ }
+ }
+ }
}
}
}
-