You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

250 lines
8.5 KiB

1 year ago
  1. import '~/styles/personal.scss'
  2. import { Button, Divider, List, Overlay, Swiper, SwiperInstance, Toast } from "react-vant"
  3. import BackBar from "~/components/BackBar"
  4. import { useEffect, useRef, useState } from 'react'
  5. import { getTime, splitAddress } from '~/utils'
  6. import { observer } from 'mobx-react'
  7. import store from '~/store'
  8. import { my_invite, team_info } from '~/api'
  9. import useCopyLink from '~/hooks/useCopy'
  10. import { InviteRecordData } from '~/types/store'
  11. import { useRouter } from '~/hooks/useRouter'
  12. import { copy } from '~/utils/copy'
  13. import QRCode from 'qrcode'
  14. const Team = () => {
  15. const { push } = useRouter()
  16. const { token } = store.state
  17. const { copyVal } = useCopyLink()
  18. const [address, setAddress] = useState('')
  19. const [inviteList, setInviteList] = useState([] as InviteRecordData[])
  20. const [finished, setFinished] = useState(true);
  21. const [visible, setVisible] = useState(false);
  22. const [cardState, setCardState] = useState([
  23. [
  24. { title: '我的推薦人', value: '000000000', id: 1 },
  25. { title: '級別獎勵', value: '10% 5%', id: 2 },
  26. ],
  27. [
  28. { title: '獎勵金額', value: '0U', id: 4 },
  29. { title: '直推人數', value: '0人', id: 6 },
  30. { title: '閒推人數', value: '0人', id: 5 },
  31. ],
  32. ])
  33. const query = useRef({ page: 1, page_size: 20 })
  34. const getInviteData = async () => {
  35. let res: any = await my_invite(query.current);
  36. if (res && res.code === 0 && res.data) {
  37. if (res.data.length < 20) {
  38. if (inviteList.length <= 0) {
  39. setInviteList(res.data)
  40. } else {
  41. setInviteList([...inviteList, ...res.data])
  42. }
  43. setFinished(true)
  44. return
  45. }
  46. query.current.page = query.current.page + 1
  47. if (inviteList.length <= 0) {
  48. setInviteList(res.data)
  49. } else {
  50. setInviteList([...inviteList, ...res.data])
  51. };
  52. setFinished(false)
  53. }
  54. }
  55. useEffect(() => {
  56. const getData = async () => {
  57. const res: any = await team_info()
  58. if (res && res.code === 0) {
  59. cardState[0][0].value = res.data.inviti_address || '000000000000000'
  60. cardState[1][0].value = res.data.award ? res.data.award + "U" : "0U"
  61. cardState[1][1].value = res.data.direct_count ? res.data.direct_count + '人' : '0人'
  62. cardState[1][2].value = res.data.indirect_count ? res.data.indirect_count + '人' : '0人'
  63. setCardState([...cardState])
  64. setAddress(res.data.address)
  65. }
  66. }
  67. token && getData()
  68. token && getInviteData();
  69. !token && push('/', null, true)
  70. }, [token])
  71. return (
  72. <div className="plr-2 team">
  73. <BackBar
  74. title='团队'
  75. />
  76. <Button className="mt-2 button" onClick={() => setVisible(true)}></Button>
  77. <div className="row-between" style={{ alignItems: 'flex-end' }}>
  78. <div className='fz-24 fz-wb-550 mb-6px'></div>
  79. <div className="tar">
  80. <div className="fz-wb-550"></div>
  81. <div className="fz-wb-550 fz-60">10%</div>
  82. </div>
  83. </div>
  84. <div className='card-box'>
  85. {
  86. cardState.map((v, index) => (
  87. <div key={index} className="row-between" style={{ justifyContent: 'space-around' }}>
  88. {
  89. v.map(item => (
  90. <div key={item.id} className={`tac ${index === 1 && 'mt-2'}`}>
  91. <div className='fz-14'>{item.title}</div>
  92. <div className='mt-1 fz-wb-550'>
  93. {item.id === 1 ? splitAddress(item.value) : item.value}
  94. {
  95. item.id === 1 && (
  96. <i className='iconfont icon-fuzhi_copy white ml-5px' onClick={() => copyVal(item.value)}></i>
  97. )
  98. }
  99. </div>
  100. </div>
  101. ))
  102. }
  103. </div>
  104. ))
  105. }
  106. </div>
  107. <div className='mt-3'>
  108. <div className='fz-18'></div>
  109. <div className='mt-5px'>
  110. <Divider style={{ margin: 0, borderColor: '#2A2C24' }} />
  111. </div>
  112. <div className='row mt-1 tac fz-14'>
  113. <div style={{ flex: 1 }}></div>
  114. <div style={{ flex: 1 }}></div>
  115. <div style={{ flex: 1 }}></div>
  116. </div>
  117. <List
  118. finished={finished}
  119. onLoad={getInviteData}
  120. errorText="請求失敗,點擊重新加載"
  121. finishedText="已經到底了"
  122. offset={10}
  123. >
  124. <div>
  125. {
  126. inviteList.map((item, index) => (
  127. <div className='row mt-2 tac fz-14' key={index}>
  128. <div style={{ flex: 1 }}>{splitAddress(item.address)}</div>
  129. <div style={{ flex: 1 }}></div>
  130. <div style={{ flex: 1 }}>{getTime(item.time * 1000)}</div>
  131. </div>
  132. ))
  133. }
  134. </div>
  135. </List>
  136. </div>
  137. {
  138. visible && <ShareModal visible={visible} setVisible={setVisible} address={address} />
  139. }
  140. </div>
  141. )
  142. }
  143. const ShareModal = (
  144. { visible, setVisible, address }: { visible: boolean, setVisible: Function, address: string }
  145. ) => {
  146. const [swiperIndex, setSwiperIndex] = useState(0)
  147. const swiperRef = useRef<SwiperInstance>(null)
  148. const [qrcodeUri, setQrcodeUri] = useState('')
  149. const handleSwiper = () => {
  150. if (swiperIndex === 0) {
  151. swiperRef.current?.swipeNext()
  152. } else {
  153. swiperRef.current?.swipePrev()
  154. }
  155. }
  156. const downloadQrcode = () => {
  157. if (!qrcodeUri) return
  158. const link = document.createElement('a')
  159. link.href = qrcodeUri
  160. link.download = `${Date.now()}.png`
  161. link.click()
  162. link.remove()
  163. }
  164. useEffect(() => {
  165. copy(process.env.REACT_APP_SHARE_LINK + address)
  166. QRCode.toDataURL(process.env.REACT_APP_SHARE_LINK + address, (err, url) => {
  167. if (url) {
  168. setQrcodeUri(url)
  169. }
  170. })
  171. }, [])
  172. return (
  173. <Overlay visible={visible}>
  174. <div className='mt-5 white-color overlay'>
  175. <div className='row-justify-end pr-3'>
  176. <i className='iconfont icon-close fz-36' onClick={() => setVisible(false)}></i>
  177. </div>
  178. <Swiper
  179. ref={swiperRef}
  180. indicator={() => <></>}
  181. onChange={(index) => setSwiperIndex(index)}
  182. initialSwipe={swiperIndex}
  183. touchable={false}
  184. >
  185. <Swiper.Item>
  186. <div className='swiper-height'>
  187. <div className='row-center'>
  188. <div className='mt-5'>
  189. <img src={require('~/assets/share.png')} alt="" className='share-img' />
  190. </div>
  191. </div>
  192. <div className='url mt-2 row-center'>
  193. {splitAddress(process.env.REACT_APP_SHARE_LINK + address, 14)}
  194. <i className='iconfont icon-fuzhi_copy ml-1 fz-24' onClick={() => {
  195. copy(process.env.REACT_APP_SHARE_LINK + address, () => {
  196. Toast.success('复制成功')
  197. })
  198. }}></i>
  199. </div>
  200. <div className='mt-2 tac fz-wb-550 fz-26'></div>
  201. <div className='mt-2 tac'></div>
  202. </div>
  203. </Swiper.Item>
  204. <Swiper.Item>
  205. <div className='swiper-height'>
  206. <div className='row-center mt-5'>
  207. <img src={qrcodeUri} alt="" className='share-img' />
  208. </div>
  209. <div className='url mt-2 row-center'>
  210. <i className='iconfont icon-download ml-1 fz-24' onClick={downloadQrcode}></i>
  211. </div>
  212. <div className='mt-2 tac fz-wb-550 fz-26'></div>
  213. <div className='mt-2 tac'></div>
  214. </div>
  215. </Swiper.Item>
  216. </Swiper>
  217. <div className='row-center' >
  218. <div className='button' onClick={handleSwiper}>
  219. <div className='text-index plr-2'>
  220. <div>
  221. {swiperIndex === 0 ? '切換二維碼' : '切換分享鏈接'}
  222. </div>
  223. <i className='iconfont icon-arrow-right-bold fz-20'></i>
  224. </div>
  225. </div>
  226. </div>
  227. </div>
  228. </Overlay>
  229. )
  230. }
  231. export default observer(Team)