Browse Source

commit

master
yyy9608 11 months ago
parent
commit
7ea81eafbb
  1. 3
      package.json
  2. 12
      src/api/index.ts
  3. BIN
      src/assets/avatar.png
  4. BIN
      src/assets/buy-success.png
  5. BIN
      src/assets/cover.png
  6. BIN
      src/assets/nft/dragon.jpg
  7. BIN
      src/assets/nft/兔.jpg
  8. BIN
      src/assets/nft/牛.jpg
  9. BIN
      src/assets/nft/狗.jpg
  10. BIN
      src/assets/nft/猪.jpg
  11. BIN
      src/assets/nft/猴.jpg
  12. BIN
      src/assets/nft/羊.jpg
  13. BIN
      src/assets/nft/虎.jpg
  14. BIN
      src/assets/nft/蛇.jpg
  15. BIN
      src/assets/nft/马.jpg
  16. BIN
      src/assets/nft/鸡.jpg
  17. BIN
      src/assets/nft/鼠.jpg
  18. BIN
      src/assets/personal.png
  19. 91
      src/hooks/useNotify.ts
  20. 37
      src/hooks/useWs.ts
  21. 27
      src/router/layout/Navbar.tsx
  22. 52
      src/router/layout/Notify.tsx
  23. 20
      src/router/layout/index.tsx
  24. 1
      src/styles/home.scss
  25. 39
      src/styles/layout.scss
  26. 10
      src/types/store.d.ts

3
package.json

@ -77,7 +77,8 @@
"scripts": { "scripts": {
"start": "node scripts/start.js", "start": "node scripts/start.js",
"build": "node scripts/build.js", "build": "node scripts/build.js",
"test": "node scripts/test.js"
"test": "node scripts/test.js",
"deploy:dev": "npm run build && scp -r ./build/* testDev:/home/ceshi/pzy/nft9527"
}, },
"eslintConfig": { "eslintConfig": {
"extends": [ "extends": [

12
src/api/index.ts

@ -156,3 +156,15 @@ export const un_shelves_nft = (id: number) =>
export const no_user_info = (id: number) => export const no_user_info = (id: number) =>
request({ url: "/v1/showAccount", data: { id } }); request({ url: "/v1/showAccount", data: { id } });
/**
* @description
*/
export const clear_msg = () => request({ url: "/v1/clearMessage" });
/**
* @description
*/
export const read_all_msg = () => request({ url: "/v1/readMessage" });

BIN
src/assets/avatar.png

Before

Width: 285  |  Height: 287  |  Size: 86 KiB

BIN
src/assets/buy-success.png

Before

Width: 251  |  Height: 294  |  Size: 48 KiB

After

Width: 251  |  Height: 294  |  Size: 12 KiB

BIN
src/assets/cover.png

Before

Width: 307  |  Height: 320  |  Size: 126 KiB

BIN
src/assets/nft/dragon.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 326 KiB

BIN
src/assets/nft/兔.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 290 KiB

BIN
src/assets/nft/牛.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 298 KiB

BIN
src/assets/nft/狗.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 308 KiB

BIN
src/assets/nft/猪.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 310 KiB

BIN
src/assets/nft/猴.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 282 KiB

BIN
src/assets/nft/羊.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 308 KiB

BIN
src/assets/nft/虎.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 352 KiB

BIN
src/assets/nft/蛇.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 259 KiB

BIN
src/assets/nft/马.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 281 KiB

BIN
src/assets/nft/鸡.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 269 KiB

BIN
src/assets/nft/鼠.jpg

Before

Width: 1080  |  Height: 1528  |  Size: 300 KiB

BIN
src/assets/personal.png

Before

Width: 860  |  Height: 433  |  Size: 342 KiB

After

Width: 860  |  Height: 433  |  Size: 94 KiB

91
src/hooks/useNotify.ts

@ -0,0 +1,91 @@
import { useRef, useState } from "react";
import { Toast } from "react-vant";
import { clear_msg, read_all_msg } from "~/api";
import { MessageType } from "~/types/store";
import signGenerator from "~/utils/sign/sign";
const useNotify = (path: string, isNotity: boolean) => {
console.log(isNotity);
const baseUrl = `${process.env.REACT_APP_WS_URL}/api/v1/${path}`;
const ws = useRef<any>(null);
const filterMessage = useRef([] as MessageType[]);
const [messages, setMessages] = useState([] as MessageType[]);
const connect = (token: string) => {
let timestamp = Date.now();
let signData = {
uri: `/api/v1/${path}`,
timestamp: timestamp,
args: "",
};
const sign = signGenerator(signData);
ws.current = new WebSocket(
`${baseUrl}?Token=${token}&sign=${sign}&timestamp=${timestamp}`
);
ws.current.onmessage = (event: any) => {
if (
event &&
event.data &&
event.origin === process.env.REACT_APP_WS_URL
) {
let message = JSON.parse(event.data) as MessageType;
let item = filterMessage.current.find((v) => v.id === message.id);
if (item) return;
filterMessage.current.push(message);
setMessages((_) => [...filterMessage.current]);
// 如果打開了消息列表,則推送直接設置為已讀
if (isNotity) {
readAllMsg();
}
}
};
};
// 斷開連接
const disconnect = () => {
ws.current && ws.current.close();
ws.current = null;
resetMessages();
};
// 重置消息列表
const resetMessages = () => {
filterMessage.current = [];
setMessages([]);
};
// 刪除所有消息
const deleteAllMsg = async () => {
if (messages.length <= 0) return;
const res: any = await clear_msg();
if (res && res.code === 0) {
Toast.success("清除成功");
resetMessages();
}
};
// 設置所有消息為已讀
const readAllMsg = async () => {
const res: any = await read_all_msg();
if (res && res.code === 0) {
// 把消息改爲已讀
filterMessage.current.forEach((item) => {
item.status = 2;
});
setMessages([...filterMessage.current]);
}
};
return {
connect,
disconnect,
messages,
resetMessages,
readAllMsg,
deleteAllMsg,
};
};
export default useNotify;

37
src/hooks/useWs.ts

@ -1,37 +0,0 @@
import { useRef } from "react";
import signGenerator from "~/utils/sign/sign";
const useWs = (path: string) => {
const baseUrl = `ws://14.29.101.215:30307/api/v1/${path}`;
// const baseUrl = `ws://192.168.124.52:8083/api/v1/${path}`;
const ws = useRef<any>(null);
const connect = (token: string) => {
let timestamp = Date.now();
let signData = {
uri: `/api/v1/${path}`,
timestamp: timestamp,
args: "",
};
const sign = signGenerator(signData);
ws.current = new WebSocket(
`${baseUrl}?Token=${token}&sign=${sign}&timestamp=${timestamp}`
);
ws.current.onMessage = (data: any) => {
console.log(data);
};
};
const disconnect = () => {
ws.current && ws.current.close();
ws.current = null;
};
return {
connect,
disconnect,
};
};
export default useWs;

27
src/router/layout/Navbar.tsx

@ -1,24 +1,43 @@
import { useMemo } from 'react'
import { useRouter } from '~/hooks/useRouter' import { useRouter } from '~/hooks/useRouter'
import store from '~/store'
import '~/styles/layout.scss' import '~/styles/layout.scss'
import { MessageType } from '~/types/store'
import ConnectButton from './ConnectButton' import ConnectButton from './ConnectButton'
interface NavbarProps { interface NavbarProps {
pathname: string, pathname: string,
setVisible: Function
setVisible: Function,
token: string,
messages: MessageType[],
readAllMsg: Function
} }
const Navbar = (props: NavbarProps) => { const Navbar = (props: NavbarProps) => {
const { pathname, setVisible } = props
const { pathname, setVisible, token, messages, readAllMsg } = props
const { push } = useRouter() const { push } = useRouter()
const msgCount = useMemo(() => {
// status 1.未讀 2.已讀
let list = messages.filter(v => v.status === 1)
console.log(list);
return list.length
}, [messages])
const isBlue = () => { const isBlue = () => {
if (pathname === '/share') return 'header-bg-color' if (pathname === '/share') return 'header-bg-color'
if (pathname === '/noShare') return 'header-bg-color' if (pathname === '/noShare') return 'header-bg-color'
return '' return ''
} }
const openMsg = () => {
if (!token) return store.setVisibleUnLogin(true)
readAllMsg()
setVisible(true)
}
return ( return (
<div> <div>
<div className={`header plr-3 ${isBlue()}`}> <div className={`header plr-3 ${isBlue()}`}>
@ -34,8 +53,8 @@ const Navbar = (props: NavbarProps) => {
{/* <div style={{ flex: 1 }} className='tac'>首页</div> */} {/* <div style={{ flex: 1 }} className='tac'>首页</div> */}
<div className='row-justify-end' style={{ flex: 1 }}> <div className='row-justify-end' style={{ flex: 1 }}>
<ConnectButton /> <ConnectButton />
<div className='row ml-2' onClick={() => setVisible(true)}>
<div className='notify-circle'></div>
<div className='row ml-2' onClick={openMsg}>
{msgCount > 0 && <div className='notify-circle'></div>}
<i className='iconfont icon-messages fz-24 fz-wb-1000' /> <i className='iconfont icon-messages fz-24 fz-wb-1000' />
</div> </div>
</div> </div>

52
src/router/layout/Notify.tsx

@ -1,21 +1,33 @@
import '~/styles/layout.scss' import '~/styles/layout.scss'
import { Button, Divider, Popup } from "react-vant"
import { Button, Dialog, Divider, Popup } from "react-vant"
import { MessageType } from '~/types/store'
interface NotifyProps { interface NotifyProps {
visible: boolean, visible: boolean,
setVisible: Function
setVisible: Function,
messages: MessageType[],
deleteAllMsg: Function
} }
const Notify = (props: NotifyProps) => { const Notify = (props: NotifyProps) => {
const { visible, setVisible } = props
const { visible, setVisible, messages, deleteAllMsg } = props
const data = [
{ title: '提醒', color: '#F96900', imgName: 'register-success', desc: '您挂单的“生肖唐彩-狗”NFT, @Miner 出价 4,153.00 USDT,您挂单的“生肖唐彩-狗”NFT, @Miner 出价 4,153.00 USDT,您挂单的“生肖唐彩-狗”NFT, @Miner 出价 4,153.00 USDT' },
{ title: '注册成功', color: '#11C0CB', imgName: 'warn', desc: '恭喜,您已成功注册,9527NFT数字交易平台.' },
]
const confirmDelete = async () => {
if (messages.length <= 0) return
Dialog.alert({
showCancelButton: true,
showConfirmButton: true,
title: '提示',
message: '確定清除所有歷史消息嗎?',
confirmButtonText: '確定',
confirmButtonColor: '#0FC6D4',
onConfirm: () => deleteAllMsg()
})
}
return ( return (
<>
<Popup <Popup
visible={visible} visible={visible}
onClose={() => setVisible(false)} onClose={() => setVisible(false)}
@ -29,38 +41,44 @@ const Notify = (props: NotifyProps) => {
}} }}
overlayStyle={{ backgroundColor: 'rgba(0,0,0,0.05)' }} overlayStyle={{ backgroundColor: 'rgba(0,0,0,0.05)' }}
> >
<div className="p-2">
<div className="notify">
<div className='header plr-2'>
<div style={{ width: '100%' }}>
<div className="fz-wb-550"></div> <div className="fz-wb-550"></div>
<Divider className="" style={{ borderColor: '#EEE' }} />
<div>
</div>
</div>
<div className='notify-box'>
{ {
data.map((item, index) => (
<div className="notify-box row mt-2" key={index}>
<img src={require(`~/assets/${item.imgName}.png`)} className="img" alt="" />
messages.map((item) => (
<div className="notify-item-box row mt-2" key={item.id}>
<img src={item.url} className="img" alt="" />
<div className='ml-2'> <div className='ml-2'>
<div className='fz-14 fz-wb-550' style={{ color: item.color }}>{item.title}</div> <div className='fz-14 fz-wb-550' style={{ color: item.color }}>{item.title}</div>
<div className='fz-12 sub-text mt-4px'>{item.desc}</div>
<div className='fz-12 sub-text mt-4px' style={{ wordBreak: 'break-word' }}>{item.message}</div>
</div> </div>
</div> </div>
)) ))
} }
</div>
<div className='mt-5 row-center'>
<div className='mtb-3 row-center'>
<Button <Button
round round
size="small" size="small"
className='fz-wb-550' className='fz-wb-550'
color='#EEEEEE' color='#EEEEEE'
onClick={() => confirmDelete()}
> >
<div className='black'></div> <div className='black'></div>
</Button> </Button>
</div> </div>
</div>
<div className='close'> <div className='close'>
<i className='iconfont icon-right-double-arrow fz-22 sub-text' onClick={() => setVisible(false)}></i> <i className='iconfont icon-right-double-arrow fz-22 sub-text' onClick={() => setVisible(false)}></i>
</div> </div>
</div> </div>
</Popup> </Popup>
</>
) )
} }

20
src/router/layout/index.tsx

@ -8,7 +8,7 @@ import Navbar from './Navbar';
import Tabbar from './Tabbar'; import Tabbar from './Tabbar';
import { observer } from 'mobx-react'; import { observer } from 'mobx-react';
import store from '~/store'; import store from '~/store';
import useWs from '~/hooks/useWs';
import useNotify from '~/hooks/useNotify';
import { ethers } from 'ethers'; import { ethers } from 'ethers';
import { bind_rmd } from '~/api'; import { bind_rmd } from '~/api';
import { AlreadyBind, BindRmd, BindSuccess, DefaultBind, UnLogin, VaildLink } from './ui'; import { AlreadyBind, BindRmd, BindSuccess, DefaultBind, UnLogin, VaildLink } from './ui';
@ -16,9 +16,9 @@ import { AlreadyBind, BindRmd, BindSuccess, DefaultBind, UnLogin, VaildLink } fr
const LayoutRouter = () => { const LayoutRouter = () => {
const { location, push } = useRouter() const { location, push } = useRouter()
const messageWs = useWs('getMessage')
const { token, walletAddress, userInfo, visibleUnLogin } = store.state
const [visible, setVisible] = useState(false) const [visible, setVisible] = useState(false)
const messageWs = useNotify('getMessage', visible)
const { token, walletAddress, userInfo, visibleUnLogin } = store.state
const [visibleVaildLink, setVisibleVaildLink] = useState(false) //无效的链接 const [visibleVaildLink, setVisibleVaildLink] = useState(false) //无效的链接
const [visibleAlreadyBind, setVisibleAlreadyBind] = useState(false) //已绑定 const [visibleAlreadyBind, setVisibleAlreadyBind] = useState(false) //已绑定
@ -55,8 +55,8 @@ const LayoutRouter = () => {
store.resetNft("myNft") store.resetNft("myNft")
} }
// token && messageWs.connect(token)
// !token && messageWs.disconnect()
token && messageWs.connect(token)
!token && messageWs.disconnect()
}, [token]) }, [token])
useEffect(() => { useEffect(() => {
@ -102,6 +102,9 @@ const LayoutRouter = () => {
<Navbar <Navbar
pathname={location.pathname} pathname={location.pathname}
setVisible={setVisible} setVisible={setVisible}
token={token}
messages={messageWs.messages}
readAllMsg={messageWs.readAllMsg}
/> />
<div className='pages'> <div className='pages'>
<RenderRouter /> <RenderRouter />
@ -118,7 +121,12 @@ const LayoutRouter = () => {
/> />
) )
} }
<Notify visible={visible} setVisible={setVisible} />
<Notify
visible={visible}
setVisible={setVisible}
messages={messageWs.messages}
deleteAllMsg={messageWs.deleteAllMsg}
/>
<div className="ui"> <div className="ui">
{/* 無效鏈接 */} {/* 無效鏈接 */}

1
src/styles/home.scss

@ -5,7 +5,6 @@
width: 100%; width: 100%;
border-radius: 30px; border-radius: 30px;
overflow: hidden; overflow: hidden;
background-color: $primary;
position: relative; position: relative;
img{ img{

39
src/styles/layout.scss

@ -99,24 +99,43 @@
display: none; display: none;
} }
.notify-box{
.notify{
width: 100%;
height: 100%;
position: relative;
.header{
height: 50px;
width: 100%;
display: flex;
align-items: center;
border-bottom: 1px solid #eee;
}
.close{
position: absolute;
top: 49%;
left: -4px;
}
.notify-box{
height: calc(100% - 51px);
overflow: hidden;
overflow-y: scroll;
padding: 0px 20px;
.notify-item-box{
padding: 10px 20px; padding: 10px 20px;
border: 1px solid #eeeeee; border: 1px solid #eeeeee;
box-shadow: 8px 8px 20px 0px rgba(0, 0, 0, 0.1); box-shadow: 8px 8px 20px 0px rgba(0, 0, 0, 0.1);
border-radius: 10px; border-radius: 10px;
overflow: hidden;
.img{ .img{
@include img-size(32px,32px) @include img-size(32px,32px)
} }
}
.rv-popup{
position: relative;
.close{
position: absolute;
top: 49%;
left: 0;
}
} }
} }

10
src/types/store.d.ts

@ -76,10 +76,20 @@ interface InviteRecordData {
id: number; id: number;
} }
interface MessageType {
id: number;
url: string;
status: number;
title: string;
message: string;
color: string;
}
export { export {
StoreLocalStorageKey, StoreLocalStorageKey,
UserInfo, UserInfo,
CoinList, CoinList,
MarketNFTData, MarketNFTData,
InviteRecordData, InviteRecordData,
MessageType,
}; };
Loading…
Cancel
Save