diff --git a/pages/notifications.tsx b/pages/notifications.tsx index 98a6d6f6..663ab48b 100644 --- a/pages/notifications.tsx +++ b/pages/notifications.tsx @@ -27,6 +27,7 @@ import { getUserName } from "utils/user" import moment from 'moment' import userCustomTheme from "theme/user-custom" import Link from "next/link" +import Notifications from "components/notifications" const filters = [ {icon: 'bell',label:'All',type: 0}, @@ -39,26 +40,22 @@ const filters = [ const NotificationPage = () => { const [filter, setFilter]= useState(filters[0]) - const [notifications,setNotifications]: [Notification[],any] = useState([]) - const stackBorderColor = useColorModeValue(userCustomTheme.borderColor.light, userCustomTheme.borderColor.dark) useEffect(() => { initData() },[]) const initData = async () => { - await getNotifications() await requestApi.post(`/notifications/unread`) } - const getNotifications = async (f?) => { - const res = await requestApi.get(`/notifications/list/${f ? f.type : filter.type}`) - setNotifications(res.data) + const getNotifications = async (p) => { + const res = await requestApi.get(`/notifications/list/${filter.type}?page=${p}`) + return res } const onFilterChange = (f) => { setFilter(f) - getNotifications(f) } return ( @@ -88,25 +85,7 @@ const filters = [ } } - {notifications.length !== 0 - ? - }> - {notifications.map((p,i) => - - - - - {getUserName(p.user)} - {p.title} - - {p.subTitle && {p.subTitle}} - {moment(p.created).fromNow()} {!p.read&& unread} - - )} - - : - - } + diff --git a/server/internal/api/notification.go b/server/internal/api/notification.go index ca1c2a71..57f8dfbd 100644 --- a/server/internal/api/notification.go +++ b/server/internal/api/notification.go @@ -14,7 +14,11 @@ func GetNotifications(c *gin.Context) { tp, _ := strconv.Atoi(c.Param("type")) u := user.CurrentUser(c) - nos, err := notification.Query(u, tp) + page, err0 := strconv.Atoi(c.Query("page")) + if err0 != nil { + page = 1 + } + nos, err := notification.Query(u, tp, page) if err != nil { c.JSON(err.Status, common.RespError(err.Message)) return diff --git a/server/internal/notification/notification.go b/server/internal/notification/notification.go index 2c4ae297..46f0cc07 100644 --- a/server/internal/notification/notification.go +++ b/server/internal/notification/notification.go @@ -31,15 +31,17 @@ func Send(userID, orgID string, noType int, noID string, operatorID string) { } } -func Query(user *models.User, tp int) ([]*models.Notification, *e.Error) { +const perPage = 10 + +func Query(user *models.User, tp int, page int) ([]*models.Notification, *e.Error) { var rows *sql.Rows var err error if tp == 0 { - rows, err = db.Conn.Query("SELECT operator_id,notifiable_type,notifiable_id,read,created FROM user_notification WHERE user_id=? ORDER BY created DESC", user.ID) + rows, err = db.Conn.Query("SELECT operator_id,notifiable_type,notifiable_id,read,created FROM user_notification WHERE user_id=? ORDER BY created DESC LIMIT ?,?", user.ID, (page-1)*perPage, page*perPage) } else if tp == models.NotificationComment { - rows, err = db.Conn.Query("SELECT operator_id,notifiable_type,notifiable_id,read,created FROM user_notification WHERE user_id=? and notifiable_type in ('1','6') ORDER BY created DESC", user.ID) + rows, err = db.Conn.Query("SELECT operator_id,notifiable_type,notifiable_id,read,created FROM user_notification WHERE user_id=? and notifiable_type in ('1','6') ORDER BY created DESC LIMIT ?,?", user.ID, (page-1)*perPage, page*perPage) } else { - rows, err = db.Conn.Query("SELECT operator_id,notifiable_type,notifiable_id,read,created FROM user_notification WHERE user_id=? and notifiable_type=? ORDER BY created DESC", user.ID, tp) + rows, err = db.Conn.Query("SELECT operator_id,notifiable_type,notifiable_id,read,created FROM user_notification WHERE user_id=? and notifiable_type=? ORDER BY created DESC LIMIT ?,?", user.ID, tp, (page-1)*perPage, page*perPage) } if err != nil { diff --git a/src/components/notifications.tsx b/src/components/notifications.tsx new file mode 100644 index 00000000..c30e6006 --- /dev/null +++ b/src/components/notifications.tsx @@ -0,0 +1,98 @@ +import React, { useEffect, useState } from "react" +import { Box, Center, Heading, HStack, Image, Link, StackDivider, Tag, Text, useColorModeValue, VStack } from "@chakra-ui/react" + +import userCustomTheme from "theme/user-custom" +import useInfiniteScroll from 'src/hooks/use-infinite-scroll' +import { concat } from "lodash" +import Empty from "src/components/empty" +import { Notification } from "src/types/notification" +import moment from 'moment' +import { getUserName } from "utils/user" + +interface Props { + onLoad?: any + filter?: any +} + + +export const Notifications = (props: Props) => { + const { onLoad, filter } = props + const [notifications,setNotifications]: [Notification[],any] = useState([]) + const [noMore, setNoMore] = useState(false) + + const [isFetching, setIsFetching] = useInfiniteScroll(fetchMoreListItems); + const [page, setPage] = useState(1) + const stackBorderColor = useColorModeValue(userCustomTheme.borderColor.light, userCustomTheme.borderColor.dark) + + useEffect(() => { + setNotifications([]) + setNoMore(false) + setPage(1) + onLoad(1).then(res => { + if (res.data.length < 10) { + setNoMore(true) + } + setNotifications(res.data) + }) + }, [filter]) + + function fetchMoreListItems() { + if (page === 1 && notifications.length === 0) { + // 走到这里面说明视图逻辑出问题了,你可以这样触发 + // 进入tag或者个人页面,然后把文章拉到第二页 + // 此时点击tag,会瞬间同时加载第一页和第二页的文章 + // 因为第一页的文章还没加载完毕,没有更新posts,第二页的文章就会覆盖掉第一页的数据 + // 这样第一页的数据就丢失了 + + // 走到该函数意味着已经是第二页的加载逻辑了,在此时posts不应该为空 + //@ts-ignore + setIsFetching(false) + return + } + if (noMore) { + //@ts-ignore + setIsFetching(false) + return + } + setPage(page + 1) + onLoad(page + 1).then(res => { + if (res.data.length < 5) { + setNoMore(true) + } + setNotifications(concat(notifications, ...res.data)) + } + ) + //@ts-ignore + setIsFetching(false) + } + + + return ( + <> + {notifications.length !== 0 + ? + <> + }> + {notifications.map((p,i) => + + + + + {getUserName(p.user)} + {p.title} + + {p.subTitle && {p.subTitle}} + {moment(p.created).fromNow()} {!p.read&& unread} + + )} + + {noMore &&
没有更多消息了
} + + : + + } + + ) +} + +export default Notifications