mac
6 months ago
43 changed files with 48636 additions and 15968 deletions
-
BIN.DS_Store
-
2.env
-
48112package-lock.json
-
5package.json
-
2src/App.tsx
-
27src/api/index.ts
-
5src/assets/js/publicFunc.ts
-
3src/components/MyTable/index.tsx
-
2src/components/TabPanes/index.tsx
-
10src/config/index.ts
-
26src/package/SimpleTrade/api/admin-permission.ts
-
33src/package/SimpleTrade/api/admin-user.ts
-
105src/package/SimpleTrade/api/client.ts
-
40src/package/SimpleTrade/api/index.ts
-
68src/package/SimpleTrade/config/layout.ts
-
117src/package/SimpleTrade/config/menu.ts
-
53src/package/SimpleTrade/pages/admininvite/chart/data.ts
-
131src/package/SimpleTrade/pages/admininvite/chart/index.tsx
-
268src/package/SimpleTrade/pages/adminpermission/list/index.tsx
-
43src/package/SimpleTrade/pages/adminupload/uploadapk/index.tsx
-
3src/package/SimpleTrade/pages/adminuser/adminuser.less
-
211src/package/SimpleTrade/pages/adminuser/edit/index.tsx
-
250src/package/SimpleTrade/pages/adminuser/list/index.tsx
-
61src/package/SimpleTrade/pages/client/mt4history/index.tsx
-
110src/package/SimpleTrade/pages/client/mt4order/index.tsx
-
47src/package/SimpleTrade/pages/client/mt4settlementorder/index.tsx
-
236src/package/SimpleTrade/pages/client/user/index.tsx
-
128src/package/SimpleTrade/pages/client/withdraw/index.tsx
-
352src/package/SimpleTrade/pages/home/index.tsx
-
177src/package/SimpleTrade/route/routes.ts
-
38src/package/SimpleTrade/types/enum.ts
-
0src/pages/home/index.css
-
0src/pages/home/index.less
-
114src/pages/home/index.tsx
-
0src/pages/home/vector.png
-
75src/pages/interest/index.tsx
-
2src/pages/login/index.tsx
-
120src/pages/order/index.tsx
-
52src/pages/recharge/index.tsx
-
92src/pages/withdraw/index.tsx
-
60src/route/routes.ts
-
4src/utils/axios.ts
-
13420yarn.lock
@ -0,0 +1,2 @@ |
|||
REACT_APP_BASE_URL=http://192.168.124.20:3009/api/v1 |
|||
SKIP_PREFLIGHT_CHECK=true |
48112
package-lock.json
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,10 +0,0 @@ |
|||
export const httpIp = { |
|||
simpleTradeKey: { |
|||
dev: 'http://125.94.244.254:30303/api/v1', |
|||
prod: 'https://simpletrade.site/api/v1' |
|||
} |
|||
} |
|||
|
|||
export const getBaseURL = () => { |
|||
return httpIp.simpleTradeKey.dev |
|||
} |
@ -1,26 +0,0 @@ |
|||
import $axios from '@/utils/axios' |
|||
|
|||
export default { |
|||
getAdminPermissions(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.get('/admin/adminpermissions', params) |
|||
}, |
|||
|
|||
getAdminPermission(id: number | string): Promise<CommonObjectType<string>> { |
|||
return $axios.get(`/admin/adminpermissions/${id}`) |
|||
}, |
|||
|
|||
addAdminPermission(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/adminpermissions', params) |
|||
}, |
|||
|
|||
updateAdminPermission( |
|||
id: number, |
|||
params: object |
|||
): Promise<CommonObjectType<string>> { |
|||
return $axios.put(`/admin/adminpermissions/${id}`, params) |
|||
}, |
|||
|
|||
deleteAdminPermission(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.delete('/admin/adminpermissions', params) |
|||
} |
|||
} |
@ -1,33 +0,0 @@ |
|||
import $axios from '@/utils/axios' |
|||
|
|||
export default { |
|||
getAdminUserList(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.get('/admin/adminusers', params) |
|||
}, |
|||
|
|||
getAdminUser(id: number | string): Promise<CommonObjectType<string>> { |
|||
return $axios.get(`/admin/adminusers/${id}`) |
|||
}, |
|||
|
|||
addAdminUser(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/adminusers', params) |
|||
}, |
|||
|
|||
updateAdminUser( |
|||
id: number | string, |
|||
params: object |
|||
): Promise<CommonObjectType<string>> { |
|||
return $axios.put(`/admin/adminusers/${id}`, params) |
|||
}, |
|||
|
|||
updateAdminUserPwd( |
|||
id: number, |
|||
params: object |
|||
): Promise<CommonObjectType<string>> { |
|||
return $axios.put(`/admin/adminusers/pwd/${id}`, params) |
|||
}, |
|||
|
|||
deleteAdminUser(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.delete('/admin/adminusers', params) |
|||
} |
|||
} |
@ -1,105 +0,0 @@ |
|||
import $axios from '@/utils/axios' |
|||
|
|||
export default { |
|||
/** |
|||
* @description 获取用户列表 |
|||
* @param {page} 页 |
|||
* @param {page_size} 数量 |
|||
*/ |
|||
user_list(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/user/list', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 获取提现列表 |
|||
* @param {page} 页 |
|||
* @param {page_size} 数量 |
|||
*/ |
|||
withdraw_list(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/chain/withdraw', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 获取提现列表 |
|||
* @param {page} 页 |
|||
* @param {page_size} 数量 |
|||
*/ |
|||
recharge_list(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/chain/deposit', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 获取邀请关系网 |
|||
*/ |
|||
user_relation(): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/user/relation'); |
|||
}, |
|||
|
|||
/** |
|||
* @description 追加邀请 |
|||
*/ |
|||
add_relation(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/user/relation/add', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description MT4历史记录 |
|||
*/ |
|||
mt4_history(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/forex/mt4/history', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description MT4下单列表 |
|||
*/ |
|||
mt4_order_list(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/forex/order/list', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description MT4结算列表 |
|||
*/ |
|||
mt4_settle_list(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/forex/settle/list', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 设置等级 |
|||
*/ |
|||
up_levle(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/debug/upLevel', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 创建模拟账号 |
|||
*/ |
|||
add_debug_user(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/debug/addDebugUser', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 提币审核 |
|||
*/ |
|||
withdraw_check(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/chain/withdraw/check', params); |
|||
}, |
|||
|
|||
/** |
|||
* @description 平仓 |
|||
*/ |
|||
close_order(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/forex/orderClose', params); |
|||
}, |
|||
/** |
|||
* @description 修改昵称 |
|||
*/ |
|||
user_rename(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/user/upRemark', params); |
|||
}, |
|||
/** |
|||
* @description 修改昵称 |
|||
*/ |
|||
user_deactivate(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/user/upDeactivate', params); |
|||
} |
|||
} |
@ -1,40 +0,0 @@ |
|||
import $axios from '@/utils/axios' |
|||
|
|||
export default { |
|||
// 获取数据
|
|||
getList(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.get('https://randomuser.me/api', params) |
|||
}, |
|||
|
|||
// 登录
|
|||
login(params: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/login', params) |
|||
}, |
|||
|
|||
// 首页用户统计
|
|||
user_statistics(): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/userAmount') |
|||
}, |
|||
|
|||
// 首页充值提现统计
|
|||
recharge_withdraw_statistics(): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/depositWithdrawal', { type: 1 }) |
|||
}, |
|||
|
|||
// 首页周期充值提现统计
|
|||
week_recharge_withdraw_statistics( |
|||
params: object |
|||
): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/depositWithdrawal', params) |
|||
}, |
|||
|
|||
/** |
|||
* @description 交易统计 |
|||
* @param {number} end_time 结束时间 |
|||
* @param {number} start_time 开始时间 |
|||
* @param {number} type 1.今日交易订单统计 2.周期交易订单统计 |
|||
*/ |
|||
transaction_statistics(params?: object): Promise<CommonObjectType<string>> { |
|||
return $axios.post('/admin/prodruct', params) |
|||
} |
|||
} |
@ -1,68 +0,0 @@ |
|||
const formItemLayout = { |
|||
labelCol: { |
|||
xs: { span: 24 }, |
|||
sm: { span: 3 } |
|||
}, |
|||
wrapperCol: { |
|||
xs: { span: 24 }, |
|||
sm: { span: 17 } |
|||
} |
|||
} |
|||
|
|||
const wrapperCol = { |
|||
xs: { span: 24, offset: 0 }, |
|||
sm: { span: 16, offset: 3 } |
|||
} |
|||
|
|||
const modalLayoutSm = { |
|||
labelCol: { |
|||
xs: { span: 4 }, |
|||
sm: { span: 4 } |
|||
}, |
|||
wrapperCol: { |
|||
xs: { span: 20 }, |
|||
sm: { span: 20 } |
|||
} |
|||
} |
|||
|
|||
const modalLayoutSm5 = { |
|||
labelCol: { |
|||
xs: { span: 5 }, |
|||
sm: { span: 5 } |
|||
}, |
|||
wrapperCol: { |
|||
xs: { span: 20 }, |
|||
sm: { span: 20 } |
|||
} |
|||
} |
|||
|
|||
const modalLayoutMd = { |
|||
labelCol: { |
|||
xs: { span: 6 }, |
|||
sm: { span: 6 } |
|||
}, |
|||
wrapperCol: { |
|||
xs: { span: 18 }, |
|||
sm: { span: 18 } |
|||
} |
|||
} |
|||
|
|||
const modalLayoutLg = { |
|||
labelCol: { |
|||
xs: { span: 8 }, |
|||
sm: { span: 8 } |
|||
}, |
|||
wrapperCol: { |
|||
xs: { span: 16 }, |
|||
sm: { span: 16 } |
|||
} |
|||
} |
|||
|
|||
export { |
|||
formItemLayout, |
|||
wrapperCol, |
|||
modalLayoutSm, |
|||
modalLayoutSm5, |
|||
modalLayoutMd, |
|||
modalLayoutLg |
|||
} |
@ -1,117 +0,0 @@ |
|||
import { HomeOutlined, UserOutlined, AuditOutlined } from '@ant-design/icons' |
|||
|
|||
const menus = [ |
|||
{ |
|||
path: '/', |
|||
name: '首页', |
|||
key: 'home', |
|||
icon: HomeOutlined, |
|||
routes: [], |
|||
}, |
|||
{ |
|||
path: '/adminuser', |
|||
name: '用户管理', |
|||
key: 'adminuser', |
|||
type: 'subMenu', |
|||
icon: UserOutlined, |
|||
iconfont: 'icon-xiaoshouzongjian', |
|||
routes: [ |
|||
{ |
|||
path: '/adminuser/list', |
|||
name: '用户列表', |
|||
key: 'adminuser:list:view' |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/adminpermission', |
|||
name: '权限管理', |
|||
key: 'adminpermission', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/adminpermission/list', |
|||
name: '权限列表', |
|||
key: 'adminpermission:list:view', |
|||
remove: true |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/admininvite', |
|||
name: '邀请', |
|||
key: 'admininvite', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/admininvite/chart', |
|||
name: '关联图', |
|||
key: 'admininvite:list:chart' |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/adminupload', |
|||
name: '上传管理', |
|||
key: 'adminupload', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/adminupload/uploadapk', |
|||
name: '上传APK', |
|||
key: 'admininvite:list:uploadapk' |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/client', |
|||
name: '客户端', |
|||
key: 'client', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/client/userlist', |
|||
name: '用户列表', |
|||
exact: true, |
|||
key: 'client:userlist:view', |
|||
remove: true |
|||
}, |
|||
{ |
|||
path: '/client/recharge', |
|||
name: '充值记录', |
|||
exact: true, |
|||
key: 'client:recharge:view', |
|||
}, |
|||
{ |
|||
path: '/client/withdraw', |
|||
name: '提现记录', |
|||
exact: true, |
|||
key: 'client:withdraw:view', |
|||
}, |
|||
{ |
|||
path: '/client/mt4history', |
|||
name: 'MT4历史记录', |
|||
exact: true, |
|||
key: 'client:mt4history:view', |
|||
}, |
|||
{ |
|||
path: '/client/mt4order', |
|||
name: 'MT4订单列表', |
|||
exact: true, |
|||
key: 'client:mt4order:view', |
|||
}, |
|||
{ |
|||
path: '/client/mt4settlementorder', |
|||
name: 'MT4结算订单列表', |
|||
exact: true, |
|||
key: 'client:mt4settlementorder:view', |
|||
} |
|||
] |
|||
} |
|||
] |
|||
|
|||
export default menus |
@ -1,53 +0,0 @@ |
|||
import dagre from 'dagre'; |
|||
const edgeType = 'smoothstep'; |
|||
|
|||
export const flattenTree = (tree) => { |
|||
let stack = [tree]; |
|||
let nodes = []; |
|||
let edges = []; |
|||
while (stack.length > 0) { |
|||
let node = stack.pop(); |
|||
nodes.push({ id: node.id, data: { ...node.data, label: `${node.data.name}` }, position: node.position }); |
|||
if (node.children && node.children.length > 0) { |
|||
node.children.map(item => { |
|||
edges.push({ source: node.id, target: item.id, id: item.id, type: edgeType, animated: true }); |
|||
stack.unshift(item); |
|||
}); |
|||
}; |
|||
}; |
|||
return { nodes, edges }; |
|||
}; |
|||
|
|||
export const getLayoutedElements = (nodes, edges, direction = 'TB') => { |
|||
const dagreGraph = new dagre.graphlib.Graph(); |
|||
dagreGraph.setDefaultEdgeLabel(() => ({})); |
|||
|
|||
const nodeWidth = 172; |
|||
const nodeHeight = 36; |
|||
const isHorizontal = direction === 'LR'; |
|||
dagreGraph.setGraph({ rankdir: direction }); |
|||
|
|||
nodes.forEach((node: any) => { |
|||
dagreGraph.setNode(node.id, { width: nodeWidth, height: nodeHeight }); |
|||
}); |
|||
|
|||
edges.forEach((edge: any) => { |
|||
dagreGraph.setEdge(edge.source, edge.target); |
|||
}); |
|||
|
|||
dagre.layout(dagreGraph); |
|||
|
|||
nodes.forEach((node: any) => { |
|||
const nodeWithPosition = dagreGraph.node(node.id); |
|||
node.targetPosition = isHorizontal ? 'left' : 'top'; |
|||
node.sourcePosition = isHorizontal ? 'right' : 'bottom'; |
|||
node.position = { |
|||
x: nodeWithPosition.x - nodeWidth / 2, |
|||
y: nodeWithPosition.y - nodeHeight / 2, |
|||
}; |
|||
|
|||
return node; |
|||
}); |
|||
|
|||
return { nodes, edges }; |
|||
}; |
@ -1,131 +0,0 @@ |
|||
import React, { useCallback, FC, useEffect, useState, useRef } from 'react'; |
|||
import ReactFlow, { |
|||
addEdge, |
|||
ConnectionLineType, |
|||
useNodesState, |
|||
useEdgesState, |
|||
Controls |
|||
} from 'react-flow-renderer'; |
|||
import { getLayoutedElements, flattenTree } from './data'; |
|||
import { Button, Input, Modal, notification } from 'antd'; |
|||
import clientApi from '@/package/SimpleTrade/api/client'; |
|||
|
|||
const InviteChart: FC = () => { |
|||
const [nodes, setNodes, onNodesChange] = useNodesState([]); |
|||
const [edges, setEdges, onEdgesChange] = useEdgesState([]); |
|||
const [isOpenModal, setIsOpenModal] = useState(false) |
|||
const [loading, setLoading] = useState(false) |
|||
const [inviteCode, setInviteCode] = useState('') |
|||
const [address, setAddress] = useState('') |
|||
|
|||
const onConnect = useCallback( |
|||
(params: any) => { |
|||
setEdges((eds) => |
|||
addEdge({ ...params, type: ConnectionLineType.SmoothStep, animated: true }, eds) |
|||
) |
|||
}, |
|||
[] |
|||
); |
|||
|
|||
const onLayout = useCallback( |
|||
(direction: any) => { |
|||
const { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements( |
|||
nodes, |
|||
edges, |
|||
direction |
|||
); |
|||
|
|||
setNodes([...layoutedNodes]); |
|||
setEdges([...layoutedEdges]); |
|||
}, |
|||
[nodes, edges] |
|||
); |
|||
|
|||
// 获取节点
|
|||
const getNodes = async () => { |
|||
const res: any = await clientApi.user_relation(); |
|||
if (res.code === 0 && Object.keys(res.data).length > 0) { |
|||
let { nodes, edges } = flattenTree(res.data) // 处理节点及连接线
|
|||
let { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(nodes, edges)//计算节点位置
|
|||
setNodes(layoutedNodes) |
|||
setEdges(layoutedEdges) |
|||
}; |
|||
}; |
|||
|
|||
// 添加
|
|||
const addNodes = async () => { |
|||
if (!address) { |
|||
notification.error({ |
|||
message: '请输入地址' |
|||
}) |
|||
return; |
|||
} |
|||
setLoading(true) |
|||
try { |
|||
const res: any = await clientApi.add_debug_user({ |
|||
address, |
|||
invite_code: inviteCode |
|||
}); |
|||
setLoading(false) |
|||
if (res.code === 0) { |
|||
notification.success({ |
|||
message: '创建成功' |
|||
}) |
|||
getNodes() |
|||
setIsOpenModal(false) |
|||
// let { nodes, edges } = flattenTree(res.data) // 处理节点及连接线
|
|||
// let { nodes: layoutedNodes, edges: layoutedEdges } = getLayoutedElements(nodes, edges)//计算节点位置
|
|||
// setNodes(layoutedNodes)
|
|||
// setEdges(layoutedEdges)
|
|||
} |
|||
} catch (error) { |
|||
setLoading(false) |
|||
} |
|||
} |
|||
|
|||
useEffect(() => { |
|||
getNodes(); |
|||
}, []); |
|||
|
|||
useEffect(() => { |
|||
if (!isOpenModal) { |
|||
setInviteCode('') |
|||
setAddress('') |
|||
} |
|||
}, [isOpenModal]) |
|||
|
|||
return ( |
|||
<div> |
|||
<Button type='primary' onClick={() => onLayout('TB')}>垂直布局</Button> |
|||
<Button type='primary' onClick={() => onLayout('LR')}>水平布局</Button> |
|||
<div style={{ width: '100%', height: window.innerHeight - 165 }}> |
|||
<ReactFlow |
|||
nodes={nodes} |
|||
edges={edges} |
|||
onNodesChange={onNodesChange} |
|||
onEdgesChange={onEdgesChange} |
|||
onConnect={onConnect} |
|||
connectionLineType={ConnectionLineType.SmoothStep} |
|||
fitView |
|||
onNodeClick={(e, node) => { |
|||
setInviteCode(node.data.invite_code) |
|||
setIsOpenModal(true) |
|||
}} |
|||
> |
|||
<Controls /> |
|||
</ReactFlow> |
|||
</div> |
|||
<Modal |
|||
visible={isOpenModal} |
|||
onCancel={() => setIsOpenModal(false)} |
|||
onOk={addNodes} |
|||
title="创建模拟账号" |
|||
confirmLoading={loading} |
|||
> |
|||
<Input value={address} onChange={e => setAddress(e.target.value)} placeholder="请输入地址" /> |
|||
</Modal> |
|||
</div> |
|||
); |
|||
}; |
|||
|
|||
export default InviteChart; |
@ -1,268 +0,0 @@ |
|||
import React, { FC, useEffect, useRef, useState } from 'react' |
|||
import { |
|||
isAuthorized, |
|||
makeTree, |
|||
makeTreeSelectData |
|||
} from '@/assets/js/publicFunc' |
|||
import { |
|||
Button, |
|||
Table, |
|||
Modal, |
|||
Form, |
|||
Switch, |
|||
Input, |
|||
TreeSelect, |
|||
message, |
|||
Spin |
|||
} from 'antd' |
|||
import { modalLayoutSm } from '@/package/SimpleTrade/config/layout' |
|||
import AdminPermissionApi from '@/package/SimpleTrade/api/admin-permission' |
|||
import SearchForm from '@/components/SearchForm' |
|||
|
|||
interface AdminPermission { |
|||
id: number; |
|||
name: string; |
|||
code: string; |
|||
isHelp: boolean; |
|||
parentId: number; |
|||
updateTime: string; |
|||
createTime: string; |
|||
} |
|||
|
|||
const AdminPermissionList: FC = () => { |
|||
const [loading, setLoading] = useState<boolean>(false) |
|||
const [btnLoading, setBtnLoading] = useState<boolean>(false) |
|||
const [visible, setVisible] = useState<boolean>(false) |
|||
const [title, setTitle] = useState<string>('新增权限') |
|||
const [permissionId, setPermissionId] = useState<number>(0) |
|||
const [permissionList, setPermissionList] = useState<Array<any>>([]) |
|||
const [treeSelectList, setTreeSelectList] = useState<Array<any>>([]) |
|||
const [form] = Form.useForm() |
|||
const { setFieldsValue, getFieldsValue, resetFields } = form |
|||
const searchForm = useRef() |
|||
|
|||
const getAdminPermissions = (search: object = {}) => { |
|||
AdminPermissionApi.getAdminPermissions(search).then((res: any) => { |
|||
const permissions = res.data ? res.data : [] |
|||
const adminPermissionsTree = makeTree(permissions) |
|||
setPermissionList(adminPermissionsTree) |
|||
}) |
|||
} |
|||
|
|||
const setTreeSelectData = () => { |
|||
const root = [{ value: 0, title: '根所属' }] |
|||
const treeSelectData = root.concat( |
|||
makeTreeSelectData(permissionList, 'id', 'name') |
|||
) |
|||
setTreeSelectList(treeSelectData) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
getAdminPermissions() |
|||
// eslint-disable-next-line
|
|||
}, []) |
|||
|
|||
const add = () => { |
|||
resetFields() |
|||
setPermissionId(0) |
|||
setVisible(true) |
|||
setTitle('新增权限') |
|||
setFieldsValue({ parentId: 0, code: '' }) |
|||
setTreeSelectData() |
|||
} |
|||
|
|||
const edit = (record: any) => { |
|||
setPermissionId(record.id) |
|||
setFieldsValue({ ...record }) |
|||
setVisible(true) |
|||
setTitle('编辑权限') |
|||
setTreeSelectData() |
|||
} |
|||
|
|||
const handleSearch = (values) => { |
|||
getAdminPermissions(values) |
|||
} |
|||
|
|||
const cancelModel = () => { |
|||
setVisible(false) |
|||
} |
|||
|
|||
const delAdminPermission = (record: AdminPermission) => { |
|||
setBtnLoading(true) |
|||
const ids = [record.id] |
|||
AdminPermissionApi.deleteAdminPermission(ids) |
|||
.then((res) => { |
|||
message.success(res.message) |
|||
getAdminPermissions() |
|||
}) |
|||
.finally(() => { |
|||
setBtnLoading(false) |
|||
}) |
|||
} |
|||
|
|||
const handleSubmit = () => { |
|||
setLoading(true) |
|||
if (permissionId) { |
|||
AdminPermissionApi.updateAdminPermission(permissionId, getFieldsValue()) |
|||
.then((res) => { |
|||
message.success(res.message) |
|||
setVisible(false) |
|||
getAdminPermissions() |
|||
}) |
|||
.finally(() => { |
|||
setLoading(false) |
|||
}) |
|||
} else { |
|||
AdminPermissionApi.addAdminPermission(getFieldsValue()) |
|||
.then((res) => { |
|||
message.success(res.message) |
|||
setVisible(false) |
|||
getAdminPermissions() |
|||
}) |
|||
.finally(() => { |
|||
setLoading(false) |
|||
}) |
|||
} |
|||
} |
|||
const AddBtn = () => ( |
|||
<Button className="fr" onClick={add} type="primary"> |
|||
新增权限 |
|||
</Button> |
|||
) |
|||
const columns: any = [ |
|||
{ |
|||
title: '名称', |
|||
dataIndex: 'name' |
|||
}, |
|||
{ |
|||
title: '权限标识', |
|||
dataIndex: 'code' |
|||
}, |
|||
{ |
|||
title: '操作', |
|||
dataIndex: 'operations', |
|||
align: 'center', |
|||
render: (text, record) => ( |
|||
<> |
|||
{isAuthorized('adminpermission:list:del') && ( |
|||
<Button |
|||
className="btn mr-5" |
|||
onClick={() => delAdminPermission(record)} |
|||
size="small" |
|||
type="primary" |
|||
loading={btnLoading} |
|||
danger |
|||
> |
|||
删除 |
|||
</Button> |
|||
)} |
|||
{isAuthorized('adminpermission:list:edit') && ( |
|||
<Button |
|||
className="btn" |
|||
onClick={() => edit(record)} |
|||
size="small" |
|||
type="primary" |
|||
> |
|||
编辑 |
|||
</Button> |
|||
)} |
|||
</> |
|||
) |
|||
} |
|||
] |
|||
|
|||
// 搜索栏配置项
|
|||
const searchConfigList = [ |
|||
{ |
|||
key: 'name', |
|||
slot: <Input placeholder="名称" allowClear />, |
|||
initialValue: '' |
|||
} |
|||
] |
|||
const nameValidator = (rule, value) => { |
|||
if (!value) { |
|||
return Promise.reject(new Error('请输入名称')) |
|||
} |
|||
return Promise.resolve() |
|||
} |
|||
const codeValidator = (rule, value) => { |
|||
const parentId = form.getFieldValue('parentId') |
|||
const isHelp = form.getFieldValue('isHelp') |
|||
if (isHelp) { |
|||
return Promise.resolve() |
|||
} |
|||
if (!parentId && !value) { |
|||
return Promise.reject(new Error('请输入权限标识')) |
|||
} |
|||
if (!parentId && !/^[a-zA-Z0-9:]+$/.test(value)) { |
|||
return Promise.reject(new Error('权限标识格式不正确')) |
|||
} |
|||
return Promise.resolve() |
|||
} |
|||
return ( |
|||
<> |
|||
{isAuthorized('adminpermission:list:add') && <AddBtn />} |
|||
{visible && ( |
|||
<Modal |
|||
title={title} |
|||
visible={visible} |
|||
onCancel={cancelModel} |
|||
footer={null} |
|||
> |
|||
<Spin spinning={loading}> |
|||
<Form {...modalLayoutSm} form={form} onFinish={handleSubmit}> |
|||
<Form.Item label="所属" name="parentId"> |
|||
<TreeSelect |
|||
style={{ width: '100%' }} |
|||
dropdownStyle={{ maxHeight: 400, overflow: 'auto' }} |
|||
treeData={treeSelectList} |
|||
placeholder="请选择" |
|||
/> |
|||
</Form.Item> |
|||
<Form.Item label="辅助信息" name="isHelp" valuePropName="checked"> |
|||
<Switch /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
label="名称" |
|||
name="name" |
|||
rules={[{ validator: nameValidator }]} |
|||
> |
|||
<Input placeholder="请输入名称" /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
label="权限标识" |
|||
name="code" |
|||
rules={[{ validator: codeValidator }]} |
|||
> |
|||
<Input placeholder="格式(字母数字:组合):abc:cde" /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
wrapperCol={{ |
|||
xs: { span: 20, offset: 4 }, |
|||
sm: { span: 20, offset: 4 } |
|||
}} |
|||
> |
|||
<Button type="primary" htmlType="submit"> |
|||
提交 |
|||
</Button> |
|||
</Form.Item> |
|||
</Form> |
|||
</Spin> |
|||
</Modal> |
|||
)} |
|||
<SearchForm |
|||
ref={searchForm} |
|||
handleSearch={handleSearch} |
|||
config={searchConfigList} |
|||
/> |
|||
<Table |
|||
rowKey={(record) => record.id} |
|||
columns={columns} |
|||
dataSource={permissionList} |
|||
pagination={false} |
|||
/> |
|||
</> |
|||
) |
|||
} |
|||
|
|||
export default AdminPermissionList |
@ -1,43 +0,0 @@ |
|||
import React, { FC } from 'react'; |
|||
import { InboxOutlined } from '@ant-design/icons'; |
|||
import { message, Upload } from 'antd'; |
|||
|
|||
const props = { |
|||
name: 'file', |
|||
multiple: true, |
|||
action: 'https://www.mocky.io/v2/5cc8019d300000980a055e76', |
|||
onChange(info) { |
|||
const { status } = info.file; |
|||
if (status !== 'uploading') { |
|||
console.log(info.file, info.fileList); |
|||
} |
|||
if (status === 'done') { |
|||
message.success(`${info.file.name} file uploaded successfully.`); |
|||
} else if (status === 'error') { |
|||
message.error(`${info.file.name} file upload failed.`); |
|||
} |
|||
}, |
|||
onDrop(e) { |
|||
console.log('Dropped files', e.dataTransfer.files); |
|||
}, |
|||
}; |
|||
|
|||
const { Dragger } = Upload; |
|||
|
|||
const UploadAPK: FC = () => { |
|||
return ( |
|||
<div style={{ height: '50vh' }}> |
|||
<div style={{ width: '100%' }}> |
|||
<Dragger {...props}> |
|||
<p className="ant-upload-drag-icon"> |
|||
<InboxOutlined /> |
|||
</p> |
|||
<p className="ant-upload-text">点击进行上传</p> |
|||
<p className="ant-upload-hint">把需要上传的文件拖拽至此处</p> |
|||
</Dragger> |
|||
</div> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default UploadAPK; |
@ -1,3 +0,0 @@ |
|||
.mr-5 { |
|||
margin-right: 5px; |
|||
} |
@ -1,211 +0,0 @@ |
|||
import React, { useState, FC, useEffect } from 'react' |
|||
import { useHistory } from 'react-router-dom' |
|||
import { Form, Input, Button, message, Spin, Tree } from 'antd' |
|||
import { formItemLayout, wrapperCol } from '@/package/SimpleTrade/config/layout' |
|||
import { |
|||
closeTabAction, |
|||
getQuery, |
|||
makeTree, |
|||
makeTreeData, |
|||
treeFindParentById, |
|||
diffArray |
|||
} from '@/assets/js/publicFunc' |
|||
import MySelect from '@/components/MySelect' |
|||
import AdminUserApi from '@/package/SimpleTrade/api/admin-user' |
|||
import AdminPermissionApi from '@/package/SimpleTrade/api/admin-permission' |
|||
|
|||
const FormView: FC = () => { |
|||
const query = getQuery() |
|||
const { id } = query |
|||
|
|||
// 原始权限tree
|
|||
let originalTreeData: Array<any> = [] |
|||
|
|||
const [form] = Form.useForm() |
|||
const { setFieldsValue, getFieldsValue, resetFields } = form |
|||
|
|||
const [loading, setLoading] = useState<boolean>(false) |
|||
const [treeData, setTreeData] = useState<Array<any>>([]) |
|||
const [checkedKeys, setCheckedKeys] = useState<Array<number | string>>([]) |
|||
|
|||
const history: CommonObjectType = useHistory() |
|||
|
|||
// 获取权限列表数据
|
|||
const getPermissions = async () => { |
|||
await AdminPermissionApi.getAdminPermissions().then((res: any) => { |
|||
const data: Array<any> = res.data ? res.data : [] |
|||
originalTreeData = makeTree(data) |
|||
const treeDataTemp = makeTreeData(originalTreeData, 'id', 'name') |
|||
setTreeData(treeDataTemp) |
|||
}) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
getPermissions() |
|||
if (id) { |
|||
AdminUserApi.getAdminUser(id).then((res) => { |
|||
const data: any = res.data ? res.data : {} |
|||
const adminUsers = data.adminUser ? data.adminUser : {} |
|||
const permissions = data.permissions ? data.permissions : [] |
|||
const permissionIds = permissions.map((item) => { |
|||
return item.permissionId |
|||
}) |
|||
|
|||
// tree父子受控回显需要过滤掉父级ID
|
|||
let parents: Array<number | string> = [] |
|||
|
|||
permissionIds.forEach((item: number | string) => { |
|||
const temp: Array<number | string> = treeFindParentById( |
|||
originalTreeData, |
|||
item |
|||
) |
|||
parents = parents.concat(temp) |
|||
}) |
|||
|
|||
const checkIds: Array<number | string> = diffArray( |
|||
permissionIds, |
|||
parents |
|||
) |
|||
setCheckedKeys(checkIds) |
|||
|
|||
adminUsers.status = adminUsers.status.toString() |
|||
resetFields() |
|||
setFieldsValue({ ...adminUsers }) |
|||
}) |
|||
} else { |
|||
setFieldsValue({ status: '1' }) |
|||
} |
|||
// eslint-disable-next-line
|
|||
}, [id]) |
|||
|
|||
const onCheck = (checkedKeysValue: any) => { |
|||
setCheckedKeys(checkedKeysValue) |
|||
setFieldsValue({ permissions: checkedKeysValue }) |
|||
} |
|||
|
|||
const handleSubmit = () => { |
|||
setLoading(true) |
|||
const submitForm: any = { ...getFieldsValue() } |
|||
if (typeof submitForm.status === 'string') { |
|||
submitForm.status = parseInt(submitForm.status, 0) |
|||
} |
|||
if (id) { |
|||
AdminUserApi.updateAdminUser(id, submitForm) |
|||
.then((res) => { |
|||
message.success(res.message) |
|||
}) |
|||
.finally(() => { |
|||
setLoading(false) |
|||
}) |
|||
} else { |
|||
AdminUserApi.addAdminUser(submitForm) |
|||
.then((res) => { |
|||
setLoading(false) |
|||
message.success(res.message) |
|||
const returnUrl = '/adminuser/list' |
|||
closeTabAction(history, returnUrl) |
|||
}) |
|||
.catch(() => { |
|||
setLoading(false) |
|||
}) |
|||
} |
|||
} |
|||
|
|||
const nameValidator = (rule, value) => { |
|||
if (value.length < 4) { |
|||
return Promise.reject(new Error('用户名最少4个字符')) |
|||
} |
|||
if (!/^[a-zA-Z0-9]{4,}$/.test(value)) { |
|||
return Promise.reject(new Error('用户名只能是数字字母下划线组合')) |
|||
} |
|||
return Promise.resolve() |
|||
} |
|||
|
|||
const repasswordValidator = (rule, value) => { |
|||
const password = form.getFieldValue('password') |
|||
if (password && password !== value) { |
|||
return Promise.reject(new Error('两次密码输入不一致')) |
|||
} |
|||
return Promise.resolve() |
|||
} |
|||
|
|||
return ( |
|||
<Spin spinning={loading}> |
|||
<Form {...formItemLayout} form={form} onFinish={handleSubmit}> |
|||
<Form.Item |
|||
label="用户名" |
|||
name="name" |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
validator: nameValidator |
|||
} |
|||
]} |
|||
> |
|||
<Input placeholder="请输入用户名" /> |
|||
</Form.Item> |
|||
{!id && ( |
|||
<Form.Item |
|||
label="密码" |
|||
name="password" |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
message: '请输入密码' |
|||
}, |
|||
{ |
|||
min: 6 |
|||
} |
|||
]} |
|||
> |
|||
<Input placeholder="请输入密码" /> |
|||
</Form.Item> |
|||
)} |
|||
{!id && ( |
|||
<Form.Item |
|||
label="确认密码" |
|||
name="repassword" |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
validator: repasswordValidator |
|||
} |
|||
]} |
|||
> |
|||
<Input placeholder="请输入确认密码" /> |
|||
</Form.Item> |
|||
)} |
|||
<Form.Item |
|||
label="状态" |
|||
name="status" |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
message: '请选择状态' |
|||
} |
|||
]} |
|||
> |
|||
<MySelect |
|||
data={[{ key: '0', name: '冻结' }, { key: '1', name: '正常' }]} |
|||
placeholder="请选择状态" |
|||
/> |
|||
</Form.Item> |
|||
<Form.Item label="权限" name="permissions"> |
|||
<Tree |
|||
checkable |
|||
onCheck={onCheck} |
|||
checkedKeys={checkedKeys} |
|||
treeData={treeData} |
|||
/> |
|||
</Form.Item> |
|||
<Form.Item wrapperCol={wrapperCol}> |
|||
<Button type="primary" htmlType="submit"> |
|||
提交 |
|||
</Button> |
|||
</Form.Item> |
|||
</Form> |
|||
</Spin> |
|||
) |
|||
} |
|||
|
|||
export default FormView |
@ -1,250 +0,0 @@ |
|||
import React, { useRef, FC, useState } from 'react' |
|||
import { useHistory } from 'react-router-dom' |
|||
import { Button, Form, Input, Modal, Tag, Spin, message } from 'antd' |
|||
import MyTable from '@/components/MyTable' |
|||
import { isAuthorized } from '@/assets/js/publicFunc' |
|||
import MySelect from '@/components/MySelect' |
|||
import AdminUserApi from '@/package/SimpleTrade/api/admin-user' |
|||
import { modalLayoutSm5 } from '@/package/SimpleTrade/config/layout' |
|||
import '../adminuser.less' |
|||
|
|||
interface AdminUser { |
|||
id: number; |
|||
name: string; |
|||
status: number; |
|||
updateTime: string; |
|||
createTime: string; |
|||
} |
|||
|
|||
const StatusArr: Array<string> = ['冻结', '正常'] |
|||
|
|||
const StatusTagArr: Array<string> = ['gold', 'blue'] |
|||
|
|||
const AdminUserList: FC = () => { |
|||
const tableRef: RefType = useRef() |
|||
const history = useHistory() |
|||
const [form] = Form.useForm() |
|||
const { getFieldsValue, resetFields } = form |
|||
|
|||
const [loading, setLoading] = useState<boolean>(false) |
|||
const [btnLoading, setBtnLoading] = useState<boolean>(false) |
|||
const [visible, setVisible] = useState<boolean>(false) |
|||
const [id, setId] = useState<number>(0) |
|||
const [delIds, setDelIds] = useState<Array<string | number>>([]) |
|||
const [delDisabeld, setDelDisabeld] = useState<boolean>(true) |
|||
|
|||
const addAdminUser = () => { |
|||
history.push('/adminuser/list/add') |
|||
} |
|||
|
|||
const editAdminUserPwd = (record: AdminUser) => { |
|||
resetFields() |
|||
setVisible(true) |
|||
setId(record.id) |
|||
} |
|||
|
|||
const cancelModel = () => { |
|||
setVisible(false) |
|||
} |
|||
|
|||
const editAdminUser = (record: AdminUser) => { |
|||
history.push(`/adminuser/list/edit?id=${record.id}`) |
|||
} |
|||
|
|||
const onSelectRow = (rowKeys: Array<string | number>) => { |
|||
setDelIds(rowKeys) |
|||
if (rowKeys.length > 0) { |
|||
setDelDisabeld(false) |
|||
} else { |
|||
setDelDisabeld(true) |
|||
} |
|||
} |
|||
|
|||
const repasswordValidator = (rule, value) => { |
|||
const password = form.getFieldValue('password') |
|||
if (password && password !== value) { |
|||
return Promise.reject(new Error('两次密码输入不一致')) |
|||
} |
|||
return Promise.resolve() |
|||
} |
|||
|
|||
const delAdminUser = () => { |
|||
setBtnLoading(true) |
|||
AdminUserApi.deleteAdminUser(delIds) |
|||
.then((res: any) => { |
|||
message.success(res.message) |
|||
tableRef.current.update() |
|||
}) |
|||
.finally(() => { |
|||
setBtnLoading(false) |
|||
}) |
|||
} |
|||
|
|||
const handleSubmit = () => { |
|||
setLoading(true) |
|||
const submitForm = { ...getFieldsValue() } |
|||
AdminUserApi.updateAdminUserPwd(id, submitForm) |
|||
.then((res: any) => { |
|||
message.success(res.message) |
|||
}) |
|||
.finally(() => { |
|||
setLoading(false) |
|||
}) |
|||
} |
|||
|
|||
// 搜索栏配置项
|
|||
const searchConfigList = [ |
|||
{ |
|||
key: 'name', |
|||
slot: <Input placeholder="用户名" allowClear />, |
|||
initialValue: '' |
|||
}, |
|||
{ |
|||
key: 'status', |
|||
slot: ( |
|||
<MySelect |
|||
data={[{ name: '正常', key: '1' }, { name: '冻结', key: '0' }]} |
|||
placeholder="状态" |
|||
/> |
|||
) |
|||
} |
|||
] |
|||
const columns = [ |
|||
{ |
|||
title: '用户名', |
|||
dataIndex: 'name' |
|||
}, |
|||
{ |
|||
title: '状态', |
|||
dataIndex: 'status', |
|||
render: (status: number) => ( |
|||
<> |
|||
<Tag color={StatusTagArr[status]}>{StatusArr[status]}</Tag> |
|||
</> |
|||
) |
|||
}, |
|||
{ |
|||
title: '更新时间', |
|||
dataIndex: 'updateTime' |
|||
}, |
|||
{ |
|||
title: '创建时间', |
|||
dataIndex: 'createTime' |
|||
}, |
|||
{ |
|||
title: '操作', |
|||
dataIndex: 'operations', |
|||
align: 'center', |
|||
render: (text, record) => ( |
|||
<> |
|||
{isAuthorized('adminuser:list:edit') && ( |
|||
<div> |
|||
<Button |
|||
className="btn mr-5" |
|||
onClick={() => editAdminUserPwd(record)} |
|||
size="small" |
|||
type="primary" |
|||
danger |
|||
> |
|||
修改密码 |
|||
</Button> |
|||
<Button |
|||
className="btn" |
|||
onClick={() => editAdminUser(record)} |
|||
size="small" |
|||
type="primary" |
|||
> |
|||
编辑 |
|||
</Button> |
|||
</div> |
|||
)} |
|||
</> |
|||
) |
|||
} |
|||
] |
|||
|
|||
const delAdminUserEl = ( |
|||
<Button |
|||
className="fr mr-5" |
|||
onClick={delAdminUser} |
|||
type="primary" |
|||
disabled={delDisabeld} |
|||
loading={btnLoading} |
|||
danger |
|||
> |
|||
删除用户 |
|||
</Button> |
|||
) |
|||
|
|||
const addAdminUserEl = ( |
|||
<Button className="fr" onClick={addAdminUser} type="primary"> |
|||
新增用户 |
|||
</Button> |
|||
) |
|||
|
|||
return ( |
|||
<> |
|||
{visible && ( |
|||
<Modal |
|||
title="修改密码" |
|||
visible={visible} |
|||
onCancel={cancelModel} |
|||
footer={null} |
|||
> |
|||
<Spin spinning={loading}> |
|||
<Form {...modalLayoutSm5} form={form} onFinish={handleSubmit}> |
|||
<Form.Item |
|||
label="新密码" |
|||
name="password" |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
message: '请输入新密码' |
|||
}, |
|||
{ |
|||
min: 6, |
|||
message: '新密码长度最少6个字符' |
|||
} |
|||
]} |
|||
> |
|||
<Input placeholder="请输入新密码" /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
label="确认新密码" |
|||
name="repassword" |
|||
rules={[ |
|||
{ |
|||
required: true, |
|||
validator: repasswordValidator |
|||
} |
|||
]} |
|||
> |
|||
<Input placeholder="请输入确认新密码" /> |
|||
</Form.Item> |
|||
<Form.Item |
|||
wrapperCol={{ |
|||
xs: { span: 20, offset: 5 }, |
|||
sm: { span: 20, offset: 5 } |
|||
}} |
|||
> |
|||
<Button type="primary" htmlType="submit"> |
|||
提交 |
|||
</Button> |
|||
</Form.Item> |
|||
</Form> |
|||
</Spin> |
|||
</Modal> |
|||
)} |
|||
{isAuthorized('adminuser:list:add') && addAdminUserEl} |
|||
{isAuthorized('adminuser:list:del') && delAdminUserEl} |
|||
<MyTable |
|||
apiFun={AdminUserApi.getAdminUserList} |
|||
columns={columns} |
|||
ref={tableRef} |
|||
onSelectRow={onSelectRow} |
|||
searchConfigList={searchConfigList} |
|||
/> |
|||
</> |
|||
) |
|||
} |
|||
export default AdminUserList |
@ -1,61 +0,0 @@ |
|||
import MyTable from "@/components/MyTable"; |
|||
import React, { FC } from "react"; |
|||
import clientApi from "@/package/SimpleTrade/api/client"; |
|||
import { Input } from "antd"; |
|||
|
|||
const MT4History: FC = () => { |
|||
|
|||
const column = [ |
|||
{ |
|||
title: '订单号', |
|||
dataIndex: 'ticket', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '手数', |
|||
dataIndex: 'volume', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '开仓价格', |
|||
dataIndex: 'open_price', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '开仓时间', |
|||
dataIndex: 'open_time', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '平仓价格', |
|||
dataIndex: 'close_price', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '平仓时间', |
|||
dataIndex: 'close_time', |
|||
align: 'center' |
|||
}, |
|||
] |
|||
|
|||
const searchConfigList = [ |
|||
{ |
|||
key: 'login', |
|||
slot: <Input placeholder="输入MT4账号" allowClear />, |
|||
initialValue: '', |
|||
} |
|||
] |
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
apiFun={clientApi.mt4_history} |
|||
columns={column} |
|||
rowKey="ticket" |
|||
searchConfigList={searchConfigList} |
|||
/> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default MT4History; |
@ -1,110 +0,0 @@ |
|||
import React, { FC, useState, useMemo, useRef } from "react"; |
|||
import MyTable from "@/components/MyTable"; |
|||
import clientApi from "@/package/SimpleTrade/api/client"; |
|||
import { Button, Modal, notification } from "antd"; |
|||
|
|||
const MT4Order: FC = () => { |
|||
|
|||
const tableRefs = useRef<any>() |
|||
const [visible, setVisible] = useState(false) |
|||
const [currentItem, setCurrentItem] = useState({} as { [key: string]: any }) |
|||
const statusText = useMemo(() => ( |
|||
{ |
|||
'-2': '创建订单失败', |
|||
'-1': '取消订单', |
|||
'0': '发送前', |
|||
'1': '挂单中', |
|||
'2': '寻找B仓', |
|||
'3': '止盈止损设置', |
|||
'4': '持仓中', |
|||
'5': '已结算', |
|||
} |
|||
), []) |
|||
|
|||
const column = useMemo(() => [ |
|||
{ |
|||
title: '订单ID', |
|||
dataIndex: 'order' |
|||
}, |
|||
{ |
|||
title: '账号', |
|||
dataIndex: 'login' |
|||
}, |
|||
{ |
|||
title: '开仓价格', |
|||
dataIndex: 'open_price' |
|||
}, |
|||
{ |
|||
title: '开仓时间', |
|||
dataIndex: 'open_time', |
|||
render: (_time) => (<div>{_time}</div>) |
|||
}, |
|||
{ |
|||
title: '平仓价格', |
|||
dataIndex: 'close_price', |
|||
}, |
|||
{ |
|||
title: '平仓时间', |
|||
dataIndex: 'close_time', |
|||
render: (time) => <div>{time.indexOf('1970-01-01') < 0 && time}</div> |
|||
}, |
|||
{ |
|||
title: '状态', |
|||
dataIndex: 'handle_status', |
|||
render: (status) => ( |
|||
<div>{statusText[`${status}`] || ''}</div> |
|||
) |
|||
}, |
|||
// {
|
|||
// title: '操作',
|
|||
// dataIndex: 'operations',
|
|||
// align: 'center',
|
|||
// key: Date.now(),
|
|||
// render: (text, record) => (
|
|||
// <div>
|
|||
// {record.account_forex_type === 1 && record.handle_status === 4 && (
|
|||
// <Button type='primary' size='small' onClick={() => {
|
|||
// setVisible(true)
|
|||
// setCurrentItem(record)
|
|||
// }}>平仓</Button>
|
|||
// )}
|
|||
// </div>
|
|||
// )
|
|||
// }
|
|||
], []) |
|||
|
|||
// const closePosition = async () => {
|
|||
// let params = {
|
|||
// login: currentItem.login,
|
|||
// ticket: `${currentItem.order}`,
|
|||
// volume: currentItem.volume
|
|||
// }
|
|||
// setVisible(false)
|
|||
// const res: any = await clientApi.close_order(params)
|
|||
// if (res.code === 0) {
|
|||
// notification.success({
|
|||
// message: '平仓成功'
|
|||
// })
|
|||
// setCurrentItem({})
|
|||
// setTimeout(() => {
|
|||
// tableRefs.current?.update()
|
|||
// }, 1000)
|
|||
// }
|
|||
// }
|
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
ref={tableRefs} |
|||
apiFun={clientApi.mt4_order_list} |
|||
columns={column} |
|||
rowKey="order" |
|||
/> |
|||
{/* <Modal visible={visible} onCancel={() => setVisible(false)} title='提示' onOk={closePosition}> |
|||
<div>确认平仓吗?</div> |
|||
</Modal> */} |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default MT4Order; |
@ -1,47 +0,0 @@ |
|||
import MyTable from "@/components/MyTable"; |
|||
import React, { FC } from "react"; |
|||
import clientApi from "@/package/SimpleTrade/api/client"; |
|||
|
|||
const MT4SettlementOrder: FC = () => { |
|||
|
|||
const columns = [ |
|||
{ |
|||
title: '订单ID', |
|||
dataIndex: 'ticket' |
|||
}, |
|||
{ |
|||
title: '用户ID', |
|||
dataIndex: 'user_id', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '手数', |
|||
dataIndex: 'volume', |
|||
align: 'center', |
|||
render: (volume) => ( |
|||
<div>{Number(volume) / 100}</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '开仓价格', |
|||
dataIndex: 'open_price', |
|||
align: 'center' |
|||
}, |
|||
{ |
|||
title: '开仓时间', |
|||
dataIndex: 'open_time', |
|||
align: 'center' |
|||
}, |
|||
] |
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
apiFun={clientApi.mt4_settle_list} |
|||
columns={columns} |
|||
/> |
|||
</div> |
|||
) |
|||
} |
|||
|
|||
export default MT4SettlementOrder; |
@ -1,236 +0,0 @@ |
|||
import React, { FC, useEffect, useMemo, useRef, useState } from "react"; |
|||
import clientApi from "@/package/SimpleTrade/api/client"; |
|||
import MyTable from "@/components/MyTable"; |
|||
import { Button, Input, Modal, notification, Popconfirm, Select } from "antd"; |
|||
import { copy, splitAddress } from "@/utils"; |
|||
import { CopyOutlined } from "@ant-design/icons"; |
|||
|
|||
const UserList: FC = () => { |
|||
|
|||
const [currentItem, setCurrentItem] = useState({} as any) |
|||
const [isModalOpen, setIsModalOpen] = useState(false) |
|||
const [lv, setLv] = useState(0); |
|||
const tableRefs = useRef<any>() |
|||
const options = useMemo(() => [ |
|||
{ value: 0, label: 'R' }, |
|||
{ value: 1, label: 'G' }, |
|||
{ value: 2, label: 'G1' }, |
|||
{ value: 3, label: 'G2' }, |
|||
{ value: 4, label: 'G3' }, |
|||
{ value: 5, label: 'G4' }, |
|||
{ value: 6, label: 'G5' }, |
|||
], []) |
|||
const columns = [ |
|||
{ |
|||
title: '邮箱', |
|||
dataIndex: 'email' |
|||
}, |
|||
{ |
|||
title: '备注昵称', |
|||
dataIndex: 'remark' |
|||
}, |
|||
{ |
|||
title: '地址', |
|||
dataIndex: 'address', |
|||
render: (address) => ( |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div>{splitAddress(address, 5)}</div> |
|||
<div style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => copy(address)}> |
|||
<CopyOutlined /> |
|||
</div> |
|||
</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: 'A账号', |
|||
dataIndex: 'a_mt4_login' |
|||
}, |
|||
{ |
|||
title: 'A仓余额', |
|||
dataIndex: 'a_mt4_balance' |
|||
}, |
|||
{ |
|||
title: 'A仓订单数量', |
|||
dataIndex: 'a_product' |
|||
}, |
|||
{ |
|||
title: 'B账号', |
|||
dataIndex: 'b_mt4_login' |
|||
}, |
|||
{ |
|||
title: 'B仓余额', |
|||
dataIndex: 'b_mt4_balance' |
|||
}, |
|||
{ |
|||
title: 'B仓订单数量', |
|||
dataIndex: 'b_product' |
|||
}, |
|||
{ |
|||
title: '手数', |
|||
dataIndex: 'volume' |
|||
}, |
|||
{ |
|||
title: '级别', |
|||
dataIndex: 'level', |
|||
render: (level) => ( |
|||
<div>{options[level] ? options[level].label : level}</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '保险开关', |
|||
dataIndex: 'insurance', |
|||
render: (status) => ( |
|||
<div>{status === 1 ? '开' : '关'}</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '邀请码', |
|||
dataIndex: 'invite_code' |
|||
}, |
|||
{ |
|||
title: '推荐人', |
|||
dataIndex: 'referrer' |
|||
}, |
|||
{ |
|||
title: '操作', |
|||
dataIndex: 'operations', |
|||
align: 'center', |
|||
fixed: 'right', |
|||
key: Date.now(), |
|||
width: 180, |
|||
render: (text, record) => { |
|||
return ( |
|||
<div> |
|||
<div> |
|||
<Button type="primary" className="btn" size="small" onClick={() => { |
|||
setCurrentItem(record) |
|||
setIsModalOpen(true) |
|||
setLv(record.level) |
|||
}}>修改等级</Button> |
|||
<Button style={{ marginLeft: 10 }} type="primary" className="btn" size="small" onClick={() => rename(record.remark, record.invite_code)}>修改备注</Button> |
|||
</div> |
|||
<div style={{ marginTop: 10 }}> |
|||
<Popconfirm title={`确认${!record.deactivate?'停用':'启用'}账号?`} onConfirm={()=>deactivateAccount(record.invite_code,record.deactivate)}> |
|||
<Button type="primary" className="btn" size="small" danger={!record.deactivate}>{!record.deactivate ? '停用账号' :'启用账号'}</Button> |
|||
</Popconfirm> |
|||
</div> |
|||
</div> |
|||
) |
|||
} |
|||
} |
|||
] |
|||
// 搜索栏配置项
|
|||
const searchConfigList = [ |
|||
{ |
|||
key: 'name', |
|||
slot: <Input placeholder="用户名" allowClear />, |
|||
initialValue: '' |
|||
} |
|||
] |
|||
const nicknameRefs = useRef(null) |
|||
|
|||
const deactivateAccount = async (code:string,status:boolean)=>{ |
|||
const res:any = await clientApi.user_deactivate({ |
|||
invite_code:code, |
|||
deactivate:!status |
|||
}) |
|||
if(res.code === 0){ |
|||
notification.success({ |
|||
message: !status ? '停用成功' : '启用成功' |
|||
}) |
|||
tableRefs.current?.update() |
|||
} |
|||
} |
|||
|
|||
const rename = async (name: string, code: string) => { |
|||
Modal.confirm({ |
|||
title: '修改昵称', |
|||
content: ( |
|||
<Input ref={nicknameRefs} placeholder="请输入昵称" /> |
|||
), |
|||
onOk: async () => { |
|||
let _name = nicknameRefs.current.state.value |
|||
const res: any = await clientApi.user_rename({ |
|||
invite_code: code, |
|||
remark: _name |
|||
}) |
|||
if (res.code === 0) { |
|||
notification.success({ |
|||
message: '设置成功' |
|||
}) |
|||
tableRefs.current?.update() |
|||
} |
|||
}, |
|||
onCancel: () => { |
|||
nicknameRefs.current && nicknameRefs.current.setValue('') |
|||
}, |
|||
|
|||
}) |
|||
setTimeout(() => { |
|||
nicknameRefs.current && nicknameRefs.current.setValue(name) |
|||
}, 100) |
|||
|
|||
} |
|||
|
|||
const setLevel = async () => { |
|||
if (currentItem.level === lv) { |
|||
notification.error({ |
|||
message: '设置等级相同', |
|||
}) |
|||
return; |
|||
} |
|||
let res: any = await clientApi.up_levle({ |
|||
level: lv, |
|||
invite_code: currentItem.invite_code |
|||
}) |
|||
if (res.code === 0) { |
|||
notification.success({ |
|||
message: '设置成功' |
|||
}) |
|||
setIsModalOpen(false) |
|||
tableRefs.current?.update() |
|||
} |
|||
} |
|||
|
|||
const handleChange = (_, e) => { |
|||
setLv(e.value) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
if (!isModalOpen) { |
|||
setCurrentItem({}) |
|||
setLv(0) |
|||
} |
|||
}, [isModalOpen]) |
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
ref={tableRefs} |
|||
columns={columns} |
|||
apiFun={clientApi.user_list} |
|||
searchConfigList={searchConfigList} |
|||
rowKey="invite_code" |
|||
/> |
|||
<Modal |
|||
title="设置等级" |
|||
visible={isModalOpen} |
|||
onOk={setLevel} |
|||
onCancel={() => setIsModalOpen(false)} |
|||
> |
|||
{ |
|||
isModalOpen && ( |
|||
<Select |
|||
defaultValue={currentItem.level || 0} |
|||
options={options} |
|||
style={{ width: '100%' }} |
|||
onChange={handleChange} |
|||
/> |
|||
) |
|||
} |
|||
</Modal> |
|||
</div> |
|||
) |
|||
}; |
|||
|
|||
export default UserList; |
@ -1,128 +0,0 @@ |
|||
import React, { FC, useRef } from "react"; |
|||
import clientApi from "@/package/SimpleTrade/api/client"; |
|||
import MyTable from "@/components/MyTable"; |
|||
import { Button, Input, notification, Popconfirm } from "antd"; |
|||
import { CopyOutlined } from "@ant-design/icons"; |
|||
import { copy, getTime, splitAddress } from "@/utils"; |
|||
import { Withdraw_Check } from "@/package/SimpleTrade/types/enum"; |
|||
|
|||
const WithdrawRecord: FC = () => { |
|||
|
|||
const tableRefs = useRef(null) |
|||
|
|||
const columns = [ |
|||
{ |
|||
title: '账号ID', |
|||
dataIndex: 'a_mt4_login' |
|||
}, |
|||
{ |
|||
title: '备注昵称', |
|||
dataIndex: 'remark' |
|||
}, |
|||
{ |
|||
title: '交易ID', |
|||
dataIndex: 'tx_hash', |
|||
render: (tx_hash) => ( |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div>{splitAddress(tx_hash, 5)}</div> |
|||
<div style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => copy(tx_hash)}> |
|||
<CopyOutlined /> |
|||
</div> |
|||
</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '链ID', |
|||
dataIndex: 'chain_id' |
|||
}, |
|||
{ |
|||
title: '提币地址', |
|||
dataIndex: 'to_address', |
|||
render: (to_address) => ( |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div>{splitAddress(to_address, 5)}</div> |
|||
<div style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => copy(to_address)}> |
|||
<CopyOutlined /> |
|||
</div> |
|||
</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '数量', |
|||
dataIndex: 'amount' |
|||
}, |
|||
{ |
|||
title: '币种', |
|||
dataIndex: 'symbol' |
|||
}, |
|||
{ |
|||
title: '提现状态', |
|||
dataIndex: 'status' |
|||
}, |
|||
{ |
|||
title: '处理时间', |
|||
dataIndex: 'handle_time', |
|||
render: (time) => ( |
|||
<div>{getTime(time * 1000)}</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '操作', |
|||
dataIndex: 'operations', |
|||
align: 'center', |
|||
key: Date.now(), |
|||
render: (_, item) => { |
|||
return item.check_status === 1 ? (<div> |
|||
<Popconfirm |
|||
title="确认拒绝吗?" |
|||
onConfirm={() => handleOrder(item, Withdraw_Check.WithdrawCheckReject)} |
|||
> |
|||
<Button size="small" type="primary" danger style={{ marginRight: 20 }}>拒绝</Button> |
|||
</Popconfirm> |
|||
<Popconfirm |
|||
title="确认同意吗?" |
|||
onConfirm={() => handleOrder(item, Withdraw_Check.WithdrawCheckAgree)} |
|||
> |
|||
<Button size="small" type="primary">同意</Button> |
|||
</Popconfirm> |
|||
</div>) : (<></>) |
|||
} |
|||
} |
|||
] |
|||
|
|||
// 搜索栏配置项
|
|||
const searchConfigList = [ |
|||
{ |
|||
key: 'name', |
|||
slot: <Input placeholder="用户名" allowClear />, |
|||
initialValue: '' |
|||
} |
|||
] |
|||
|
|||
const handleOrder = async (item, type: Withdraw_Check) => { |
|||
const res: any = await clientApi.withdraw_check({ |
|||
id: item.id, |
|||
status: type |
|||
}) |
|||
if (res.code === 0) { |
|||
notification.success({ |
|||
message: type === Withdraw_Check.WithdrawCheckAgree ? '已同意' : '已拒绝' |
|||
}) |
|||
tableRefs.current?.update() |
|||
} |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
ref={tableRefs} |
|||
columns={columns} |
|||
apiFun={clientApi.withdraw_list} |
|||
searchConfigList={searchConfigList} |
|||
rowKey="id" |
|||
/> |
|||
</div> |
|||
) |
|||
}; |
|||
|
|||
export default WithdrawRecord; |
@ -1,352 +0,0 @@ |
|||
import React, { FC, useEffect, useState } from 'react' |
|||
import './index.less' |
|||
import { useSelector } from 'react-redux' |
|||
import api from '@/package/SimpleTrade/api' |
|||
import { DatePicker } from 'antd'; |
|||
import dayjs from 'dayjs'; |
|||
import customParseFormat from 'dayjs/plugin/customParseFormat'; |
|||
import weekday from "dayjs/plugin/weekday" |
|||
import localeData from "dayjs/plugin/localeData" |
|||
dayjs.extend(customParseFormat); |
|||
dayjs.extend(weekday); |
|||
dayjs.extend(localeData); |
|||
const { RangePicker } = DatePicker; |
|||
const dateFormat = 'YYYY-MM-DD'; |
|||
|
|||
const Home: FC = () => { |
|||
|
|||
const theme = useSelector((state: any) => state.storeData.theme) |
|||
|
|||
const [userTable, setUserTable] = useState([]) |
|||
const [newToDay, setNewToDay] = useState(0) //今日新增
|
|||
const [userTotal, setUserTotal] = useState(0) //用户统计
|
|||
const start_time = dayjs().subtract(7, 'days') |
|||
const end_time = dayjs() |
|||
|
|||
const [defaultValue, setDefaultValue] = useState([start_time, end_time] as any) //周期合约时间
|
|||
const [withdrawTime, setWithdrawTime] = useState([start_time, end_time] as any) //周期充值提现时间
|
|||
|
|||
const [toDayTx, setToDayTx] = useState([ |
|||
{ title: '今日订单金额', value: '0' }, |
|||
{ title: '今日订单数量', value: '0' }, |
|||
{ title: 'A仓盈利订单数量', value: '0', color: '#3BB900' }, |
|||
{ title: 'B仓盈利订单数量', value: '0', color: '#3BB900' }, |
|||
{ title: 'A仓亏损订单数量', value: '0', color: '#F4002C' }, |
|||
{ title: 'B仓亏损订单数量', value: '0', color: '#F4002C' }, |
|||
{ title: '盈利订单金额', value: '0', color: '#3BB900' }, |
|||
{ title: '亏损订单金额', value: '0', color: '#F4002C' }, |
|||
]) |
|||
|
|||
const [weekTx, setWeekTx] = useState([ |
|||
{ title: '订单总金额', value: '0' }, |
|||
{ title: '订单总数量', value: '0' }, |
|||
{ title: 'A仓盈利订单数量', value: '0', color: '#3BB900' }, |
|||
{ title: 'B仓盈利订单数量', value: '0', color: '#3BB900' }, |
|||
{ title: 'A仓亏损订单数量', value: '0', color: '#F4002C' }, |
|||
{ title: 'B仓亏损订单数量', value: '0', color: '#F4002C' }, |
|||
{ title: '盈利订单金额', value: '0', color: '#3BB900' }, |
|||
{ title: '亏损订单金额', value: '0', color: '#F4002C' }, |
|||
]) |
|||
|
|||
const [transaction, setTransaction] = useState([]) |
|||
const [weekTransaction, setWeekTransaction] = useState([]) |
|||
|
|||
// 用户统计
|
|||
const getUserData = async () => { |
|||
const res: any = await api.user_statistics() |
|||
if (res.code === 0) { |
|||
setNewToDay(res.data.NewToday) |
|||
setUserTotal(res.data.total_amount) |
|||
setUserTable(res.data.AdminUserAmountList) |
|||
} |
|||
} |
|||
|
|||
// 周期合约交易订单统计
|
|||
const getWeekTxOrderStatic = async () => { |
|||
const start = Math.floor(defaultValue[0].valueOf() / 1000) |
|||
const end = Math.floor(defaultValue[1].valueOf() / 1000) |
|||
const res: any = await api.transaction_statistics({ |
|||
end_time: end, |
|||
start_time: start, |
|||
type: 2 |
|||
}) |
|||
if (res.code === 0) { |
|||
weekTx[0].value = res.data.product_amount |
|||
weekTx[1].value = res.data.product_num |
|||
weekTx[2].value = res.data.a_profit_num |
|||
weekTx[3].value = res.data.b_profit_num |
|||
weekTx[4].value = res.data.a_loss_num |
|||
weekTx[5].value = res.data.b_loss_num |
|||
weekTx[6].value = res.data.profit_amount |
|||
weekTx[7].value = res.data.loss_amount |
|||
setWeekTx([...weekTx]) |
|||
} |
|||
} |
|||
|
|||
// 周期充值提现
|
|||
const getWeekTransaction = async () => { |
|||
const start = Math.floor(withdrawTime[0].valueOf() / 1000) |
|||
const end = Math.floor(withdrawTime[1].valueOf() / 1000) |
|||
const res: any = await api.week_recharge_withdraw_statistics({ |
|||
end_time: end, |
|||
start_time: start, |
|||
type: 2 |
|||
}) |
|||
if (res.code === 0 && res.data) { |
|||
|
|||
setWeekTransaction(res.data) |
|||
} |
|||
} |
|||
|
|||
// 今日合约交易订单统计
|
|||
const getDayTxOrderStatic = async () => { |
|||
const res: any = await api.transaction_statistics({ |
|||
type: 1 |
|||
}) |
|||
if (res.code === 0) { |
|||
toDayTx[0].value = res.data.product_amount |
|||
toDayTx[1].value = res.data.product_num |
|||
toDayTx[2].value = res.data.a_profit_num |
|||
toDayTx[3].value = res.data.b_profit_num |
|||
toDayTx[4].value = res.data.a_loss_num |
|||
toDayTx[5].value = res.data.b_loss_num |
|||
toDayTx[6].value = res.data.profit_amount |
|||
toDayTx[7].value = res.data.loss_amount |
|||
setToDayTx([...toDayTx]) |
|||
} |
|||
} |
|||
|
|||
// 充值提现统计
|
|||
const getRechargeAndWithdraw = async () => { |
|||
const res: any = await api.recharge_withdraw_statistics() |
|||
if (res.code === 0) { |
|||
setTransaction(res.data) |
|||
} |
|||
} |
|||
|
|||
useEffect(() => { |
|||
getUserData() |
|||
getDayTxOrderStatic() |
|||
getRechargeAndWithdraw() |
|||
}, []) |
|||
|
|||
useEffect(() => { |
|||
getWeekTxOrderStatic() |
|||
}, [defaultValue]) |
|||
|
|||
useEffect(() => { |
|||
getWeekTransaction() |
|||
}, [withdrawTime]) |
|||
|
|||
return ( |
|||
<div className='home' style={{ minHeight: '80vh', backgroundColor: theme && '#fff' }}> |
|||
<h3>Hello, Randy!</h3> |
|||
<div>Today is a good day to start trading crypto assets!</div> |
|||
{/* */} |
|||
<div className='box' style={{ backgroundColor: theme ? '#f5f5f5' : '#333' }}> |
|||
<div style={{ fontWeight: 'bold' }}>用户统计</div> |
|||
<div className='row'> |
|||
<div style={{ flex: 3, marginTop: 30 }}> |
|||
<h2>{userTotal.toLocaleString()}</h2> |
|||
<div className='row-items' style={{ marginTop: 20 }}> |
|||
<div className='img-box'> |
|||
<img src={require('./vector.png')} alt="" /> |
|||
</div> |
|||
<div style={{ marginLeft: 10 }}> |
|||
<div style={{ fontWeight: 'bold' }}>+{newToDay.toLocaleString()}</div> |
|||
<div style={{ fontSize: 12, marginTop: 5 }}>今日新增</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div className='solid' style={{ backgroundColor: theme ? '#e8e8e8' : '#555' }}></div> |
|||
<div style={{ flex: 4, marginLeft: 20 }}> |
|||
<div className='row' style={{ textAlign: 'center' }}> |
|||
<div style={{ flex: 1 }}>类型</div> |
|||
<div style={{ flex: 1 }}>截止昨日</div> |
|||
<div style={{ flex: 1 }}>今日新增</div> |
|||
</div> |
|||
<div> |
|||
{ |
|||
userTable.map((item, index) => ( |
|||
<div key={index} className='row' style={{ textAlign: 'center', marginTop: 20 }}> |
|||
<div style={{ flex: 1 }}>{item.type}</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>{Number(item.yesterday_amount).toLocaleString()}</div> |
|||
<div>{item.yesterday_percentage}</div> |
|||
</div> |
|||
<div style={{ flex: 1, color: '#44D600' }}> |
|||
<div>{Number(item.new_today_amount).toLocaleString()}</div> |
|||
<div>{item.new_today_percentage}</div> |
|||
</div> |
|||
</div> |
|||
)) |
|||
} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
{/* */} |
|||
<div className='box row' style={{ backgroundColor: theme ? '#f5f5f5' : '#333', marginTop: 30 }}> |
|||
<div style={{ flex: 3 }}> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14 }}>今日合约交易订单统计</div> |
|||
<div style={{ marginTop: 20, textAlign: 'center', flexWrap: 'wrap' }} className='row-items'> |
|||
{ |
|||
toDayTx.map((item, index) => ( |
|||
<div key={index} style={{ width: '50%', marginTop: 10 }}> |
|||
<div style={{ fontSize: 14 }}>{item.title}</div> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14, color: item.color }}>{Number(item.value).toLocaleString()}</div> |
|||
</div> |
|||
)) |
|||
} |
|||
</div> |
|||
</div> |
|||
<div className='solid' style={{ backgroundColor: theme ? '#e8e8e8' : '#555', margin: '0 20px' }}></div> |
|||
<div style={{ flex: 4 }}> |
|||
<div className='row-between'> |
|||
<div className='row-items'> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14 }}>周期合约交易订单统计</div> |
|||
<div style={{ marginLeft: 10 }}> |
|||
<RangePicker |
|||
defaultValue={defaultValue} |
|||
onChange={setDefaultValue} |
|||
format={dateFormat} |
|||
/> |
|||
</div> |
|||
</div> |
|||
<div className='row-items'> |
|||
{/* <div>导出</div> */} |
|||
</div> |
|||
</div> |
|||
<div style={{ marginTop: 20, textAlign: 'center', flexWrap: 'wrap' }} className='row-items'> |
|||
{ |
|||
weekTx.map((item, index) => ( |
|||
<div key={index} style={{ width: '50%', marginTop: 10 }}> |
|||
<div style={{ fontSize: 14 }}>{item.title}</div> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14, color: item.color }}>{Number(item.value).toLocaleString()}</div> |
|||
</div> |
|||
)) |
|||
} |
|||
</div> |
|||
</div> |
|||
</div> |
|||
{/* */} |
|||
{transaction[0] && transaction[1] && <div className='box row' style={{ backgroundColor: theme ? '#f5f5f5' : '#333', marginTop: 30 }}> |
|||
<div style={{ flex: 4 }}> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14 }}>{transaction[0].symbol} 充值提现</div> |
|||
{/* <div style={{ fontSize: 14, marginTop: 30 }}>净入金:<span style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>2131223</span></div> |
|||
<div style={{ fontSize: 14, marginTop: 30 }}>充值提现比:<span style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>150%</span></div> */} |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 30 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总充值</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(transaction[0].deposit_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>充值笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{transaction[0].deposit_num}</div> |
|||
</div> |
|||
</div> |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 20 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总提现</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(transaction[0].withdrawal_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>提现笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{transaction[0].withdrawal_num}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div className='solid' style={{ backgroundColor: theme ? '#e8e8e8' : '#555', margin: '0 20px' }}></div> |
|||
<div style={{ flex: 4 }}> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14 }}>{transaction[1].symbol} 充值提现</div> |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 30 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总充值</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(transaction[1].deposit_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>充值笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{transaction[1].deposit_num}</div> |
|||
</div> |
|||
</div> |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 20 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总提现</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(transaction[1].withdrawal_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>提现笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{transaction[1].withdrawal_num}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div>} |
|||
{/* */} |
|||
{weekTransaction[0] && weekTransaction[1] && ( |
|||
<div className='box' style={{ marginTop: 30, backgroundColor: theme ? '#f5f5f5' : '#333' }}> |
|||
<div> |
|||
<RangePicker |
|||
defaultValue={withdrawTime} |
|||
onChange={setWithdrawTime} |
|||
format={dateFormat} |
|||
/> |
|||
</div> |
|||
<div className='row' style={{ marginTop: 20 }}> |
|||
<div style={{ flex: 4 }}> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14 }}>{weekTransaction[0].symbol} 周期充值提现</div> |
|||
{/* <div style={{ fontSize: 14, marginTop: 30 }}>净入金:<span style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>2131223</span></div> |
|||
<div style={{ fontSize: 14, marginTop: 30 }}>充值提现比:<span style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>150%</span></div> */} |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 30 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总充值</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(weekTransaction[0].deposit_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>充值笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{weekTransaction[0].deposit_num}</div> |
|||
</div> |
|||
</div> |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 20 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总提现</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(weekTransaction[0].withdrawal_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>提现笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{weekTransaction[0].withdrawal_num}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
<div className='solid' style={{ backgroundColor: theme ? '#e8e8e8' : '#555', margin: '0 20px' }}></div> |
|||
<div style={{ flex: 4 }}> |
|||
<div style={{ fontWeight: 'bold', fontSize: 14 }}>{weekTransaction[1].symbol} 周期充值提现</div> |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 30 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总充值</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(weekTransaction[1].deposit_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>充值笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{weekTransaction[1].deposit_num}</div> |
|||
</div> |
|||
</div> |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 20 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>总提现</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(weekTransaction[1].withdrawal_amount).toLocaleString()}</div> |
|||
</div> |
|||
<div style={{ flex: 1 }}> |
|||
<div>提现笔数</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{weekTransaction[1].withdrawal_num}</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
</div> |
|||
)} |
|||
<div style={{ display: 'block', height: 30 }}></div> |
|||
</div > |
|||
) |
|||
} |
|||
|
|||
export default Home |
@ -1,177 +0,0 @@ |
|||
import Home from '@/package/SimpleTrade/pages/home' |
|||
import ErrorPage from '@/pages/public/errorPage' |
|||
|
|||
import AdminUserList from '@/package/SimpleTrade/pages/adminuser/list' |
|||
import AdminUserEdit from '@/package/SimpleTrade/pages/adminuser/edit' |
|||
|
|||
import AdminPermissionList from '@/package/SimpleTrade/pages/adminpermission/list' |
|||
|
|||
import InviteChart from '@/package/SimpleTrade/pages/admininvite/chart' |
|||
import UploadAPK from '@/package/SimpleTrade/pages/adminupload/uploadapk' |
|||
import UserList from '@/package/SimpleTrade/pages/client/user' |
|||
import WithdrawRecord from '@/package/SimpleTrade/pages/client/withdraw' |
|||
import RechargeRecord from '@/package/SimpleTrade/pages/client/recharge' |
|||
import MT4History from '@/package/SimpleTrade/pages/client/mt4history' |
|||
import MT4Order from '@/package/SimpleTrade/pages/client/mt4order' |
|||
import MT4SettlementOrder from '@/package/SimpleTrade/pages/client/mt4settlementorder' |
|||
|
|||
import { HomeOutlined, UserOutlined, AuditOutlined } from '@ant-design/icons' |
|||
|
|||
/** |
|||
* path 跳转的路径 |
|||
* component 对应路径显示的组件 |
|||
* exact 匹配规则,true的时候则精确匹配。 |
|||
*/ |
|||
const menus = [ |
|||
{ |
|||
path: '/', |
|||
name: '首页', |
|||
exact: true, |
|||
key: 'home', |
|||
icon: HomeOutlined, |
|||
component: Home, |
|||
routes: [] |
|||
}, |
|||
{ |
|||
path: '/adminuser', |
|||
name: '用户管理', |
|||
key: 'adminuser', |
|||
type: 'subMenu', |
|||
icon: UserOutlined, |
|||
iconfont: 'icon-xiaoshouzongjian', |
|||
routes: [ |
|||
{ |
|||
path: '/adminuser/list', |
|||
name: '用户列表', |
|||
exact: true, |
|||
key: 'adminuser:list:view', |
|||
component: AdminUserList |
|||
}, |
|||
{ |
|||
path: '/adminuser/list/add', |
|||
name: '新增用户', |
|||
exact: true, |
|||
key: 'adminuser:list:add', |
|||
component: AdminUserEdit, |
|||
remove: true |
|||
}, |
|||
{ |
|||
path: '/adminuser/list/edit', |
|||
name: '编辑用户', |
|||
exact: true, |
|||
key: 'adminuser:list:edit', |
|||
component: AdminUserEdit, |
|||
remove: true |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/adminpermission', |
|||
name: '权限管理', |
|||
key: 'adminpermission', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/adminpermission/list', |
|||
name: '权限列表', |
|||
exact: true, |
|||
key: 'adminpermission:list:view', |
|||
component: AdminPermissionList |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/admininvite', |
|||
name: '邀请', |
|||
key: 'admininvite', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/admininvite/chart', |
|||
name: '关联图', |
|||
exact: true, |
|||
key: 'admininvite:chart:view', |
|||
component: InviteChart |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/adminupload', |
|||
name: '上传管理', |
|||
key: 'adminupload', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/adminupload/uploadapk', |
|||
name: '上传APK', |
|||
exact: true, |
|||
key: 'adminupload:uploadapk:view', |
|||
component: UploadAPK |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/client', |
|||
name: '客户端', |
|||
key: 'client', |
|||
type: 'subMenu', |
|||
icon: AuditOutlined, |
|||
routes: [ |
|||
{ |
|||
path: '/client/userlist', |
|||
name: '用户列表', |
|||
exact: true, |
|||
key: 'client:userlist:view', |
|||
component: UserList |
|||
}, |
|||
{ |
|||
path: '/client/recharge', |
|||
name: '充值记录', |
|||
exact: true, |
|||
key: 'client:recharge:view', |
|||
component: RechargeRecord |
|||
}, |
|||
{ |
|||
path: '/client/withdraw', |
|||
name: '提现记录', |
|||
exact: true, |
|||
key: 'client:withdraw:view', |
|||
component: WithdrawRecord |
|||
}, |
|||
{ |
|||
path: '/client/mt4history', |
|||
name: 'MT4历史记录', |
|||
exact: true, |
|||
key: 'client:mt4history:view', |
|||
component: MT4History |
|||
}, |
|||
{ |
|||
path: '/client/mt4order', |
|||
name: 'MT4订单列表', |
|||
exact: true, |
|||
key: 'client:mt4order:view', |
|||
component: MT4Order |
|||
}, |
|||
{ |
|||
path: '/client/mt4settlementorder', |
|||
name: 'MT4结算订单列表', |
|||
exact: true, |
|||
key: 'client:mt4settlementorder:view', |
|||
component: MT4SettlementOrder |
|||
} |
|||
] |
|||
}, |
|||
{ |
|||
path: '/403', |
|||
name: '暂无权限', |
|||
exact: true, |
|||
key: '/403', |
|||
component: ErrorPage, |
|||
remove: true |
|||
} |
|||
] |
|||
|
|||
export default menus |
@ -1,38 +0,0 @@ |
|||
// 提币状态
|
|||
export enum Withdraw_Status { |
|||
WithdrawStatusFail = -1, //链上错误
|
|||
WithdrawStatusInit = 0, //初始状态
|
|||
WithdrawStatusCheck = 1, //审核
|
|||
WithdrawStatusHex = 2, //生成签名数据
|
|||
WithdrawStatusSend = 3, //已发送
|
|||
WithdrawStatusConfirm = 4, //确认中
|
|||
WithdrawStatusEnd = 5, //完成
|
|||
} |
|||
|
|||
export enum Withdraw_Check { |
|||
WithdrawCheckNIL =0, // 无需审核0
|
|||
WithdrawCheckWait =1, // 审核中1
|
|||
WithdrawCheckReject =2, // 审核 驳回2
|
|||
WithdrawCheckAgree =3, // 审核同意完成3
|
|||
} |
|||
|
|||
// 提现状态
|
|||
export enum Recharge_Status { |
|||
TxStatusErr = -1 ,//业务错误
|
|||
TxStatusFail = -2, //链上错误
|
|||
TxStatusInit = 0, //初始记录
|
|||
TxStatusConfirm = 1, //确认数到账 100块后 转入到账户中
|
|||
TxStatusNotify = 2, //允许交易
|
|||
} |
|||
|
|||
// 用户状态
|
|||
export enum User_Status{ |
|||
EmailUserStatusRoot = 0, //根邀请人
|
|||
EmailUserStatusInit = 1, //H5注册
|
|||
EmailUserStatusUse = 2, //提交激活信息
|
|||
EmailUserStatusAMT4 = 3, //创建A仓账号
|
|||
EmailUserStatusBMT4 = 4, //创建B仓账号
|
|||
EmailUserStatusCopy = 5, //A->B账号关联反向下单
|
|||
EmailUserStatusSendEmail = 6, //仓位账号初始化完成进行邮件发送
|
|||
EmailUserStatusActivated = 7, //完成激活
|
|||
} |
@ -0,0 +1,114 @@ |
|||
import React, { FC, useEffect, useRef, useState } from 'react' |
|||
import './index.less' |
|||
import api from '@/api' |
|||
import { useSelector } from 'react-redux' |
|||
import { Button, Form, Input, Modal, notification } from 'antd' |
|||
|
|||
const Home: FC = () => { |
|||
|
|||
const theme = useSelector((state: any) => state.storeData.theme) |
|||
|
|||
|
|||
const [userData, setUserData] = useState({} as any) |
|||
const [visible, setVisible] = useState(false) |
|||
|
|||
const amountRef = useRef(null) |
|||
const addressRef = useRef(null) |
|||
const typeRef = useRef(0) |
|||
|
|||
|
|||
// 充值提现统计
|
|||
const getRechargeAndWithdraw = async () => { |
|||
const res: any = await api.home_info() |
|||
if (res.code === 0) { |
|||
setUserData(res.data) |
|||
} |
|||
} |
|||
|
|||
// 1.利息 2.已到期质押提现
|
|||
const withdraw = async () => { |
|||
const params = { |
|||
address: addressRef.current.state.value, |
|||
amount: amountRef.current.state.value, |
|||
type: typeRef.current |
|||
} |
|||
setVisible(false) |
|||
const res: any = await api.withdraw(params) |
|||
if (res.code === 0) { |
|||
getRechargeAndWithdraw() |
|||
notification.success({ |
|||
message: '提现成功' |
|||
}) |
|||
} |
|||
} |
|||
|
|||
const openModal = (type: number) => { |
|||
typeRef.current = type |
|||
setVisible(true) |
|||
} |
|||
|
|||
useEffect(() => { |
|||
getRechargeAndWithdraw() |
|||
}, []) |
|||
|
|||
useEffect(() => { |
|||
const resetQuery = () => { |
|||
|
|||
addressRef.current && (amountRef.current.state.value = '') |
|||
addressRef.current && (addressRef.current.state.value = '') |
|||
typeRef.current = 0 |
|||
} |
|||
!visible && resetQuery() |
|||
}, [visible]) |
|||
|
|||
return ( |
|||
<div className='home' style={{ minHeight: '80vh', backgroundColor: theme && '#fff' }}> |
|||
<h3>Hello, Randy!</h3> |
|||
<div>Today is a good day to start trading crypto assets!</div> |
|||
{/* */} |
|||
<div className='box row' style={{ backgroundColor: theme ? '#f5f5f5' : '#333', marginTop: 30 }}> |
|||
<div style={{ flex: 4 }}> |
|||
{/* <div style={{ fontSize: 14, marginTop: 30 }}>净入金:<span style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>2131223</span></div> |
|||
<div style={{ fontSize: 14, marginTop: 30 }}>充值提现比:<span style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>150%</span></div> */} |
|||
<div className='row' style={{ textAlign: 'center', marginTop: 30 }}> |
|||
<div style={{ flex: 1 }}> |
|||
<div>质押数量</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(userData.pledge_amount).toLocaleString()}</div> |
|||
</div> |
|||
|
|||
<div style={{ flex: 1 }}> |
|||
<div>总利息</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(userData.interest_balance).toLocaleString()}</div> |
|||
<Button type='primary' onClick={() => openModal(1)}>提现</Button> |
|||
</div> |
|||
|
|||
<div style={{ flex: 1 }}> |
|||
<div>已到期质押余额</div> |
|||
<div style={{ fontSize: 20, color: '#3BB900', fontWeight: 'bold' }}>{Number(userData.expired_pledge_balance).toLocaleString()}</div> |
|||
<Button type='primary' onClick={() => openModal(2)}>提现</Button> |
|||
</div> |
|||
|
|||
</div> |
|||
|
|||
|
|||
</div> |
|||
</div> |
|||
<div style={{ display: 'block', height: 30 }}></div> |
|||
|
|||
<Modal visible={visible} onCancel={() => setVisible(false)} onOk={withdraw}> |
|||
<div style={{ marginTop: 40 }}> |
|||
<Form> |
|||
<Form.Item label="地址"> |
|||
<Input placeholder='输入提现地址' ref={addressRef} /> |
|||
</Form.Item> |
|||
<Form.Item label="数量"> |
|||
<Input placeholder='输入提现数量' ref={amountRef} /> |
|||
</Form.Item> |
|||
</Form> |
|||
</div> |
|||
</Modal> |
|||
</div > |
|||
) |
|||
} |
|||
|
|||
export default Home |
Before Width: 90 | Height: 90 | Size: 589 B After Width: 90 | Height: 90 | Size: 589 B |
@ -0,0 +1,75 @@ |
|||
import React, { FC } from "react"; |
|||
import MyTable from "@/components/MyTable"; |
|||
import { Button, Input } from "antd"; |
|||
import { copy, getTime, splitAddress } from "@/utils"; |
|||
import { CopyOutlined } from "@ant-design/icons"; |
|||
import api from "@/api"; |
|||
import { store } from "@/store"; |
|||
import { RootStateOrAny, useSelector } from "react-redux"; |
|||
|
|||
const Interest: FC = () => { |
|||
|
|||
const { storeData } = useSelector((state: RootStateOrAny) => state) |
|||
|
|||
|
|||
const columns = [ |
|||
// {
|
|||
// title: '地址',
|
|||
// dataIndex: 'to_address',
|
|||
// render: (address) => (
|
|||
// <div style={{ display: 'flex', alignItems: 'center' }}>
|
|||
// <div>{splitAddress(address, 5)}</div>
|
|||
// <div style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => copy(address)}>
|
|||
// <CopyOutlined />
|
|||
// </div>
|
|||
// </div>
|
|||
// )
|
|||
// },
|
|||
{ |
|||
title: 'ID', |
|||
dataIndex: 'id' |
|||
}, |
|||
{ |
|||
title: '利息', |
|||
dataIndex: 'amount', |
|||
width: 350 |
|||
}, |
|||
|
|||
{ |
|||
title: '类型', |
|||
dataIndex: 'type' |
|||
}, |
|||
{ |
|||
title: '币种', |
|||
dataIndex: 'symbol' |
|||
}, |
|||
|
|||
{ |
|||
title: '创建时间', |
|||
dataIndex: 'created_time', |
|||
render: (_time) => (<div>{getTime(_time * 1000)}</div>) |
|||
}, |
|||
] |
|||
|
|||
// 搜索栏配置项
|
|||
// const searchConfigList = [
|
|||
// {
|
|||
// key: 'name',
|
|||
// slot: <Input placeholder="用户名" allowClear />,
|
|||
// initialValue: ''
|
|||
// }
|
|||
// ]
|
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
columns={columns} |
|||
apiFun={api.income_list} |
|||
// searchConfigList={searchConfigList}
|
|||
rowKey="id" |
|||
/> |
|||
</div> |
|||
) |
|||
}; |
|||
|
|||
export default Interest; |
@ -0,0 +1,120 @@ |
|||
import React, { FC } from "react"; |
|||
import MyTable from "@/components/MyTable"; |
|||
import { Button, Input } from "antd"; |
|||
import { copy, getTime, splitAddress } from "@/utils"; |
|||
import { CopyOutlined } from "@ant-design/icons"; |
|||
import api from "@/api"; |
|||
import { store } from "@/store"; |
|||
import { RootStateOrAny, useSelector } from "react-redux"; |
|||
|
|||
const Order: FC = () => { |
|||
|
|||
const { storeData } = useSelector((state: RootStateOrAny) => state) |
|||
|
|||
|
|||
const columns = [ |
|||
{ |
|||
title: 'ID', |
|||
dataIndex: 'id' |
|||
}, |
|||
{ |
|||
title: '质押数量', |
|||
dataIndex: 'product_amount' |
|||
}, |
|||
{ |
|||
title: '产品总天数', |
|||
dataIndex: 'product_day' |
|||
}, |
|||
{ |
|||
title: '产品当前天数', |
|||
dataIndex: 'released_day' |
|||
}, |
|||
|
|||
{ |
|||
title: '年化', |
|||
dataIndex: 'annualized' |
|||
}, |
|||
|
|||
{ |
|||
title: '状态', |
|||
dataIndex: 'status_name' |
|||
}, |
|||
|
|||
{ |
|||
title: '总利息', |
|||
dataIndex: 'amount' |
|||
}, |
|||
|
|||
{ |
|||
title: '已释放利息', |
|||
dataIndex: 'available' |
|||
}, |
|||
|
|||
{ |
|||
title: '未释放利息', |
|||
dataIndex: 'hold' |
|||
}, |
|||
|
|||
{ |
|||
title: '币种', |
|||
dataIndex: 'symbol' |
|||
}, |
|||
|
|||
{ |
|||
title: '订单创建时间', |
|||
dataIndex: 'time', |
|||
render: (_time) => (<div>{getTime(_time * 1000)}</div>) |
|||
}, |
|||
|
|||
{ |
|||
title: '订单生效时间', |
|||
dataIndex: 'start_time', |
|||
render: (_time) => (<div>{getTime(_time * 1000)}</div>) |
|||
}, |
|||
|
|||
{ |
|||
title: '订单结束时间', |
|||
dataIndex: 'end_time', |
|||
render: (_time) => (<div>{getTime(_time * 1000)}</div>) |
|||
}, |
|||
] |
|||
|
|||
// 搜索栏配置项
|
|||
// const searchConfigList = [
|
|||
// {
|
|||
// key: 'name',
|
|||
// slot: <Input placeholder="用户名" allowClear />,
|
|||
// initialValue: ''
|
|||
// }
|
|||
// ]
|
|||
|
|||
const exprotExcel = async () => { |
|||
// window.open(`${process.env.REACT_APP_BASE_URL}/admin/product/excel`)
|
|||
const { token = '' } = storeData.userInfo || {} |
|||
const res = await fetch(`${process.env.REACT_APP_BASE_URL}/admin/product/excel`, { |
|||
headers: { |
|||
Token: token |
|||
}, |
|||
method: 'get', |
|||
}) |
|||
const blob = await res.blob() |
|||
const url = window.URL.createObjectURL(blob) |
|||
window.open(url) |
|||
} |
|||
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
columns={columns} |
|||
apiFun={api.order_list} |
|||
// searchConfigList={searchConfigList}
|
|||
rowKey="id" |
|||
/> |
|||
<div style={{ marginBottom: 20 }} > |
|||
<Button onClick={exprotExcel}>导出订单(excel)</Button> |
|||
</div> |
|||
</div> |
|||
) |
|||
}; |
|||
|
|||
export default Order; |
@ -0,0 +1,92 @@ |
|||
import React, { FC, useRef } from "react"; |
|||
import MyTable from "@/components/MyTable"; |
|||
import { Button, Input, notification, Popconfirm } from "antd"; |
|||
import { CopyOutlined } from "@ant-design/icons"; |
|||
import { copy, getTime, splitAddress } from "@/utils"; |
|||
import api from "@/api"; |
|||
|
|||
const Withdraw: FC = () => { |
|||
|
|||
const tableRefs = useRef(null) |
|||
|
|||
const columns = [ |
|||
{ |
|||
title: 'ID', |
|||
dataIndex: 'id' |
|||
}, |
|||
{ |
|||
title: '提币地址', |
|||
dataIndex: 'to_address', |
|||
render: (to_address) => ( |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div>{splitAddress(to_address, 5)}</div> |
|||
<div style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => copy(to_address)}> |
|||
<CopyOutlined /> |
|||
</div> |
|||
</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '交易ID', |
|||
dataIndex: 'tx_hash', |
|||
render: (tx_hash) => ( |
|||
<div style={{ display: 'flex', alignItems: 'center' }}> |
|||
<div>{splitAddress(tx_hash, 5)}</div> |
|||
<div style={{ marginLeft: 5, cursor: 'pointer' }} onClick={() => copy(tx_hash)}> |
|||
<CopyOutlined /> |
|||
</div> |
|||
</div> |
|||
) |
|||
}, |
|||
{ |
|||
title: '链ID', |
|||
dataIndex: 'chain_id' |
|||
}, |
|||
{ |
|||
title: '数量', |
|||
dataIndex: 'amount' |
|||
}, |
|||
{ |
|||
title: '币种', |
|||
dataIndex: 'symbol' |
|||
}, |
|||
{ |
|||
title: '提现状态', |
|||
dataIndex: 'status_name' |
|||
}, |
|||
{ |
|||
title: '提现类型', |
|||
dataIndex: 'type' |
|||
}, |
|||
{ |
|||
title: '处理时间', |
|||
dataIndex: 'created_time', |
|||
render: (time) => ( |
|||
<div>{getTime(time * 1000)}</div> |
|||
) |
|||
} |
|||
|
|||
] |
|||
|
|||
// 搜索栏配置项
|
|||
// const searchConfigList = [
|
|||
// {
|
|||
// key: 'name',
|
|||
// slot: <Input placeholder="用户名" allowClear />,
|
|||
// initialValue: ''
|
|||
// }
|
|||
// ]
|
|||
return ( |
|||
<div> |
|||
<MyTable |
|||
ref={tableRefs} |
|||
columns={columns} |
|||
apiFun={api.withdraw_list} |
|||
// searchConfigList={searchConfigList}
|
|||
rowKey="id" |
|||
/> |
|||
</div> |
|||
) |
|||
}; |
|||
|
|||
export default Withdraw; |
@ -1,9 +1,57 @@ |
|||
import SimpleTradeRoutes from '@/package/SimpleTrade/route/routes' |
|||
import Home from "@/pages/home" |
|||
import Interest from "@/pages/interest" |
|||
import Order from "@/pages/order" |
|||
import Recharge from "@/pages/recharge" |
|||
import Withdraw from "@/pages/withdraw" |
|||
import { HomeOutlined, SolutionOutlined } from "@ant-design/icons" |
|||
|
|||
const routes = { |
|||
simpleTradeKey: [...SimpleTradeRoutes], |
|||
} |
|||
const routes = [ |
|||
{ |
|||
path: '/', |
|||
name: '首页', |
|||
exact: true, |
|||
key: 'home', |
|||
icon: HomeOutlined, |
|||
component: Home, |
|||
routes: [] |
|||
}, |
|||
{ |
|||
path: '/recharge', |
|||
name: '充值', |
|||
exact: true, |
|||
key: 'recharge', |
|||
icon: SolutionOutlined, |
|||
component: Recharge, |
|||
routes: [] |
|||
}, |
|||
{ |
|||
path: '/withdraw', |
|||
name: '提现', |
|||
exact: true, |
|||
key: 'withdraw', |
|||
icon: SolutionOutlined, |
|||
component: Withdraw, |
|||
routes: [] |
|||
}, |
|||
{ |
|||
path: '/order', |
|||
name: '订单', |
|||
exact: true, |
|||
key: 'order', |
|||
icon: SolutionOutlined, |
|||
component: Order, |
|||
routes: [] |
|||
}, |
|||
{ |
|||
path: '/interest', |
|||
name: '利息', |
|||
exact: true, |
|||
key: 'interest', |
|||
icon: SolutionOutlined, |
|||
component: Interest, |
|||
routes: [] |
|||
} |
|||
] |
|||
|
|||
const currentItem = routes.simpleTradeKey |
|||
|
|||
export default currentItem |
|||
export default routes |
13420
yarn.lock
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
Write
Preview
Loading…
Cancel
Save
Reference in new issue