-
4.env
-
5env-temp
-
9package.json
-
BINpublic/favicon.ico
-
2public/index.html
-
BINpublic/login192.png
-
BINpublic/login512.png
-
BINpublic/logo192.png
-
BINpublic/logo512.png
-
15src/App.tsx
-
BINsrc/assets/_line2.png
-
BINsrc/assets/login.jpg
-
BINsrc/assets/login.png
-
BINsrc/assets/root.png
-
27src/components/Button.tsx
-
71src/components/CountdownTimer.tsx
-
302src/components/MyTable/index.tsx
-
49src/components/MyTable/tableHook.tsx
-
78src/components/SearchForm/index.tsx
-
143src/components/layout/Header.tsx
-
42src/components/layout/Slider.tsx
-
111src/components/profitChart.tsx
-
49src/http/api.ts
-
31src/http/axios_config.ts
-
65src/http/service.ts
-
20src/http/sign.ts
-
38src/http/sort.js
-
66src/http/types.ts
-
101src/pages/account/index.tsx
-
97src/pages/create-proxy/index.tsx
-
163src/pages/deposit/index.tsx
-
50src/pages/forget/index.tsx
-
103src/pages/home/index.tsx
-
51src/pages/link/index.tsx
-
93src/pages/login/index.tsx
-
53src/pages/personal/index.tsx
-
216src/pages/record/assets/index.tsx
-
111src/pages/record/bonus/index.tsx
-
75src/pages/record/deposit/index.tsx
-
67src/pages/record/escrow/index.tsx
-
81src/pages/record/withdraw/index.tsx
-
75src/pages/security/index.tsx
-
78src/pages/submit/index.tsx
-
110src/pages/team/index.tsx
-
73src/pages/transfer/index.tsx
-
95src/pages/withdraw/index.tsx
-
43src/router/index.tsx
-
3src/router/renderRouter.tsx
-
46src/router/routes.tsx
-
38src/store/index.ts
-
10src/styles/app.scss
-
4src/styles/components.scss
-
23src/styles/global.scss
-
110src/styles/home.scss
-
10src/styles/login.scss
-
27src/types/index.ts
-
47src/utils/index.ts
-
68yarn.lock
@ -0,0 +1,4 @@ |
|||||
|
SKIP_PREFLIGHT_CHECK=true |
||||
|
GENERATE_SOURCEMAP=false |
||||
|
REACT_APP_BASEURL='https://matontrading.com' |
||||
|
REACT_APP_ORIGIN='https://matontrading.com' |
@ -0,0 +1,5 @@ |
|||||
|
REACT_APP_BASEURL='https://matontrading.com' |
||||
|
REACT_APP_ORIGIN='https://matontrading.com' |
||||
|
|
||||
|
REACT_APP_BASEURL='http://203.161.61.234:8082' |
||||
|
REACT_APP_ORIGIN='http://162.254.37.253:8086' |
After Width: 564 | Height: 442 | Size: 100 KiB |
After Width: 564 | Height: 442 | Size: 100 KiB |
Before Width: 192 | Height: 192 | Size: 5.2 KiB |
Before Width: 512 | Height: 512 | Size: 9.4 KiB |
After Width: 41 | Height: 41 | Size: 178 B |
Before Width: 200 | Height: 200 | Size: 5.8 KiB |
After Width: 564 | Height: 442 | Size: 100 KiB |
After Width: 24 | Height: 22 | Size: 1.7 KiB |
@ -1,19 +1,28 @@ |
|||||
|
import { forwardRef } from 'react'; |
||||
import '../styles/components.scss' |
import '../styles/components.scss' |
||||
|
|
||||
interface ButtonProps { |
interface ButtonProps { |
||||
children?: string | JSX.Element; |
children?: string | JSX.Element; |
||||
className?: string; |
className?: string; |
||||
style?: React.CSSProperties, |
|
||||
onClick?: Function |
|
||||
|
style?: React.CSSProperties; |
||||
|
onClick?: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void; |
||||
|
htmlType?: "button" | "submit" | "reset" | undefined |
||||
} |
} |
||||
|
|
||||
const Button = (props: ButtonProps) => { |
|
||||
|
|
||||
const { children, style, className, onClick } = props |
|
||||
|
const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => { |
||||
|
const { children, style, className, onClick, htmlType = "button" } = props; |
||||
|
|
||||
return ( |
return ( |
||||
<div onClick={() => onClick && onClick()} className={`default-button ${className}`} style={style}>{children}</div> |
|
||||
) |
|
||||
} |
|
||||
|
<button |
||||
|
ref={ref} |
||||
|
type={htmlType} |
||||
|
onClick={onClick} |
||||
|
className={`default-button ${className}`} |
||||
|
style={style} |
||||
|
> |
||||
|
{children} |
||||
|
</button> |
||||
|
); |
||||
|
}); |
||||
|
|
||||
export default Button |
|
||||
|
export default Button; |
@ -0,0 +1,71 @@ |
|||||
|
import React, { useState, useEffect, forwardRef, useImperativeHandle } from 'react'; |
||||
|
|
||||
|
interface CountdownTimerProps { |
||||
|
initialSeconds: number, |
||||
|
onComplete?: Function |
||||
|
} |
||||
|
|
||||
|
export interface CountdownTimerRef { |
||||
|
handleStop: Function, |
||||
|
handleStart: Function, |
||||
|
handleReset: Function, |
||||
|
isActive: boolean |
||||
|
} |
||||
|
|
||||
|
const CountdownTimer = forwardRef<CountdownTimerRef, CountdownTimerProps>((props, ref) => { |
||||
|
|
||||
|
const { initialSeconds, onComplete } = props |
||||
|
|
||||
|
const [seconds, setSeconds] = useState(initialSeconds); |
||||
|
const [isActive, setIsActive] = useState(false); |
||||
|
const [title, setTitle] = useState('发送验证码') |
||||
|
|
||||
|
useImperativeHandle(ref, () => ({ |
||||
|
handleStop, |
||||
|
handleReset, |
||||
|
handleStart, |
||||
|
isActive |
||||
|
})) |
||||
|
|
||||
|
const handleStop = () => { |
||||
|
setIsActive(false); |
||||
|
setTitle('发送验证码') |
||||
|
}; |
||||
|
|
||||
|
const handleStart = () => { |
||||
|
if (isActive) return |
||||
|
setSeconds(initialSeconds) |
||||
|
setIsActive(true); |
||||
|
}; |
||||
|
|
||||
|
const handleReset = () => { |
||||
|
setSeconds(initialSeconds); |
||||
|
setIsActive(true); |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
let interval: any = null; |
||||
|
console.log(seconds); |
||||
|
console.log(isActive); |
||||
|
|
||||
|
if (isActive && seconds > 0) { |
||||
|
interval = setInterval(() => { |
||||
|
setSeconds(seconds => seconds - 1); |
||||
|
}, 1000); |
||||
|
} else { |
||||
|
clearInterval(interval) |
||||
|
seconds <= 0 && setTitle('重新发送') |
||||
|
setIsActive(false) |
||||
|
// onComplete && onComplete(seconds)
|
||||
|
} |
||||
|
console.log(1); |
||||
|
|
||||
|
return () => clearInterval(interval); |
||||
|
}, [isActive, seconds, onComplete]); |
||||
|
|
||||
|
return ( |
||||
|
<div>{isActive ? <span className='fz-18 fw550'>{seconds}s</span> : title}</div> |
||||
|
); |
||||
|
}); |
||||
|
|
||||
|
export default CountdownTimer; |
@ -0,0 +1,302 @@ |
|||||
|
import React, { |
||||
|
useState, |
||||
|
forwardRef, |
||||
|
useImperativeHandle, |
||||
|
useRef, |
||||
|
ReactNode, |
||||
|
FC |
||||
|
} from 'react' |
||||
|
import { Table } from 'antd' |
||||
|
import useService from './tableHook' |
||||
|
import SearchView from '../SearchForm' |
||||
|
|
||||
|
/** |
||||
|
* 封装列表、分页、多选、搜索组件 |
||||
|
* @param {RefType} ref 表格的实例,用于调用内部方法 |
||||
|
* @param {object[]} columns 表格列的配置 |
||||
|
* @param {function} apiFun 表格数据的请求方法 |
||||
|
* @param {object[]} searchConfigList 搜索栏配置 |
||||
|
* @param {function} beforeSearch 搜索前的操作(如处理一些特殊数据) |
||||
|
* @param {function} onFieldsChange 处理搜索栏表单联动事件 |
||||
|
* @param {object} extraProps 额外的搜索参数(不在搜索配置内的) |
||||
|
* @param {function} onSelectRow 复选框操作回调 |
||||
|
* @param {string} rowKey 表格行的key |
||||
|
* @param {function} sortConfig 自定义表格排序字段 |
||||
|
* @param {function} expandedRowRender 额外的展开行 |
||||
|
* @param {function} onExpand 点击展开图标时触发 |
||||
|
* @param {string} rowClassName 表格行的样式名 |
||||
|
* @param {boolean} small 表格和分页的展示大小 |
||||
|
* @param {string[]} extraPagation 额外的分页大小 |
||||
|
*/ |
||||
|
|
||||
|
interface TableProps { |
||||
|
columns: object[]; |
||||
|
apiFun: (arg0?: unknown[]) => Promise<{}>; |
||||
|
ref?: any; |
||||
|
searchConfigList?: object[]; |
||||
|
extraProps?: object; |
||||
|
rowKey?: string; |
||||
|
rowClassName?: string; |
||||
|
small?: boolean; |
||||
|
showHeader?: boolean; |
||||
|
extraPagation?: string[]; |
||||
|
beforeSearch?: (arg0?: unknown) => void; |
||||
|
onSelectRow?: (arg0?: string[], arg1?: string[]) => void; |
||||
|
onFieldsChange?: (arg0?: unknown, arg1?: unknown) => void; |
||||
|
sortConfig?: (arg0?: object) => any; |
||||
|
expandedRowRender?: () => ReactNode; |
||||
|
onExpand?: () => void; |
||||
|
header?: JSX.Element |
||||
|
} |
||||
|
|
||||
|
const MyTable: FC<TableProps> = forwardRef( |
||||
|
(props: TableProps, ref: any) => { |
||||
|
/** |
||||
|
* @forwardRef |
||||
|
* 引用父组件的ref实例,成为子组件的一个参数 |
||||
|
* 可以引用父组件的ref绑定到子组件自身的节点上. |
||||
|
*/ |
||||
|
const searchForm: any = useRef(null) |
||||
|
const { |
||||
|
columns, |
||||
|
apiFun, |
||||
|
searchConfigList, |
||||
|
extraProps, |
||||
|
rowKey, |
||||
|
rowClassName, |
||||
|
small, |
||||
|
showHeader, |
||||
|
extraPagation, |
||||
|
beforeSearch, |
||||
|
onSelectRow, |
||||
|
onFieldsChange, |
||||
|
sortConfig, |
||||
|
expandedRowRender, |
||||
|
onExpand, |
||||
|
header |
||||
|
} = props |
||||
|
|
||||
|
// 搜索参数,如果有特殊需要处理的参数,就处理
|
||||
|
const searchObj = searchConfigList && searchConfigList.reduce( |
||||
|
(prev: any, next: any) => { |
||||
|
return Object.assign(prev, { |
||||
|
[next.key]: next.fn ? next.fn(next.initialValue) : next.initialValue |
||||
|
}) |
||||
|
}, |
||||
|
{} |
||||
|
) |
||||
|
|
||||
|
// 初始参数
|
||||
|
const initParams = { |
||||
|
...searchObj, |
||||
|
...extraProps, |
||||
|
page: 1, |
||||
|
page_size: 20 |
||||
|
} |
||||
|
|
||||
|
// 多选框的选择值
|
||||
|
const [selectedKeys, setSelectedKeys] = useState([]) |
||||
|
// 列表所有的筛选参数(包括搜索、分页、排序等)
|
||||
|
const [tableParams, setTableParams] = useState(initParams) |
||||
|
// 列表搜索参数
|
||||
|
const [searchParams, setSearchParams] = useState(searchObj) |
||||
|
// 列表排序参数
|
||||
|
const [sortParams, setSortParams] = useState({}) |
||||
|
// 列表分页参数
|
||||
|
const [curPageNo, setCurPageNo] = useState(initParams.page) |
||||
|
const [curPageSize, setCurPageSize] = useState(initParams.page_size) |
||||
|
|
||||
|
const { loading = false, response = {} }: any = useService( |
||||
|
apiFun, |
||||
|
tableParams |
||||
|
); |
||||
|
|
||||
|
let tableData = [] as any[]; |
||||
|
let total = 0; |
||||
|
const validData = response?.data ? response.data : []; |
||||
|
if (Array.isArray(validData) && validData.length >= 0) { |
||||
|
tableData = validData; |
||||
|
total = validData.length; |
||||
|
} |
||||
|
|
||||
|
if (validData.rows) { |
||||
|
tableData = validData.rows; |
||||
|
total = validData.total; |
||||
|
} |
||||
|
|
||||
|
// const validData = response?.data ? response.data : {}
|
||||
|
// const { rows: tableData = [], total } = validData
|
||||
|
|
||||
|
// 执行搜索操作
|
||||
|
const handleSearch = (val: any): void => { |
||||
|
if (val.login) { |
||||
|
val.login = Number(val.login) |
||||
|
} |
||||
|
|
||||
|
const obj = { |
||||
|
...val |
||||
|
} |
||||
|
if (Array.isArray(obj.chain_id)) { |
||||
|
obj.chain_id = Number(obj.chain_id[0]) |
||||
|
} |
||||
|
|
||||
|
setSearchParams(obj) |
||||
|
|
||||
|
setTableParams({ ...tableParams, ...obj, page: 1 }) |
||||
|
} |
||||
|
|
||||
|
// 重置列表部分状态
|
||||
|
const resetAction = (page?: number): void => { |
||||
|
setSelectedKeys([]) |
||||
|
const nextPage = page || curPageNo |
||||
|
const nextParmas = page === 1 ? {} : { ...searchParams, ...sortParams } |
||||
|
setCurPageNo(nextPage) |
||||
|
setTableParams({ |
||||
|
...initParams, |
||||
|
...nextParmas, |
||||
|
page: nextPage, |
||||
|
page_size: curPageSize |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
// 列表复选框选中变化
|
||||
|
const onSelectChange = ( |
||||
|
selectedRowKeys: any[], |
||||
|
selectedRows: any[] |
||||
|
): void => { |
||||
|
setSelectedKeys(selectedRowKeys as any) |
||||
|
onSelectRow && onSelectRow(selectedRowKeys, selectedRows) |
||||
|
} |
||||
|
// 复选框配置
|
||||
|
const rowSelection = { |
||||
|
selectedRowKeys: selectedKeys, |
||||
|
onChange: onSelectChange |
||||
|
} |
||||
|
// 判断是否有复选框显示
|
||||
|
const showCheckbox = onSelectRow ? { rowSelection } : {} |
||||
|
|
||||
|
// 展开配置
|
||||
|
const expendConfig = { |
||||
|
expandedRowRender, |
||||
|
onExpand, |
||||
|
rowClassName |
||||
|
} |
||||
|
// 判断是否有展开行
|
||||
|
const showExpend = expandedRowRender ? expendConfig : {} |
||||
|
|
||||
|
// 表格和分页的大小
|
||||
|
const tableSize = small ? 'small' : 'middle' |
||||
|
const pagationSize = small ? 'small' : 'default' |
||||
|
|
||||
|
// 分页、筛选、排序变化时触发
|
||||
|
const onTableChange = ( |
||||
|
pagination: any, |
||||
|
filters: any, |
||||
|
sorter: object |
||||
|
): void => { |
||||
|
// 如果有sort排序并且sort参数改变时,优先排序
|
||||
|
const sortObj = sortConfig ? sortConfig(sorter) : {} |
||||
|
setSortParams(sortObj) |
||||
|
|
||||
|
const { current: page, pageSize } = pagination |
||||
|
|
||||
|
setCurPageNo(page) |
||||
|
setCurPageSize(pageSize) |
||||
|
setTableParams({ |
||||
|
...initParams, |
||||
|
...searchParams, |
||||
|
...sortObj, |
||||
|
page, |
||||
|
page_size: pageSize |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @useImperativeHandle |
||||
|
* 第一个参数,接收一个通过forwardRef引用父组件的ref实例 |
||||
|
* 第二个参数一个回调函数,返回一个对象,对象里面存储需要暴露给父组件的属性或方法 |
||||
|
*/ |
||||
|
useImperativeHandle(ref, () => ({ |
||||
|
// 更新列表
|
||||
|
update(page?: number): void { |
||||
|
resetAction(page) |
||||
|
}, |
||||
|
// 更新列表,并重置搜索字段
|
||||
|
resetForm(page?: number): void { |
||||
|
if (searchForm.current) searchForm.current.resetFields() |
||||
|
setSearchParams({}) |
||||
|
resetAction(page) |
||||
|
}, |
||||
|
// 仅重置搜索字段
|
||||
|
resetField(field?: string[]): void { |
||||
|
return field |
||||
|
? searchForm.current.resetFields([...field]) |
||||
|
: searchForm.current.resetFields() |
||||
|
}, |
||||
|
// 获取当前列表数据
|
||||
|
getTableData(): any[] { |
||||
|
return tableData |
||||
|
} |
||||
|
})) |
||||
|
|
||||
|
return ( |
||||
|
<div> |
||||
|
{/* 搜索栏 */} |
||||
|
{searchConfigList && searchConfigList.length > 0 && ( |
||||
|
<div style={{ display: 'flex', justifyContent: 'space-between' }}> |
||||
|
<SearchView |
||||
|
ref={searchForm} |
||||
|
config={searchConfigList} |
||||
|
beforeSearch={beforeSearch} |
||||
|
handleSearch={handleSearch} |
||||
|
onFieldsChange={onFieldsChange} |
||||
|
/> |
||||
|
{header} |
||||
|
</div> |
||||
|
)} |
||||
|
{/* 列表 */} |
||||
|
<Table |
||||
|
// {...showCheckbox}
|
||||
|
{...showExpend} |
||||
|
rowKey={rowKey} |
||||
|
loading={loading} |
||||
|
dataSource={tableData} |
||||
|
columns={columns} |
||||
|
onChange={onTableChange} |
||||
|
size={tableSize} |
||||
|
showHeader={showHeader} |
||||
|
style={{ minWidth: 1000 }} |
||||
|
pagination={{ |
||||
|
size: pagationSize, |
||||
|
total, |
||||
|
pageSize: tableParams.page_size, |
||||
|
current: tableParams.page, |
||||
|
showQuickJumper: true, |
||||
|
showSizeChanger: true, |
||||
|
pageSizeOptions: ['20', '50', '100', '200', ...extraPagation as any], |
||||
|
showTotal: (all) => `共 ${all} 条`, |
||||
|
}} |
||||
|
/> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
MyTable.defaultProps = { |
||||
|
searchConfigList: [], |
||||
|
ref: null, |
||||
|
extraProps: {}, |
||||
|
rowKey: 'id', |
||||
|
rowClassName: '', |
||||
|
small: false, |
||||
|
showHeader: true, |
||||
|
extraPagation: [], |
||||
|
beforeSearch: () => { }, |
||||
|
onSelectRow: () => { }, |
||||
|
onFieldsChange: () => { }, |
||||
|
sortConfig: () => { }, |
||||
|
expandedRowRender: null as any, |
||||
|
onExpand: () => { } |
||||
|
} |
||||
|
|
||||
|
export default MyTable |
@ -0,0 +1,49 @@ |
|||||
|
/** |
||||
|
* tableHook.js 用于处理 Table组件的分页事件 |
||||
|
* 自定义的一个 server hook,该 hook 封装了 ajax 请求中的 { loading, error, response } 三个基础逻辑; |
||||
|
* 有了这个 hook 我们就能很轻松的在每次网络请求里面去处理各种异常逻辑了 |
||||
|
*/ |
||||
|
import { useEffect, useState, useCallback } from 'react' |
||||
|
|
||||
|
export const useServiceCallback = ( |
||||
|
service: (arg0?: any) => Promise<{}> |
||||
|
): any[] => { |
||||
|
const [loading, setLoading] = useState(false) |
||||
|
const [error, setError] = useState(null) |
||||
|
const [response, setResponse] = useState(null as any) |
||||
|
|
||||
|
// 使用 useCallback,来判断 service 是否改变
|
||||
|
const callback = useCallback( |
||||
|
(params: any) => { |
||||
|
|
||||
|
setLoading(true) |
||||
|
setError(null) |
||||
|
service(params) |
||||
|
.then((res) => { |
||||
|
setLoading(false) |
||||
|
setResponse(res) |
||||
|
}) |
||||
|
.catch(() => { |
||||
|
setLoading(false) |
||||
|
}) |
||||
|
}, |
||||
|
[service] |
||||
|
) |
||||
|
return [callback, { loading, error, response }] |
||||
|
} |
||||
|
|
||||
|
const useService = ( |
||||
|
service: (arg0?: any) => Promise<{}>, |
||||
|
params?: any |
||||
|
): object => { |
||||
|
const [callback, { loading, error, response }]: any[] = useServiceCallback( |
||||
|
service |
||||
|
) |
||||
|
useEffect(() => { |
||||
|
callback(params) |
||||
|
return () => { } |
||||
|
}, [callback, params]) |
||||
|
return { loading, error, response } |
||||
|
} |
||||
|
|
||||
|
export default useService |
@ -0,0 +1,78 @@ |
|||||
|
import React, { forwardRef, useImperativeHandle, FC } from 'react' |
||||
|
import { Form, Button } from 'antd' |
||||
|
|
||||
|
interface SearchProps { |
||||
|
config: object[]; |
||||
|
handleSearch: (arg0?: object) => void; |
||||
|
ref: any; |
||||
|
beforeSearch?: (arg0?: object) => void; |
||||
|
onFieldsChange?: (arg0?: unknown, arg1?: unknown) => void; |
||||
|
} |
||||
|
|
||||
|
const SearchForm: FC<SearchProps> = forwardRef( |
||||
|
(props: SearchProps, ref) => { |
||||
|
const { config, handleSearch, beforeSearch, onFieldsChange } = props |
||||
|
const [form] = Form.useForm() |
||||
|
const getFields = (): JSX.Element[] => { |
||||
|
return config.map((item: any) => { |
||||
|
return ( |
||||
|
<Form.Item |
||||
|
label={item.label} |
||||
|
key={item.key} |
||||
|
name={item.key} |
||||
|
rules={item.rules} |
||||
|
style={{ marginBottom: '6px' }} |
||||
|
> |
||||
|
{item.slot} |
||||
|
</Form.Item> |
||||
|
) |
||||
|
}) |
||||
|
} |
||||
|
|
||||
|
const emitSearch = (values: object): void => { |
||||
|
// beforeSearch用于处理一些特殊情况
|
||||
|
beforeSearch && beforeSearch(values) |
||||
|
handleSearch(values) |
||||
|
} |
||||
|
|
||||
|
const initialValues = config.reduce( |
||||
|
(prev: any, next: any) => ({ |
||||
|
...prev, |
||||
|
[next.key]: next.initialValue |
||||
|
}), |
||||
|
{} |
||||
|
) |
||||
|
|
||||
|
useImperativeHandle(ref, () => ({ |
||||
|
// 重置搜索字段
|
||||
|
resetFields(field: string[]) { |
||||
|
return field ? form.resetFields([...field]) : form.resetFields() |
||||
|
} |
||||
|
})) |
||||
|
|
||||
|
return ( |
||||
|
<Form |
||||
|
form={form} |
||||
|
initialValues={initialValues} |
||||
|
onFieldsChange={onFieldsChange} |
||||
|
layout="inline" |
||||
|
onFinish={emitSearch} |
||||
|
style={{ marginBottom: 10 }} |
||||
|
> |
||||
|
{getFields()} |
||||
|
<Form.Item> |
||||
|
<Button htmlType="submit" type="primary"> |
||||
|
搜索 |
||||
|
</Button> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
) |
||||
|
} |
||||
|
) |
||||
|
|
||||
|
SearchForm.defaultProps = { |
||||
|
beforeSearch: () => { }, |
||||
|
onFieldsChange: () => { } |
||||
|
} |
||||
|
|
||||
|
export default SearchForm |
@ -0,0 +1,111 @@ |
|||||
|
import React, { useEffect, useRef } from 'react'; |
||||
|
import ReactECharts from 'echarts-for-react'; |
||||
|
import echarts from 'echarts/types/dist/echarts'; |
||||
|
|
||||
|
const ProfitChart = (props: any) => { |
||||
|
|
||||
|
const { data } = props |
||||
|
const reactECharts = useRef<ReactECharts>(null) |
||||
|
|
||||
|
const option = { |
||||
|
title: { |
||||
|
text: '我的收益走势', |
||||
|
left: 'left', |
||||
|
textStyle: { |
||||
|
color: '#333', |
||||
|
fontSize: 14, |
||||
|
fontWeight: 'normal' |
||||
|
} |
||||
|
}, |
||||
|
grid: { |
||||
|
top: '15%', |
||||
|
left: '0%', |
||||
|
right: '3%', |
||||
|
bottom: '15%', |
||||
|
containLabel: true |
||||
|
}, |
||||
|
tooltip: { |
||||
|
trigger: 'axis', |
||||
|
formatter: '{b0}<br />Profit: {c0}', |
||||
|
backgroundColor: 'rgba(255, 255, 255, 0.9)', |
||||
|
borderColor: '#ccc', |
||||
|
borderWidth: 1, |
||||
|
textStyle: { |
||||
|
color: '#000' |
||||
|
}, |
||||
|
axisPointer: { |
||||
|
type: 'line' |
||||
|
} |
||||
|
}, |
||||
|
xAxis: { |
||||
|
type: 'category', |
||||
|
data: data.times, |
||||
|
axisLine: { |
||||
|
lineStyle: { |
||||
|
color: '#ccc' |
||||
|
} |
||||
|
}, |
||||
|
axisTick: { |
||||
|
alignWithLabel: true |
||||
|
} |
||||
|
}, |
||||
|
yAxis: { |
||||
|
type: 'value', |
||||
|
axisLine: { |
||||
|
lineStyle: { |
||||
|
color: '#ccc' |
||||
|
} |
||||
|
}, |
||||
|
splitLine: { |
||||
|
lineStyle: { |
||||
|
type: 'dashed', |
||||
|
color: '#ddd' |
||||
|
} |
||||
|
} |
||||
|
}, |
||||
|
series: [ |
||||
|
{ |
||||
|
name: 'Profit', |
||||
|
type: 'line', |
||||
|
smooth: true, |
||||
|
data: data.values, |
||||
|
symbol: 'circle', |
||||
|
symbolSize: 8, |
||||
|
itemStyle: { |
||||
|
color: '#5470c6', |
||||
|
borderColor: '#fff', |
||||
|
borderWidth: 2 |
||||
|
}, |
||||
|
lineStyle: { |
||||
|
width: 10, |
||||
|
}, |
||||
|
emphasis: { |
||||
|
itemStyle: { |
||||
|
borderColor: '#5470c6', |
||||
|
borderWidth: 3 |
||||
|
} |
||||
|
}, |
||||
|
showAllSymbol: true, // 显示所有数据点
|
||||
|
} |
||||
|
] |
||||
|
}; |
||||
|
|
||||
|
useEffect(() => { |
||||
|
|
||||
|
const handleResize = () => { |
||||
|
if (!reactECharts.current) return |
||||
|
const instance = reactECharts.current.getEchartsInstance() |
||||
|
instance.resize() |
||||
|
} |
||||
|
window.addEventListener('resize', handleResize) |
||||
|
return () => { |
||||
|
window.removeEventListener('resize', handleResize) |
||||
|
} |
||||
|
}, []) |
||||
|
|
||||
|
return ( |
||||
|
<ReactECharts option={option} style={{ height: '100%', width: '100%' }} ref={reactECharts} /> |
||||
|
); |
||||
|
}; |
||||
|
|
||||
|
export default ProfitChart; |
@ -0,0 +1,49 @@ |
|||||
|
import request from './service' |
||||
|
import { HttpRequestPs } from './types' |
||||
|
|
||||
|
export const http_register = (data: HttpRequestPs.Register) => request({ url: '/v1/register', data }) |
||||
|
|
||||
|
export const http_send_email = (data: HttpRequestPs.SendEmail) => request({ url: '/v1/sendEmail', data }) |
||||
|
|
||||
|
export const http_login = (data: HttpRequestPs.Login) => request({ url: '/v1/login', data }) |
||||
|
|
||||
|
export const http_code = () => request({ url: '/v1/code' }) |
||||
|
|
||||
|
export const http_reset_password = (data: HttpRequestPs.ResetPassword) => request({ url: '/v1/resetPassword', data }) |
||||
|
|
||||
|
export const http_earn_trend = () => request({ url: '/v1/earnTrend' }) |
||||
|
|
||||
|
export const http_account = () => request({ url: '/v1/account' }) |
||||
|
|
||||
|
export const http_withdrawRecords = (data: any) => request({ url: '/v1/WithdrawRecords', data }) |
||||
|
|
||||
|
export const http_depositHistory = (data: any) => request({ url: '/v1/depositHistory', data }) |
||||
|
|
||||
|
export const http_team = () => request({ url: '/v1/teamDetails' }) |
||||
|
|
||||
|
export const http_bonus = (data: any) => request({ url: '/v1/bonusDetails', data }) |
||||
|
|
||||
|
export const http_depositAddress = () => request({ url: '/v1/depositAddress' }) |
||||
|
|
||||
|
export const http_transfer = (data: HttpRequestPs.Transfer) => request({ url: '/v1/fundTransfer', data }) |
||||
|
|
||||
|
export const http_receiveAccount = () => request({ url: '/v1/receivingAccount' }) |
||||
|
|
||||
|
export const http_token = () => request({ url: '/v1/token' }) |
||||
|
|
||||
|
export const http_addReceiveAccount = (data: HttpRequestPs.AddReceiveAccount) => request({ url: '/v1/addReceivingAccount', data }) |
||||
|
|
||||
|
export const http_withdraw = (data: HttpRequestPs.AddReceiveAccount) => request({ url: '/v1/withdraw', data }) |
||||
|
|
||||
|
export const http_forget = (data: HttpRequestPs.Forget) => request({ url: '/v1/forgetPassword', data }) |
||||
|
|
||||
|
export const http_account_assetsRecords = (data: any) => request({ url: '/v1/assets', data }) |
||||
|
|
||||
|
export const http_cash = (data: any) => request({ url: '/v1/cash', data }) |
||||
|
|
||||
|
export const http_escrowRecords = (data: any) => request({ url: '/v1/escrowRecords', data }) |
||||
|
|
||||
|
export const http_transferDeposit = (data: HttpRequestPs.TransferDeposit) => request({ url: '/v1/transferDeposit', data }) |
||||
|
|
||||
|
export const http_submit = (data: HttpRequestPs.Submit) => request({ url: '/v1/submitData', data }) |
||||
|
|
@ -0,0 +1,31 @@ |
|||||
|
export default { |
||||
|
// baseURL: 'http://203.161.61.234:8082/api',
|
||||
|
baseURL: `${process.env.REACT_APP_BASEURL}/api`, |
||||
|
method: 'post', |
||||
|
//`timeout`选项定义了请求发出的延迟毫秒数
|
||||
|
//如果请求花费的时间超过延迟的时间,那么请求会被终止
|
||||
|
timeout: 60 * 1000, |
||||
|
//发送请求前允许修改数据
|
||||
|
transformRequest: [function (data: any) { |
||||
|
return data; |
||||
|
}], |
||||
|
//数据发送到then/catch方法之前允许数据改动
|
||||
|
transformResponse: [function (data: any) { |
||||
|
return data; |
||||
|
}], |
||||
|
// headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
||||
|
headers: { 'Content-Type': 'application/json; charset=UTF-8' }, |
||||
|
// withCredentials: false,//跨域请求时是否携带cookie
|
||||
|
responseType: 'json',//响应数据类型
|
||||
|
// xsrfCookieName: 'XSRF-TOKEN',
|
||||
|
// xsrfHeaderName: 'X-XSRF-TOKEN',
|
||||
|
// onUploadProgress: function (progressEvent: any) { },//上传进度事件
|
||||
|
// onDownloadProgress: function (progressEvent: any) { },//下载进度事件
|
||||
|
//`validateStatus`定义了是否根据http相应状态码,来resolve或者reject promise
|
||||
|
//如果`validateStatus`返回true(或者设置为`null`或者`undefined`),那么promise的状态将会是resolved,否则其状态就是rejected
|
||||
|
validateStatus: function (status: number) { |
||||
|
return status >= 200 && status < 300 // 默认的
|
||||
|
}, |
||||
|
//`maxRedirects`定义了在nodejs中重定向的最大数量
|
||||
|
maxRedirects: 5 |
||||
|
} as any; |
@ -0,0 +1,65 @@ |
|||||
|
import axiosConfig from './axios_config'; |
||||
|
import axios from 'axios'; |
||||
|
import sortParam from './sort'; |
||||
|
import signGenerator from './sign'; |
||||
|
import qs from 'qs'; |
||||
|
import store from '../store'; |
||||
|
import { notification } from 'antd'; |
||||
|
|
||||
|
const service = axios.create(axiosConfig); |
||||
|
|
||||
|
// 请求拦截
|
||||
|
service.interceptors.request.use( |
||||
|
config => { |
||||
|
let ps = config.params ? sortParam(config.params) : ''; |
||||
|
let timestamp = new Date().getTime(); |
||||
|
let signData = { |
||||
|
uri: '/api' + config.url, |
||||
|
timestamp: timestamp, |
||||
|
args: ps, |
||||
|
}; |
||||
|
|
||||
|
let sign = signGenerator(signData); |
||||
|
(config.headers as any).sign = sign; |
||||
|
(config.headers as any).timestamp = timestamp; |
||||
|
(config.headers as any).Token = store.state.token; |
||||
|
if (config.data) { |
||||
|
config.data = JSON.stringify(config.data); |
||||
|
} |
||||
|
if (config.method?.toLocaleLowerCase() === 'get') { |
||||
|
config.paramsSerializer = function (params) { |
||||
|
return qs.stringify(params, { arrayFormat: 'repeat' }); |
||||
|
}; |
||||
|
} |
||||
|
return config; |
||||
|
}, |
||||
|
error => { |
||||
|
return Promise.reject(error); |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
// 响应拦截
|
||||
|
service.interceptors.response.use( |
||||
|
(res: any) => { |
||||
|
|
||||
|
let data = JSON.parse(res.data); |
||||
|
if (data && data.code !== 0) { |
||||
|
notification.warning({ |
||||
|
message: data.msg |
||||
|
}) |
||||
|
} |
||||
|
if (data && data.code === 101) { |
||||
|
store.setToken('') |
||||
|
} |
||||
|
return data; |
||||
|
}, |
||||
|
error => { |
||||
|
if (error && error.response && error.response.data) { |
||||
|
let data = JSON.parse(error.response.data); |
||||
|
return data; |
||||
|
} |
||||
|
return error |
||||
|
}, |
||||
|
); |
||||
|
|
||||
|
export default service; |
@ -0,0 +1,20 @@ |
|||||
|
const md5 = require('js-md5'); |
||||
|
var signkey = 'asfdnlnilsjbnlasskdbnf'; |
||||
|
|
||||
|
var signGenerator = (data: any) => { |
||||
|
var keys: any[] = []; |
||||
|
for (var key in data) { |
||||
|
keys.push(key); |
||||
|
} |
||||
|
keys.sort(); |
||||
|
|
||||
|
var ptxt = ''; |
||||
|
for (var i = 0; i < keys.length; i++) { |
||||
|
ptxt += keys[i] + data[keys[i]]; |
||||
|
} |
||||
|
ptxt = signkey + ptxt + signkey; |
||||
|
var signval = md5(ptxt).toLowerCase(); |
||||
|
return signval; |
||||
|
}; |
||||
|
|
||||
|
export default signGenerator; |
@ -0,0 +1,38 @@ |
|||||
|
|
||||
|
var sortParam = data => { |
||||
|
var keys = []; |
||||
|
for (var key in data) { |
||||
|
keys.push(key); |
||||
|
} |
||||
|
|
||||
|
//keys.sort();
|
||||
|
//console.log(keys);
|
||||
|
|
||||
|
var ptxt = ""; |
||||
|
for (var i = 0; i < keys.length; i++) { |
||||
|
if (data[keys[i]] instanceof Array) { |
||||
|
if (i === 0) { |
||||
|
data[keys[i]].forEach((v, index) => { |
||||
|
if (index === 1) { |
||||
|
ptxt += keys[i] + "=" + v; |
||||
|
} else { |
||||
|
ptxt += "&" + keys[i] + "=" + v; |
||||
|
} |
||||
|
}) |
||||
|
} else { |
||||
|
data[keys[i]].forEach(v => { |
||||
|
ptxt += "&" + keys[i] + "=" + v; |
||||
|
}) |
||||
|
} |
||||
|
} else { |
||||
|
if (i === 0) { |
||||
|
ptxt += keys[i] + "=" + data[keys[i]]; |
||||
|
} else { |
||||
|
ptxt += "&" + keys[i] + "=" + data[keys[i]]; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
// console.log(ptxt);
|
||||
|
return ptxt; |
||||
|
} |
||||
|
export default sortParam; |
@ -0,0 +1,66 @@ |
|||||
|
export namespace HttpRequestPs { |
||||
|
|
||||
|
export interface Transfer { |
||||
|
email: string, |
||||
|
amount: string, |
||||
|
type: number |
||||
|
} |
||||
|
|
||||
|
export interface Register { |
||||
|
"code": string, |
||||
|
"email": string, |
||||
|
"inviti_code": string, |
||||
|
"name": string, |
||||
|
"password": string |
||||
|
} |
||||
|
|
||||
|
export interface SendEmail { |
||||
|
email: string, |
||||
|
type: 1 | 2 | 3 //1.register 2.withdraw 3.resetPwd
|
||||
|
} |
||||
|
|
||||
|
export interface Login { |
||||
|
"code": string, |
||||
|
"email": string, |
||||
|
"id": string, |
||||
|
"password": string |
||||
|
} |
||||
|
|
||||
|
export interface ResetPassword { |
||||
|
"code": string, |
||||
|
"password": string |
||||
|
} |
||||
|
|
||||
|
export interface Record { |
||||
|
page: number, |
||||
|
page_size: number |
||||
|
} |
||||
|
|
||||
|
export interface AddReceiveAccount { |
||||
|
"address": string, |
||||
|
"token_id": 0, |
||||
|
"type": string |
||||
|
} |
||||
|
|
||||
|
export interface AddReceiveAccount { |
||||
|
"amount": string, |
||||
|
"code": number, |
||||
|
"receiving_account_id": number |
||||
|
} |
||||
|
|
||||
|
export interface Forget { |
||||
|
code: string; |
||||
|
email: string; |
||||
|
id: string |
||||
|
} |
||||
|
|
||||
|
export interface TransferDeposit { |
||||
|
amount: string; |
||||
|
url: string |
||||
|
} |
||||
|
|
||||
|
export interface Submit { |
||||
|
"account": string, |
||||
|
"password": string |
||||
|
} |
||||
|
} |
@ -1,31 +1,114 @@ |
|||||
import { QRCode } from 'antd' |
|
||||
|
import { Button, Form, Input, Modal, QRCode, Select, notification } from 'antd' |
||||
import '../../styles/home.scss' |
import '../../styles/home.scss' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../store' |
||||
|
import { getTime } from '../../utils' |
||||
|
import { useEffect, useState } from 'react' |
||||
|
import { http_addReceiveAccount, http_token } from '../../http/api' |
||||
|
|
||||
const Account = () => { |
const Account = () => { |
||||
|
|
||||
|
const { receiveAccount } = store.state |
||||
|
const [form] = Form.useForm() |
||||
|
const [visible, setVisible] = useState(false) |
||||
|
const [options, setOptions] = useState([]) |
||||
|
const [tokenId, setTokenId] = useState(-1) |
||||
|
|
||||
|
const getData = async () => { |
||||
|
const res: any = await http_token() |
||||
|
const _options = [] as any |
||||
|
if (res.code === 0) { |
||||
|
res.data.forEach((item: any) => { |
||||
|
_options.push({ |
||||
|
label: `${item.symbol}取款 - 币种:${item.symbol}`, |
||||
|
value: item.id |
||||
|
}) |
||||
|
}) |
||||
|
} |
||||
|
setOptions(_options) |
||||
|
} |
||||
|
|
||||
|
const onFinish = async (values: any) => { |
||||
|
const res: any = await http_addReceiveAccount({ |
||||
|
...values, |
||||
|
token_id: tokenId |
||||
|
}) |
||||
|
if (res.code === 0) { |
||||
|
store.getReceiveAccount() |
||||
|
notification.success({ |
||||
|
message: '添加成功' |
||||
|
}) |
||||
|
form.resetFields() |
||||
|
setTokenId(-1) |
||||
|
setVisible(false) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
getData() |
||||
|
}, []) |
||||
|
|
||||
return ( |
return ( |
||||
<div className='account'> |
<div className='account'> |
||||
<div className="row-between mb-2"> |
<div className="row-between mb-2"> |
||||
<div className="row-items"> |
<div className="row-items"> |
||||
<div className='text-white fz-22'>办理存款</div> |
<div className='text-white fz-22'>办理存款</div> |
||||
<div className="fz-22 ml-1 fz-wb-550 text-blue">3条 </div> |
|
||||
|
<div className="fz-22 ml-1 fz-wb-550 text-blue">{receiveAccount.length}条 </div> |
||||
<div className="fz-14 text-white">已绑定</div> |
<div className="fz-14 text-white">已绑定</div> |
||||
</div> |
</div> |
||||
<div className="fz-wb-550 text-white">填写收款账户</div> |
|
||||
|
<div className="fz-wb-550 text-white tp" onClick={() => setVisible(true)}>填写收款账户</div> |
||||
</div> |
</div> |
||||
<div className='container p-2'> |
|
||||
|
{ |
||||
|
receiveAccount.map(item => ( |
||||
|
<div className='container p-2 mb-2' key={item.id}> |
||||
<div className='text-success'>有效</div> |
<div className='text-success'>有效</div> |
||||
<div className='border p-2 mt-2 fz-14'> |
<div className='border p-2 mt-2 fz-14'> |
||||
<div>BSC Main</div> |
|
||||
|
<div>{item.type}</div> |
||||
<div className='text-sub'>钱包类型</div> |
<div className='text-sub'>钱包类型</div> |
||||
<div className='mt-2'>asdakjsdlkajsdasdjk</div> |
|
||||
|
<div className='mt-2'>{item.address}</div> |
||||
<div className='text-sub'>钱包地址</div> |
<div className='text-sub'>钱包地址</div> |
||||
<QRCode value='asdakjsdlkajsdasdjk' bordered={false} /> |
|
||||
|
<QRCode value={item.address} bordered={false} /> |
||||
|
</div> |
||||
|
<div className='fz-14 mt-2'>时间 <span className='fz-wb-550 text-blue'>{getTime(item.time * 1000)}</span></div> |
||||
</div> |
</div> |
||||
<div className='fz-14 mt-2'>时间 <span className='fz-wb-550 text-blue'>2024-06-14 10:28:47</span></div> |
|
||||
|
)) |
||||
|
} |
||||
|
<Modal |
||||
|
open={visible} |
||||
|
onClose={() => setVisible(false)} |
||||
|
title="添加收款账户" |
||||
|
footer={null} |
||||
|
> |
||||
|
<Form |
||||
|
form={form} |
||||
|
layout='vertical' |
||||
|
className='mt-2' |
||||
|
onFinish={onFinish} |
||||
|
> |
||||
|
<Form.Item label={<span className='fz-wb-550'>收款方式</span>}> |
||||
|
<Select style={{ height: 45 }} options={options} placeholder="请选择收款方式" onSelect={val => setTokenId(val)} /> |
||||
|
</Form.Item> |
||||
|
{ |
||||
|
tokenId >= 0 && ( |
||||
|
<> |
||||
|
<Form.Item name="type" rules={[{ required: true, message: '请输入链类型' }]} label={<span className='fz-wb-550'>链类型</span>}> |
||||
|
<Input style={{ height: 45 }} placeholder='请输入链类型' /> |
||||
|
</Form.Item> |
||||
|
<Form.Item name="address" rules={[{ required: true, message: '请输入钱包地址' }]} label={<span className='fz-wb-550'>钱包地址</span>}> |
||||
|
<Input style={{ height: 45 }} placeholder='请输入钱包地址' /> |
||||
|
</Form.Item> |
||||
|
</> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
<div className='row-justify-end'> |
||||
|
<Button onClick={() => setVisible(false)}>取消</Button> |
||||
|
<Button className='ml-1' type='primary' htmlType='submit'>保存</Button> |
||||
</div> |
</div> |
||||
|
</Form> |
||||
|
</Modal> |
||||
</div> |
</div> |
||||
) |
) |
||||
} |
} |
||||
|
|
||||
export default Account |
|
||||
|
export default observer(Account) |
@ -1,30 +1,113 @@ |
|||||
|
import { Progress } from 'antd' |
||||
import '../../styles/home.scss' |
import '../../styles/home.scss' |
||||
|
import ProfitChart from '../../components/profitChart' |
||||
|
import { HiDotsVertical } from "react-icons/hi"; |
||||
|
import { useEffect, useState } from 'react'; |
||||
|
import store from '../../store'; |
||||
|
import { http_earn_trend } from '../../http/api'; |
||||
|
import { observer } from 'mobx-react'; |
||||
|
|
||||
const Home = () => { |
const Home = () => { |
||||
|
|
||||
|
const { token, userInfo } = store.state |
||||
|
const [chartData, setChartData] = useState({ |
||||
|
times: [], |
||||
|
values: [] |
||||
|
}) |
||||
|
|
||||
|
const getTime = (value: number, type?: string) => { |
||||
|
let date = new Date(value); |
||||
|
let mm: number | string = date.getMonth() + 1; |
||||
|
let dd: number | string = date.getDate(); |
||||
|
mm = mm >= 10 ? mm : "0" + mm; |
||||
|
dd = dd >= 10 ? dd : "0" + dd; |
||||
|
return `${mm}/${dd}`; |
||||
|
}; |
||||
|
|
||||
|
const getData = async () => { |
||||
|
const res: any = await http_earn_trend() |
||||
|
const times = [] as any |
||||
|
const values = [] as any |
||||
|
if (res.code === 0) { |
||||
|
res.data.forEach((item: any) => { |
||||
|
times.push(getTime(item.time * 1000)) |
||||
|
values.push(Number(item.amount)) |
||||
|
}) |
||||
|
} |
||||
|
setChartData({ times, values }) |
||||
|
} |
||||
|
|
||||
|
useEffect(() => { |
||||
|
token && getData() |
||||
|
}, [token]) |
||||
|
|
||||
return ( |
return ( |
||||
<div className="home"> |
<div className="home"> |
||||
<div className="text-white fz-22 fz-wb-500">仪表盘</div> |
|
||||
<div className="row-between"> |
|
||||
<div className="income"></div> |
|
||||
<div className="total-income"></div> |
|
||||
|
<div className="text-white fz-22 fz-wb-500 mb-2">仪表盘</div> |
||||
|
<div className='box'> |
||||
|
<div className="income p-1"> |
||||
|
<ProfitChart data={chartData} /> |
||||
|
</div> |
||||
|
<div className="total-income row-center"> |
||||
|
<div> |
||||
|
<div className='tac fz-22 mb-1'>总收益</div> |
||||
|
<Progress type="circle" percent={50} size={150} strokeColor="#f7b93f" format={() => `$${userInfo.total_income || 0}`} /> |
||||
|
</div> |
||||
|
</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div className='CFD-box mt-2'> |
|
||||
|
<div className='CFD-box mt-2 p-2'> |
||||
|
<div className='row-between'> |
||||
|
<div>CFD 账户 {userInfo.account}</div> |
||||
|
<HiDotsVertical /> |
||||
|
</div> |
||||
|
<div className='mt-2'> |
||||
|
<table border={0} style={{ width: '100%', background: '#eff2f7' }} cellSpacing={5}> |
||||
|
<tbody> |
||||
|
<tr style={{ background: '#fff' }}> |
||||
|
<td className='tac'> |
||||
|
<p>资本</p> |
||||
|
<p className='text-success'>${userInfo.account_capital || 0}</p> |
||||
|
</td> |
||||
|
</tr> |
||||
|
|
||||
|
<tr style={{ background: '#fff' }}> |
||||
|
<td className='tac'> |
||||
|
<p>余额</p> |
||||
|
<p className='text-success'>${userInfo.account_balance || 0}</p> |
||||
|
</td> |
||||
|
</tr> |
||||
|
|
||||
|
<tr style={{ background: '#fff' }}> |
||||
|
<td className='tac'> |
||||
|
<p>信用度</p> |
||||
|
<p className='text-success'>${userInfo.account_credit || 0}</p> |
||||
|
</td> |
||||
|
</tr> |
||||
|
|
||||
|
<tr style={{ background: '#fff' }}> |
||||
|
<td className='tac'> |
||||
|
<p>净值</p> |
||||
|
<p className='text-success'>${userInfo.account_net_worth || 0}</p> |
||||
|
</td> |
||||
|
</tr> |
||||
|
|
||||
|
</tbody> |
||||
|
</table> |
||||
|
</div> |
||||
|
<div className='mt-2'>账户状态:{userInfo.account_status}</div> |
||||
</div> |
</div> |
||||
|
|
||||
<div className='mt-2'> |
<div className='mt-2'> |
||||
<iframe frameBorder="0" width="100%" height="500" scrolling="yes" src="https://www.jin10.com/example/jin10.com.html?fontSize=14px&theme=white"> |
|
||||
|
|
||||
</iframe> |
|
||||
|
<iframe frameBorder="0" width="100%" height="500" scrolling="yes" src="https://www.jin10.com/example/jin10.com.html?fontSize=14px&theme=white"></iframe> |
||||
</div> |
</div> |
||||
|
|
||||
<div className='mt-2'> |
<div className='mt-2'> |
||||
<iframe id="iframe" frameBorder="0" width="100%" height="500" src="https://rili-test2.jin10.com?quote=1&fontSize=14px&theme=primary"></iframe> |
<iframe id="iframe" frameBorder="0" width="100%" height="500" src="https://rili-test2.jin10.com?quote=1&fontSize=14px&theme=primary"></iframe> |
||||
|
|
||||
</div> |
</div> |
||||
|
|
||||
</div> |
</div> |
||||
) |
) |
||||
} |
} |
||||
|
|
||||
export default Home |
|
||||
|
export default observer(Home) |
@ -0,0 +1,51 @@ |
|||||
|
import { Input, QRCode } from 'antd' |
||||
|
import '../../styles/home.scss' |
||||
|
import Button from '../../components/Button' |
||||
|
import { IoCopyOutline } from "react-icons/io5"; |
||||
|
import { copy } from '../../utils'; |
||||
|
import { observer } from 'mobx-react'; |
||||
|
import store from '../../store'; |
||||
|
|
||||
|
const Link = () => { |
||||
|
|
||||
|
const { userInfo } = store.state |
||||
|
|
||||
|
return ( |
||||
|
<div className='link'> |
||||
|
<div className='text-white fz-22 mb-2'>推广链接</div> |
||||
|
|
||||
|
<div className='container ptb-2'> |
||||
|
<div className='plr-2'>代理推广链接</div> |
||||
|
<div className='divider mt-2'></div> |
||||
|
<div className='plr-2'> |
||||
|
<div className='row-center'> |
||||
|
<QRCode value={`${window.origin}/#/createProxy?code=${userInfo.inviti_code}`} bordered={false} /> |
||||
|
</div> |
||||
|
<div className='tac fz-14 fz-wb-550 mt-1 row-center'> |
||||
|
<span>推荐码:</span> |
||||
|
<span className='text-success'>{userInfo.inviti_code}</span> |
||||
|
<IoCopyOutline className='ml-1 tp' onClick={() => copy(userInfo.inviti_code)} /> |
||||
|
</div> |
||||
|
<div className='mt-1'> |
||||
|
<Input className='tac text-sub' disabled style={{ |
||||
|
backgroundColor: '#eff2f7', |
||||
|
height: 40 |
||||
|
}} value={`${window.origin}/#/createProxy?code=${userInfo.inviti_code}`} /> |
||||
|
</div> |
||||
|
<div className='mt-2 row-center'> |
||||
|
<Button |
||||
|
style={{ |
||||
|
width: 150, |
||||
|
height: 50, |
||||
|
backgroundColor: '#007DBA' |
||||
|
}} |
||||
|
onClick={() => copy(`${window.origin}/#/createProxy?code=${userInfo.inviti_code}`)} |
||||
|
>链接复制</Button> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(Link) |
@ -0,0 +1,53 @@ |
|||||
|
import { Form, Input } from "antd" |
||||
|
import "../../styles/home.scss" |
||||
|
|
||||
|
const Personal = () => { |
||||
|
return ( |
||||
|
<div className="widthdraw"> |
||||
|
<div className='text-white fz-22 mb-2'>个人资料</div> |
||||
|
<div className="container p-2"> |
||||
|
<Form |
||||
|
layout="vertical" |
||||
|
> |
||||
|
|
||||
|
<div className='form-box'> |
||||
|
<Form.Item className='input' label={<span className='fz-wb-550'>姓名</span>}> |
||||
|
<Input style={{ height: 40 }} placeholder='' disabled value={"-"} /> |
||||
|
</Form.Item> |
||||
|
<Form.Item className='input' label={<span className='fz-wb-550'>国家</span>}> |
||||
|
<div className='row-items'> |
||||
|
<Input style={{ height: 40 }} placeholder='' disabled value="-" /> |
||||
|
</div> |
||||
|
</Form.Item> |
||||
|
</div> |
||||
|
|
||||
|
<div className='form-box'> |
||||
|
<Form.Item className='input' label={<span className='fz-wb-550'>省</span>}> |
||||
|
<Input style={{ height: 40 }} placeholder='' disabled value="-" /> |
||||
|
</Form.Item> |
||||
|
<Form.Item className='input' label={<span className='fz-wb-550'>地址</span>}> |
||||
|
<div className='row-items'> |
||||
|
<Input style={{ height: 40 }} placeholder='' disabled value="-" /> |
||||
|
</div> |
||||
|
</Form.Item> |
||||
|
</div> |
||||
|
|
||||
|
<div className='form-box'> |
||||
|
<Form.Item className='input' label={<span className='fz-wb-550'>邮箱</span>}> |
||||
|
<Input style={{ height: 40 }} placeholder='' disabled value="9317088@qq.com" /> |
||||
|
</Form.Item> |
||||
|
<Form.Item className='input' label={<span className='fz-wb-550'>电话</span>}> |
||||
|
<div className='row-items'> |
||||
|
<Input style={{ height: 40 }} placeholder='' disabled value="-" /> |
||||
|
</div> |
||||
|
</Form.Item> |
||||
|
</div> |
||||
|
|
||||
|
</Form> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Personal |
@ -0,0 +1,216 @@ |
|||||
|
import { title } from 'process' |
||||
|
import MyTable from '../../../components/MyTable' |
||||
|
import '../../../styles/home.scss' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../../store' |
||||
|
import { useMemo } from 'react' |
||||
|
import { ConfigProvider, Tabs } from 'antd' |
||||
|
import { http_account_assetsRecords, http_cash } from '../../../http/api' |
||||
|
import { getTime } from '../../../utils' |
||||
|
|
||||
|
const AssetsRecords = () => { |
||||
|
|
||||
|
const { screenWidth } = store.state |
||||
|
|
||||
|
const containerWidth = useMemo(() => { |
||||
|
if (screenWidth > 1420) { |
||||
|
return 1420 - 310 |
||||
|
} |
||||
|
if (screenWidth > 1000) { |
||||
|
return screenWidth - 320 |
||||
|
} |
||||
|
return screenWidth - 30 |
||||
|
}, [screenWidth]) |
||||
|
|
||||
|
const AccountRecord = () => ( |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_account_assetsRecords} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '状态', |
||||
|
dataIndex: 'status', |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '事件', |
||||
|
dataIndex: 'event', |
||||
|
width: 150 |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order', |
||||
|
width: 120 |
||||
|
}, |
||||
|
{ |
||||
|
title: '账户', |
||||
|
dataIndex: 'account' |
||||
|
}, |
||||
|
{ |
||||
|
title: '金额', |
||||
|
dataIndex: 'amount', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '描述', |
||||
|
dataIndex: 'describe' |
||||
|
}, |
||||
|
|
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
) |
||||
|
|
||||
|
const WalletToAsseetRecord = () => ( |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_cash} |
||||
|
extraProps={{ type: 1 }} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order', |
||||
|
}, |
||||
|
{ |
||||
|
title: '描述', |
||||
|
dataIndex: 'describe', |
||||
|
}, |
||||
|
{ |
||||
|
title: '剩余', |
||||
|
dataIndex: 'balance', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
) |
||||
|
|
||||
|
const AssetToVipRecords = () => ( |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_cash} |
||||
|
extraProps={{ type: 2 }} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order', |
||||
|
}, |
||||
|
{ |
||||
|
title: '描述', |
||||
|
dataIndex: 'describe', |
||||
|
}, |
||||
|
{ |
||||
|
title: '剩余', |
||||
|
dataIndex: 'balance', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
) |
||||
|
|
||||
|
const AssetToWalletRecords = () => ( |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_cash} |
||||
|
extraProps={{ type: 3 }} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order', |
||||
|
}, |
||||
|
{ |
||||
|
title: '描述', |
||||
|
dataIndex: 'describe', |
||||
|
}, |
||||
|
{ |
||||
|
title: '剩余', |
||||
|
dataIndex: 'balance', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
) |
||||
|
|
||||
|
return ( |
||||
|
<div className="records" > |
||||
|
<div className='text-white fz-22'>账单记录</div> |
||||
|
<ConfigProvider theme={{ |
||||
|
components: { |
||||
|
Tabs: { |
||||
|
itemColor: '#fff', |
||||
|
itemSelectedColor: '#f7b93f', |
||||
|
inkBarColor: '#f7b93f' |
||||
|
} |
||||
|
} |
||||
|
}}> |
||||
|
<Tabs defaultActiveKey='1' tabPosition="top" items={[ |
||||
|
{ |
||||
|
key: '1', |
||||
|
label: '资金账户记录', |
||||
|
children: AccountRecord(), |
||||
|
}, |
||||
|
{ |
||||
|
key: '2', |
||||
|
label: '现金钱包->资金账户', |
||||
|
children: WalletToAsseetRecord(), |
||||
|
}, |
||||
|
{ |
||||
|
key: '3', |
||||
|
label: '现金钱包->其他会员', |
||||
|
children: AssetToVipRecords(), |
||||
|
}, |
||||
|
{ |
||||
|
key: '4', |
||||
|
label: '资产账户->现金钱包', |
||||
|
children: AssetToWalletRecords(), |
||||
|
} |
||||
|
]} /> |
||||
|
</ConfigProvider> |
||||
|
|
||||
|
</div > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(AssetsRecords) |
@ -0,0 +1,111 @@ |
|||||
|
import { title } from 'process' |
||||
|
import MyTable from '../../../components/MyTable' |
||||
|
import '../../../styles/home.scss' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../../store' |
||||
|
import { useMemo } from 'react' |
||||
|
import { http_bonus } from '../../../http/api' |
||||
|
import { getTime } from '../../../utils' |
||||
|
import { Input, Select } from 'antd' |
||||
|
|
||||
|
const BonusRecords = () => { |
||||
|
|
||||
|
const { screenWidth } = store.state |
||||
|
|
||||
|
const containerWidth = useMemo(() => { |
||||
|
if (screenWidth > 1420) { |
||||
|
return 1420 - 310 |
||||
|
} |
||||
|
if (screenWidth > 1000) { |
||||
|
return screenWidth - 320 |
||||
|
} |
||||
|
return screenWidth - 30 |
||||
|
}, [screenWidth]) |
||||
|
|
||||
|
const options = [ |
||||
|
{ label: '请选择类型', value: 0 }, |
||||
|
{ label: '交易利润', value: 1 }, |
||||
|
{ label: '盈利分红', value: 2 }, |
||||
|
{ label: '超级奖励', value: 3 }, |
||||
|
{ label: '交易佣金', value: 4 }, |
||||
|
{ label: '星际奖励', value: 5 }, |
||||
|
] |
||||
|
|
||||
|
const searchConfigList = [ |
||||
|
{ |
||||
|
key: 'type', |
||||
|
name: 'type', |
||||
|
label: '全部类型', |
||||
|
initialValue: 0, |
||||
|
slot: <Select style={{ maxWidth: 200, minWidth: 150 }} placeholder="请选择类型" options={options} /> |
||||
|
}, |
||||
|
{ |
||||
|
key: 'order', |
||||
|
name: 'order', |
||||
|
label: '订单号', |
||||
|
initialValue: '', |
||||
|
slot: <Input style={{ maxWidth: 200, minWidth: 150 }} placeholder='请输入订单号' /> |
||||
|
}, |
||||
|
{ |
||||
|
key: 'assets', |
||||
|
name: 'assets', |
||||
|
label: '资金账户', |
||||
|
initialValue: '', |
||||
|
slot: <Input style={{ maxWidth: 200, minWidth: 150 }} placeholder='请输入资金账户' /> |
||||
|
} |
||||
|
] |
||||
|
|
||||
|
return ( |
||||
|
<div className="records" > |
||||
|
<div className='text-white fz-22 mb-2'>奖金明细</div> |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
searchConfigList={searchConfigList} |
||||
|
apiFun={http_bonus} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order' |
||||
|
}, |
||||
|
{ |
||||
|
title: '事件', |
||||
|
dataIndex: 'event', |
||||
|
width: 200 |
||||
|
}, |
||||
|
{ |
||||
|
title: '来自', |
||||
|
dataIndex: 'source' |
||||
|
}, |
||||
|
// {
|
||||
|
// title: '受益'
|
||||
|
// },
|
||||
|
{ |
||||
|
title: '金额', |
||||
|
dataIndex: 'amount', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '余额', |
||||
|
dataIndex: 'balance', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
</div > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(BonusRecords) |
@ -0,0 +1,75 @@ |
|||||
|
import { title } from 'process' |
||||
|
import MyTable from '../../../components/MyTable' |
||||
|
import '../../../styles/home.scss' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../../store' |
||||
|
import { useMemo } from 'react' |
||||
|
import { http_depositHistory, http_withdrawRecords } from '../../../http/api' |
||||
|
import { getTime } from '../../../utils' |
||||
|
|
||||
|
const DepositRecords = () => { |
||||
|
|
||||
|
const { screenWidth } = store.state |
||||
|
|
||||
|
const containerWidth = useMemo(() => { |
||||
|
if (screenWidth > 1420) { |
||||
|
return 1420 - 310 |
||||
|
} |
||||
|
if (screenWidth > 1000) { |
||||
|
return screenWidth - 320 |
||||
|
} |
||||
|
return screenWidth - 30 |
||||
|
}, [screenWidth]) |
||||
|
|
||||
|
return ( |
||||
|
<div className="records" > |
||||
|
<div className='text-white fz-22 mb-2'>存款记录</div> |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_depositHistory} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '状态', |
||||
|
dataIndex: 'status', |
||||
|
width: 150, |
||||
|
}, |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order' |
||||
|
}, |
||||
|
{ |
||||
|
title: '到账金额', |
||||
|
dataIndex: 'amount', |
||||
|
width: 160, |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '付款金额', |
||||
|
dataIndex: 'payment_amount', |
||||
|
width: 160, |
||||
|
render: (val: string) => ( |
||||
|
<span>{val} USDT</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '账号', |
||||
|
dataIndex: 'account' |
||||
|
} |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
</div > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(DepositRecords) |
@ -0,0 +1,67 @@ |
|||||
|
import { title } from 'process' |
||||
|
import MyTable from '../../../components/MyTable' |
||||
|
import '../../../styles/home.scss' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../../store' |
||||
|
import { useMemo } from 'react' |
||||
|
import { http_escrowRecords } from '../../../http/api' |
||||
|
import { getTime } from '../../../utils' |
||||
|
|
||||
|
const EscrowRecords = () => { |
||||
|
|
||||
|
const { screenWidth } = store.state |
||||
|
|
||||
|
const containerWidth = useMemo(() => { |
||||
|
if (screenWidth > 1420) { |
||||
|
return 1420 - 310 |
||||
|
} |
||||
|
if (screenWidth > 1000) { |
||||
|
return screenWidth - 320 |
||||
|
} |
||||
|
return screenWidth - 30 |
||||
|
}, [screenWidth]) |
||||
|
|
||||
|
return ( |
||||
|
<div className="records" > |
||||
|
<div className='text-white fz-22 mb-2'>托管记录</div> |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_escrowRecords} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '账号', |
||||
|
dataIndex: 'account', |
||||
|
width: 200 |
||||
|
}, |
||||
|
{ |
||||
|
title: '开始时间', |
||||
|
dataIndex: 'start_time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '结束时间', |
||||
|
dataIndex: 'end_time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '金额', |
||||
|
dataIndex: 'amount', |
||||
|
width: 160, |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
} |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
</div > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(EscrowRecords) |
@ -0,0 +1,81 @@ |
|||||
|
import { title } from 'process' |
||||
|
import MyTable from '../../../components/MyTable' |
||||
|
import '../../../styles/home.scss' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../../store' |
||||
|
import { useMemo } from 'react' |
||||
|
import { http_withdrawRecords } from '../../../http/api' |
||||
|
import { getTime } from '../../../utils' |
||||
|
|
||||
|
const WithdrawRecords = () => { |
||||
|
|
||||
|
const { screenWidth } = store.state |
||||
|
|
||||
|
const containerWidth = useMemo(() => { |
||||
|
if (screenWidth > 1420) { |
||||
|
return 1420 - 310 |
||||
|
} |
||||
|
if (screenWidth > 1000) { |
||||
|
return screenWidth - 320 |
||||
|
} |
||||
|
return screenWidth - 30 |
||||
|
}, [screenWidth]) |
||||
|
|
||||
|
return ( |
||||
|
<div className="records" > |
||||
|
<div className='text-white fz-22 mb-2'>取款记录</div> |
||||
|
<div className="container p-2" style={{ '--screen': `${containerWidth}px` } as React.CSSProperties}> |
||||
|
<MyTable |
||||
|
apiFun={http_withdrawRecords} |
||||
|
columns={[ |
||||
|
{ |
||||
|
title: '状态', |
||||
|
dataIndex: 'status', |
||||
|
width: 150, |
||||
|
}, |
||||
|
{ |
||||
|
title: '时间', |
||||
|
dataIndex: 'time', |
||||
|
width: 200, |
||||
|
render: (time: number) => ( |
||||
|
<span>{getTime(time * 1000)}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '订单', |
||||
|
dataIndex: 'order' |
||||
|
}, |
||||
|
{ |
||||
|
title: '取款金额', |
||||
|
dataIndex: 'amount', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '到账金额', |
||||
|
dataIndex: 'receipt_amount', |
||||
|
render: (val: string) => ( |
||||
|
<span>${val}</span> |
||||
|
) |
||||
|
}, |
||||
|
{ |
||||
|
title: '账号', |
||||
|
dataIndex: 'account' |
||||
|
}, |
||||
|
{ |
||||
|
title: '收款户名', |
||||
|
dataIndex: 'type' |
||||
|
}, |
||||
|
{ |
||||
|
title: '收款地址', |
||||
|
dataIndex: 'address' |
||||
|
} |
||||
|
]} |
||||
|
/> |
||||
|
</div> |
||||
|
</div > |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(WithdrawRecords) |
@ -0,0 +1,78 @@ |
|||||
|
import { Form, FormProps, Input, notification } from 'antd' |
||||
|
import '../../styles/login.scss' |
||||
|
import Button from '../../components/Button' |
||||
|
import { useRouter } from '../../hooks/useRouter' |
||||
|
import store from '../../store' |
||||
|
import { useEffect, useState } from 'react' |
||||
|
import { http_code, http_login, http_submit } from '../../http/api' |
||||
|
type FieldType = { |
||||
|
account: string; |
||||
|
password: string; |
||||
|
}; |
||||
|
|
||||
|
const Submit = () => { |
||||
|
|
||||
|
const [form] = Form.useForm() |
||||
|
|
||||
|
const onFinish: FormProps<FieldType>['onFinish'] = async (values) => { |
||||
|
const res: any = await http_submit({ |
||||
|
...values |
||||
|
}) |
||||
|
if (res.code === 0) { |
||||
|
notification.success({ |
||||
|
message: '提交成功' |
||||
|
}) |
||||
|
form.resetFields() |
||||
|
} |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
useEffect(() => { |
||||
|
}, []) |
||||
|
|
||||
|
return ( |
||||
|
<div className='login'> |
||||
|
<div className='container'> |
||||
|
<div className='row-center'> |
||||
|
<img src={require('../../assets/login.png')} className='img' alt="" /> |
||||
|
</div> |
||||
|
<div className='row-center'> |
||||
|
<div style={{ maxWidth: 500, width: '100%', padding: '0 20px' }}> |
||||
|
<Form |
||||
|
onFinish={onFinish} |
||||
|
form={form} |
||||
|
> |
||||
|
<Form.Item |
||||
|
name="account" |
||||
|
rules={[ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入账号!', |
||||
|
}, |
||||
|
]} |
||||
|
> |
||||
|
<Input className='input' placeholder='账号' ></Input> |
||||
|
</Form.Item> |
||||
|
<Form.Item |
||||
|
name="password" |
||||
|
rules={[ |
||||
|
{ |
||||
|
required: true, |
||||
|
message: '请输入密码!', |
||||
|
}, |
||||
|
]} |
||||
|
> |
||||
|
<Input.Password className='input' placeholder='请输入密码' /> |
||||
|
</Form.Item> |
||||
|
<Form.Item> |
||||
|
<Button htmlType="submit">提交</Button> |
||||
|
</Form.Item> |
||||
|
</Form> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default Submit |
@ -0,0 +1,110 @@ |
|||||
|
import { QRCode } from 'antd' |
||||
|
import '../../styles/home.scss' |
||||
|
import { useEffect, useState } from 'react' |
||||
|
import { http_team } from '../../http/api' |
||||
|
import { observer } from 'mobx-react' |
||||
|
import store from '../../store' |
||||
|
|
||||
|
const Team = () => { |
||||
|
|
||||
|
const { token } = store.state |
||||
|
const [rootAccount, setRootState] = useState('') |
||||
|
const [teamAccount, setTeamAccount] = useState([]) |
||||
|
|
||||
|
useEffect(() => { |
||||
|
const getData = async () => { |
||||
|
const res: any = await http_team() |
||||
|
if (res.code === 0) { |
||||
|
setRootState(res.data.email) |
||||
|
setTeamAccount(res.data.team) |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
token && getData() |
||||
|
}, [token]) |
||||
|
|
||||
|
return ( |
||||
|
<div className='team'> |
||||
|
<div className='text-white fz-22 mb-2'>团队详情</div> |
||||
|
|
||||
|
<div className='container p-2'> |
||||
|
|
||||
|
<div className='row-items'> |
||||
|
<img src={require('../../assets/root.png')} alt="" /> |
||||
|
<div className='ml-1 tp'>{rootAccount}</div> |
||||
|
</div> |
||||
|
|
||||
|
{ |
||||
|
teamAccount.map((item: any) => ( |
||||
|
<div className='row-items' key={item.id}> |
||||
|
<img src={require('../../assets/_line2.png')} alt="" /> |
||||
|
<div className='ml-1 tp'>{item.account}</div> |
||||
|
</div> |
||||
|
)) |
||||
|
} |
||||
|
|
||||
|
</div> |
||||
|
|
||||
|
{/* <div className='container p-2 mt-2'> |
||||
|
<div className='text-sub fz-wb-550'>CE08,658532</div> |
||||
|
<div className='row-items mt-2 flex-wrap'> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>总存款</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>总取款</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>总交易量</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>总利润</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div className='container p-2 mt-2'> |
||||
|
<div className='text-sub fz-wb-550'>团队统计数量</div> |
||||
|
<div className='row-items mt-2 flex-wrap'> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>团队总资本金</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>团队总余额</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>1</div> |
||||
|
<div className='text-sub'>团队人数</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>团队存款</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>团队取款</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>0</div> |
||||
|
<div className='text-sub'>团队总交易量</div> |
||||
|
</div> |
||||
|
<div className='box-width'> |
||||
|
<div>$0</div> |
||||
|
<div className='text-sub'>团队总利润</div> |
||||
|
</div> |
||||
|
|
||||
|
</div> |
||||
|
</div> */} |
||||
|
|
||||
|
</div> |
||||
|
) |
||||
|
} |
||||
|
|
||||
|
export default observer(Team) |
@ -0,0 +1,27 @@ |
|||||
|
export namespace Store { |
||||
|
export interface AccountDetails { |
||||
|
account: string; |
||||
|
account_balance: string; |
||||
|
account_capital: string; |
||||
|
account_credit: string; |
||||
|
account_net_worth: string; |
||||
|
account_observer_password: string; |
||||
|
account_prepaid: string; |
||||
|
account_status: string; |
||||
|
balance: string; |
||||
|
email: string; |
||||
|
inviti_code: string; |
||||
|
name: string; |
||||
|
total_assets: string; |
||||
|
total_income: string; |
||||
|
} |
||||
|
|
||||
|
export interface ReceiveAccount { |
||||
|
"address": string, |
||||
|
"fee": string, |
||||
|
"id": number, |
||||
|
"time": number, |
||||
|
"type": string |
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1,47 @@ |
|||||
|
import { notification } from "antd" |
||||
|
|
||||
|
export function copy(value: string, cb?: Function) { |
||||
|
// 动态创建 textarea 标签
|
||||
|
const textarea: any = document.createElement('textarea') |
||||
|
// 将该 textarea 设为 readonly 防止 iOS 下自动唤起键盘,同时将 textarea 移出可视区域
|
||||
|
textarea.readOnly = 'readonly' |
||||
|
textarea.style.position = 'absolute' |
||||
|
textarea.style.left = '-9999px' |
||||
|
// 将要 copy 的值赋给 textarea 标签的 value 属性
|
||||
|
// 网上有些例子是赋值给innerText,这样也会赋值成功,但是识别不了\r\n的换行符,赋值给value属性就可以
|
||||
|
textarea.value = value |
||||
|
// 将 textarea 插入到 body 中
|
||||
|
document.body.appendChild(textarea) |
||||
|
// 选中值并复制
|
||||
|
textarea.select() |
||||
|
textarea.setSelectionRange(0, textarea.value.length) |
||||
|
document.execCommand('Copy') |
||||
|
document.body.removeChild(textarea) |
||||
|
notification.success({ |
||||
|
message: '复制成功' |
||||
|
}) |
||||
|
if (cb && Object.prototype.toString.call(cb) === '[object Function]') { |
||||
|
cb() |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
/** |
||||
|
* @param value |
||||
|
* @returns |
||||
|
*/ |
||||
|
export const getTime = (value: number, type?: string) => { |
||||
|
let date = new Date(value); |
||||
|
let yy: number | string = date.getFullYear(); |
||||
|
let mm: number | string = date.getMonth() + 1; |
||||
|
let dd: number | string = date.getDate(); |
||||
|
let xs: number | string = date.getHours(); |
||||
|
let ff: number | string = date.getMinutes(); |
||||
|
let ss: number | string = date.getSeconds(); |
||||
|
mm = mm >= 10 ? mm : "0" + mm; |
||||
|
dd = dd >= 10 ? dd : "0" + dd; |
||||
|
xs = xs >= 10 ? xs : "0" + xs; |
||||
|
ff = ff >= 10 ? ff : "0" + ff; |
||||
|
ss = ss >= 10 ? ss : "0" + ss; |
||||
|
if (type === "day") return `${yy}-${mm}-${dd}`; |
||||
|
return `${yy}-${mm}-${dd} ${xs}:${ff}`; |
||||
|
}; |