Skip to content

Commit

Permalink
优化布局, 引入缓存
Browse files Browse the repository at this point in the history
  • Loading branch information
LeafYeeXYZ committed Aug 10, 2024
1 parent beb85c9 commit c9a7fbe
Show file tree
Hide file tree
Showing 8 changed files with 190 additions and 75 deletions.
3 changes: 3 additions & 0 deletions app/(auth)/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useRouter } from 'next/navigation'
import { useEffect, useState, useOptimistic } from 'react'
import { auth } from './action'
import sha256 from 'crypto-js/sha256'
import { clear } from 'idb-keyval'

type FieldType = {
email: string
Expand Down Expand Up @@ -73,6 +74,8 @@ export default function Login() {
useEffect(() => {
if (localStorage.getItem('email') && localStorage.getItem('password')) {
router.push('/inbox')
} else {
clear() // Promise<void>
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
Expand Down
12 changes: 12 additions & 0 deletions app/(dashboard)/inbox/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,15 @@ export async function getMails(email: string, password: string, limit: number, s
}
return mails
}

// 判断是否有新邮件
export async function hasNewEmail(email: string, password: string, localDate: string): Promise<boolean | string> {
// 验证邮箱和密码
const auth = await user.findOne({ email, password }, { projection: {} })
if (!auth) {
return '401'
}
// 获取邮箱列表
const data = await inbox.findOne({ 'workers.to': email, date: { $gt: localDate } }, { projection: {} })
return Boolean(data)
}
111 changes: 88 additions & 23 deletions app/(dashboard)/inbox/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

import { Button, message, Drawer, Popconfirm } from 'antd'
import { LoadingOutlined, CaretDownFilled, DeleteOutlined } from '@ant-design/icons'
import { useState, useEffect, useRef } from 'react'
import { getMails, Mail, getEmail, deleteEmail } from './action'
import { useState, useEffect } from 'react'
import { getMails, Mail, getEmail, deleteEmail, hasNewEmail } from './action'
import { useRouter } from 'next/navigation'
import { flushSync } from 'react-dom'
import { get, set, del } from 'idb-keyval'

export default function Inbox() {

Expand Down Expand Up @@ -89,6 +90,7 @@ export default function Inbox() {
} else {
messageAPI.success('删除成功')
setMails(mails.filter(mail => mail._id !== _id))
del('inbox') // Promise<void>
}
}

Expand All @@ -97,32 +99,95 @@ export default function Inbox() {
const email = localStorage.getItem('email') ?? sessionStorage.getItem('email') ?? ''
const password = localStorage.getItem('password') ?? sessionStorage.getItem('password') ?? ''
const username = localStorage.getItem('username') ?? sessionStorage.getItem('username') ?? ''
setUseremail(email)
setPassword(password)
setUsername(username)
if (!email.length || !password.length) {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
setTimeout(() => {
router.push('/login')
}, 2000)
return () => messageAPI.destroy()
}
const localDate = localStorage.getItem('inboxDate')
let hasNew: boolean
if (localDate) {
// 判断是否有新邮件
hasNewEmail(email, password, localDate)
.then(res => {
if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 2000)
return 'continue'
} else if (typeof res === 'boolean') {
hasNew = res
return get('inbox')
} else {
throw new Error(res)
}
})
// 从缓存获取邮件
.then(res => {
if (res === 'continue') {
return 'continue'
} else if (res && !hasNew) {
return res as Mail[]
} else {
return getMails(email, password, mailsPerPage, 0)
}
})
// 从服务器获取邮件
.then(res => {
if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 2000)
return 'continue'
} else if (res === 'continue') {
return 'continue'
} else {
setMails(res as Mail[])
setBtn(res.length === mailsPerPage ? 'loaded' : 'null')
setUseremail(email)
setPassword(password)
setUsername(username)
set('inbox', res as Mail[]) // Promise<void>
// 更新缓存时间
localStorage.setItem('inboxDate', new Date().toISOString())
}
})
.catch(err => {
messageAPI.error(`获取邮件失败: ${err instanceof Error ? err.message : err}`)
})
} else {
// 直接从服务器获取邮件
getMails(email, password, mailsPerPage, 0)
.then(res => {
if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 2000)
} else {
setMails(res as Mail[])
setBtn(res.length === mailsPerPage ? 'loaded' : 'null')
}
})
.catch(err => {
messageAPI.error(`获取邮件失败: ${err instanceof Error ? err.message : err}`)
})
.then(res => {
if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 2000)
} else {
setMails(res as Mail[])
setBtn(res.length === mailsPerPage ? 'loaded' : 'null')
setUseremail(email)
setPassword(password)
setUsername(username)
set('inbox', res as Mail[]) // Promise<void>
// 更新缓存时间
localStorage.setItem('inboxDate', new Date().toISOString())
}
})
.catch(err => {
messageAPI.error(`获取邮件失败: ${err instanceof Error ? err.message : err}`)
})
}
return () => {
messageAPI.destroy()
Expand Down Expand Up @@ -164,7 +229,7 @@ export default function Inbox() {
style={{ scrollbarWidth: 'none' }}
className='rounded-t-2xl'
>
<div className='w-dvw h-full absolute left-0 grid grid-rows-[3rem,1fr] sm:grid-rows-[1.75rem,1fr] items-center'>
<div className='w-dvw h-[calc(100%-5rem)] absolute left-0 grid grid-rows-[3rem,1fr] sm:grid-rows-[1.75rem,1fr] items-center'>
<div className='w-full h-full flex flex-col sm:flex-row items-start justify-start -mt-8 px-3 gap-1 sm:flex-wrap'>
<div className='w-full sm:w-[49.5%] text-left text-xs text-gray-500'>来自 {email?.fromName?.length ? `${email?.fromName} <${email?.from}>` : email?.from}</div>
<div className='w-full sm:w-[49.5%] sm:text-right text-left text-xs text-gray-500'>收件人 {`${username} <${useremail}>`}</div>
Expand All @@ -173,7 +238,7 @@ export default function Inbox() {
<div className='w-full h-full border-t'>
<iframe
srcDoc={email?.content}
className='w-full h-full p-2'
className='w-full h-full'
style={{scrollbarWidth: 'none'}}
sandbox=''
></iframe>
Expand Down
86 changes: 55 additions & 31 deletions app/(dashboard)/profile/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
'use client'

import { Button, Input, Form, message, Space } from 'antd'
import { UserOutlined, AuditOutlined, CameraOutlined, BankOutlined, FileTextOutlined, KeyOutlined } from '@ant-design/icons'
import { UserOutlined, AuditOutlined, CameraOutlined, BankOutlined, FileTextOutlined, KeyOutlined, CodeOutlined } from '@ant-design/icons'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { flushSync } from 'react-dom'
import { getUser, updateUser } from './action'
import { UserData } from '@/app/COLL_TYPE'
import Image from 'next/image'
import sha256 from 'crypto-js/sha256'
import { clear, set, get, del } from 'idb-keyval'

export default function Profile() {

Expand All @@ -30,25 +31,31 @@ export default function Profile() {
setTimeout(() => {
router.push('/login')
}, 2000)
} else {
getUser(email, password)
.then(res => {
if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 2000)
} else {
setUser(res as UserData)
setForm(res as UserData)
}
})
.catch(err => {
messageAPI.error(`获取用户失败: ${err instanceof Error ? err.message : err}`)
})
return () => messageAPI.destroy()
}
get<UserData>('user')
// 先从缓存中获取用户信息
.then(res => {
return res ?? getUser(email, password)
})
// 缓存中没有再从服务器获取
.then(res => {
if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 2000)
} else {
setUser(res as UserData)
setForm(res as UserData)
set('user', res as UserData) // Promise<void>
}
})
.catch(err => {
messageAPI.error(`获取用户失败: ${err instanceof Error ? err.message : err}`)
})
return () => {
messageAPI.destroy()
setUser(null)
Expand All @@ -71,18 +78,21 @@ export default function Profile() {
messageAPI.destroy()
if (res === '200') {
messageAPI.success('更新成功')
if (field === 'password') {
messageAPI.info('即将跳转至登录页')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 800)
} else {
setTimeout(() => {
location.reload()
}, 800)
}
// 清除缓存
del('user').then(() => {
if (field === 'password') {
messageAPI.info('即将跳转至登录页')
localStorage.clear()
sessionStorage.clear()
setTimeout(() => {
router.push('/login')
}, 800)
} else {
setTimeout(() => {
location.reload()
}, 800)
}
})
} else if (res === '401') {
messageAPI.error('登陆失效 (2秒后自动跳转至登录页)')
localStorage.clear()
Expand Down Expand Up @@ -219,6 +229,20 @@ export default function Profile() {
className='w-full my-2'
disabled={form?.password !== form?.confirm || !form?.password?.length || !form?.confirm?.length || disabled}
>修改密码</Button>
{/* 清除缓存 */}
<p className='w-full text-left text-sm font-bold text-gray-700 my-2 pl-1'><CodeOutlined /> 高级设置</p>
<Button
onClick={async () => {
flushSync(() => setDisabled(true))
await clear()
messageAPI.success('清除成功')
setTimeout(() => {
location.reload()
}, 800)
}}
type='default'
className='w-full my-2'
>清除缓存</Button>
</Form>
</div>
)
Expand Down
4 changes: 3 additions & 1 deletion app/(dashboard)/send/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Markdown from 'react-markdown'
import remarkGfm from 'remark-gfm'
import rehypeRaw from 'rehype-raw'
import 'github-markdown-css/github-markdown.css'
import { del } from 'idb-keyval'

type FieldType = {
to: string
Expand Down Expand Up @@ -70,6 +71,7 @@ export default function Send() {
messageAPI.success('发送成功')
form.resetFields()
setContent('')
del('sent') // Promise<void>
}
})
.catch(err => {
Expand Down Expand Up @@ -171,7 +173,7 @@ export default function Send() {
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeRaw]}
>
{content + '<br /><br />'}
{content + '\n<br />'}
</Markdown>
</div>
<Form.Item
Expand Down
Loading

0 comments on commit c9a7fbe

Please sign in to comment.