| New file |
| | |
| | | /** |
| | | * AppHeader 组件 - 蓝色顶部导航栏 |
| | | * 包含系统名称、通知图标、调解员信息 |
| | | */ |
| | | |
| | | import React, { useState, useCallback } from 'react'; |
| | | import { Badge, Popover, List, Avatar } from 'antd'; |
| | | import { BellOutlined, UserOutlined } from '@ant-design/icons'; |
| | | import { getMergedParams } from '../../utils/urlParams'; |
| | | import './AppHeader.css'; |
| | | |
| | | // 默认头像 |
| | | const DEFAULT_AVATAR = '/app_logo.png'; |
| | | |
| | | /** |
| | | * 从URL参数获取调解员信息 |
| | | */ |
| | | const getMediatorInfo = () => { |
| | | const params = getMergedParams(); |
| | | return { |
| | | trueName: params.trueName || '调解员', |
| | | unit: params.unit || '', |
| | | roleName: params.roleName || '管理员', |
| | | avatar: params.avatar || '' |
| | | }; |
| | | }; |
| | | |
| | | /** |
| | | * 通知列表组件 |
| | | */ |
| | | const NotificationList = ({ notifications, onClose }) => { |
| | | if (!notifications?.length) { |
| | | return ( |
| | | <div className="notification-empty"> |
| | | <span>暂无新通知</span> |
| | | </div> |
| | | ); |
| | | } |
| | | |
| | | return ( |
| | | <List |
| | | className="notification-list" |
| | | dataSource={notifications} |
| | | renderItem={(item) => ( |
| | | <List.Item className="notification-item"> |
| | | <div className="notification-content"> |
| | | <span className="notification-text">{item.content || item.title}</span> |
| | | <span className="notification-time">{item.create_time || item.time}</span> |
| | | </div> |
| | | </List.Item> |
| | | )} |
| | | /> |
| | | ); |
| | | }; |
| | | |
| | | /** |
| | | * AppHeader 主组件 |
| | | */ |
| | | const AppHeader = ({ notifications = [] }) => { |
| | | const [popoverVisible, setPopoverVisible] = useState(false); |
| | | const mediatorInfo = getMediatorInfo(); |
| | | |
| | | // 处理Popover显示状态 |
| | | const handlePopoverChange = useCallback((visible) => { |
| | | setPopoverVisible(visible); |
| | | }, []); |
| | | |
| | | // 渲染通知图标和气泡 |
| | | const renderNotificationIcon = () => ( |
| | | <Badge count={notifications.length} offset={[-2, 2]} size="small"> |
| | | <BellOutlined className="header-bell-icon" /> |
| | | </Badge> |
| | | ); |
| | | |
| | | // 渲染调解员信息 |
| | | const renderMediatorInfo = () => ( |
| | | <div className="header-mediator"> |
| | | <Avatar |
| | | src={mediatorInfo.avatar || DEFAULT_AVATAR} |
| | | icon={!mediatorInfo.avatar && <UserOutlined />} |
| | | className="mediator-avatar" |
| | | /> |
| | | <div className="mediator-details"> |
| | | <span className="mediator-name">{mediatorInfo.trueName}</span> |
| | | <span className="mediator-role"> |
| | | {mediatorInfo.unit && `${mediatorInfo.unit} | `}{mediatorInfo.roleName} |
| | | </span> |
| | | </div> |
| | | <span className="mediator-status-dot" /> |
| | | </div> |
| | | ); |
| | | |
| | | return ( |
| | | <header className="app-header"> |
| | | {/* 左侧:系统名称 */} |
| | | <div className="header-left"> |
| | | <span className="header-title">矛盾纠纷应用</span> |
| | | </div> |
| | | |
| | | {/* 右侧:通知+调解员信息 */} |
| | | <div className="header-right"> |
| | | {/* 通知图标 */} |
| | | <Popover |
| | | content={<NotificationList notifications={notifications} />} |
| | | title="系统通知" |
| | | trigger="click" |
| | | open={popoverVisible} |
| | | onOpenChange={handlePopoverChange} |
| | | placement="bottomRight" |
| | | overlayClassName="notification-popover" |
| | | > |
| | | <div className="header-notification"> |
| | | {renderNotificationIcon()} |
| | | </div> |
| | | </Popover> |
| | | |
| | | {/* 调解员信息 */} |
| | | {renderMediatorInfo()} |
| | | </div> |
| | | </header> |
| | | ); |
| | | }; |
| | | |
| | | export default AppHeader; |