diff --git a/.env b/.env index 0c2dcd1..cd3cba2 100644 --- a/.env +++ b/.env @@ -1,5 +1,6 @@ SKIP_PREFLIGHT_CHECK=true GENERATE_SOURCEMAP=false REACT_APP_BASE_URL='http://14.29.101.215:30307' +REACT_APP_WS_URL='ws://14.29.101.215:30307' REACT_APP_SHARE_LINK='http://14.29.101.215:30305/#/' REACT_APP_SIGN_KEY='9527nft9527_@fsdgfsx' \ No newline at end of file diff --git a/package.json b/package.json index 283f49c..48fe6dc 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "postcss-normalize": "^10.0.1", "postcss-preset-env": "^7.0.1", "prompts": "^2.4.2", + "qrcode": "^1.5.3", "react": "^18.2.0", "react-app-polyfill": "^3.0.0", "react-dev-utils": "^12.0.1", @@ -70,7 +71,8 @@ "webpack": "^5.64.4", "webpack-dev-server": "^4.6.0", "webpack-manifest-plugin": "^4.0.2", - "workbox-webpack-plugin": "^6.4.1" + "workbox-webpack-plugin": "^6.4.1", + "ws": "^8.16.0" }, "scripts": { "start": "node scripts/start.js", @@ -97,6 +99,7 @@ }, "devDependencies": { "@types/lodash": "^4.14.202", + "@types/qrcode": "^1.5.5", "postcss-px-to-viewport": "^1.1.1", "sass": "^1.69.5", "sass-resources-loader": "^2.2.5" diff --git a/public/index.html b/public/index.html index 74c8dd8..23fd73e 100644 --- a/public/index.html +++ b/public/index.html @@ -4,7 +4,8 @@ - + + diff --git a/src/api/index.ts b/src/api/index.ts index cf245a1..c5118dd 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -1,8 +1,9 @@ import { PerformSignin, PerformSNonce } from "~/types"; +import { HTTPHistoryParams, HTTPWithdrawParams } from "~/types/api"; import request from "./service"; /** - * @description 获取随机数 + * @description random */ export const getNonce = (query: PerformSNonce) => request({ @@ -11,28 +12,87 @@ export const getNonce = (query: PerformSNonce) => }); /** - * @description 签名 + * @description Sign */ export const performSignin = (query: PerformSignin) => request({ url: "/v1/signin", data: query }); /** - * @description 上传图片 + * @description Upload avatar */ -export const uploadImage = (file: File) => { +export const upload_image = (file: File) => { const body = new FormData(); - console.log(body); - body.append("img", file); - return request({ url: "/v1/uploadImg", data: body }) + return request({ url: "/v1/uploadImg", data: body }); }; /** - * @description 用户信息 + * @description 用戶信息 */ -export const accountInfo = () => request({ url: '/v1/account' }) +export const accountInfo = () => request({ url: "/v1/account" }); /** * @description coin list */ -export const coin_list = () => request({ url: '/v1/tokenList' }) +export const coin_list = () => request({ url: "/v1/tokenList" }); + +/** + * @description market list + * @param {type} 1.拍賣 2.售賣 + */ +export const market_list = (type: 1 | 2) => + request({ url: "/v1/market", data: { type } }); + +/** + * @description 重命名 + * @param {name} 昵稱 + */ +export const reset_name = (name: string) => + request({ url: "/v1/rename", data: { name } }); + +/** + * @description 開放藝術頁面 + * @param {type} 1.展示 2.隱藏 + */ +export const open_page = (type: 1 | 2) => + request({ url: "/v1/assetsShow", data: { show: type } }); + +/** + * @description 我的NFT 我喜歡的 + * @param {type} 1.我的 2.我喜歡的 + */ +export const personal_nft = (type: number) => + request({ url: "/v1/myNft", data: { type: type } }); + +/** + * @description 體現 + * @param {type} 1.我的 2.我喜歡的 + */ +export const user_withdraw = (query: HTTPWithdrawParams) => + request({ url: "/v1/withdraw", data: query }); + +/** + * @description 歷史記錄 + * @param {type} 0.體現 1.體現 2.收益 + * @param {page_size} 數量 + * @param {page} 頁數 + */ +export const history_record = (query: HTTPHistoryParams) => + request({ url: "/v1/hisory", data: query }); + +/** + * @description 團隊信息 + */ +export const team_info = () => request({ url: "/v1/invitiInfo" }); + +/** + * @description 我的邀請 + */ +export const my_invite = (query: { page: number; page_size: number }) => + request({ url: "/v1/invitiDetails", data: query }); + +/** + * @description 綁定推薦人 + */ +export const bind_rmd = (address: string) => + request({ url: "/v1/binding", data: { address } }); diff --git a/src/api/service.ts b/src/api/service.ts index 538c1e8..702843f 100644 --- a/src/api/service.ts +++ b/src/api/service.ts @@ -1,5 +1,5 @@ import axiosConfig from "./axios_config"; -import axios from "axios"; +import axios, { AxiosResponse } from "axios"; import signGenerator from "../utils/sign/sign"; import { Toast } from "react-vant"; import sortParam from "../utils/sign/sort"; @@ -10,8 +10,6 @@ const service = axios.create(axiosConfig); // 请求拦截 service.interceptors.request.use( (config) => { - console.log(config); - (config.headers as any).token = store.state.token; if (!config.data) config.data = {}; let ps = config.params ? sortParam(config.params) : ""; @@ -24,9 +22,9 @@ service.interceptors.request.use( let sign = signGenerator(signData); (config.headers as any).sign = sign; (config.headers as any).timestamp = timestamp; - - if(config.data instanceof FormData) return config - + + if (config.data instanceof FormData) return config; + config.data = JSON.stringify(config.data); return config; }, diff --git a/src/assets/iconfont/iconfont.css b/src/assets/iconfont/iconfont.css index b65d74d..8986fe5 100644 --- a/src/assets/iconfont/iconfont.css +++ b/src/assets/iconfont/iconfont.css @@ -1,8 +1,8 @@ @font-face { font-family: "iconfont"; /* Project id 4379626 */ - src: url('iconfont.woff2?t=1703840169958') format('woff2'), - url('iconfont.woff?t=1703840169958') format('woff'), - url('iconfont.ttf?t=1703840169958') format('truetype'); + src: url('iconfont.woff2?t=1704271682012') format('woff2'), + url('iconfont.woff?t=1704271682012') format('woff'), + url('iconfont.ttf?t=1704271682012') format('truetype'); } .iconfont { @@ -13,6 +13,26 @@ -moz-osx-font-smoothing: grayscale; } +.icon-close:before { + content: "\e6a7"; +} + +.icon-download:before { + content: "\e60d"; +} + +.icon-fuzhi_copy:before { + content: "\e618"; +} + +.icon-chenggong:before { + content: "\e63c"; +} + +.icon-bianji:before { + content: "\e67f"; +} + .icon-datijilu:before { content: "\e606"; } diff --git a/src/assets/iconfont/iconfont.js b/src/assets/iconfont/iconfont.js index 1710846..76b33cd 100644 --- a/src/assets/iconfont/iconfont.js +++ b/src/assets/iconfont/iconfont.js @@ -1 +1 @@ -window._iconfont_svg_string_4379626='',function(e){var t=(t=document.getElementsByTagName("script"))[t.length-1],c=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var l,o,i,n,s,a=function(t,c){c.parentNode.insertBefore(t,c)};if(c&&!e.__iconfont__svg__cssinject__){e.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}l=function(){var t,c=document.createElement("div");c.innerHTML=e._iconfont_svg_string_4379626,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(t=document.body).firstChild?a(c,t.firstChild):t.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(l,0):(o=function(){document.removeEventListener("DOMContentLoaded",o,!1),l()},document.addEventListener("DOMContentLoaded",o,!1)):document.attachEvent&&(i=l,n=e.document,s=!1,h(),n.onreadystatechange=function(){"complete"==n.readyState&&(n.onreadystatechange=null,d())})}function d(){s||(s=!0,i())}function h(){try{n.documentElement.doScroll("left")}catch(t){return void setTimeout(h,50)}d()}}(window); \ No newline at end of file +window._iconfont_svg_string_4379626='',function(l){var t=(t=document.getElementsByTagName("script"))[t.length-1],c=t.getAttribute("data-injectcss"),t=t.getAttribute("data-disable-injectsvg");if(!t){var o,i,e,a,s,n=function(t,c){c.parentNode.insertBefore(t,c)};if(c&&!l.__iconfont__svg__cssinject__){l.__iconfont__svg__cssinject__=!0;try{document.write("")}catch(t){console&&console.log(t)}}o=function(){var t,c=document.createElement("div");c.innerHTML=l._iconfont_svg_string_4379626,(c=c.getElementsByTagName("svg")[0])&&(c.setAttribute("aria-hidden","true"),c.style.position="absolute",c.style.width=0,c.style.height=0,c.style.overflow="hidden",c=c,(t=document.body).firstChild?n(c,t.firstChild):t.appendChild(c))},document.addEventListener?~["complete","loaded","interactive"].indexOf(document.readyState)?setTimeout(o,0):(i=function(){document.removeEventListener("DOMContentLoaded",i,!1),o()},document.addEventListener("DOMContentLoaded",i,!1)):document.attachEvent&&(e=o,a=l.document,s=!1,d(),a.onreadystatechange=function(){"complete"==a.readyState&&(a.onreadystatechange=null,h())})}function h(){s||(s=!0,e())}function d(){try{a.documentElement.doScroll("left")}catch(t){return void setTimeout(d,50)}h()}}(window); \ No newline at end of file diff --git a/src/assets/iconfont/iconfont.json b/src/assets/iconfont/iconfont.json index 232d65f..7d0e83c 100644 --- a/src/assets/iconfont/iconfont.json +++ b/src/assets/iconfont/iconfont.json @@ -5,6 +5,41 @@ "css_prefix_text": "icon-", "description": "", "glyphs": [ + { + "icon_id": "257406", + "name": "close", + "font_class": "close", + "unicode": "e6a7", + "unicode_decimal": 59047 + }, + { + "icon_id": "598164", + "name": "download", + "font_class": "download", + "unicode": "e60d", + "unicode_decimal": 58893 + }, + { + "icon_id": "23870326", + "name": "复制_copy", + "font_class": "fuzhi_copy", + "unicode": "e618", + "unicode_decimal": 58904 + }, + { + "icon_id": "7408311", + "name": "成功", + "font_class": "chenggong", + "unicode": "e63c", + "unicode_decimal": 58940 + }, + { + "icon_id": "7443382", + "name": "编辑", + "font_class": "bianji", + "unicode": "e67f", + "unicode_decimal": 59007 + }, { "icon_id": "1240492", "name": "答题记录", diff --git a/src/assets/iconfont/iconfont.ttf b/src/assets/iconfont/iconfont.ttf index c64293a..ec6839b 100644 Binary files a/src/assets/iconfont/iconfont.ttf and b/src/assets/iconfont/iconfont.ttf differ diff --git a/src/assets/iconfont/iconfont.woff b/src/assets/iconfont/iconfont.woff index 3d501f8..a270a93 100644 Binary files a/src/assets/iconfont/iconfont.woff and b/src/assets/iconfont/iconfont.woff differ diff --git a/src/assets/iconfont/iconfont.woff2 b/src/assets/iconfont/iconfont.woff2 index e76f34d..86bf4cc 100644 Binary files a/src/assets/iconfont/iconfont.woff2 and b/src/assets/iconfont/iconfont.woff2 differ diff --git a/src/assets/share.png b/src/assets/share.png new file mode 100644 index 0000000..7403264 Binary files /dev/null and b/src/assets/share.png differ diff --git a/src/components/CoinPicker.tsx b/src/components/CoinPicker.tsx new file mode 100644 index 0000000..9042ff8 --- /dev/null +++ b/src/components/CoinPicker.tsx @@ -0,0 +1,46 @@ +import { useMemo } from "react"; +import { Picker } from "react-vant"; +import { CoinList } from "~/types/store"; + +interface CoinPickerProps { + setIndex: Function; + list: CoinList[]; + index: number +} + +const CoinPicker = ({ setIndex, list, index }: CoinPickerProps) => { + + const coinList = useMemo(() => list.map(item => item.symbol), [list]); + + return ( + { + setIndex(_index); + }} + placeholder="" + value={coinList[index]} + > + {(_val, _, _action) => ( +
_action.open()} style={{ width: '100%' }}> + { + list[index] && ( +
+
+ +
{list[index].symbol}
+
+
+
+ ) + } +
+ )} +
+ ) +} + +export default CoinPicker; \ No newline at end of file diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx new file mode 100644 index 0000000..9274971 --- /dev/null +++ b/src/components/Modal.tsx @@ -0,0 +1,51 @@ +import { Overlay } from 'react-vant'; +import '~/styles/components.scss' + +interface ModalProps { + buttonText: string; + title: string; + children: JSX.Element; + buttonClick: Function; + visible: boolean; + setVisible: Function; + hiddenCloseIcon?: boolean; + showCancelButton?: boolean; + showCancelButtonText?: string; + showCancelButtonClick?: Function; +} + +const Modal = ( + { title, buttonClick, visible, setVisible, children, buttonText, hiddenCloseIcon, showCancelButton, showCancelButtonText, showCancelButtonClick }: ModalProps +) => { + return ( + +
+
+
+
{title}
+
+ { + !hiddenCloseIcon && ( + setVisible(false)} /> + ) + } +
+
+ {children} +
+
buttonClick()}>{buttonText}
+ { + showCancelButton && +
showCancelButtonClick && showCancelButtonClick()}>{showCancelButtonText || '關閉'}
+ } +
+
+
+ ) +} + +export default Modal \ No newline at end of file diff --git a/src/components/ProductItem.tsx b/src/components/ProductItem.tsx index 131b010..a306d18 100644 --- a/src/components/ProductItem.tsx +++ b/src/components/ProductItem.tsx @@ -1,17 +1,26 @@ import '~/styles/components.scss' +import { MarketNFTData } from '~/types/store' +import { splitAddress, toThousands } from '~/utils' + +interface ProductItemProps { + data: MarketNFTData +} + +const ProductItem = (props: ProductItemProps) => { + + const { data } = props -const ProductItem = () => { return (
- {/* */} -
+ + {/*
*/}
-
卡达鸭
+
{data.name}
-
USDT 10000
+
{data?.symbol} {toThousands(data?.price)}
- -
jackasddf
+ +
{splitAddress(data.sell_name,4)}
diff --git a/src/hooks/useWs.ts b/src/hooks/useWs.ts new file mode 100644 index 0000000..8763471 --- /dev/null +++ b/src/hooks/useWs.ts @@ -0,0 +1,37 @@ +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(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}×tamp=${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; diff --git a/src/index.tsx b/src/index.tsx index 525aa1f..66ac3e0 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -8,7 +8,7 @@ const root = ReactDOM.createRoot( ); root.render( - - - + // + + // ); \ No newline at end of file diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index 92a5c29..22961c8 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -2,39 +2,60 @@ import '~/styles/home.scss' import ProductItem from '~/components/ProductItem' import { useRouter } from '~/hooks/useRouter' import { Button } from 'react-vant' +import { useEffect, useState } from 'react' +import { market_list } from '~/api' +import { MarketNFTData } from '~/types/store' +import { splitAddress } from '~/utils' +import { observer } from 'mobx-react' const Home = () => { const { push } = useRouter() + const [marketData, setMarketData] = useState([] as MarketNFTData[]) + const [auctionData, setAuctionData] = useState([] as MarketNFTData[]) + + + useEffect(() => { + const getMarketData = async () => { + const res: any = await market_list(2) + res && res.code === 0 && res.data && setMarketData(res.data) + } + const getAuctionData = async () => { + const res: any = await market_list(1) + res && res.code === 0 && res.data && setAuctionData(res.data) + } + getMarketData() + getAuctionData() + }, []) return (
拍卖趋势
{ - Array.from({ length: 5 }).map((_, index) => ( + auctionData.map((item, index) => (
- push('/detail')} /> + push('/detail', { id: item.id })} />
-
生肖唐彩-龙
+
{item.name}
铸造者
- -
Filefast
+ +
{splitAddress(item.cast_name, 4)}
售卖者
- -
Filefast
+ +
{splitAddress(item.sell_name, 4)}
@@ -55,12 +76,15 @@ const Home = () => {
{ - Array.from({ length: 10 }).map((_, index) => ( - + marketData.map((item, index) => ( +
push('/detail', { id: item.id })}> + +
)) }
+
) } diff --git a/src/pages/personal/AccountAssetsCard.tsx b/src/pages/personal/AccountAssetsCard.tsx index 76d7b73..b89c510 100644 --- a/src/pages/personal/AccountAssetsCard.tsx +++ b/src/pages/personal/AccountAssetsCard.tsx @@ -1,15 +1,18 @@ import '~/styles/personal.scss' import { useMemo } from "react"; import { useRouter } from "~/hooks/useRouter"; +import { observer } from 'mobx-react'; +import store from '~/store'; const AccountAssetsCard = () => { const { push } = useRouter(); + const { userInfo } = store.state const balanceList = useMemo(() => [ - { title: 'USDT资产', value: 0, symbol: 'USDT' }, - { title: 'FIL资产', value: 0, symbol: 'FIL' }, - ], []); + { title: 'USDT资产', value: userInfo.balance_Usdt || 0, symbol: 'USDT' }, + { title: 'FIL资产', value: userInfo.balance_fil || 0, symbol: 'FIL' }, + ], [userInfo]); const menu = useMemo(() => [ { title: '充值', icon: require('~/assets/recharge.png'), path: '/recharge' }, @@ -24,7 +27,7 @@ const AccountAssetsCard = () => {
总资产估值
-
1429.32 USDT
+
{userInfo.total} USDT
{ @@ -58,4 +61,4 @@ const AccountAssetsCard = () => { ) }; -export default AccountAssetsCard; \ No newline at end of file +export default observer(AccountAssetsCard); \ No newline at end of file diff --git a/src/pages/personal/index.tsx b/src/pages/personal/index.tsx index b2bd1d9..eab0fc9 100644 --- a/src/pages/personal/index.tsx +++ b/src/pages/personal/index.tsx @@ -1,17 +1,15 @@ +import { observer } from 'mobx-react' import { Divider } from 'react-vant' +import store from '~/store' import '~/styles/personal.scss' import AccountAssetsCard from './AccountAssetsCard' const Personal = () => { + const { userInfo } = store.state + return (
- {/* Toast.info('文件大小不能超过500kb')} - upload={upload} - /> */}
@@ -25,18 +23,24 @@ const Personal = () => {
名称
可用
-
-
- -
-
USDT
-
TetherUS
-
-
-
-
100
-
$429.32
-
+
+ { + userInfo.assets && userInfo.assets.map(item => ( +
+
+ +
+
{item.symbol}
+
{item.name}
+
+
+
+
{item.amount}
+
{item.symbol !== 'USDT' && item.amount_usdt}
+
+
+ )) + }
@@ -44,4 +48,4 @@ const Personal = () => { ) } -export default Personal \ No newline at end of file +export default observer(Personal) \ No newline at end of file diff --git a/src/pages/product/index.tsx b/src/pages/product/index.tsx index 44f590f..757cadd 100644 --- a/src/pages/product/index.tsx +++ b/src/pages/product/index.tsx @@ -1,5 +1,6 @@ import { Divider } from 'react-vant' import '~/styles/product.scss' +import { MarketNFTData } from '~/types/store' import ProductItem from '../../components/ProductItem' const Product = () => { @@ -18,11 +19,11 @@ const Product = () => {
{ Array.from({ length: 6 }).map((_, index) => ( - + )) }
- +
) } diff --git a/src/pages/recharge/index.tsx b/src/pages/recharge/index.tsx index d59291d..6462e28 100644 --- a/src/pages/recharge/index.tsx +++ b/src/pages/recharge/index.tsx @@ -1,22 +1,25 @@ import '~/styles/recharge.scss' import { observer } from 'mobx-react' import store from '../../store' -import { useMemo, useRef, useState } from 'react' +import { useEffect, useMemo, useRef, useState } from 'react' import { useRouter } from '../../hooks/useRouter' -import { ethers } from 'ethers' +import { BigNumber, ethers } from 'ethers' import { Button, Toast } from 'react-vant' -import { switchNetWork } from '../../utils' +import { switchNetWork, toFixed2 } from '../../utils' import { IERC20__factory } from '../../contract/IERC20__factory' import { toWei } from '../../utils/wei' import BackBar from '~/components/BackBar' +import CoinPicker from '~/components/CoinPicker' const Recharge = () => { - const { coinIndex, coinList, userInfo } = store.state + const { coinList, userInfo, walletAddress, token } = store.state const { push } = useRouter() - const inputRef = useRef(null); + const inputRef = useRef(null) + const [coinIndex, setCoinIndex] = useState(0) const currentCoin = useMemo(() => coinList[coinIndex], [coinIndex, coinList]) - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(false) + const [balance, setBalance] = useState({} as { [key: string]: string }) const provider = useMemo(() => { if (window.ethereum) { @@ -75,6 +78,7 @@ const Recharge = () => { const handleExchange = async () => { if (!provider || loading) return; let value = inputRef.current?.value; + if (!value) { Toast.info('請輸入數量'); return; @@ -83,8 +87,10 @@ const Recharge = () => { setLoading(true); try { let isNode = await switchNetWork(); + if (!isNode) return; let data = await handleTransferParams(); + if (data == -1) { // Toast.info('请检查网络是否正常'); setLoading(false); @@ -109,27 +115,55 @@ const Recharge = () => { Toast.fail('充值失敗'); } } catch (error) { + console.log(error); + setLoading(false); } }; + useEffect(() => { + const getBalance = async () => { + if (!provider) return + + try { + + const balance = {} as { [key: string]: string } + const ps = coinList.map((item, index) => { + let _contract = IERC20__factory.connect(item.address, provider); + balance[item.symbol] = '' + return _contract.balanceOf(walletAddress) + }) + const res = await Promise.all(ps) + Array.isArray(res) && res.forEach((item, index) => { + BigNumber.isBigNumber(item) && (balance[coinList[index].symbol] = toFixed2(ethers.utils.formatUnits(item, 18), 4)) + }) + + setBalance(balance) + } catch (error) { + + } + } + + token && getBalance() + + }, [coinList, provider, token, walletAddress]) + + useEffect(() => { + inputRef.current && (inputRef.current.value = '') + }, [coinIndex]) return (
-
push('/choose')}> -
- { - currentCoin && - } -
{currentCoin && currentCoin.symbol}
-
-
- -
+
+
-
+
push('/record')}>
@@ -142,14 +176,11 @@ const Recharge = () => {
數量
-
- { - currentCoin && - } -
{currentCoin && currentCoin.symbol}
- {/*
最大
*/} -
+
{ + balance[currentCoin.symbol] && (inputRef.current!.value = balance[currentCoin.symbol]) + }}>ALL
+
可用餘額:{currentCoin.symbol ? balance[currentCoin.symbol] : 0}
diff --git a/src/pages/record/index.tsx b/src/pages/record/index.tsx index d22e441..6f08946 100644 --- a/src/pages/record/index.tsx +++ b/src/pages/record/index.tsx @@ -8,14 +8,15 @@ import BackBar from "~/components/BackBar"; import { Cell, Empty, List, Tabs } from "react-vant"; import { debounce } from 'lodash'; import '~/styles/personal.scss'; +import { history_record } from "~/api"; const Record = () => { const { token } = store.state; + const { push } = useRouter() const recordTabs = useMemo(() => ['充值', '提现', '收益'], []); const [recordIndex, setRecordIndex] = useState(0); const { copyVal } = useCopyLink(); - const { push } = useRouter(); const [query, setQuery] = useState([ { page: 1, page_size: 20 }, { page: 1, page_size: 20 }, @@ -30,8 +31,7 @@ const Record = () => { const getAssetsRecord = debounce(async () => { - // let res: any = await assets_record({ type: recordIndex + 1, ...query[recordIndex] }); - let res: any = {}; + let res: any = await history_record({ type: recordIndex + 1, ...query[recordIndex] }); if (res.code === 0) { if (res.data.length < 20) { if (assetsRecord[recordIndex].length <= 0) { @@ -62,17 +62,14 @@ const Record = () => { , , , - , - , - ]; return el[index]; }; useEffect(() => { - // token && assetsRecord[recordIndex].length <= 0 && getAssetsRecord(); - // !token && push('/', null, true); - // !token && setFinished([true, true, true, true, true, true]); + token && assetsRecord[recordIndex].length <= 0 && getAssetsRecord(); + !token && push('/', null, true); + !token && setFinished([true, true, true, true, true, true]); }, [recordIndex, token]); @@ -124,30 +121,32 @@ const RechargeRecord = ( return ( getData()} errorText="请求失败,点击重新加载" offset={10}> { - list.map(item => ( - + list.map((item) => ( +
-
{item.status === -3 ? '激活赠送' : '充值'}
-
{getTime(item.time * 1000)}
-
- 交易哈希:{splitAddress(item.order, 10)} - copy && copy(item.order)}> +
{item.name}
+
{getTime(item.time * 1000)}
+
+ 交易哈希:{splitAddress(item.tx_hash, 10)} + { + item.tx_hash && ( + copy && copy(item.tx_hash)}> + ) + }
-
+{item.amount} {item.symbol}
-
= 0 ? 'blue-color' : 'red-color'}`} - > - {item.status !== -3 && (item.status === 3 ? '完成' : item.type >= 0 ? '确认中' : '失败')} +
+{item.amount} {item.symbol}
+
+ {item.status === 1 ? '完成' : '確認中'}
)) } - + ) } @@ -159,7 +158,7 @@ const WithdrawRecord = ({ list, finished, getData, copy }: ChildProps) => { getData()} errorText="请求失败,点击重新加载" offset={10}> { list.map((item, index) => ( - +
提现
@@ -196,7 +195,7 @@ const TransferRecord = ({ list, finished, getData }: ChildProps) => { getData()} errorText="请求失败,点击重新加载" offset={10}> { list.map((item, index) => ( - +
划转 {item.name}
@@ -218,86 +217,4 @@ const TransferRecord = ({ list, finished, getData }: ChildProps) => { ) } -const OrderRecord = ( - { list, finished, getData }: ChildProps -) => { - - if (list.length <= 0 || Object.keys(list).length <= 0) return ; - - return ( - <> - getData()} errorText="请求失败,点击重新加载" offset={10}> - { - list.map(item => ( - -
-
ID {item.order}
-
{getTime(item.time * 1000)}
-
-
-
{item.type === 1 ? '主单盈亏' : '对冲单盈亏'}
-
= 0 ? "green-color" : 'red-color'}>{Number(item.amount) >= 0 && '+'}{item.amount} {item.symbol}
-
-
-
保险赔付
-
= 0 ? "green-color" : 'red-color'}>{Number(item.rebate_amount) >= 0 && '+'}{item.rebate_amount} {item.symbol}
-
-
-
结算费
-
{item.settle_fee} {item.symbol_fee}
-
-
- )) - } -
- - ) -} - -const ProfitPositionRecord = ({ list, getData, finished }: ChildProps) => { - - if (list.length <= 0 || Object.keys(list).length <= 0) return ; - - return ( - getData()} errorText="请求失败,点击重新加载" offset={10}> - { - list.map(item => ( - -
-
ID {item.order}
-
{getTime(item.time * 1000)}
-
-
-
{item.name}
-
{Number(item.amount) >= 0 && '+'}{item.amount} {item.symbol}
-
-
- )) - } -
- ) -} - -const MonthlyFeeRecord = ({ list, finished, getData }: ChildProps) => { - - if (list.length <= 0 || Object.keys(list).length <= 0) return ; - - return ( - getData()} errorText="请求失败,点击重新加载" offset={10}> - { - list.map(item => ( - -
-
{item.name}
-
{Number(item.amount) >= 0 && '+'}{item.amount} {item.symbol}
-
-
{getTime(item.time * 1000)}
-
- )) - } -
- ) -} - - export default observer(Record); \ No newline at end of file diff --git a/src/pages/share/index.tsx b/src/pages/share/index.tsx index f9c35ea..77bd4d2 100644 --- a/src/pages/share/index.tsx +++ b/src/pages/share/index.tsx @@ -1,32 +1,166 @@ -import { Tabs } from 'react-vant' import '~/styles/share.scss' +import { Popup, Tabs, Toast } from 'react-vant' import ProductItem from '~/components/ProductItem' +import { MarketNFTData } from '~/types/store' +import store from '~/store' +import { observer } from 'mobx-react' +import { toFixed2 } from '~/utils' +import { useEffect, useMemo, useRef, useState } from 'react' +import { open_page, personal_nft, reset_name, upload_image } from '~/api' const Share = () => { + + const { userInfo, token } = store.state + const [visible, setVisible] = useState(false) + const inputRef = useRef(null) + const nameRef = useRef(null) + const [edit, setEdit] = useState(false) + const prevent = useRef(false) //阻止重複點擊 + const fileRef = useRef(null as any) + const [tempUrl, setTempUrl] = useState(null as any) + const [nftList, setNftList] = useState([ + [], //我的 + [],//我喜歡的 + ] as MarketNFTData[][]) + const tabs = useMemo(() => ['我的NFT', '我喜歡的NFT'], []) + + const avatarmenuClick = (event: any) => { + const dataType = event.target.dataset.type; + + switch (dataType) { + case "photo": //相册 + inputRef.current?.click() + break + case "save": //保存 + !fileRef.current && Toast.info('請選擇圖片') + fileRef.current && uploader(fileRef.current) + break + case "cancel": //取消 + closePopup() + break + } + } + + const uploader = async (file: File | null) => { + if (!file) return + setVisible(false) + const res: any = await upload_image(file) + res.code === 0 && await store.getUserInfo() + res.code === 0 && Toast.success('保存成功') + closePopup() + } + + const saveName = async () => { + if (nameRef.current?.value === userInfo.name) return + const res: any = await reset_name(nameRef.current!.value) + res.code === 0 && store.getUserInfo() + setEdit(false) + } + + const openPages = async () => { + if (prevent.current) return + prevent.current = true + const res: any = await open_page(userInfo.show === 1 ? 2 : 1) + res.code === 0 && store.getUserInfo() + res.code === 0 && Toast.success({ + message: userInfo.show === 1 ? '已隐藏' : '已开放', + forbidClick: true + }) + prevent.current = false + } + + const onChangeImage = (event: React.ChangeEvent) => { + let file = event.target.files ? event.target.files[0] : null + if (!file) return + + fileRef.current = file + const reader = new FileReader() + reader.onloadend = function () { + const base64String = reader.result + setTempUrl(base64String) + } + reader.readAsDataURL(file) + inputRef.current!.value = '' + } + + const closePopup = () => { + setVisible(false) + setTempUrl('') + fileRef.current = null + inputRef.current!.value = '' + } + + useEffect(() => { + const getData = async () => { + const res: any = await personal_nft(1) + if (res && res.code === 0) { + nftList[0] = res.data + setNftList([...nftList]) + } + } + + token && getData() + }, [token]) + return ( -
+
- + { + setVisible(true) + }} />
-
IamjackRider
+ { + token ? ( +
+ { + edit ? ( + { + setTimeout(() => { + setEdit(false) + }, 100) + }} /> + ) : ( +
{userInfo.name}
+ ) + } +
+ { + edit ? ( + + ) : ( + { + setEdit(true) + setTimeout(() => { + nameRef.current!.value = userInfo.name + nameRef.current!.focus() + }, 20) + }} /> + ) + } +
+
+ ) : ( +
未登录
+ ) + }
-
开放我的资产
+
{userInfo.show === 2 ? '开放我的艺术页面' : '隐藏我的艺术页面'}
-
5
+
{userInfo.sell}
售卖作品
-
15
+
{userInfo.auction}
拍卖作品
-
255 FIL
+
{toFixed2(userInfo.income, 2)} FIL
收入
@@ -40,32 +174,45 @@ const Share = () => { animated swipeable > - - 我的NFT - 25 -
} - titleClass='fz-wb-550' - > -
- {Array.from({ length: 10 }).map((_, index) => )} -
- - - 我喜欢的NFT - 999+ -
} - titleClass='fz-wb-550' - > -
- {Array.from({ length: 10 }).map((_, index) => )} -
- + { + tabs.map((item, index) => ( + + {item} + {nftList[index].length} +
} + titleClass='fz-wb-550' + > +
+ {nftList[index].map((item, index) => )} +
+ + )) + } +
+ + +
+
+
从手机相册选择
+
保存图片
+
+
+
取消
+
+
) } -export default Share \ No newline at end of file +export default observer(Share) \ No newline at end of file diff --git a/src/pages/team/index.tsx b/src/pages/team/index.tsx new file mode 100644 index 0000000..a4b1927 --- /dev/null +++ b/src/pages/team/index.tsx @@ -0,0 +1,252 @@ +import '~/styles/personal.scss' +import { Button, Divider, List, Overlay, Swiper, SwiperInstance, Toast } from "react-vant" +import BackBar from "~/components/BackBar" +import { useEffect, useRef, useState } from 'react' +import { getTime, splitAddress } from '~/utils' +import { observer } from 'mobx-react' +import store from '~/store' +import { my_invite, team_info } from '~/api' +import useCopyLink from '~/hooks/useCopy' +import { InviteRecordData } from '~/types/store' +import { useRouter } from '~/hooks/useRouter' +import { copy } from '~/utils/copy' +import QRCode from 'qrcode' + +const Team = () => { + + const { push } = useRouter() + const { token } = store.state + const { copyVal } = useCopyLink() + const [address, setAddress] = useState('') + const [inviteList, setInviteList] = useState([] as InviteRecordData[]) + const [finished, setFinished] = useState(true); + const [visible, setVisible] = useState(false); + const [cardState, setCardState] = useState([ + [ + { title: '我的推薦人', value: '000000000', id: 1 }, + { title: '級別獎勵', value: '10% 5%', id: 2 }, + ], + [ + { title: '獎勵金額', value: '0U', id: 4 }, + { title: '直推人數', value: '0人', id: 6 }, + { title: '閒推人數', value: '0人', id: 5 }, + ], + ]) + + const query = useRef({ page: 1, page_size: 20 }) + + const getInviteData = async () => { + let res: any = await my_invite(query.current); + if (res && res.code === 0 && res.data) { + if (res.data.length < 20) { + if (inviteList.length <= 0) { + setInviteList(res.data) + } else { + setInviteList([...inviteList, ...res.data]) + } + setFinished(true) + return + } + query.current.page = query.current.page + 1 + if (inviteList.length <= 0) { + setInviteList(res.data) + } else { + setInviteList([...inviteList, ...res.data]) + }; + setFinished(false) + } + } + + + useEffect(() => { + const getData = async () => { + const res: any = await team_info() + if (res && res.code === 0) { + cardState[0][0].value = res.data.inviti_address || '000000000000000' + cardState[1][0].value = res.data.award ? res.data.award + "U" : "0U" + cardState[1][1].value = res.data.direct_count ? res.data.direct_count + '人' : '0人' + cardState[1][2].value = res.data.indirect_count ? res.data.indirect_count + '人' : '0人' + setCardState([...cardState]) + setAddress(res.data.address) + } + console.log(res); + } + + token && getData() + token && getInviteData(); + !token && push('/', null, true) + }, [token]) + + return ( +
+ + +
+
邀请好友,挣奖励
+
+
最高可得
+
10%
+
+
+ +
+ { + cardState.map((v, index) => ( +
+ { + v.map(item => ( +
+
{item.title}
+
+ {item.id === 1 ? splitAddress(item.value) : item.value} + { + item.id === 1 && ( + copyVal(item.value)}> + ) + } +
+
+ )) + } +
+ )) + } +
+ +
+
我的邀请
+
+ +
+
+
地址
+
+
時間
+
+ +
+ { + inviteList.map((item, index) => ( +
+
{splitAddress(item.address)}
+
+
{getTime(item.time * 1000)}
+
+ )) + } +
+
+
+ { + visible && + } +
+ ) +} + +const ShareModal = ( + { visible, setVisible, address }: { visible: boolean, setVisible: Function, address: string } +) => { + + const [swiperIndex, setSwiperIndex] = useState(0) + const swiperRef = useRef(null) + const [qrcodeUri, setQrcodeUri] = useState('') + + const handleSwiper = () => { + if (swiperIndex === 0) { + swiperRef.current?.swipeNext() + } else { + swiperRef.current?.swipePrev() + } + } + + const downloadQrcode = () => { + if (!qrcodeUri) return + const link = document.createElement('a') + link.href = qrcodeUri + link.download = `${Date.now()}.png` + link.click() + link.remove() + } + + useEffect(() => { + copy(process.env.REACT_APP_SHARE_LINK + address) + QRCode.toDataURL(process.env.REACT_APP_SHARE_LINK + address, (err, url) => { + if (url) { + setQrcodeUri(url) + } + }) + }, []) + + return ( + +
+
+ setVisible(false)}> +
+ <>} + onChange={(index) => setSwiperIndex(index)} + initialSwipe={swiperIndex} + touchable={false} + > + +
+
+
+ +
+
+
+ {splitAddress(process.env.REACT_APP_SHARE_LINK + address, 14)} + { + copy(process.env.REACT_APP_SHARE_LINK + address, () => { + Toast.success('复制成功') + }) + }}> +
+
成功複製分享碼
+
轉發給好友並在錢包裏打開完成綁定
+
+
+ +
+
+ +
+
+ 截圖或下載圖片 + +
+
掃描綁定關係
+
在好友錢包裡掃一掃完成綁定
+
+
+
+ +
+
+
+
+ {swiperIndex === 0 ? '切換二維碼' : '切換分享鏈接'} +
+ +
+
+
+
+
+ ) +} + + +export default observer(Team) \ No newline at end of file diff --git a/src/pages/withdraw/index.tsx b/src/pages/withdraw/index.tsx index 60fc316..3291d55 100644 --- a/src/pages/withdraw/index.tsx +++ b/src/pages/withdraw/index.tsx @@ -3,33 +3,59 @@ import { observer } from 'mobx-react' import store from '../../store' import { useMemo, useRef, useState } from 'react' import { useRouter } from '../../hooks/useRouter' -import { Button } from 'react-vant' +import { Button, Toast } from 'react-vant' import BackBar from '~/components/BackBar' +import CoinPicker from '~/components/CoinPicker' +import { user_withdraw } from '~/api' +import { getChainId } from '~/utils' const Recharge = () => { - const { coinIndex, coinList } = store.state + const { coinList, walletAddress } = store.state + const [coinIndex, setCoinIndex] = useState(0) const { push } = useRouter() const inputRef = useRef(null); const currentCoin = useMemo(() => coinList[coinIndex], [coinIndex, coinList]) const [loading, setLoading] = useState(false); + const withdraw = async () => { + const amount = inputRef.current?.value + const balance = currentCoin.balance + if (!balance) return + if (!amount) return Toast.fail("請輸入數量") + if (Number(balance) < Number(amount)) return Toast.fail("餘額不足") + setLoading(true) + try { + const chainId = await getChainId() + let res: any = await user_withdraw({ + symbol: currentCoin.symbol, + chainId: chainId || -1, + amount + }); + if (res.code === 0 || res.code === 101) { + res.code === 0 && Toast.success('提交成功'); + setTimeout(() => { + push('/record', { index: 1 }, true) + }, 1000) + }; + } catch (error) { + setLoading(false) + } + }; + + return (
-
push('/choose')}> -
- { - currentCoin && - } -
{currentCoin && currentCoin.symbol}
-
-
- -
+
+
-
+
push('/record', { index: 1 })}>
@@ -38,7 +64,7 @@ const Recharge = () => {
提现地址
-
0xasdasd;lasdljaslkdjklasdjlkasjdlk
+
{walletAddress}
@@ -51,22 +77,22 @@ const Recharge = () => {
数量
- +
-
FIL
+
{currentCoin && currentCoin.symbol}
最大
-
可用余额:0 USDT
+
可用余额:{currentCoin ? currentCoin.balance : 0} {currentCoin && currentCoin.symbol}
手续费
-
0.1000 FIL
+
{currentCoin ? currentCoin.withdraw_fee : 0} {currentCoin && currentCoin.symbol}
- +
diff --git a/src/router/layout/index.tsx b/src/router/layout/index.tsx index cd0d8c0..2a08142 100644 --- a/src/router/layout/index.tsx +++ b/src/router/layout/index.tsx @@ -1,17 +1,93 @@ import '~/styles/layout.scss' -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useRouter } from '~/hooks/useRouter'; import Notify from './Notify'; import RenderRouter from './RenderRouter'; -import { tabbarData } from '../routes'; +import routes, { tabbarData } from '../routes'; import Navbar from './Navbar'; import Tabbar from './Tabbar'; +import { observer } from 'mobx-react'; +import store from '~/store'; +import useWs from '~/hooks/useWs'; +import { ethers } from 'ethers'; +import { bind_rmd } from '~/api'; +import { AlreadyBind, BindRmd, BindSuccess, DefaultBind, UnLogin, VaildLink } from './ui'; const LayoutRouter = () => { const { location, push } = useRouter() + const messageWs = useWs('getMessage') + const { token, walletAddress, userInfo, visibleUnLogin } = store.state const [visible, setVisible] = useState(false) + const [visibleVaildLink, setVisibleVaildLink] = useState(false) //无效的链接 + const [visibleAlreadyBind, setVisibleAlreadyBind] = useState(false) //已绑定 + const [visibleBindRmd, setVisibleBindRmd] = useState(false) //直接绑定 + const [shareAddress, setShareAddress] = useState('') + const [visibleBindSuccess, setVisibleBindSuccess] = useState(false) //綁定成功 + const [visibleDefault, setVisibleDefault] = useState(false) //默認綁定 + + + const bindRecommend = async () => { + const res: any = await bind_rmd(shareAddress) + if (res.code === 0) { + setVisibleBindRmd(false) + store.getUserInfo() + setTimeout(() => { + push('/', null, true) + setVisibleBindSuccess(true) + }, 200) + } + } + + useEffect(() => { + token && store.getUserInfo() + token && store.getCoinList() + !token && store.resetCoinList() + !token && store.resetUserInfo() + // token && messageWs.connect(token) + // !token && messageWs.disconnect() + }, [token]) + + useEffect(() => { + const isModal = async () => { + let user = userInfo + let isRouter = routes.find(v => v.path === location.pathname) + const address = location.pathname.substring(1, location.pathname.length) + + if (user.is_bound) return + if (isRouter) return + + if (Object.keys(user).length <= 0) { + const res: any = await store.getUserInfo() + if (res) { + user = res + } + } + if (!ethers.utils.isAddress(address)) { + // 无效的分享链接 + setVisibleVaildLink(true) + return + } + // 地址相同 + if (address.toLocaleLowerCase() === walletAddress.toLocaleLowerCase()) return + setShareAddress(address) + // 绑定推荐人 + + if (!user.is_bound && ethers.utils.isAddress(address)) { + setVisibleBindRmd(true) + return + } + // 已有推荐人 + if (user.is_bound) { + setVisibleAlreadyBind(true) + } + } + + token && isModal() + !token && setVisibleBindRmd(false) + }, [token, walletAddress]) + return (
{ ) } + +
+ {/* 無效鏈接 */} + {visibleVaildLink && } + {/* 已經綁定 */} + {visibleAlreadyBind && ( + { + push('/', null, true) + setVisibleAlreadyBind(false) + push('/share') + }} + visible={visibleAlreadyBind} + setVisible={setVisibleAlreadyBind} + /> + )} + {/* 綁定推薦人 */} + {visibleBindRmd && ( + + )} + { + visibleUnLogin && ( + store.setVisibleUnLogin(false)} + /> + ) + } + {visibleDefault && ( + setVisibleDefault(false)} + onClick={bindRecommend} + /> + )} + {visibleBindSuccess && ( + setVisibleBindSuccess(false)} + address={shareAddress} + /> + )} + +
); } -export default LayoutRouter \ No newline at end of file +export default observer(LayoutRouter) \ No newline at end of file diff --git a/src/router/layout/ui.tsx b/src/router/layout/ui.tsx new file mode 100644 index 0000000..0f1204b --- /dev/null +++ b/src/router/layout/ui.tsx @@ -0,0 +1,123 @@ +import { ethers } from "ethers"; +import { useRef } from "react"; +import { Toast } from "react-vant"; +import Modal from "../../components/Modal"; +interface UIProps { + visible: boolean, + setVisible: Function, + onClick?: Function, + address?: string +} + +export const UnLogin = ({ visible, setVisible }: UIProps) => ( + +
+
訪問失敗
+
未檢測到錢包,請登錄錢包後重新點擊
+
+
+) + +export const VaildLink = ({ visible, setVisible }: UIProps) => ( + setVisible(false)} + setVisible={() => setVisible(false)} + visible={visible} + buttonText="關閉" + > +
+
綁定失敗
+
無效的分享鏈接
+
+
+) + +export const DefaultBind = ({ visible, setVisible, onClick }: UIProps) => { + + const addressRefs = useRef(null) + + const confirm = () => { + let value = addressRefs.current?.value + if (!value) return Toast.info('請輸入推薦鏈接!') + let newValue = value?.split('/#/') + if (!ethers.utils.isAddress(newValue[1])) return Toast.info('無效的分享鏈接') + onClick && onClick(newValue[1]) + } + + return ( + +
+
推薦鏈接
+ +
+
+ ) +} + +export const BindRmd = ({ visible, setVisible, address, onClick }: UIProps) => ( + setVisible(false)} + title="綁定推薦人" + buttonClick={() => onClick && onClick(address)} + buttonText="確認綁定" + hiddenCloseIcon + > +
+
推薦人地址
+
{address}
+
+
+) + +export const BindSuccess = ({ visible, setVisible, address }: UIProps) => ( + +
+
綁定成功
+
{address}
+
+
+) + + +export const AlreadyBind = ({ visible, setVisible, onClick }: UIProps) => ( + onClick && onClick()} + setVisible={() => setVisible(false)} + visible={visible} + buttonText='查看綁定人' + showCancelButton + showCancelButtonClick={() => setVisible(false)} + > +
+
綁定失敗
+
該錢包已有推薦人,不可重複綁定推薦人
+
+
+) \ No newline at end of file diff --git a/src/router/routes.tsx b/src/router/routes.tsx index eb2d627..6bc2b1a 100644 --- a/src/router/routes.tsx +++ b/src/router/routes.tsx @@ -9,12 +9,17 @@ const Detail = lazy(() => import("~/pages/detail")); const Recharge = lazy(() => import("~/pages/recharge")); const Withdraw = lazy(() => import("~/pages/withdraw")); const Record = lazy(() => import("~/pages/record")); +const Team = lazy(() => import("~/pages/team")) const routes = [ { path: "/", element: }, + { + path: '/:id', + component: + }, { path: "/product", element: , @@ -42,8 +47,11 @@ const routes = [ { path: "/record", element: , + }, + { + path: '/team', + element: } - ] as RouteObject[]; export const tabbarData = [ diff --git a/src/store/index.ts b/src/store/index.ts index fbf03c6..e650b53 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -14,6 +14,7 @@ class AppStore implements Store { coinIndex: 0, coinList: [] as CoinList[], userInfo: {} as UserInfo, + visibleUnLogin: false, }; constructor() { @@ -48,12 +49,15 @@ class AppStore implements Store { } async getUserInfo(): Promise { - const res: any = await accountInfo() + const res: any = await accountInfo(); if (res && res.code === 0) { - this.state.userInfo = res.data - window.sessionStorage.setItem('userInfo', JSON.stringify(res.data)) + this.state.userInfo = res.data; } - return res && res.data + return res && res.data; + } + + resetUserInfo() { + this.state.userInfo = {} as UserInfo; } /** @@ -73,18 +77,22 @@ class AppStore implements Store { } async getCoinList(): Promise { - const res: any = await coin_list() + const res: any = await coin_list(); if (res && res.code === 0 && res.data) { - this.state.coinList = res.data + this.state.coinList = res.data; } } resetCoinList(): void { - this.state.coinList = [] + this.state.coinList = []; } setCoinIndex(index: number): void { - this.state.coinIndex = index + this.state.coinIndex = index; + } + + setVisibleUnLogin(bool: boolean): void { + this.state.visibleUnLogin = bool } } diff --git a/src/styles/components.scss b/src/styles/components.scss index 290400c..a65b71c 100644 --- a/src/styles/components.scss +++ b/src/styles/components.scss @@ -6,8 +6,8 @@ width: 171px; height: 132px; margin-left: 5px; + object-fit:cover ; border-radius: 10px; - background: $button-background; box-shadow: 8px 8px 20px 0px rgba(0, 0, 0, 0.1); } .desc-box{ @@ -92,4 +92,21 @@ top: -15px; } } +} + +.modal-content{ + width: 340px; + border-radius: 5px; + background: $page; + padding: 20px; + color:$black; + .modal-button{ + position: relative; + width: 130px; + height: 44px; + overflow: hidden; + border-radius: 10px; + background: $button-background; + color: $white; + } } \ No newline at end of file diff --git a/src/styles/layout.scss b/src/styles/layout.scss index 524defb..15718cd 100644 --- a/src/styles/layout.scss +++ b/src/styles/layout.scss @@ -36,9 +36,6 @@ .pages{ height: 100%; width: 100%; - overflow: hidden; - overflow-y: scroll; - &::-webkit-scrollbar{display: none;} } .tabbar{ @@ -72,6 +69,30 @@ height: 100px; width: 100%; } + + .ui{ + .unlogin-box{ + width: 100%; + height: 32px; + border-radius: 5px; + background-color: $white; + margin-top: 10px; + color: #E45546; + font-size: 14; + } + + .default-bind-input{ + width: 100%; + border: none; + background-color: $white; + color: $black; + height: 31px; + border-radius: 5px; + text-align: center; + font-size: 12px; + margin-top: 10px; + } + } } .rv-popup::-webkit-scrollbar{ diff --git a/src/styles/personal.scss b/src/styles/personal.scss index 0ba5762..7403414 100644 --- a/src/styles/personal.scss +++ b/src/styles/personal.scss @@ -49,8 +49,93 @@ .tabs{ padding: 10px 0px; .rv-tabs__nav--capsule .rv-tab.rv-tab--active .rv-tab__text { - background-color: #EAEAEA; - color: #727272; + background-color: $primary; + color: $white; } + + } +} + +.team{ + + .mb-6px{ + margin-bottom: 8px; + } + + .fz-60{ + font-size: 60px; + } + + .card-box{ + width: 100%; + padding: 30px; + background-color: $primary; + margin-top: 10px; + border-radius: 10px; + color: $white; + } + + .button{ + width: 145px; + height: 45px; + border-radius: 10px; + background-color: $primary; + color: $white; + font-weight: bold; + } +} + +.overlay{ + + color:$white; + + .text{ + font-family:'Gill Sans', 'Gill Sans MT', Calibri, 'Trebuchet MS', sans-serif; + } + + .solid{ + flex:5; + width: 100%; + height: 2px; + background-color: rgba(244, 244, 244, 0.3); + } + + .share-img{ + width: 220px; + height: 220px; + object-fit: cover; + } + + .url{ + font-size: 18px; + font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif; + text-align: center; + } + .button{ + margin-top: 30px; + width: 228px; + height: 52px; + border-radius: 28px; + background: $button-background; + color: $white; + position: relative; + overflow: hidden; + .text-index{ + position: relative; + z-index: 1; + display: flex; + justify-content: space-between; + align-items: center; + height: 100%; + font-family:Georgia, 'Times New Roman', Times, serif; + } + + &:active{ + opacity: 0.85; + } + } + + .swiper-height{ + // height: 460px; } } \ No newline at end of file diff --git a/src/styles/recharge.scss b/src/styles/recharge.scss index fc9d744..29515ab 100644 --- a/src/styles/recharge.scss +++ b/src/styles/recharge.scss @@ -67,5 +67,8 @@ height: 53px; background-color: $primary; border-radius: 16px; + color: $white; + font-size: 18px; + font-weight: bold; } } \ No newline at end of file diff --git a/src/styles/share.scss b/src/styles/share.scss index a180f11..cad626b 100644 --- a/src/styles/share.scss +++ b/src/styles/share.scss @@ -1,4 +1,4 @@ -.personal{ +.share{ .box{ @@ -28,12 +28,30 @@ } } + .name-box{ + height: 30px; + + input{ + border:none; + background: none; + font-weight: bold; + max-width: 200px; + text-align: center; + } + } + .box-block{ display: block; height: 71px; width: 100%; } + .text-overflow{ + max-width: 200px; + overflow: hidden; + text-overflow: ellipsis; + } + .tag{ background: linear-gradient(104deg, #1DD0DF -2%, #1DD0DF -2%, #1BEDFF -2%, #14BDEB 108%); padding: 5px 15px; diff --git a/src/styles/theme.scss b/src/styles/theme.scss index 860c7ea..c88fffb 100644 --- a/src/styles/theme.scss +++ b/src/styles/theme.scss @@ -1,4 +1,4 @@ -$primary:#1BEDFF; +$primary:#0FC6D4; $background:#fff; $primary-text:#000; $sub-text:#727272; diff --git a/src/types/api.d.ts b/src/types/api.d.ts index 5a86228..de801a7 100644 --- a/src/types/api.d.ts +++ b/src/types/api.d.ts @@ -9,4 +9,16 @@ interface PerformSignin { signature: string; } -export { PerformSNonce, PerformSignin } +interface HTTPWithdrawParams { + amount: string; + chainId: number; + symbol: string; +} + +interface HTTPHistoryParams { + page: number; + type: number; + type: number; +} + +export { PerformSNonce, PerformSignin, HTTPWithdrawParams, HTTPHistoryParams }; diff --git a/src/types/store.d.ts b/src/types/store.d.ts index ad54de2..9272438 100644 --- a/src/types/store.d.ts +++ b/src/types/store.d.ts @@ -15,6 +15,15 @@ interface UserInfo { show: number; total: string; url: string; + assets: Assets[]; +} + +interface Assets { + amount: string; + amount_usdt: string; + id: number; + symbol: string; + name: string; } interface CoinList { @@ -26,4 +35,42 @@ interface CoinList { withdraw_fee: string; } -export { StoreLocalStorageKey, UserInfo, CoinList }; +interface MarketNFTData { + auction_price: string; + award: string; + cast_id: number; + cast_name: string; + cast_show: number; + cast_url: string; + day: number; + end_Time: number; + function: string; + id: number; + mark: number; + name: string; + number: number; + platform: string; + price: string; + sell_id: number; + sell_name: string; + sell_show: number; + sell_url: string; + symbol: string; + time: number; + total_stock: number; + url: string; +} + +interface InviteRecordData { + address: string; + time: number; + id: number; +} + +export { + StoreLocalStorageKey, + UserInfo, + CoinList, + MarketNFTData, + InviteRecordData, +}; diff --git a/src/utils/copy.ts b/src/utils/copy.ts index d260631..3b46cdd 100644 --- a/src/utils/copy.ts +++ b/src/utils/copy.ts @@ -1,5 +1,5 @@ -export function copy(value: string, cb: Function) { +export function copy(value: string, cb?: Function) { // 动态创建 textarea 标签 const textarea: any = document.createElement('textarea') // 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域 diff --git a/src/utils/index.ts b/src/utils/index.ts index fc5d673..c36e8b9 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -15,16 +15,23 @@ const splitAddress = (address: string, index?: number) => { } }; +export const getChainId = async () => { + return toBig( + await window.ethereum.request({ + method: "eth_chainId", + }) + ).toNumber(); +}; + const switchNetWork = () => { - return new Promise((resolve) => { + return new Promise(async (resolve) => { if (!window.ethereum) { resolve(false); return; } - if ( - toBig(window.ethereum.chainId).toNumber() === 97 || - toBig(window.ethereum.chainId).toNumber() === 56 - ) { + let chainId = await getChainId(); + + if (chainId === 97 || chainId === 56) { //测试 resolve(true); return; @@ -72,4 +79,18 @@ const getTime = (value: number) => { return `${yy}-${mm}-${dd} ${xs}:${ff}`; }; -export { splitAddress, switchNetWork, toThousands, getTime }; +const toFixed2 = (val: string, double: number) => { + try { + if (val.indexOf(".") > -1) { + return val.substring( + 0, + val.indexOf(".") + (double === 0 ? double : double + 1) + ); + } + return val; + } catch (error) { + return "0"; + } +}; + +export { splitAddress, switchNetWork, toThousands, getTime, toFixed2 }; diff --git a/src/utils/sign/sign.ts b/src/utils/sign/sign.ts index 6f088ee..8d7fc3d 100644 --- a/src/utils/sign/sign.ts +++ b/src/utils/sign/sign.ts @@ -14,6 +14,7 @@ var signGenerator = (data: any) => { ptxt += keys[i] + data[keys[i]]; } ptxt = signkey + ptxt + signkey; + var signval = md5(ptxt).toLowerCase() return signval; } diff --git a/yarn.lock b/yarn.lock index e55afc5..84c4a96 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2552,6 +2552,13 @@ resolved "https://registry.npmmirror.com/@types/q/-/q-1.5.8.tgz#95f6c6a08f2ad868ba230ead1d2d7f7be3db3837" integrity sha512-hroOstUScF6zhIi+5+x0dzqrHA1EJi+Irri6b1fxolMTqqHIV/Cg77EtnQcZqZCu8hR3mX2BzIxN4/GzI68Kfw== +"@types/qrcode@^1.5.5": + version "1.5.5" + resolved "https://registry.npmmirror.com/@types/qrcode/-/qrcode-1.5.5.tgz#993ff7c6b584277eee7aac0a20861eab682f9dac" + integrity sha512-CdfBi/e3Qk+3Z/fXYShipBT13OJ2fDO2Q2w5CIP5anLTLIndQG9z6P1cnm+8zCWSpm5dnxMFd/uREtb0EXuQzg== + dependencies: + "@types/node" "*" + "@types/qs@*": version "6.9.10" resolved "https://registry.npmmirror.com/@types/qs/-/qs-6.9.10.tgz#0af26845b5067e1c9a622658a51f60a3934d51e8" @@ -3617,7 +3624,7 @@ camelcase-css@^2.0.1: resolved "https://registry.npmmirror.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== -camelcase@^5.3.1: +camelcase@^5.0.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.npmmirror.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -3724,6 +3731,15 @@ clean-css@^5.2.2: dependencies: source-map "~0.6.0" +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.npmmirror.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.npmmirror.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -4188,6 +4204,11 @@ debug@^3.2.7: dependencies: ms "^2.1.1" +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.npmmirror.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + decimal.js@^10.2.1: version "10.4.3" resolved "https://registry.npmmirror.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23" @@ -4320,6 +4341,11 @@ diff-sequences@^29.6.3: resolved "https://registry.npmmirror.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== +dijkstrajs@^1.0.1: + version "1.0.3" + resolved "https://registry.npmmirror.com/dijkstrajs/-/dijkstrajs-1.0.3.tgz#4c8dbdea1f0f6478bff94d9c49c784d623e4fc23" + integrity sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.npmmirror.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -4514,6 +4540,11 @@ emojis-list@^3.0.0: resolved "https://registry.npmmirror.com/emojis-list/-/emojis-list-3.0.0.tgz#5570662046ad29e2e916e71aae260abdff4f6a78" integrity sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q== +encode-utf8@^1.0.3: + version "1.0.3" + resolved "https://registry.npmmirror.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.npmmirror.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -5365,7 +5396,7 @@ gensync@^1.0.0-beta.2: resolved "https://registry.npmmirror.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== -get-caller-file@^2.0.5: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.npmmirror.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -7662,6 +7693,11 @@ pkg-up@^3.1.0: dependencies: find-up "^3.0.0" +pngjs@^5.0.0: + version "5.0.0" + resolved "https://registry.npmmirror.com/pngjs/-/pngjs-5.0.0.tgz#e79dd2b215767fd9c04561c01236df960bce7fbb" + integrity sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw== + postcss-attribute-case-insensitive@^5.0.2: version "5.0.2" resolved "https://registry.npmmirror.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz#03d761b24afc04c09e757e92ff53716ae8ea2741" @@ -8330,6 +8366,16 @@ q@^1.1.2: resolved "https://registry.npmmirror.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw== +qrcode@^1.5.3: + version "1.5.3" + resolved "https://registry.npmmirror.com/qrcode/-/qrcode-1.5.3.tgz#03afa80912c0dccf12bc93f615a535aad1066170" + integrity sha512-puyri6ApkEHYiVl4CFzo1tDkAZ+ATcnbJrJ6RiBM1Fhctdn/ix9MTE3hRph33omisEbC/2fcfemsseiKgBPKZg== + dependencies: + dijkstrajs "^1.0.1" + encode-utf8 "^1.0.3" + pngjs "^5.0.0" + yargs "^15.3.1" + qs@6.11.0: version "6.11.0" resolved "https://registry.npmmirror.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a" @@ -8666,6 +8712,11 @@ require-from-string@^2.0.2: resolved "https://registry.npmmirror.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + requires-port@^1.0.0: version "1.0.0" resolved "https://registry.npmmirror.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" @@ -8971,6 +9022,11 @@ serve-static@1.15.0: parseurl "~1.3.3" send "0.18.0" +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmmirror.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + set-function-length@^1.1.1: version "1.1.1" resolved "https://registry.npmmirror.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" @@ -10109,6 +10165,11 @@ which-collection@^1.0.1: is-weakmap "^2.0.1" is-weakset "^2.0.1" +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.npmmirror.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.9: version "1.1.13" resolved "https://registry.npmmirror.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" @@ -10308,6 +10369,15 @@ workbox-window@6.6.1: "@types/trusted-types" "^2.0.2" workbox-core "6.6.1" +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmmirror.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -10347,6 +10417,11 @@ ws@^8.13.0: resolved "https://registry.npmmirror.com/ws/-/ws-8.15.1.tgz#271ba33a45ca0cc477940f7f200cd7fba7ee1997" integrity sha512-W5OZiCjXEmk0yZ66ZN82beM5Sz7l7coYxpRkzS+p9PP+ToQry8szKh+61eNktr7EA9DOwvFGhfC605jDHbP6QQ== +ws@^8.16.0: + version "8.16.0" + resolved "https://registry.npmmirror.com/ws/-/ws-8.16.0.tgz#d1cd774f36fbc07165066a60e40323eab6446fd4" + integrity sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ== + xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.npmmirror.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -10357,6 +10432,11 @@ xmlchars@^2.2.0: resolved "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.npmmirror.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + y18n@^5.0.5: version "5.0.8" resolved "https://registry.npmmirror.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" @@ -10382,11 +10462,36 @@ yaml@^2.3.4: resolved "https://registry.npmmirror.com/yaml/-/yaml-2.3.4.tgz#53fc1d514be80aabf386dc6001eb29bf3b7523b2" integrity sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA== +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + yargs-parser@^20.2.2: version "20.2.9" resolved "https://registry.npmmirror.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs@^15.3.1: + version "15.4.1" + resolved "https://registry.npmmirror.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + yargs@^16.2.0: version "16.2.0" resolved "https://registry.npmmirror.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66"