Skip to content

短信收发 #538

Open
Open
@github-actions

Description

@github-actions

{ key: 'msg-sv', label: '短信收发', to: '/msg-sv' },

https://api.github.com/bangumi/frontend/blob/2938c9293456c605a1c7f8ddfdcd2fac8ed85783/packages/website/src/pages/index/notifications/index.tsx#L20

import dayjs from 'dayjs';
import { ok } from 'oazapfts';
import React from 'react';
import { NavLink } from 'react-router-dom';
import useSWR from 'swr';

import { ozaClient } from '@bangumi/client';
import { Button, Pagination, Tab, Typography } from '@bangumi/design';
import { ArrowPath } from '@bangumi/icons';
import { withErrorBoundary } from '@bangumi/website/components/ErrorBoundary';
import Helmet from '@bangumi/website/components/Helmet';
import { PageNeedLoginError } from '@bangumi/website/error';
import { useUser } from '@bangumi/website/hooks/use-user';
import { settings } from '@bangumi/website/shared/notifications';

import style from './index.module.less';

const NotificationPageTabs = [
  { key: 'overview', label: '提醒总览', to: '/notifications' },
  // TODO: 短信收发
  // { key: 'msg-sv', label: '短信收发', to: '/msg-sv' },
];

function NoticeItem({ notice }: { notice: ozaClient.Notice }) {
  const { id, type, title, postID, topicID, sender, createdAt, unread } = notice;

  const setting = settings[type];

  if (!setting) {
    return (
      <div id={`notice_${id}`}>
        <div>{title}</div>
      </div>
    );
  }

  return (
    <div id={`notice_${id}`} className={style.noticeItem}>
      <img src={sender.avatar.small} alt='bgm-notify__avatar' className={style.noticeItemAvatar} />

      <Typography.Link
        to={`https://bgm.tv/user/${sender.username}`}
        target='_blank'
        rel='noopener noreferrer'
      >
        {sender.nickname}
      </Typography.Link>

      <span className={style.noticeItemBody}>
        {setting.prefix}
        <Typography.Link
          to={`${setting.url}/${topicID}${setting.append ?? ''}${setting.anchor}${postID}`}
          onClick={() => {
            ozaClient.clearNotice({
              id: [id],
            });
          }}
          target='_blank'
          rel='noopener noreferrer'
          className={style.noticeItemBodyContent}
        >
          {setting.inner ?? title}
        </Typography.Link>
        {setting.suffix}
      </span>

      <span className={style.noticeItemDate}>
        @{dayjs.unix(createdAt).format('YYYY-MM-DD HH:mm')}
      </span>

      {unread && <span className={style.noticeItemRedDot} />}
    </div>
  );
}

const useNotifications = () => {
  const { data: notice, mutate } = useSWR(`listNotice`, async () => ok(ozaClient.listNotice()), {
    suspense: true,
  });
  return { notice: notice?.data ?? [], mutate, total: notice.total };
};

function Notifications() {
  const { notice, mutate, total } = useNotifications();
  const updatedAt = dayjs().format('YYYY-MM-DD HH:mm:ss');

  return (
    <>
      <Helmet title='电波提醒' />
      <div className={style.title}>电波提醒</div>
      <div className={style.subtitle}>
        <span>更新于 {updatedAt}</span>
        <ArrowPath
          onClick={() => {
            mutate();
          }}
        />
      </div>
      <div className={style.tab}>
        <Tab.Group type='borderless'>
          {NotificationPageTabs.map((item) => (
            <NavLink to={item.to} key={item.key}>
              {({ isActive }) => <Tab.Item isActive={isActive}>{item.label}</Tab.Item>}
            </NavLink>
          ))}
        </Tab.Group>
      </div>

      <div className={style.filter}>
        {/* TODO: 筛选 */}
        {/* <Input placeholder='筛选所有提醒...' wrapperClass={style.filterInput} suffix={<Enter />} /> */}
        <Button
          type='secondary'
          className={style.readAllBtn}
          onClick={async () => {
            await ozaClient.clearNotice({
              id: notice.map((x) => x.id),
            });
            await mutate();
          }}
        >
          一键全部已读
        </Button>
      </div>
      {notice.map((x) => (
        <NoticeItem key={x.id} notice={x} />
      ))}
      <div>
        <Pagination total={total} pageSize={20} />
      </div>
    </>
  );
}

function NotificationPage() {
  const { user } = useUser();
  if (!user) {
    throw PageNeedLoginError;
  }

  return <Notifications />;
}

export default withErrorBoundary(NotificationPage);

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions