修改小铃铛及浮动框相关代码

This commit is contained in:
何童崇 2021-09-14 14:56:21 +08:00
parent 3598225cac
commit bc11ac3d79
4 changed files with 364 additions and 154 deletions

View File

@ -0,0 +1,108 @@
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { Icon } from 'antd';
import _ from 'lodash';
import Nodata from '../Nodata';
class PullRefresh extends Component {
constructor(props) {
super(props);
this.state = {
}
this.pullRef = {};
//
this.onScrollList = _.throttle(this.handleScroll, 200, {
leading: false,
trailing: true,
});
}
componentDidMount() {
let dom = document.querySelector('.pull-refresh-wrap');
dom && dom.addEventListener('scroll', this.onScrollList);
}
componentWillUnmount() {
let dom = document.querySelector('.pull-refresh-wrap');
dom && dom.removeEventListener('scroll', this.onScrollList)
}
handleScroll = () => {
if (this.props.count < this.props.pageSize) return;
if (this.props.type === 1 || this.props.type === 2) return;
const wrap = this.pullRef;
const currentScroll = wrap.scrollTop + wrap.clientHeight
//
if (currentScroll >= (wrap.scrollHeight - 10)) {
this.loadData()
}
}
handleLoadClick = () => {
this.loadData();
}
loadData = () => {
this.props.onPullRefresh()
}
renderLoading() {
switch (this.props.type) {
case 0: //
return <div className='text-center' onClick={this.handleLoadClick}>显示更多</div>
case 1: //
return (
<div className='text-center'>
<Icon type="loading" />
<span className='text-center'>加载中...</span>
</div>
)
case 2: //
return <div className='text-center'>没有更多了</div>
default:
return <div className='text-center'>没有更多了</div>
}
}
render() {
const { className, count, children } = this.props;
return (
<div
className={`pull-refresh-wrap ${className}`}
ref={dom => { this.pullRef = dom }}
>
{children}
{
count < 1 && <Nodata _html="暂无未读消息"/>
}
{/* 大于分页数据才显示loading */}
{/* {this.props.count >= this.props.pageSize ? this.renderLoading() : null} */}
</div>
)
}
}
PullRefresh.propTypes = {
className: PropTypes.string,
children: PropTypes.any,
onPullRefresh: PropTypes.func.isRequired,
type: PropTypes.oneOf([0, 1, 2]),
count: PropTypes.number.isRequired,
pageSize: PropTypes.number.isRequired,
}
export default PullRefresh

View File

@ -48,6 +48,7 @@ class NewHeader extends Component {
settings: null, settings: null,
visiblemyss: false, visiblemyss: false,
openSearch:false, openSearch:false,
visible:false, //浮动消息框展示控制
} }
} }
componentDidMount() { componentDidMount() {
@ -93,9 +94,6 @@ class NewHeader extends Component {
this.setState({ this.setState({
user: newProps.user user: newProps.user
}) })
if (newProps.Headertop !== undefined) {
old_url = newProps.Headertop.old_url
}
} }
educoderlogin = () => { educoderlogin = () => {
@ -277,8 +275,12 @@ class NewHeader extends Component {
) )
} }
handleVisibleChange = visible => {
this.setState({ visible });
};
render() { render() {
const { match} = this.props; const { match ,hisroty ,showNotification} = this.props;
let current_user = this.props.user; let current_user = this.props.user;
let { let {
AccountProfiletype, AccountProfiletype,
@ -287,6 +289,7 @@ class NewHeader extends Component {
headtypesonClickbool, headtypesonClickbool,
headtypess, headtypess,
settings, settings,
visible,
} = this.state; } = this.state;
/*用户名称 用户头像url*/ /*用户名称 用户头像url*/
let activeIndex = false; let activeIndex = false;
@ -366,6 +369,7 @@ class NewHeader extends Component {
let search_url = settings && settings.common && settings.common.search; let search_url = settings && settings.common && settings.common.search;
let notice_url = settings && settings.common && settings.common.notice; let notice_url = settings && settings.common && settings.common.notice;
console.log(current_user);
return ( return (
<div className="newHeaders" id="nHeader"> <div className="newHeaders" id="nHeader">
<div className="headerContent"> <div className="headerContent">
@ -428,7 +432,6 @@ class NewHeader extends Component {
} }
</div> </div>
<div className="head-right"> <div className="head-right">
{/* {search_url ? this.SearchInput(openSearch,search_url):""} */}
{ search_url && <HeadSearch {...this.props}/>} { search_url && <HeadSearch {...this.props}/>}
{ {
current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)? current_user && (current_user.main_site || current_user.login) && (settings && settings.add && settings.add.length>0)?
@ -437,13 +440,18 @@ class NewHeader extends Component {
</Dropdown>:"" </Dropdown>:""
} }
{/* {current_user && current_user.login && notice_url ? */}
{current_user && current_user.login ? {current_user && current_user.login ?
<Popover placement={`bottomRight`} content={<NoticeContent/>}> <Popover
<a href={`/settings/notice/myNotice`} > overlayClassName="notice-popover"
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i> placement={`bottomRight`}
<span className="newslight" style={{ display: this.props.Headertop === undefined ? "none" : this.props.Headertop.new_message === true ? "block" : "none" }}> content={<NoticeContent current_user={current_user} showNotification={showNotification}/>}
</span> visible={visible}
onVisibleChange={this.handleVisibleChange}
>
<a className="message-icon" href={`/settings/notice/myNotice`}>
<Badge count={current_user.message_unread_total}>
<i className="iconfont icon-xiaoxilingdang color-grey-6 ml15 mr15"></i>
</Badge>
</a> </a>
</Popover> </Popover>
: "" : ""

View File

@ -1,156 +1,226 @@
import React, { useEffect, useState } from 'react'; import React, { useEffect, useState } from 'react';
import { Badge, Menu} from 'antd'; import { Badge, Menu } from 'antd';
import { Link } from 'react-router-dom';
import axios from 'axios';
import AppPullRefresh from './AppPullRefresh';
import './header.scss'; import './header.scss';
import '../SecuritySetting/notice/manager/Index.scss'; import '../SecuritySetting/notice/manager/Index.scss';
import '../SecuritySetting/Index.scss'; import '../SecuritySetting/Index.scss';
import '../SecuritySetting/notice/myNotice/Index.scss' import '../SecuritySetting/notice/myNotice/Index.scss';
import { timeAgo } from '../../common/DateUtil';
import { Link } from 'react-router-dom';
import Axios from 'axios';
function NoticeContent(props) {
const[noticeType,setNoticeType] = useState("0"); function NoticeContent({ showNotification, current_user: { login } }) {
const[notice_unread_count,setNotice_unread_count]=useState();// const [initialize, setInitialize] = useState(true);
const[letter_unread_count,setLetter_unread_count]=useState(10);// const [noticeType, setNoticeType] = useState("notification");
const[at_unread_count,setAt_unread_count]=useState();//@ const [letterUnreadCount, setLetterUnreadCount] = useState(0);//
const [message_list, setMessage_list] = useState([]);
const [noticeUnreadCount, setNoticeUnreadCount] = useState(0);//
const [noticePage, setNoticePage] = useState(0);
const [noticeUnreadList, setNoticeUnreadList] = useState([]);//
const [atUnreadCount, setAtUnreadCount] = useState();//@
const [atPage, setAtPage] = useState(0);
const [atUnreadList, setAtUnreadList] = useState([]);//@
const [reload, setReload] = useState(0);
useEffect(() => { useEffect(() => {
const params = { const params = {
type:noticeType==="0"?"notification":noticeType==="2"?"atme":"", type: noticeType,
limit: 20, limit: 10,
page: 0, page: noticeType === "notification" ? noticePage : noticeType === "atme" ? atPage : "",
status: 1,
} }
getMessageList(params); getMessageList(params);
}, [noticeType]) }, [noticePage, atPage]);
useEffect(() => {
const params = {
type: noticeType,
limit: 10,
page: 0,
status: 1,
};
if (initialize) {
params.type = "atme"
}
getMessageList(params);
}, [reload]);
function getMessageList(params) { function getMessageList(params) {
console.log(params); axios.get(`/users/${login}/messages.json`, {
Axios.get(`/users/yystopf/messages.json`, {
params: params, params: params,
}).then((response) => { }).then((response) => {
setNotice_unread_count(response.data.unread_notification); if (response && response.data) {
setAt_unread_count(response.data.unread_atme); setNoticeUnreadCount(response.data.unread_notification);
setMessage_list(response.data.messages); setAtUnreadCount(response.data.unread_atme);
console.log(message_list); if (params.type === "notification") {
let list = response.data.messages;
if (params.page !== 0) {
list = [...noticeUnreadList, ...list];
}
setNoticeUnreadList(list);
if (initialize) {
// tab
setInitialize(false);
if (response.data.unread_notification === 0 && response.data.unread_atme !== 0) {
setNoticeType("atme");
}
}
} else if (params.type === "atme") {
let list = response.data.messages;
if (params.page !== 0) {
list = [...atUnreadList, ...list];
}
setAtUnreadList(list);
}
}
}) })
} }
const[letter_unread_list,setLetter_unread_list]=useState([
{ function readAll() {
id: 122, axios.post(`/users/${login}/messages/read.json`, {
read: 0, //01 type: noticeType,
send_name: "蒋宇航", // ids: [-1]
send_login: "jiangYuHang", //login }).then((response) => {
content: "私信内容", // let data = response.data;
create_time: "2019-03-04 18:08", // if (!data) return;
}, if (data.status === 0) {
{ setReload(Math.random());
id: 122, } else {
read: 0, //01 showNotification(data.message);
send_name: "景霞", // }
send_login: "jiangYuHang", //login });
content: "最好的OpenStack控制台对标OpenStack社区Horizon项目在易用性、页面性能等方面进行深度优化提供简单控制台。", // }
create_time: "2019-03-04 18:08", //
}, // const [letter_unread_list, setLetter_unread_list] = useState([
{ // {
id: 122, // id: 122,
read: 0, //01 // read: 0, //01
send_name: "陈银花", // // send_name: "", //
send_login: "jiangYuHang", //login // send_login: "jiangYuHang", //login
content: "A Vue 3 Component Library. Fairly Complete. Customizable Themes. Uses TypeScript. Not too Slow.", // // content: "", //
create_time: "2019-03-04 18:08", // // create_time: "2019-03-04 18:08", //
}, // },
{ // ]);
id: 122,
read: 0, //01 function readItem(item) {
send_name: "蒋宇航", // axios.post(`/users/${login}/messages/read.json`, {
send_login: "jiangYuHang", //login type: noticeType,
content: "您好?", // ids: [item.id]
create_time: "2019-03-04 18:08", // }).then((response) => {
}, let data = response.data;
{ if (!data) return;
id: 122, if (data.status === 0) {
read: 0, //01 changeReadMark(item);
send_name: "蒋宇航", // item.notification_url && window.open(item.notification_url);
send_login: "jiangYuHang", //login } else {
content: "Open-source high-performance RISC-V processor", // showNotification(data.message);
create_time: "2019-03-04 18:08", // }
}, });
{ }
id: 122,
read: 0, //01 function changeReadMark(item) {
send_name: "蒋宇航", // if (item.type === "notification") {
send_login: "jiangYuHang", //login let list = noticeUnreadList.slice();
content: "构建卷积神经网络,训练模型,预测模型效果。", // let index = noticeUnreadList.indexOf(item);
create_time: "2019-03-04 18:08", // list[index].status = 2;
setNoticeUnreadList(list);
} else if (item.type === "atme") {
let list = atUnreadList.slice();
let index = atUnreadList.indexOf(item);
list[index].status = 2;
setAtUnreadList(list);
} }
]); }
return( return (
<div className="messageHoverDiv notice01"> <div className="messageHoverDiv notice01">
<div className="sshHead hoverNotice-head"> <div className="sshHead hoverNotice-head">
<Menu mode="horizontal" selectedKeys={noticeType} onClick={(e)=>setNoticeType(e.key)}> <Menu mode="horizontal" selectedKeys={noticeType} onClick={(e) => setNoticeType(e.key)}>
<Menu.Item key="0"><Badge count={notice_unread_count}>系统通知</Badge></Menu.Item> <Menu.Item key="notification"><Badge count={noticeUnreadCount}>系统通知</Badge></Menu.Item>
<Menu.Item key="1" id="item-private"><Badge count={letter_unread_count}>私信</Badge></Menu.Item> {/* <Menu.Item key="1" id="item-private"><Badge count={letterUnreadCount}>私信</Badge></Menu.Item> */}
<Menu.Item key="2"><Badge count={at_unread_count}>@</Badge></Menu.Item> <Menu.Item key="atme"><Badge count={atUnreadCount}>@</Badge></Menu.Item>
</Menu> </Menu>
</div> </div>
<div className="hoverNotice-body">
{message_list.map(item=>{ {/* 系统通知 */}
// {noticeType === "notification" && <AppPullRefresh
if(noticeType ==="0" && item.type === "notification" && item.status===1){ className='hoverNotice-body' // className
let contentStr = item.content.endsWith("</b>") && item.content.length>=50 && item.content.replace("</b>","").substr(0,40)+"..."; onPullRefresh={() => { setNoticePage(noticePage + 1); }} //ajaxfunction
// let iconName = item.type===1?"icon-xitongtongzhiicon":item.type===2?"icon-xiaoxi2":item.type===3?"icon-yixiuicon1":item.type===4?"icon-hebingqingqiuicon":item.type===5?"icon-lichengbeiicon":"icon-daimakuicon1"; // type={2} //
return( count={noticeUnreadCount} //
<div className="noticeCont-back"> pageSize={10} //
<div className="noticeCont" style={{height:item.content.length>30 && item.content.length<=34?'65px':""}}> >
{
noticeUnreadList.map(item => {
let contentStr = item.content.endsWith("</b>") && item.content.length >= 50 && item.content.replace("</b>", "").substr(0, 40) + "...";
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className="noticeCont" style={{ height: item.content.length > 30 && item.content.length <= 34 ? '65px' : "" }}>
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
<Badge color="#FA2020" /> <Badge color="#FA2020" />
<i className="iconfont icon-yixiuicon1"></i> </span>
<div className="noticeCont-text"> <i className="iconfont icon-yixiuicon1"></i>
<span dangerouslySetInnerHTML={{__html:contentStr?contentStr: item.content.length>=48?item.content.substr(0,48)+"...":item.content}}></span> <div className="noticeCont-text">
<span className="timeSpan">{item.time_ago}</span> <span dangerouslySetInnerHTML={{ __html: contentStr ? contentStr : item.content.length >= 48 ? item.content.substr(0, 48) + "..." : item.content }}></span>
</div> <span className="timeSpan">{item.time_ago}</span>
</div> </div>
</div> </div>
) </div>
}else if(noticeType ==="2" && item.type === "atme" && item.status===1){ )
// @ })
return( }
<div className="noticeCont-back"> </AppPullRefresh>
<div className="noticeCont" style={{height:item.content.length>30 && item.content.length<=42?'65px':""}}> }
<Badge color="#FA2020" />
<div className="noticeCont-text">
<span dangerouslySetInnerHTML={{__html:item.content.length>=56?item.content.substr(0,56)+"...@我":item.content}}></span>
<span className="timeSpan">{item.time_ago}</span>
</div>
</div>
</div>
)
}
})}
{/* 私信 */} {/* @我 */}
{noticeType==="1"?letter_unread_list.length>0?letter_unread_list.map(item=>{ {noticeType === "atme" && <AppPullRefresh
return( className='hoverNotice-body' // className
<div className="noticeCont-back"> onPullRefresh={() => { setAtPage(atPage + 1); }} //ajaxfunction
<div className="noticeCont" style={{height:item.content.length>=30 && item.content.length<=34?'65px':""}}> // type={1} //
count={atUnreadCount} //
pageSize={10} //
>
{atUnreadList.map(item => {
return (
<div key={item.id + Math.random()} className="noticeCont-back" onClick={() => { readItem(item) }}>
<div className="noticeCont" style={{ height: item.content.length > 30 && item.content.length <= 42 ? '65px' : "" }}>
<span style={{ visibility: item.status === 1 ? 'visible' : 'hidden' }}>
<Badge color="#FA2020" />
</span>
<div className="noticeCont-text">
<span dangerouslySetInnerHTML={{ __html: item.content.length >= 50 ? item.content.substr(0, 50) + "...@我" : item.content }}></span>
<span className="timeSpan">{item.time_ago}</span>
</div>
</div>
</div>
)
})
}
</AppPullRefresh>
}
{/* 私信 */}
{/* {noticeType === "1" ? letter_unread_list.length > 0 ? letter_unread_list.map(item => {
return (
<div className="noticeCont-back">
<div className="noticeCont" style={{ height: item.content.length >= 30 && item.content.length <= 34 ? '65px' : "" }}>
<Badge color="#FA2020" /> <Badge color="#FA2020" />
<div className="noticeCont-text"> <div className="noticeCont-text">
<span>{item.send_name}</span> <span>{item.send_name}</span>
<span className="boldSpan" dangerouslySetInnerHTML={{__html:item.content.length>=50?item.content.substr(0,50)+"...":item.content}}></span> <span className="boldSpan" dangerouslySetInnerHTML={{ __html: item.content.length >= 50 ? item.content.substr(0, 50) + "..." : item.content }}></span>
<span className="timeSpan">{item.create_time?timeAgo(item.create_time):"刚刚"}</span> <span className="timeSpan">{item.create_time ? timeAgo(item.create_time) : "刚刚"}</span>
</div> </div>
</div> </div>
</div> </div>
) )
}):"暂无数据":""} }) : "暂无数据" : ""} */}
</div> <div className="hoverNotice-buttom">
<div className="hoverNotice-buttom"> <Link to="/settings/notice/myNotice">全部消息</Link>
<Link to="/settings/notice/myNotice">全部消息</Link> <a onClick={readAll}>所有{noticeType === "notification" ? "系统消息" : noticeType === "letter" ? "私信" : "@我"}一键已读</a>
<a>所有{noticeType==="0"?"系统消息":noticeType==="1"?"私信":"@我"}一键已读</a>
</div>
</div> </div>
</div>
) )
} }

View File

@ -129,19 +129,26 @@
} }
} }
//popover小尖尖 // 右上角小铃铛单独样式
.ant-popover-arrow{ .notice-popover{
display: none; //popover小尖尖
.ant-popover-arrow{
display: none;
}
//popover框
.ant-popover-inner-content {
width: 386px;
height: 446px;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
margin-top: -10px;
padding: 12px 1px 12px 0;
}
} }
//popover框 .messageHoverDiv .ant-menu-item{
.ant-popover-inner-content { margin-right: 24px !important;
width: 386px;
height: 446px;
box-shadow: 0px 4px 8px 2px rgba(212, 212, 212, 0.5);
border-radius: 4px;
margin-top: -10px;
padding: 12px 1px 12px 0;
} }
.hoverNotice-head{ .hoverNotice-head{
@ -164,23 +171,37 @@
font-weight: 400; font-weight: 400;
text-shadow: 0.5px 0 0 #333; text-shadow: 0.5px 0 0 #333;
} }
.none_panels{
height: 100%;
}
} }
.message-icon{
position: relative;
.ant-scroll-number{
right:12px;
}
}
.hoverNotice-buttom{ .hoverNotice-buttom{
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
padding: 12px 18px; padding: 12px 18px;
a{ a{
color: #466AFF; color: #466AFF;
} &:hover{
a:hover{ opacity:0.85;
opacity:0.85; }
} }
} }
.noticeCont-back{ .noticeCont-back{
&:hover{ &:hover{
background: #F3F4F6; background: #F3F4F6;
cursor: pointer;
} }
} }
@ -203,7 +224,6 @@
} }
.noticeCont-text{ .noticeCont-text{
flex: auto; flex: auto;
position: relative; position: relative;
max-height: 48px; max-height: 48px;
@ -222,3 +242,7 @@
} }
} }
} }
.text-center{
text-align: center;
}