Compare commits
26 Commits
master
...
user-vance
| Author | SHA1 | Date |
|---|---|---|
|
|
e4c423acba | |
|
|
e71e8b6012 | |
|
|
de5c5695cd | |
|
|
b1ba349063 | |
|
|
494b7b467a | |
|
|
566bbd8e35 | |
|
|
144152bafc | |
|
|
d8f099d7fd | |
|
|
ca87af0bdc | |
|
|
827d10360c | |
|
|
8a8c69b8ad | |
|
|
f6a6d7ba96 | |
|
|
9ac71cf6e5 | |
|
|
b2e43272d9 | |
|
|
9f74a89073 | |
|
|
d13aab8aa4 | |
|
|
377e21b87a | |
|
|
65c09c20e6 | |
|
|
afcaddcc0f | |
|
|
d2991a5ddd | |
|
|
2d06115a4e | |
|
|
31198544d7 | |
|
|
43c2cdb98b | |
|
|
3d6c3b873c | |
|
|
2294e72882 | |
|
|
53ca93a288 |
13
README.md
13
README.md
|
|
@ -7,7 +7,7 @@ This project is initialized with [Ant Design Pro](https://pro.ant.design). Follo
|
||||||
Install `node_modules`:
|
Install `node_modules`:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install
|
yarn install
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
@ -55,3 +55,14 @@ npm test
|
||||||
## More
|
## More
|
||||||
|
|
||||||
You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro).
|
You can view full document on our [official website](https://pro.ant.design). And welcome any feedback in our [github](https://github.com/ant-design/ant-design-pro).
|
||||||
|
|
||||||
|
### 参考文档
|
||||||
|
|
||||||
|
1. [ts 入门](https://ts.xcatliu.com/)
|
||||||
|
1. [react hook 入门](https://www.ruanyifeng.com/blog/2019/09/react-hooks.html)
|
||||||
|
1. [antd4.0](https://ant-design.gitee.io/components/overview-cn/)
|
||||||
|
1. [@ant-design/pro-layout](https://procomponents.ant.design/components/layout)
|
||||||
|
1. [@ant-design/icons](https://ant.design/components/icon-cn/#API)
|
||||||
|
1. [@ant-design/pro-table](https://procomponents.ant.design/components/table)
|
||||||
|
1. [@formily/antd-components](https://formilyjs.org/#/zoi8i0/ZrsYs6hytQ)
|
||||||
|
1. [@formily](https://formilyjs.org)
|
||||||
|
|
|
||||||
|
|
@ -9,9 +9,9 @@
|
||||||
export default {
|
export default {
|
||||||
dev: {
|
dev: {
|
||||||
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
|
// localhost:8000/api/** -> https://preview.pro.ant.design/api/**
|
||||||
'/admin/': {
|
'/tbg/api/v1': {
|
||||||
// 要代理的地址
|
// 要代理的地址
|
||||||
target: '',
|
target: 'http://192.168.88.224:9999',
|
||||||
// 配置了这个可以从 http 代理到 https
|
// 配置了这个可以从 http 代理到 https
|
||||||
// 依赖 origin 的功能可能需要这个,比如 cookie
|
// 依赖 origin 的功能可能需要这个,比如 cookie
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
|
|
|
||||||
10
package.json
10
package.json
|
|
@ -56,14 +56,18 @@
|
||||||
"@formily/antd": "^2.0.7",
|
"@formily/antd": "^2.0.7",
|
||||||
"@formily/core": "^2.0.7",
|
"@formily/core": "^2.0.7",
|
||||||
"@formily/react": "^2.0.7",
|
"@formily/react": "^2.0.7",
|
||||||
|
"@metamask/detect-provider": "^1.2.0",
|
||||||
"@umijs/route-utils": "^2.0.3",
|
"@umijs/route-utils": "^2.0.3",
|
||||||
"ahooks": "^2.10.14",
|
"ahooks": "^2.10.14",
|
||||||
"antd": "^4.17.2",
|
"antd": "^4.17.2",
|
||||||
"axios": "^0.24.0",
|
"axios": "^0.24.0",
|
||||||
|
"bignumber.js": "^9.0.0",
|
||||||
"braft-editor": "^2.3.9",
|
"braft-editor": "^2.3.9",
|
||||||
"classnames": "^2.2.6",
|
"classnames": "^2.2.6",
|
||||||
|
"echarts": "^5.3.3",
|
||||||
|
"echarts-for-react": "^3.0.2",
|
||||||
"lodash": "^4.17.11",
|
"lodash": "^4.17.11",
|
||||||
"moment": "^2.25.3",
|
"moment": "^2.29.4",
|
||||||
"omit.js": "^2.0.2",
|
"omit.js": "^2.0.2",
|
||||||
"rc-menu": "^9.0.13",
|
"rc-menu": "^9.0.13",
|
||||||
"rc-util": "^5.14.0",
|
"rc-util": "^5.14.0",
|
||||||
|
|
@ -72,7 +76,9 @@
|
||||||
"react-dom": "^17.0.0",
|
"react-dom": "^17.0.0",
|
||||||
"react-helmet-async": "^1.0.4",
|
"react-helmet-async": "^1.0.4",
|
||||||
"umi": "^3.5.0",
|
"umi": "^3.5.0",
|
||||||
"umi-serve": "^1.9.10"
|
"umi-serve": "^1.9.10",
|
||||||
|
"web3": "^1.7.5",
|
||||||
|
"xlsx": "0.15.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ant-design/pro-cli": "^2.0.2",
|
"@ant-design/pro-cli": "^2.0.2",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
// 创建弹窗
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
import { modifyPassword } from '@/services/login';
|
||||||
|
|
||||||
|
interface ModifyPasswordModalPropsType extends ModalProps {
|
||||||
|
onCancel: () => void;
|
||||||
|
onOk: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const ModifyPasswordModal = ({ onOk, onCancel, ...rest }: ModifyPasswordModalPropsType) => {
|
||||||
|
const handleOk = async () => {
|
||||||
|
onOk();
|
||||||
|
const formState = form.getFormState();
|
||||||
|
await modifyPassword(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="修改密码" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="password"
|
||||||
|
title="旧密码"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请输入旧密码',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="new_password"
|
||||||
|
title="新密码"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请输入新密码',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ModifyPasswordModal;
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import React, { useCallback } from 'react';
|
import React, { useState, useCallback } from 'react';
|
||||||
import { LogoutOutlined, SettingOutlined, UserOutlined } from '@ant-design/icons';
|
import { LogoutOutlined, SettingOutlined, UserOutlined, EditOutlined } from '@ant-design/icons';
|
||||||
import { Avatar, Menu, Spin } from 'antd';
|
import { Avatar, Menu, Spin } from 'antd';
|
||||||
import { history } from 'umi';
|
import { history } from 'umi';
|
||||||
import { stringify } from 'querystring';
|
import { stringify } from 'querystring';
|
||||||
|
|
@ -8,6 +8,7 @@ import styles from './index.less';
|
||||||
import type { MenuInfo } from 'rc-menu/lib/interface';
|
import type { MenuInfo } from 'rc-menu/lib/interface';
|
||||||
import RoutePath from '@/routes/routePath';
|
import RoutePath from '@/routes/routePath';
|
||||||
import { CACHE_TOKEN } from '@/constants/cacheKey';
|
import { CACHE_TOKEN } from '@/constants/cacheKey';
|
||||||
|
import ModifyPasswordModal from '@/components/ModifyPassword/ModifyPasswordModal';
|
||||||
|
|
||||||
export type GlobalHeaderRightProps = {
|
export type GlobalHeaderRightProps = {
|
||||||
menu?: boolean;
|
menu?: boolean;
|
||||||
|
|
@ -32,8 +33,18 @@ const loginOut = async () => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
|
const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
|
||||||
|
const modifyPassword = async () => {
|
||||||
|
setIsModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
const onMenuClick = useCallback((event: MenuInfo) => {
|
const onMenuClick = useCallback((event: MenuInfo) => {
|
||||||
const { key } = event;
|
const { key } = event;
|
||||||
|
if (key === 'modify') {
|
||||||
|
modifyPassword();
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (key === 'logout') {
|
if (key === 'logout') {
|
||||||
loginOut();
|
loginOut();
|
||||||
return;
|
return;
|
||||||
|
|
@ -77,7 +88,10 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
)}
|
)}
|
||||||
{menu && <Menu.Divider />}
|
{menu && <Menu.Divider />}
|
||||||
|
<Menu.Item key="modify">
|
||||||
|
<EditOutlined />
|
||||||
|
修改密码
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item key="logout">
|
<Menu.Item key="logout">
|
||||||
<LogoutOutlined />
|
<LogoutOutlined />
|
||||||
退出登录
|
退出登录
|
||||||
|
|
@ -85,12 +99,24 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
|
||||||
</Menu>
|
</Menu>
|
||||||
);
|
);
|
||||||
return (
|
return (
|
||||||
|
<div>
|
||||||
<HeaderDropdown overlay={menuHeaderDropdown}>
|
<HeaderDropdown overlay={menuHeaderDropdown}>
|
||||||
<span className={`${styles.action} ${styles.account}`}>
|
<span className={`${styles.action} ${styles.account}`}>
|
||||||
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
|
<Avatar size="small" className={styles.avatar} src={currentUser.avatar} alt="avatar" />
|
||||||
<span className={`${styles.name} anticon`}>{currentUser.name}</span>
|
<span className={`${styles.name} anticon`}>{currentUser.name}</span>
|
||||||
</span>
|
</span>
|
||||||
</HeaderDropdown>
|
</HeaderDropdown>
|
||||||
|
<ModifyPasswordModal
|
||||||
|
visible={isModalVisible}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={function () {
|
||||||
|
console.log('onOk');
|
||||||
|
setIsModalVisible(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
.delete-btn {
|
||||||
|
color: @error-color;
|
||||||
|
&:hover {
|
||||||
|
color: @error-color !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled {
|
||||||
|
color: @disabled-color;
|
||||||
|
cursor: not-allowed;
|
||||||
|
&:hover {
|
||||||
|
color: @disabled-color !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
import React from 'react';
|
||||||
|
import { Popconfirm } from 'antd';
|
||||||
|
import styles from './index.less';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
interface PropsType {
|
||||||
|
onConfirm: () => void;
|
||||||
|
title?: string;
|
||||||
|
buttonName?: string;
|
||||||
|
disabled?: boolean;
|
||||||
|
}
|
||||||
|
const ConfirmButton: React.FC<PropsType> = ({
|
||||||
|
onConfirm,
|
||||||
|
disabled = false,
|
||||||
|
title = '',
|
||||||
|
buttonName = '',
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<Popconfirm title={title} disabled={disabled} onConfirm={onConfirm} okText="是" cancelText="否">
|
||||||
|
<a className={classNames(styles.deleteBtn, disabled ? styles.disabled : '')}>{buttonName}</a>
|
||||||
|
</Popconfirm>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default ConfirmButton;
|
||||||
|
|
@ -172,7 +172,7 @@ const Table = <T extends Record<string, any>>(props: PropsType) => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<PlusOutlined />
|
<PlusOutlined />
|
||||||
{item.text || '新建'}
|
{item.text || '添加'}
|
||||||
</Button>,
|
</Button>,
|
||||||
);
|
);
|
||||||
} else if (item.type === 'batchDelete') {
|
} else if (item.type === 'batchDelete') {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
export enum TimeType {
|
||||||
|
DAY = 'day',
|
||||||
|
WEEK = 'week',
|
||||||
|
MONTH = 'month',
|
||||||
|
}
|
||||||
|
export default TimeType;
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import echarts from 'echarts/lib/echarts';
|
||||||
|
import {
|
||||||
|
getActiveData,
|
||||||
|
getMonthUserData,
|
||||||
|
getOldUserData,
|
||||||
|
getTodayUserData,
|
||||||
|
getWeekUserData,
|
||||||
|
} from '@/services/dataBorad/activeAnalysis';
|
||||||
|
import MoreData from '@/widget/MoreData';
|
||||||
|
import ReactEcharts from 'echarts-for-react';
|
||||||
|
import { Card, Col, Row, Select } from 'antd';
|
||||||
|
const ActiveAnalysis: React.FC = () => {
|
||||||
|
const { Option } = Select;
|
||||||
|
const [timeType, setTimeType] = useState('day');
|
||||||
|
const getData = async (func) => {
|
||||||
|
const res = await func({});
|
||||||
|
return res.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
const [data, setData] = useState(getData(getTodayUserData));
|
||||||
|
const [oldUserData, setOldUserData] = useState(getData(getOldUserData));
|
||||||
|
const [weekData, setWeekData] = useState(getData(getWeekUserData));
|
||||||
|
const [monthData, setMonthData] = useState(getData(getMonthUserData));
|
||||||
|
|
||||||
|
const getOption = async (item = 'day') => {
|
||||||
|
const res = await getActiveData({ time_type: item });
|
||||||
|
const xData: any = [];
|
||||||
|
const seriesData: any = [];
|
||||||
|
res.data.foreach((item: any) => {
|
||||||
|
xData.push(item.time);
|
||||||
|
seriesData.push(item.dwn);
|
||||||
|
});
|
||||||
|
const option = {
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||||
|
// data: xData,
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
data: [150, 230, 224, 218, 135, 147, 360],
|
||||||
|
// data: seriesData.reverse(),
|
||||||
|
type: 'line',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
return option;
|
||||||
|
};
|
||||||
|
const [option, setOption] = useState(getOption);
|
||||||
|
const setTimeOption = (val: any) => {
|
||||||
|
setTimeType(val);
|
||||||
|
setOption(getOption(val));
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row gutter={24} justify="space-between" style={{ marginBottom: 10 }}>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(data, '今日活跃用户数')}</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(oldUserData, '今日登录老用户数')}</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(weekData, 'WAU(本周去重人数)')}</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(monthData, 'MAU(本月去重人数)')}</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
<Card style={{ width: '100%' }}>
|
||||||
|
<Row gutter={32} style={{ marginBottom: 10 }}>
|
||||||
|
<Col span={6}>
|
||||||
|
<h1>登陆人数数据图</h1>
|
||||||
|
<Select
|
||||||
|
defaultValue="lucy"
|
||||||
|
value={timeType}
|
||||||
|
style={{ width: 100 }}
|
||||||
|
bordered={false}
|
||||||
|
onChange={(val) => {
|
||||||
|
setTimeOption(val);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Option value="day">每日</Option>
|
||||||
|
<Option value="week">每周</Option>
|
||||||
|
<Option value="month">每月</Option>
|
||||||
|
</Select>
|
||||||
|
</Col>
|
||||||
|
<Col span={18}>
|
||||||
|
<ReactEcharts option={option} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default ActiveAnalysis;
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import moment from 'moment';
|
||||||
|
import TimeType from '@/constants/enum/timeType';
|
||||||
|
import { getData } from '@/utils/getData';
|
||||||
|
import MoreData from '@/widget/MoreData';
|
||||||
|
import {
|
||||||
|
getCoreData,
|
||||||
|
getPayData,
|
||||||
|
getTodayUserData,
|
||||||
|
getMonthPayData,
|
||||||
|
getNewUserData,
|
||||||
|
} from '@/services/dataBorad/coreData';
|
||||||
|
import { Card, Col, Row, Select } from 'antd';
|
||||||
|
const CoreData: React.FC = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const [timeType, setTimeType] = useState(TimeType.DAY);
|
||||||
|
|
||||||
|
// const [date, setDate] = useState(getData);
|
||||||
|
const [userDate, setUserDate] = useState(getData(getTodayUserData));
|
||||||
|
const [newUserdate, setNewUserDate] = useState(getData(getNewUserData));
|
||||||
|
const [payData, setPayDate] = useState(getData(getMonthPayData));
|
||||||
|
const [allPay, setAllPayDate] = useState(getData(getPayData));
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '时间类型',
|
||||||
|
dataIndex: 'coinType',
|
||||||
|
hideInTable: true,
|
||||||
|
initialValue: TimeType.DAY,
|
||||||
|
renderFormItem: (item, { type, defaultRender, ...rest }, form) => {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: '每日',
|
||||||
|
value: TimeType.DAY,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '每周',
|
||||||
|
value: TimeType.WEEK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '每月',
|
||||||
|
value: TimeType.MONTH,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onChange={(val) => {
|
||||||
|
setTimeType(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '日期',
|
||||||
|
dataIndex: 'time',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '10%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'select_time',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
width: '20%',
|
||||||
|
hideInTable: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '活跃用户数',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '新用户数量',
|
||||||
|
dataIndex: 'new_user',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '当日充值总额',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '付费用户数',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '付费率',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ARPU',
|
||||||
|
dataIndex: 'arpu',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ARPPU',
|
||||||
|
dataIndex: 'arppu',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Row gutter={24} style={{ marginBottom: 10 }}>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(userDate, '今日活跃用户数', '人')}</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(newUserdate, '今日新增人数', '人')}</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(payData, '本月充值总额', '万元')}</Card>
|
||||||
|
</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Card style={{ height: '200px' }}>{MoreData(allPay, '充值总额', '万元')}</Card>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
if ((params.select_time ?? '') !== '') {
|
||||||
|
params.start_time = moment(params.select_time[0]).valueOf() / 1000;
|
||||||
|
params.end_time = moment(params.select_time[1]).valueOf() / 1000;
|
||||||
|
}
|
||||||
|
return getCoreData(params);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CoreData;
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { getRententionData } from '@/services/dataBorad/rechargeAnalysis';
|
||||||
|
import { Select } from 'antd';
|
||||||
|
import moment from 'moment';
|
||||||
|
import TimeType from '@/constants/enum/timeType';
|
||||||
|
const Address: React.FC = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const [timeType, setTimeType] = useState(TimeType.DAY);
|
||||||
|
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '时间类型',
|
||||||
|
dataIndex: 'time_type',
|
||||||
|
hideInTable: true,
|
||||||
|
initialValue: TimeType.DAY,
|
||||||
|
renderFormItem: (item, { type, defaultRender, ...rest }, form) => {
|
||||||
|
return (
|
||||||
|
<Select
|
||||||
|
options={[
|
||||||
|
{
|
||||||
|
label: '每日',
|
||||||
|
value: TimeType.DAY,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '每周',
|
||||||
|
value: TimeType.WEEK,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: '每月',
|
||||||
|
value: TimeType.MONTH,
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
onChange={(val) => {
|
||||||
|
setTimeType(val);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '日期',
|
||||||
|
dataIndex: 'time',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间筛选',
|
||||||
|
dataIndex: 'timeData',
|
||||||
|
hideInTable: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'select_time',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
width: '20%',
|
||||||
|
hideInTable: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '付费次数',
|
||||||
|
dataIndex: 'pay_num',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '付费用户数',
|
||||||
|
dataIndex: 'pay_user',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '付费金额',
|
||||||
|
dataIndex: 'pay_price',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '付费率',
|
||||||
|
dataIndex: 'rate',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ARPU',
|
||||||
|
dataIndex: 'arpu',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'ARPPU',
|
||||||
|
dataIndex: 'arppu',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
actionRef={tableRef}
|
||||||
|
// search={false}
|
||||||
|
request={async (params) => {
|
||||||
|
if ((params.select_time ?? '') !== '') {
|
||||||
|
params.start_time = moment(params.select_time[0]).valueOf() / 1000;
|
||||||
|
params.end_time = moment(params.select_time[1]).valueOf() / 1000;
|
||||||
|
}
|
||||||
|
return getRententionData(params);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Address;
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import TimeText from '@/components/Typography/TimeText';
|
||||||
|
import { getChannelData } from '@/services/dataBorad/retentionAnalysis';
|
||||||
|
|
||||||
|
interface TableModalPropsType extends ModalProps {
|
||||||
|
modalData: any;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
const TableModal = ({ onCancel, modalData, ...rest }: TableModalPropsType) => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'time',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
render: (_, row) => [<TimeText value={row} format={'YYYY-MM-DD'} />],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '渠道类型',
|
||||||
|
dataIndex: 'channel_name',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '登录用户数',
|
||||||
|
dataIndex: 'login_user',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第一日',
|
||||||
|
dataIndex: 'day_one',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第二日',
|
||||||
|
dataIndex: 'day_two',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第四日',
|
||||||
|
dataIndex: 'day_three',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第五日',
|
||||||
|
dataIndex: 'day_four',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第六日',
|
||||||
|
dataIndex: 'day_five',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第七日',
|
||||||
|
dataIndex: 'day_seven',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="渠道活跃分析" onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
search={false}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
params.time = modalData;
|
||||||
|
return fetchTableData(getChannelData, params);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default TableModal;
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import { getRententionData } from '@/services/dataBorad/retentionAnalysis';
|
||||||
|
import TableModal from './components/TableModal';
|
||||||
|
|
||||||
|
const RetentionAnalysis = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [requestData, setRequestData] = useState();
|
||||||
|
const sendData = (row: any) => {
|
||||||
|
setVisible(true);
|
||||||
|
setRequestData(row.time);
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'time',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'select_time',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
width: '20%',
|
||||||
|
hideInTable: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '登录用户数',
|
||||||
|
dataIndex: 'login_user',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第一日',
|
||||||
|
dataIndex: 'day_one',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第二日',
|
||||||
|
dataIndex: 'day_two',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第四日',
|
||||||
|
dataIndex: 'day_three',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第五日',
|
||||||
|
dataIndex: 'day_four',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第六日',
|
||||||
|
dataIndex: 'day_five',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '第七日',
|
||||||
|
dataIndex: 'day_seven',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 150,
|
||||||
|
render: (_, row) => [
|
||||||
|
<button
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
sendData(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
查看
|
||||||
|
</button>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
if ((params.select_time ?? '') !== '') {
|
||||||
|
params.start_time = moment(params.select_time[0]).valueOf() / 1000;
|
||||||
|
params.end_time = moment(params.select_time[1]).valueOf() / 1000;
|
||||||
|
}
|
||||||
|
return await fetchTableData(getRententionData, params);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<TableModal
|
||||||
|
visible={visible}
|
||||||
|
modalData={requestData}
|
||||||
|
onCancel={function () {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RetentionAnalysis;
|
||||||
|
|
@ -35,7 +35,7 @@ const Login: React.FC = () => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProFormText
|
<ProFormText
|
||||||
name="username"
|
name="name"
|
||||||
fieldProps={{
|
fieldProps={{
|
||||||
size: 'large',
|
size: 'large',
|
||||||
prefix: <UserOutlined className={styles.prefixIcon} />,
|
prefix: <UserOutlined className={styles.prefixIcon} />,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
// import { fetchTableData } from '@/utils/table';
|
||||||
|
import { Form, FormItem, Input, NumberPicker } from '@formily/antd';
|
||||||
|
|
||||||
|
interface AddNftContractModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
NumberPicker,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const AddNftContractModal = ({ onOk, onCancel, ...rest }: AddNftContractModalPropsType) => {
|
||||||
|
const handleOk = () => {
|
||||||
|
form.submit(async () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="添加合约" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="contract_name"
|
||||||
|
title="合约名称"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="address"
|
||||||
|
title="合约地址"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="description"
|
||||||
|
title="描述"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="contract_symbol"
|
||||||
|
title="合约符号"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddNftContractModal;
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { message } from 'antd';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import AddNftContractModal from './components/AddNftContract';
|
||||||
|
import { getContractData, createContract } from '@/services/nft/contract';
|
||||||
|
|
||||||
|
const Address: React.FC = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const [NftModal, setNftModal] = useState(false);
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '合约名称',
|
||||||
|
dataIndex: 'time',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '合约地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'NFT数量',
|
||||||
|
dataIndex: 'nft_num',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
search={false}
|
||||||
|
actionRef={tableRef}
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
text: '新建NFT合约',
|
||||||
|
onConfirm: () => {
|
||||||
|
setVisible(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
request={async (params) => {
|
||||||
|
return fetchTableData(getContractData, params);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddNftContractModal
|
||||||
|
visible={visible}
|
||||||
|
onCancel={function () {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
try {
|
||||||
|
const params = { ...val };
|
||||||
|
await createContract(params);
|
||||||
|
message.success('添加成功');
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
message.success('发生错误');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Address;
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import Upload from '@/components/Upload';
|
||||||
|
import { Button, message } from 'antd';
|
||||||
|
// import { fetchTableData } from '@/utils/table';
|
||||||
|
import {
|
||||||
|
Form,
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
NumberPicker,
|
||||||
|
ArrayItems,
|
||||||
|
FormButtonGroup,
|
||||||
|
ArrayTable,
|
||||||
|
} from '@formily/antd';
|
||||||
|
|
||||||
|
interface AddNftModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
NumberPicker,
|
||||||
|
Upload,
|
||||||
|
ArrayItems,
|
||||||
|
FormButtonGroup,
|
||||||
|
ArrayTable,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const AddNftModal = ({ onOk, onCancel, ...rest }: AddNftModalPropsType) => {
|
||||||
|
const handleOk = () => {
|
||||||
|
form.submit(async () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleAddResoruce = () => {
|
||||||
|
const resourceList = form.getFieldState('contacts').value;
|
||||||
|
if (resourceList.length >= 1) {
|
||||||
|
message.warning('只能添加1个属性');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
form.setFieldState('contacts', (state) => {
|
||||||
|
state.value = [...resourceList, {}];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="添加NFT" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="name"
|
||||||
|
title="名称"
|
||||||
|
x-validator={{ required: true }}
|
||||||
|
x-component="Input"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
/>
|
||||||
|
<SchemaField.Number
|
||||||
|
name="contract"
|
||||||
|
title="合约"
|
||||||
|
required
|
||||||
|
x-validator={{ required: true }}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.Number
|
||||||
|
name="description"
|
||||||
|
title="描述"
|
||||||
|
required
|
||||||
|
x-validator={{ required: true }}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="image"
|
||||||
|
title="图片"
|
||||||
|
required
|
||||||
|
x-validator={{ required: true }}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Upload"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="avatar"
|
||||||
|
title="avatar"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.Array
|
||||||
|
name="contacts"
|
||||||
|
title="属性"
|
||||||
|
required
|
||||||
|
// x-validator={[{ required: true }]}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="ArrayItems"
|
||||||
|
>
|
||||||
|
<SchemaField.Object x-component="ArrayItems.Item">
|
||||||
|
<SchemaField.Void x-decorator="FormItem" />
|
||||||
|
<SchemaField.Void
|
||||||
|
name="popover"
|
||||||
|
title=""
|
||||||
|
required
|
||||||
|
x-decorator="Editable.Popover"
|
||||||
|
x-component="FormLayout"
|
||||||
|
x-component-props={{
|
||||||
|
layout: 'vertical',
|
||||||
|
}}
|
||||||
|
x-reactions={[
|
||||||
|
{
|
||||||
|
fulfill: {
|
||||||
|
schema: {
|
||||||
|
title: '{{$self.query(".name").value() }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SchemaField.String
|
||||||
|
name="trait_type"
|
||||||
|
required
|
||||||
|
title="类型"
|
||||||
|
x-validator={{ required: true }}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
style: {
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="value"
|
||||||
|
title="值"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
style: {
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaField.Void>
|
||||||
|
<SchemaField.Void x-decorator="FormItem" x-component="ArrayItems.Remove" />
|
||||||
|
</SchemaField.Object>
|
||||||
|
</SchemaField.Array>
|
||||||
|
</SchemaField>
|
||||||
|
<FormButtonGroup.FormItem style={{ marginBottom: 20 }}>
|
||||||
|
<Button type="dashed" onClick={handleAddResoruce} block>
|
||||||
|
添加属性
|
||||||
|
</Button>
|
||||||
|
</FormButtonGroup.FormItem>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddNftModal;
|
||||||
|
|
@ -0,0 +1,160 @@
|
||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import Upload from '@/components/Upload';
|
||||||
|
import { Button, message } from 'antd';
|
||||||
|
import { Form, FormItem, Input, NumberPicker, ArrayItems, FormButtonGroup } from '@formily/antd';
|
||||||
|
|
||||||
|
interface EditNftModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
modalData: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
NumberPicker,
|
||||||
|
Upload,
|
||||||
|
ArrayItems,
|
||||||
|
FormButtonGroup,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const EditNftModal = ({ onOk, onCancel, modalData, ...rest }: EditNftModalPropsType) => {
|
||||||
|
useEffect(() => {
|
||||||
|
form.setInitialValues(modalData);
|
||||||
|
});
|
||||||
|
const handleOk = () => {
|
||||||
|
form.submit(async () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleAddResoruce = () => {
|
||||||
|
const resourceList = form.getFieldState('contacts').value;
|
||||||
|
if (resourceList.length >= 1) {
|
||||||
|
message.warning('只能添加1个属性');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
form.setFieldState('contacts', (state) => {
|
||||||
|
state.value = [...resourceList, {}];
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="添加NFT" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String name="name" title="名称" x-decorator="FormItem" x-component="Input" />
|
||||||
|
<SchemaField.String
|
||||||
|
name="token_id"
|
||||||
|
title="tokenID"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="contract"
|
||||||
|
title="合约"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="description"
|
||||||
|
title="描述"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="image"
|
||||||
|
title="图片"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Upload"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="avatar"
|
||||||
|
title="avatar"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.Array
|
||||||
|
name="contacts"
|
||||||
|
title="属性"
|
||||||
|
required
|
||||||
|
// x-validator={[{ required: true }]}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="ArrayItems"
|
||||||
|
>
|
||||||
|
<SchemaField.Object x-component="ArrayItems.Item">
|
||||||
|
<SchemaField.Void x-decorator="FormItem" />
|
||||||
|
<SchemaField.Void
|
||||||
|
name="popover"
|
||||||
|
title=""
|
||||||
|
required
|
||||||
|
x-decorator="Editable.Popover"
|
||||||
|
x-component="FormLayout"
|
||||||
|
x-component-props={{
|
||||||
|
layout: 'vertical',
|
||||||
|
}}
|
||||||
|
x-reactions={[
|
||||||
|
{
|
||||||
|
fulfill: {
|
||||||
|
schema: {
|
||||||
|
title: '{{$self.query(".name").value() }}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<SchemaField.String
|
||||||
|
name="trait_type"
|
||||||
|
required
|
||||||
|
title="类型"
|
||||||
|
x-validator={{ required: true }}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
style: {
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="value"
|
||||||
|
title="值"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
style: {
|
||||||
|
width: 300,
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaField.Void>
|
||||||
|
<SchemaField.Void x-decorator="FormItem" x-component="ArrayItems.Remove" />
|
||||||
|
</SchemaField.Object>
|
||||||
|
</SchemaField.Array>
|
||||||
|
</SchemaField>
|
||||||
|
<FormButtonGroup.FormItem style={{ marginBottom: 20 }}>
|
||||||
|
<Button type="dashed" onClick={handleAddResoruce} block>
|
||||||
|
添加属性
|
||||||
|
</Button>
|
||||||
|
</FormButtonGroup.FormItem>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditNftModal;
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import { message, Button, Upload, Space, Row } from 'antd';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { RcFile } from 'antd/lib/upload';
|
||||||
|
import XLSX from 'xlsx';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import EditNftModal from './components/EditNftModel';
|
||||||
|
import AddNftModal from './components/AddNftModel';
|
||||||
|
import PaySelectModal from '@/widget/PaySelectModal';
|
||||||
|
import { getNftData, createNft, editNft, getTokenId } from '@/services/nft/nft';
|
||||||
|
|
||||||
|
const Address: React.FC = () => {
|
||||||
|
const [visible, setVisible] = useState(false);
|
||||||
|
const [editVisible, setEditVisible] = useState(false);
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const [payVisible, setPayVisible] = useState(false);
|
||||||
|
const [nftData, setNFTData] = useState({});
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
setNFTData(row);
|
||||||
|
setEditVisible(true);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
};
|
||||||
|
const onImportExcel = (file: RcFile, FileList: RcFile[]) => {
|
||||||
|
let resData = [{}];
|
||||||
|
const fileReader = new FileReader();
|
||||||
|
fileReader.readAsBinaryString(file);
|
||||||
|
fileReader.onload = (event) => {
|
||||||
|
try {
|
||||||
|
const result = event.target?.result;
|
||||||
|
const workbook = XLSX.read(result, { type: 'binary' });
|
||||||
|
for (const sheet in workbook.Sheets) {
|
||||||
|
if (workbook.Sheets.hasOwnProperty(sheet)) {
|
||||||
|
resData = XLSX.utils.sheet_to_json(workbook.Sheets[sheet]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(resData);
|
||||||
|
} catch (e) {
|
||||||
|
message.error('文件类型不正确');
|
||||||
|
console.log('文件类型不正确', e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '合约名称',
|
||||||
|
dataIndex: 'contract',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '导入分配NFT',
|
||||||
|
dataIndex: 'share',
|
||||||
|
hideInTable: true,
|
||||||
|
renderFormItem: (item, { type, defaultRender, ...rest }, form) => {
|
||||||
|
return (
|
||||||
|
<Upload beforeUpload={onImportExcel} onRemove={() => {}}>
|
||||||
|
<Button type="link">选择文件</Button>
|
||||||
|
</Upload>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'NFT名称',
|
||||||
|
dataIndex: 'Nft_name',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '描述',
|
||||||
|
dataIndex: 'description',
|
||||||
|
hideInSearch: true,
|
||||||
|
width: '20%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'TokenId',
|
||||||
|
dataIndex: 'token_id',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'image',
|
||||||
|
dataIndex: 'image',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'avatar',
|
||||||
|
dataIndex: 'avatar',
|
||||||
|
width: 150,
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 180,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<div>
|
||||||
|
<h3 className="part-title">NFT</h3>
|
||||||
|
<Space>
|
||||||
|
<Button
|
||||||
|
type="primary"
|
||||||
|
onClick={() => {
|
||||||
|
setVisible(true);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
新增NFT
|
||||||
|
</Button>
|
||||||
|
<Upload beforeUpload={onImportExcel} onRemove={() => {}}>
|
||||||
|
<Button type="primary">导入分发NFT</Button>
|
||||||
|
</Upload>
|
||||||
|
</Space>
|
||||||
|
</div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
search={false}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
return fetchTableData(getNftData, params);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddNftModal
|
||||||
|
visible={visible}
|
||||||
|
onCancel={function () {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
try {
|
||||||
|
const params = { ...val };
|
||||||
|
console.log(val);
|
||||||
|
await createNft(params);
|
||||||
|
message.success('添加成功');
|
||||||
|
setVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
message.success('发生错误');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<EditNftModal
|
||||||
|
visible={editVisible}
|
||||||
|
modalData={nftData}
|
||||||
|
onCancel={function () {
|
||||||
|
setVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
try {
|
||||||
|
const params = { ...val };
|
||||||
|
await editNft(params);
|
||||||
|
message.success('添加成功');
|
||||||
|
tableRef.current?.reload();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
message.success('发生错误');
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<PaySelectModal
|
||||||
|
visible={payVisible}
|
||||||
|
onCancel={function () {
|
||||||
|
setPayVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
// setPayVisible(false);
|
||||||
|
// try {
|
||||||
|
// const params = { ...val };
|
||||||
|
// // await creatNftAddress(params);
|
||||||
|
// console.log(params);
|
||||||
|
// message.success('添加成功');
|
||||||
|
// } catch (e) {
|
||||||
|
// console.log(e);
|
||||||
|
// message.success('发生错误');
|
||||||
|
// setPayVisible(false);
|
||||||
|
// }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Address;
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
// 创建弹窗
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core';
|
||||||
|
import { FormProvider, createSchemaField } from '@formily/react';
|
||||||
|
import { getCoinTypeList } from '@/services/recharge/coinType';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
import { action } from '@formily/reactive';
|
||||||
|
|
||||||
|
interface AddAddressModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const useAsyncDataSource = (
|
||||||
|
pattern: FormPathPattern,
|
||||||
|
service: (field: Field) => Promise<{ label: string; value: any }[]>,
|
||||||
|
) => {
|
||||||
|
onFieldReact(pattern, (field) => {
|
||||||
|
service(field).then(
|
||||||
|
action.bound((data) => {
|
||||||
|
field.dataSource = data;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = createForm({
|
||||||
|
effects: () => {
|
||||||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
useAsyncDataSource('bc_name', async (field) => {
|
||||||
|
const list = await getCoinTypeList({ page: 1, page_size: 10 });
|
||||||
|
const option = [];
|
||||||
|
for (let index = 0; index < list.items.length; index++) {
|
||||||
|
const element = list.items[index];
|
||||||
|
const item = {
|
||||||
|
label: element.bc_name,
|
||||||
|
value: element.bc_name,
|
||||||
|
};
|
||||||
|
option.push(item);
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const AddAddressModal = ({ onOk, onCancel, ...rest }: AddAddressModalPropsType) => {
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="创建收款地址" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<FormProvider form={form}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="bc_name"
|
||||||
|
title="游戏币名称"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Select"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="address"
|
||||||
|
title="收款地址"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '不传则后台生成',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</FormProvider>
|
||||||
|
{/* <Form form={form} labelCol={4} wrapperCol={18}> */}
|
||||||
|
|
||||||
|
{/* </Form> */}
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddAddressModal;
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
// 修改弹窗
|
||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import { createForm, onFieldReact, FormPathPattern, Field } from '@formily/core';
|
||||||
|
import { getCoinTypeList } from '@/services/recharge/coinType';
|
||||||
|
import { FormProvider, createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
import { action } from '@formily/reactive';
|
||||||
|
|
||||||
|
interface EditAddressModalPropsType extends ModalProps {
|
||||||
|
editModalData: any;
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const EditAddressModal = ({
|
||||||
|
onOk,
|
||||||
|
onCancel,
|
||||||
|
editModalData,
|
||||||
|
...rest
|
||||||
|
}: EditAddressModalPropsType) => {
|
||||||
|
const useAsyncDataSource = (
|
||||||
|
pattern: FormPathPattern,
|
||||||
|
service: (field: Field) => Promise<{ label: string; value: any }[]>,
|
||||||
|
) => {
|
||||||
|
onFieldReact(pattern, (field) => {
|
||||||
|
service(field).then(
|
||||||
|
action.bound((data) => {
|
||||||
|
field.dataSource = data;
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const form = createForm({
|
||||||
|
effects: () => {
|
||||||
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
||||||
|
useAsyncDataSource('bc_name', async (field) => {
|
||||||
|
const list = await getCoinTypeList({ page: 1, page_size: 10 });
|
||||||
|
const option = [];
|
||||||
|
for (let index = 0; index < list.items.length; index++) {
|
||||||
|
const element = list.items[index];
|
||||||
|
const item = {
|
||||||
|
label: element.bc_name,
|
||||||
|
value: element.bc_name,
|
||||||
|
};
|
||||||
|
option.push(item);
|
||||||
|
}
|
||||||
|
return option;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
form.setInitialValues(editModalData);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="修改收款地址" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="address"
|
||||||
|
title="旧收款地址"
|
||||||
|
x-disabled
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="bc_name"
|
||||||
|
title="游戏币名称"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Select"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="new_address"
|
||||||
|
title="新收款地址"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditAddressModal;
|
||||||
|
|
@ -0,0 +1,114 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import {
|
||||||
|
getAddressList,
|
||||||
|
deleteAddress,
|
||||||
|
createAddress,
|
||||||
|
modifyAddress,
|
||||||
|
} from '@/services/recharge/address';
|
||||||
|
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import DeleteButton from '@/components/Table/DeleteButton';
|
||||||
|
import AddAddressModal from '../Components/AddAddressModal';
|
||||||
|
import EditAddressModal from '../Components/EditAddressModal';
|
||||||
|
|
||||||
|
const CollectionAddressList = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||||
|
const [modalData, setModalData] = useState({});
|
||||||
|
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
row.new_address = '';
|
||||||
|
setModalData(row);
|
||||||
|
setIsEditModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async (address: any) => {
|
||||||
|
await deleteAddress({ address: address });
|
||||||
|
tableRef.current?.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '收款地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收款游戏币名称',
|
||||||
|
dataIndex: 'bc_name',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 150,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
<DeleteButton
|
||||||
|
key="delete"
|
||||||
|
onDelete={() => {
|
||||||
|
handleDelete(row.address);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {
|
||||||
|
setIsModalVisible(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getAddressList, params);
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddAddressModal
|
||||||
|
visible={isModalVisible}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
await createAddress(val);
|
||||||
|
setIsModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<EditAddressModal
|
||||||
|
visible={isEditModalVisible}
|
||||||
|
editModalData={modalData}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
await modifyAddress(val);
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CollectionAddressList;
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
// 添加代币类型弹窗
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, NumberPicker } from '@formily/antd';
|
||||||
|
|
||||||
|
interface AddCoinTypeModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
NumberPicker,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const AddCoinTypeModal = ({ onOk, onCancel, ...rest }: AddCoinTypeModalPropsType) => {
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="添加代币类型" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="bc_name"
|
||||||
|
title="代币名称"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="usdt_price"
|
||||||
|
title="usdt比例"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="eth_price"
|
||||||
|
title="eth比例"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.Number
|
||||||
|
name="num"
|
||||||
|
title="数量"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="NumberPicker"
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddCoinTypeModal;
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
// 修改弹窗
|
||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
|
||||||
|
interface EditCoinTypeModalPropsType extends ModalProps {
|
||||||
|
editModalData: any;
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const EditCoinTypeModal = ({
|
||||||
|
onOk,
|
||||||
|
onCancel,
|
||||||
|
editModalData,
|
||||||
|
...rest
|
||||||
|
}: EditCoinTypeModalPropsType) => {
|
||||||
|
useEffect(() => {
|
||||||
|
form.setInitialValues(editModalData);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="修改代币类型" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="bc_name"
|
||||||
|
title="游戏币名称"
|
||||||
|
x-disabled
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="usdt_price"
|
||||||
|
title="usdt比例"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="eth_price"
|
||||||
|
title="eth比例"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditCoinTypeModal;
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { addCoinType, getCoinTypeList, modifyCoinType } from '@/services/recharge/coinType';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import AddCoinTypeModal from '../Components/AddCoinTypeModal';
|
||||||
|
import EditCoinTypeModal from '../Components/EditCoinTypeModal';
|
||||||
|
|
||||||
|
const CoinTypeList = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||||
|
const [modalData, setModalData] = useState({});
|
||||||
|
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
setModalData(row);
|
||||||
|
setIsEditModalVisible(true);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '游戏币名称',
|
||||||
|
dataIndex: 'bc_name',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'usdt比例',
|
||||||
|
dataIndex: 'usdt_price',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: 'eth比例',
|
||||||
|
dataIndex: 'eth_price',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '代币发行总量',
|
||||||
|
dataIndex: 'num',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 150,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {
|
||||||
|
setIsModalVisible(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getCoinTypeList, params);
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddCoinTypeModal
|
||||||
|
visible={isModalVisible}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
await addCoinType(val);
|
||||||
|
setIsModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<EditCoinTypeModal
|
||||||
|
visible={isEditModalVisible}
|
||||||
|
editModalData={modalData}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
await modifyCoinType(val);
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default CoinTypeList;
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { getRecordList } from '@/services/recharge/record';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import { getBalanceAmount } from '@/utils/formatBalance';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
const RecordList = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'time',
|
||||||
|
hideInTable: true,
|
||||||
|
valueType: 'dateRange',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '交易哈希',
|
||||||
|
dataIndex: 'tx_hash',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '位数',
|
||||||
|
dataIndex: 'decimals',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '游戏币类型',
|
||||||
|
dataIndex: 'bc_type',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '发送地址',
|
||||||
|
dataIndex: 'from_address',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '接受地址',
|
||||||
|
dataIndex: 'to_address',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '充值时间',
|
||||||
|
dataIndex: 'time',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
console.log('params = ', params);
|
||||||
|
if ((params.time ?? '') !== '') {
|
||||||
|
const start = Date.parse(params.time[0] + ' 00:00:00');
|
||||||
|
const end = Date.parse(params.time[1] + ' 23:59:59');
|
||||||
|
params.start_time = start / 1000;
|
||||||
|
params.end_time = end / 1000;
|
||||||
|
}
|
||||||
|
const res = await fetchTableData(getRecordList, params);
|
||||||
|
console.log('res = ', res);
|
||||||
|
for (const key in res.data) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(res.data, key)) {
|
||||||
|
const element = res.data[key];
|
||||||
|
element.price = getBalanceAmount(
|
||||||
|
new BigNumber(element.price),
|
||||||
|
element.decimals,
|
||||||
|
).toNumber();
|
||||||
|
element.time = moment(element.time * 1000).format('YYYY-MM-DD hh:mm:ss');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RecordList;
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { getWithdrawList, solveWithdraw } from '@/services/recharge/withdraw';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import { getBalanceAmount } from '@/utils/formatBalance';
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import ConfirmButton from '@/components/Table/ConfirmButton';
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
const WithdrawList = () => {
|
||||||
|
const handleConfirm = async (uuid) => {
|
||||||
|
await solveWithdraw({ uuid: uuid });
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePass = async (row) => {};
|
||||||
|
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '提现订单号',
|
||||||
|
dataIndex: 'uuid',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '金额',
|
||||||
|
dataIndex: 'price',
|
||||||
|
width: '10%',
|
||||||
|
hideInSearch: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '接收地址',
|
||||||
|
dataIndex: 'to_address',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '游戏币类型',
|
||||||
|
dataIndex: 'bc_type',
|
||||||
|
width: '10%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
width: '10%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时间',
|
||||||
|
dataIndex: 'time',
|
||||||
|
valueType: 'dateRange',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 150,
|
||||||
|
render: (_, row) => [
|
||||||
|
<ConfirmButton
|
||||||
|
key="confirm"
|
||||||
|
title="确认通知已提现?"
|
||||||
|
buttonName="通知"
|
||||||
|
onConfirm={() => {
|
||||||
|
handleConfirm(row.uuid);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
<a
|
||||||
|
key="pass"
|
||||||
|
onClick={() => {
|
||||||
|
handlePass(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
通过
|
||||||
|
</a>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getWithdrawList, params);
|
||||||
|
for (const key in res.data) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(res.data, key)) {
|
||||||
|
const element = res.data[key];
|
||||||
|
element.price = getBalanceAmount(
|
||||||
|
new BigNumber(element.price),
|
||||||
|
element.decimals,
|
||||||
|
).toNumber();
|
||||||
|
element.time = moment(element.time * 1000).format('YYYY-MM-DD hh:mm:ss');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default WithdrawList;
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
// 创建弹窗
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
import { addUser } from '@/services/system/accountManage';
|
||||||
|
|
||||||
|
interface AddAccountModalPropsType extends ModalProps {
|
||||||
|
onCancel: () => void;
|
||||||
|
onOk: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const AddAccountModal = ({ onOk, onCancel, ...rest }: AddAccountModalPropsType) => {
|
||||||
|
const handleOk = async () => {
|
||||||
|
form.submit(async () => {
|
||||||
|
onOk();
|
||||||
|
const formState = form.getFormState();
|
||||||
|
formState.values.role = parseInt(formState.values.role);
|
||||||
|
await addUser(formState.values);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="添加管理账号" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="name"
|
||||||
|
title="账号名"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请输入账号名',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="password"
|
||||||
|
title="密码"
|
||||||
|
required
|
||||||
|
x-validator={{
|
||||||
|
required: true,
|
||||||
|
}}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请输入密码',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="role"
|
||||||
|
title="角色"
|
||||||
|
required
|
||||||
|
x-validator={{
|
||||||
|
required: true,
|
||||||
|
}}
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请选择角色',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddAccountModal;
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
// 创建弹窗
|
||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
import { addUser, updateUser } from '@/services/system/accountManage';
|
||||||
|
|
||||||
|
interface AddUserModalPropsType extends ModalProps {
|
||||||
|
editModalData: any;
|
||||||
|
onCancel: () => void;
|
||||||
|
onOk: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const AddUserModal = ({ onOk, onCancel, editModalData, ...rest }: AddUserModalPropsType) => {
|
||||||
|
useEffect(() => {
|
||||||
|
form.setInitialValues(editModalData);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOk = async () => {
|
||||||
|
onOk();
|
||||||
|
const formState = form.getFormState();
|
||||||
|
formState.values.role = parseInt(formState.values.role);
|
||||||
|
await updateUser(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="编辑管理账号" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="name"
|
||||||
|
title="账号名"
|
||||||
|
required
|
||||||
|
x-disabled
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请输入账号名',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="password"
|
||||||
|
title="密码"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请输入密码',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="role"
|
||||||
|
title="角色"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
x-component-props={{
|
||||||
|
placeholder: '请选择角色',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddUserModal;
|
||||||
|
|
@ -0,0 +1,117 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import {
|
||||||
|
getAccountList,
|
||||||
|
deleteUser,
|
||||||
|
updateUser,
|
||||||
|
changeUserStatus,
|
||||||
|
} from '@/services/system/accountManage';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import DeleteButton from '@/components/Table/DeleteButton';
|
||||||
|
import { Switch } from 'antd';
|
||||||
|
import AddAccountModal from '../Components/AddAccountModal';
|
||||||
|
import EditAccountModal from '../Components/EditAccountModal';
|
||||||
|
|
||||||
|
const AccountManageList = () => {
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
const [isEditModal, setIsEditModal] = useState(false);
|
||||||
|
const [modalData, setModalData] = useState({});
|
||||||
|
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
setModalData(row);
|
||||||
|
setIsEditModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async (name: any) => {
|
||||||
|
await deleteUser({ name: name });
|
||||||
|
};
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '账号',
|
||||||
|
dataIndex: 'name',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '角色',
|
||||||
|
dataIndex: 'role',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 180,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
<Switch
|
||||||
|
key="switch"
|
||||||
|
defaultChecked={row.status}
|
||||||
|
size="small"
|
||||||
|
onChange={async (checked) => {
|
||||||
|
await changeUserStatus({ name: row.name, status: checked });
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
<DeleteButton
|
||||||
|
key="delete"
|
||||||
|
onDelete={() => {
|
||||||
|
handleDelete(row.name);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {
|
||||||
|
setIsModalVisible(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getAccountList, params);
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddAccountModal
|
||||||
|
visible={isModalVisible}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (): Promise<void> {
|
||||||
|
setIsModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<EditAccountModal
|
||||||
|
visible={isEditModal}
|
||||||
|
editModalData={modalData}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsEditModal(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (): Promise<void> {
|
||||||
|
setIsEditModal(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AccountManageList;
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
// 添加代币类型弹窗
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
|
||||||
|
interface AddNoticeModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const AddNoticeModal = ({ onOk, onCancel, ...rest }: AddNoticeModalPropsType) => {
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
formState.values.code = parseInt(formState.values.code);
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="添加通知" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="code"
|
||||||
|
title="通知码"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="addr"
|
||||||
|
title="通知地址"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.Boolean
|
||||||
|
name="status"
|
||||||
|
title="状态"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Select"
|
||||||
|
enum={[
|
||||||
|
{ label: '启用', value: true },
|
||||||
|
{ label: '禁用', value: false },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default AddNoticeModal;
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
// 修改弹窗
|
||||||
|
import React, { useRef, useEffect } from 'react';
|
||||||
|
import { createForm } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
import { Form, FormItem, Input, Select } from '@formily/antd';
|
||||||
|
|
||||||
|
interface EditNoticeModalPropsType extends ModalProps {
|
||||||
|
editModalData: any;
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const form = createForm({});
|
||||||
|
|
||||||
|
const EditNoticeModal = ({ onOk, onCancel, editModalData, ...rest }: EditNoticeModalPropsType) => {
|
||||||
|
useEffect(() => {
|
||||||
|
form.setInitialValues(editModalData);
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="修改通知" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="code"
|
||||||
|
title="通知码"
|
||||||
|
x-disabled
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="addr"
|
||||||
|
title="通知地址"
|
||||||
|
required
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default EditNoticeModal;
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { getNoticeList, createNotice, updateNotice, deleteNotice } from '@/services/system/notice';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import AddNoticeModal from '../Components/AddNoticeModal';
|
||||||
|
import DeleteButton from '@/components/Table/DeleteButton';
|
||||||
|
import { Switch } from 'antd';
|
||||||
|
import EditNoticeModal from '../Components/EditNoticeModal';
|
||||||
|
|
||||||
|
const NoticeList = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
|
||||||
|
const [isModalVisible, setIsModalVisible] = useState(false);
|
||||||
|
const [isEditModalVisible, setIsEditModalVisible] = useState(false);
|
||||||
|
const [modalData, setModalData] = useState({});
|
||||||
|
|
||||||
|
const handleEdit = (row: any) => {
|
||||||
|
setModalData(row);
|
||||||
|
setIsEditModalVisible(true);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDelete = async (code: any) => {
|
||||||
|
await deleteNotice({ code: code });
|
||||||
|
tableRef.current?.reload();
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '通知码',
|
||||||
|
dataIndex: 'code',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '通知地址',
|
||||||
|
dataIndex: 'addr',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 180,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
<Switch
|
||||||
|
key="switch"
|
||||||
|
defaultChecked={row.status}
|
||||||
|
size="small"
|
||||||
|
onChange={async (checked) => {
|
||||||
|
row.status = checked;
|
||||||
|
await updateNotice(row);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
<DeleteButton
|
||||||
|
key="delete"
|
||||||
|
onDelete={() => {
|
||||||
|
handleDelete(row.code);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {
|
||||||
|
setIsModalVisible(true);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getNoticeList, params);
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddNoticeModal
|
||||||
|
visible={isModalVisible}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
await createNotice(val);
|
||||||
|
setIsModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<EditNoticeModal
|
||||||
|
visible={isEditModalVisible}
|
||||||
|
editModalData={modalData}
|
||||||
|
onCancel={function () {
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
}}
|
||||||
|
onOk={async function (val: any): Promise<void> {
|
||||||
|
await updateNotice(val);
|
||||||
|
setIsEditModalVisible(false);
|
||||||
|
tableRef.current?.reload();
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default NoticeList;
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import DeleteButton from '@/components/Table/DeleteButton';
|
||||||
|
|
||||||
|
const PermissionsList = () => {
|
||||||
|
const handleEdit = (row: any) => {};
|
||||||
|
|
||||||
|
const handleDelete = async (name: any) => {};
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '收款地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '收款游戏币类型',
|
||||||
|
dataIndex: 'bc_type',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 150,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
<DeleteButton
|
||||||
|
key="delete"
|
||||||
|
onDelete={() => {
|
||||||
|
handleDelete(row.name);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
return {};
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PermissionsList;
|
||||||
|
|
@ -0,0 +1,78 @@
|
||||||
|
import React, { useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { getRoleList, deleteRole } from '@/services/system/role';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
import DeleteButton from '@/components/Table/DeleteButton';
|
||||||
|
|
||||||
|
const RoleList = () => {
|
||||||
|
const handleEdit = (row: any) => {};
|
||||||
|
const handleAuth = (row: any) => {};
|
||||||
|
const handleDelete = async (role: any) => {
|
||||||
|
await deleteRole({ role: role });
|
||||||
|
};
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '角色名称',
|
||||||
|
dataIndex: 'role_name',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '用户类型',
|
||||||
|
dataIndex: 'role',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
valueType: 'option',
|
||||||
|
width: 180,
|
||||||
|
render: (_, row) => [
|
||||||
|
<a
|
||||||
|
key="edit"
|
||||||
|
onClick={() => {
|
||||||
|
handleEdit(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑
|
||||||
|
</a>,
|
||||||
|
<a
|
||||||
|
key="auth"
|
||||||
|
onClick={() => {
|
||||||
|
handleAuth(row);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
授权
|
||||||
|
</a>,
|
||||||
|
<DeleteButton
|
||||||
|
key="delete"
|
||||||
|
onDelete={() => {
|
||||||
|
handleDelete(row.role);
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getRoleList, params);
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RoleList;
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
@import '~antd/es/style/themes/default.less';
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100vh;
|
||||||
|
padding: 20px;
|
||||||
|
overflow: auto;
|
||||||
|
background: white;
|
||||||
|
:global {
|
||||||
|
.ant-pro-form-login-header {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.button {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.textarea {
|
||||||
|
width: 600px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
import React, { useState, useEffect } from 'react';
|
||||||
|
import { Button, Input } from 'antd';
|
||||||
|
import styles from './index.less';
|
||||||
|
import { createSecretKey, getSecretKey } from '@/services/system/secretKey';
|
||||||
|
|
||||||
|
const { TextArea } = Input;
|
||||||
|
|
||||||
|
const SecretKey: React.FC = () => {
|
||||||
|
const [secretKey, setSecretKey] = useState('');
|
||||||
|
|
||||||
|
const create = async () => {
|
||||||
|
const data = await createSecretKey({});
|
||||||
|
setSecretKey(data + '');
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUserSecretKey = async () => {
|
||||||
|
const data = await getSecretKey();
|
||||||
|
setSecretKey(data + '');
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getUserSecretKey();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.container}>
|
||||||
|
<Button className={styles.button} type="primary" onClick={create}>
|
||||||
|
创建密钥
|
||||||
|
</Button>
|
||||||
|
<TextArea className={styles.textarea} rows={16} value={secretKey} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SecretKey;
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import React, { useState, useRef } from 'react';
|
||||||
|
import Table, { ProColumns, ActionType } from '@/components/Table';
|
||||||
|
import { getUserList } from '@/services/user/user';
|
||||||
|
import { fetchTableData } from '@/utils/table';
|
||||||
|
|
||||||
|
const UserManageList = () => {
|
||||||
|
const tableRef = useRef<ActionType>();
|
||||||
|
const columns: ProColumns<any>[] = [
|
||||||
|
{
|
||||||
|
title: '用户钱包地址',
|
||||||
|
dataIndex: 'address',
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '登陆时间',
|
||||||
|
dataIndex: 'last_time',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '注册时间',
|
||||||
|
dataIndex: 'first_time',
|
||||||
|
hideInSearch: true,
|
||||||
|
ellipsis: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
return (
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
rowKey="id"
|
||||||
|
toolBarActions={[
|
||||||
|
{
|
||||||
|
type: 'add',
|
||||||
|
onConfirm: () => {},
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
actionRef={tableRef}
|
||||||
|
request={async (params) => {
|
||||||
|
const res = await fetchTableData(getUserList, params);
|
||||||
|
return res;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default UserManageList;
|
||||||
|
|
@ -11,33 +11,128 @@ export default [
|
||||||
component: './Login',
|
component: './Login',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '设置',
|
name: '充值系统',
|
||||||
path: RoutePath.SETTING,
|
path: RoutePath.RECHARGE,
|
||||||
routes: [
|
routes: [
|
||||||
{
|
{
|
||||||
path: RoutePath.SETTING,
|
path: RoutePath.RECHARGE,
|
||||||
redirect: RoutePath.WORK.LIST,
|
redirect: RoutePath.RECORD.LIST,
|
||||||
hideInMenu: true,
|
hideInMenu: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
name: '作品',
|
name: '充值订单',
|
||||||
path: RoutePath.WORK.LIST,
|
path: RoutePath.RECORD.LIST,
|
||||||
component: './Work/List',
|
component: './Recharge/Record/List',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '作品详情',
|
name: '收款地址',
|
||||||
path: RoutePath.WORK.EDIT,
|
path: RoutePath.ADDRESS.LIST,
|
||||||
|
component: './Recharge/Address/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '代币种类',
|
||||||
|
path: RoutePath.COIN_TYPE.LIST,
|
||||||
|
component: './Recharge/CoinType/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '提现管理',
|
||||||
|
path: RoutePath.WITHDRAW.LIST,
|
||||||
|
component: './Recharge/Withdraw/List',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '系统设置',
|
||||||
|
path: RoutePath.SYSTEM,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: RoutePath.SYSTEM,
|
||||||
|
redirect: RoutePath.ACCOUNT.LIST,
|
||||||
hideInMenu: true,
|
hideInMenu: true,
|
||||||
component: './Work/Edit',
|
},
|
||||||
|
{
|
||||||
|
name: '账号管理',
|
||||||
|
path: RoutePath.ACCOUNT.LIST,
|
||||||
|
component: './System/Account/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '角色管理',
|
||||||
|
path: RoutePath.ROLE.LIST,
|
||||||
|
component: './System/Role/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '权限管理',
|
||||||
|
path: RoutePath.PERMISSIONS.LIST,
|
||||||
|
component: './System/Permissions/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '通知管理',
|
||||||
|
path: RoutePath.NOTICE.LIST,
|
||||||
|
component: './System/Notice/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '密钥管理',
|
||||||
|
path: RoutePath.SECRET_KEY,
|
||||||
|
component: './System/SecretKey',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '数据看板',
|
||||||
|
path: RoutePath.DATABOARD,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: RoutePath.DATABOARD,
|
||||||
|
redirect: RoutePath.COREDATA.LIST,
|
||||||
|
hideInMenu: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '核心看板',
|
||||||
|
path: RoutePath.COREDATA.LIST,
|
||||||
|
component: './DataBoard/CoreData/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '活跃分析',
|
||||||
|
path: RoutePath.ACTIVEANALYSIS.LIST,
|
||||||
|
component: './DataBoard/ActiveAnalysis/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '留存分析',
|
||||||
|
path: RoutePath.RETENTIONANALYSIS.LIST,
|
||||||
|
component: './DataBoard/RetentionAnalysis/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '用户充值分析',
|
||||||
|
path: RoutePath.RECHARGEANALYSIS.LIST,
|
||||||
|
component: './DataBoard/RechargeAnalysis/List',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NFT',
|
||||||
|
path: RoutePath.NFT,
|
||||||
|
routes: [
|
||||||
|
{
|
||||||
|
path: RoutePath.NFT,
|
||||||
|
redirect: RoutePath.NFTCONTRACT.LIST,
|
||||||
|
hideInMenu: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NFT合约管理',
|
||||||
|
path: RoutePath.NFTCONTRACT.LIST,
|
||||||
|
component: './NFT/NftContract/List',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'NFT管理',
|
||||||
|
path: RoutePath.NFTTOKEN.LIST,
|
||||||
|
component: './NFT/NftToken/List',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
redirect: RoutePath.WORK.LIST,
|
redirect: RoutePath.RECORD.LIST,
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
component: './404',
|
component: './404',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,62 @@
|
||||||
const SETTING = '/setting';
|
const SETTING = '/setting';
|
||||||
|
const RECHARGE = '/recharge';
|
||||||
|
const SYSTEM = '/system';
|
||||||
|
const DATABOARD = '/databoard';
|
||||||
|
const NFT = '/nft';
|
||||||
const RoutePath = {
|
const RoutePath = {
|
||||||
LOGIN: '/login',
|
LOGIN: '/login',
|
||||||
SETTING: SETTING,
|
RECHARGE: RECHARGE,
|
||||||
WORK: {
|
RECORD: {
|
||||||
LIST: `${SETTING}/work`,
|
LIST: `${RECHARGE}/record`,
|
||||||
EDIT: `${SETTING}/work/edit`,
|
|
||||||
},
|
},
|
||||||
|
ADDRESS: {
|
||||||
|
LIST: `${RECHARGE}/address`,
|
||||||
|
},
|
||||||
|
COIN_TYPE: {
|
||||||
|
LIST: `${RECHARGE}/coin_type`,
|
||||||
|
},
|
||||||
|
WITHDRAW: {
|
||||||
|
LIST: `${RECHARGE}/withdraw`,
|
||||||
|
},
|
||||||
|
SYSTEM: SYSTEM,
|
||||||
|
ACCOUNT: {
|
||||||
|
LIST: `${SYSTEM}/account`,
|
||||||
|
},
|
||||||
|
ROLE: {
|
||||||
|
LIST: `${SYSTEM}/role`,
|
||||||
|
},
|
||||||
|
PERMISSIONS: {
|
||||||
|
LIST: `${SYSTEM}/permissions`,
|
||||||
|
},
|
||||||
|
NOTICE: {
|
||||||
|
LIST: `${SYSTEM}/notice`,
|
||||||
|
},
|
||||||
|
NFT: NFT,
|
||||||
|
NFTCONTRACT: {
|
||||||
|
LIST: `${NFT}/nftcontract`,
|
||||||
|
},
|
||||||
|
NFTTOKEN: {
|
||||||
|
LIST: `${NFT}/nfttoken`,
|
||||||
|
},
|
||||||
|
DATABOARD: DATABOARD,
|
||||||
|
COREDATA: {
|
||||||
|
LIST: `${DATABOARD}/coredata`,
|
||||||
|
},
|
||||||
|
ACTIVEANALYSIS: {
|
||||||
|
LIST: `${DATABOARD}/activeanalysis`,
|
||||||
|
},
|
||||||
|
RETENTIONANALYSIS: {
|
||||||
|
LIST: `${DATABOARD}/retentionanalysis`,
|
||||||
|
},
|
||||||
|
RECHARGEANALYSIS: {
|
||||||
|
LIST: `${DATABOARD}/rechargeanalysis`,
|
||||||
|
},
|
||||||
|
SECRET_KEY: `${SYSTEM}/secret_key`,
|
||||||
|
// SETTING: SETTING,
|
||||||
|
// WORK: {
|
||||||
|
// LIST: `${SETTING}/work`,
|
||||||
|
// EDIT: `${SETTING}/work/edit`,
|
||||||
|
// },
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RoutePath;
|
export default RoutePath;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
//获取基础数据报表
|
||||||
|
export const getActiveData = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/get',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取今日登陆人数接口
|
||||||
|
export const getTodayUserData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/user/today',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//获取本日新用户人数
|
||||||
|
export const getMonthUserData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/user/month',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取本周登录人数
|
||||||
|
export const getWeekUserData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/user/week',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取本日老用户登录人数
|
||||||
|
export const getOldUserData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/user/old',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
//获取基础数据报表
|
||||||
|
export const getCoreData = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/get',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取今日登陆人数接口
|
||||||
|
export const getTodayUserData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/user/today',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//获取今日新用户
|
||||||
|
export const getNewUserData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/user/new',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取充值总额
|
||||||
|
export const getPayData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/pay/all',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 获取本月充值总额
|
||||||
|
export const getMonthPayData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/pay/month',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
//获取基础数据报表
|
||||||
|
export const getRententionData = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/get',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
//获取基础数据报表
|
||||||
|
export const getRententionData = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/get',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//获取渠道
|
||||||
|
export const getChannelData = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tgb/api/v1/data/get',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -7,3 +7,18 @@ export const login = (data) => {
|
||||||
data,
|
data,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改用户密码
|
||||||
|
* @param data
|
||||||
|
* password 用户旧密码
|
||||||
|
* new_password 用户新密码
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const modifyPassword = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/admin/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
//获取获取所有合约
|
||||||
|
export const getContractData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tbg/api/v1/contract/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 创建合约
|
||||||
|
export const createContract = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tbg/api/v1/erc721/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
//获取获取所有NFT
|
||||||
|
export const getNftData = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tbg/api/v1/nft/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 创建NFT
|
||||||
|
export const createNft = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tbg/api/v1/nft/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
//编辑NFT
|
||||||
|
export const editNft = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tbg/api/v1/nft/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
// 检查TokenId
|
||||||
|
export const getTokenId = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/tbg/api/v1/nft/check',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取开发商收款地址列表
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
* bc_type 游戏币类型
|
||||||
|
* address 地址
|
||||||
|
*/
|
||||||
|
export const getAddressList = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/address/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建开发商收款地址
|
||||||
|
* @param {Object} data
|
||||||
|
* bc_type 游戏币类型
|
||||||
|
* address 地址(不传则后台生成)
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const createAddress = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/address/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除开发商收款地址
|
||||||
|
* @param {Object} data
|
||||||
|
* address 地址
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const deleteAddress = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/address/delete',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改开发商收款地址
|
||||||
|
* @param {Object} data
|
||||||
|
* address 旧地址
|
||||||
|
* bc_type 游戏币类型
|
||||||
|
* new_address 新地址
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
export const modifyAddress = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/address/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取代币种类列表
|
||||||
|
* @param {object} params
|
||||||
|
* type 代币种类
|
||||||
|
* @returns {array} data
|
||||||
|
* bc_name 游戏币名称
|
||||||
|
* bc_type 游戏币类型
|
||||||
|
* usdt_price 游戏货币与usdt的比例
|
||||||
|
* eth_price 游戏货币与eth的比例
|
||||||
|
*/
|
||||||
|
export const getCoinTypeList = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/token/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取代币种类列表
|
||||||
|
* @param {object} params
|
||||||
|
* bc_name 游戏币名称
|
||||||
|
* usdt_price 游戏货币与usdt的比例
|
||||||
|
* eth_price 游戏货币与eth的比例
|
||||||
|
* num 代币数量
|
||||||
|
* @returns {object} data
|
||||||
|
*/
|
||||||
|
export const addCoinType = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/token/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取代币种类列表
|
||||||
|
* @param {object} params
|
||||||
|
* bc_name 游戏币名称
|
||||||
|
* bc_type 游戏币类型
|
||||||
|
* usdt_price 游戏货币与usdt的比例
|
||||||
|
* eth_price 游戏货币与eth的比例
|
||||||
|
* @returns {object} data
|
||||||
|
*/
|
||||||
|
export const modifyCoinType = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/token/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取充值列表
|
||||||
|
* @param {object} data
|
||||||
|
* page 页码
|
||||||
|
* pageSize 页码大小
|
||||||
|
* start_time 开始时间
|
||||||
|
* end_time 结束时间
|
||||||
|
* @returns {array} data
|
||||||
|
* bc_type 游戏币类型
|
||||||
|
* address 地址
|
||||||
|
*/
|
||||||
|
export const getRecordList = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/recharge/record',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取提现列表
|
||||||
|
* @param {object} params
|
||||||
|
*
|
||||||
|
* @returns {array} data
|
||||||
|
* uuid 提现订单id
|
||||||
|
* to_addrss 接收地址
|
||||||
|
* from_address 发送地址
|
||||||
|
* time 提现时间
|
||||||
|
* price 提现金额
|
||||||
|
*/
|
||||||
|
export const getWithdrawList = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/withdrawal/get',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过提现申请
|
||||||
|
* @param {object} params
|
||||||
|
* uuid 提现订单id
|
||||||
|
* @returns {object} data
|
||||||
|
*/
|
||||||
|
export const solveWithdraw = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: 'withdrawal/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后台用户列表
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const getAccountList = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加后台用户
|
||||||
|
* @param {object} data
|
||||||
|
* name 账号名称
|
||||||
|
* password 密码
|
||||||
|
* role 权限角色
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const addUser = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改后台用户
|
||||||
|
* @param {object} data
|
||||||
|
* name 账号名称
|
||||||
|
* password 密码
|
||||||
|
* role 权限角色
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const updateUser = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改后台用户状态
|
||||||
|
* @param {object} data
|
||||||
|
* name 账号名称
|
||||||
|
* status 用户状态
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const changeUserStatus = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/status',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除后台用户
|
||||||
|
* @param {object} data
|
||||||
|
* name 用户名
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const deleteUser = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/delete',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取通知管理列表
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const getNoticeList = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/notice/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建通知
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const createNotice = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/notice/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置通知
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const updateNotice = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/notice/update',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 配置通知
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const deleteNotice = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/notice/delete',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后台角色列表
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
* role_name 角色名称
|
||||||
|
* role 角色类型
|
||||||
|
*/
|
||||||
|
export const getRoleList = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/role',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除后台角色
|
||||||
|
* @param {object} params
|
||||||
|
* role 角色类型
|
||||||
|
* @returns {array} data
|
||||||
|
*/
|
||||||
|
export const deleteRole = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/user/role/delete',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取密钥
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data 密钥
|
||||||
|
*/
|
||||||
|
export const getSecretKey = () => {
|
||||||
|
return request.request({
|
||||||
|
url: '/key/get',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建密钥
|
||||||
|
* @param {object} data
|
||||||
|
* @returns {array} data 密钥
|
||||||
|
*/
|
||||||
|
export const createSecretKey = (data) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/key/create',
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import request from '@/utils/request';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取后台角色列表
|
||||||
|
* @param {object} params
|
||||||
|
* @returns {array} data
|
||||||
|
* role_name 角色名称
|
||||||
|
* role 角色类型
|
||||||
|
*/
|
||||||
|
export const getUserList = (params) => {
|
||||||
|
return request.request({
|
||||||
|
url: '/account/get',
|
||||||
|
method: 'get',
|
||||||
|
params,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -176,7 +176,7 @@
|
||||||
.ant-pro-table-list-toolbar-container {
|
.ant-pro-table-list-toolbar-container {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
padding: 0 0 20px 0;
|
padding: 20px 0 20px 0;
|
||||||
.ant-pro-table-list-toolbar-left {
|
.ant-pro-table-list-toolbar-left {
|
||||||
.ant-space-item {
|
.ant-space-item {
|
||||||
margin-bottom: 16px;
|
margin-bottom: 16px;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
import Web3 from 'web3';
|
||||||
|
import detectEthereumProvider from '@metamask/detect-provider';
|
||||||
|
import { message } from 'antd';
|
||||||
|
|
||||||
|
let provider: any;
|
||||||
|
|
||||||
|
export const web3 = new Web3();
|
||||||
|
if (typeof window.ethereum !== 'undefined') {
|
||||||
|
web3.eth.defaultAccount = window.ethereum.selectedAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function initWeb3() {
|
||||||
|
provider = await detectEthereumProvider();
|
||||||
|
|
||||||
|
if (!provider) {
|
||||||
|
console.log('请安装MetaMask');
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
web3.setProvider(provider);
|
||||||
|
const accounts = await provider.request({
|
||||||
|
method: 'eth_requestAccounts',
|
||||||
|
});
|
||||||
|
web3.eth.defaultAccount = accounts[0];
|
||||||
|
return true;
|
||||||
|
} catch (reason) {
|
||||||
|
switch (reason) {
|
||||||
|
case 'Already processing eth_requestAccounts. Please wait.': // 已有请求存在
|
||||||
|
message.warning('请打开MetaMask完成授权');
|
||||||
|
break;
|
||||||
|
case 'User rejected provider access': //如果用户拒绝了登录请求
|
||||||
|
message.warning('请同意登录请求');
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// 本不该执行到这里,但是真到这里了,说明发生了意外
|
||||||
|
message.warning('登录出错!err:' + reason);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
|
||||||
|
export const BIG_ZERO = new BigNumber(0);
|
||||||
|
export const BIG_ONE = new BigNumber(1);
|
||||||
|
export const BIG_NINE = new BigNumber(9);
|
||||||
|
export const BIG_TEN = new BigNumber(10);
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
import BigNumber from 'bignumber.js';
|
||||||
|
import { BIG_TEN } from './bigNumber';
|
||||||
|
|
||||||
|
export const getBalanceAmount = (amount: BigNumber, decimals = 18) => {
|
||||||
|
return new BigNumber(amount).dividedBy(BIG_TEN.pow(decimals));
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export const getData = async (fetch: any) => {
|
||||||
|
const res = (await fetch()) || {};
|
||||||
|
return res.data;
|
||||||
|
};
|
||||||
|
|
@ -6,13 +6,13 @@ import { CACHE_TOKEN } from '@/constants/cacheKey';
|
||||||
|
|
||||||
// create an axios instance
|
// create an axios instance
|
||||||
const request = axios.create({
|
const request = axios.create({
|
||||||
baseURL: '', //
|
baseURL: '/tbg/api/v1', //
|
||||||
timeout: 10000, // request timeout
|
timeout: 10000, // request timeout
|
||||||
});
|
});
|
||||||
// request interceptor
|
// request interceptor
|
||||||
request.interceptors.request.use(
|
request.interceptors.request.use(
|
||||||
(memo: any) => {
|
(memo: any) => {
|
||||||
memo.headers.token = localStorage.getItem(CACHE_TOKEN);
|
memo.headers.Authorization = localStorage.getItem(CACHE_TOKEN);
|
||||||
return memo;
|
return memo;
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
|
|
@ -24,7 +24,7 @@ request.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
const res: any = response.data;
|
const res: any = response.data;
|
||||||
if (res.code !== 200) {
|
if (res.code !== 200) {
|
||||||
if (res.code === 401) {
|
if (res.code === 401 || res.code === 10001) {
|
||||||
notification.error({
|
notification.error({
|
||||||
message: '错误信息',
|
message: '错误信息',
|
||||||
description: '登录失效',
|
description: '登录失效',
|
||||||
|
|
|
||||||
|
|
@ -5,12 +5,11 @@ export const fetchTableData = async (
|
||||||
formatObj: any = {},
|
formatObj: any = {},
|
||||||
) => {
|
) => {
|
||||||
params.page = params.current;
|
params.page = params.current;
|
||||||
params.num = params.pageSize;
|
params.page_size = params.pageSize;
|
||||||
delete params.current;
|
delete params.current;
|
||||||
delete params.pageSize;
|
delete params.pageSize;
|
||||||
const res = (await fetch(params)) || {};
|
const res = (await fetch(params)) || {};
|
||||||
const data = res.data;
|
const data = res.items;
|
||||||
|
|
||||||
data?.forEach((n: any) => {
|
data?.forEach((n: any) => {
|
||||||
for (const key in formatObj) {
|
for (const key in formatObj) {
|
||||||
n[key] = n[formatObj[key]];
|
n[key] = n[formatObj[key]];
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
import { Col, Row, Statistic } from 'antd';
|
||||||
|
import { ArrowDownOutlined, ArrowUpOutlined } from '@ant-design/icons';
|
||||||
|
const MoreData = (props: any, title: string, company = '人') => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<p>{title}</p>
|
||||||
|
<h2>{props.time}</h2>
|
||||||
|
<h1>
|
||||||
|
{props.mon_user}
|
||||||
|
{company}
|
||||||
|
</h1>
|
||||||
|
<div>
|
||||||
|
<Row>
|
||||||
|
<Col span={12}>
|
||||||
|
<Statistic
|
||||||
|
title="较环比"
|
||||||
|
value={props.day_proportion}
|
||||||
|
valueStyle={
|
||||||
|
props.week_proportion > 0
|
||||||
|
? { color: '#3f8600', fontSize: 15 }
|
||||||
|
: { color: '#cf1322', fontSize: 15 }
|
||||||
|
}
|
||||||
|
prefix={props.week_proportion > 0 ? <ArrowDownOutlined /> : <ArrowUpOutlined />}
|
||||||
|
suffix="%"
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
<Col span={12}>
|
||||||
|
<Statistic
|
||||||
|
title="较同比"
|
||||||
|
value={Math.abs(props.week_proportion)}
|
||||||
|
valueStyle={
|
||||||
|
props.week_proportion > 0
|
||||||
|
? { color: '#3f8600', fontSize: 15 }
|
||||||
|
: { color: '#cf1322', fontSize: 15 }
|
||||||
|
}
|
||||||
|
prefix={props.week_proportion > 0 ? <ArrowDownOutlined /> : <ArrowUpOutlined />}
|
||||||
|
suffix="%"
|
||||||
|
/>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
export default MoreData;
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
import React, { useRef, useState } from 'react';
|
||||||
|
import { createForm, onFieldReact } from '@formily/core';
|
||||||
|
import { createSchemaField } from '@formily/react';
|
||||||
|
import Modal, { ModalProps } from '@/components/Modal';
|
||||||
|
// import { fetchTableData } from '@/utils/table';
|
||||||
|
import { Form, FormItem, Input, Select, Radio, Switch } from '@formily/antd';
|
||||||
|
|
||||||
|
interface PaySelectModalPropsType extends ModalProps {
|
||||||
|
onOk: (val: any) => void;
|
||||||
|
onCancel: () => void;
|
||||||
|
// modalData: any;
|
||||||
|
}
|
||||||
|
const form = createForm({
|
||||||
|
effects() {
|
||||||
|
onFieldReact('input', (field) => {
|
||||||
|
if (field.query('type').value() == 2) {
|
||||||
|
field.display = 'none';
|
||||||
|
} else {
|
||||||
|
field.display = 'visible';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const SchemaField = createSchemaField({
|
||||||
|
components: {
|
||||||
|
FormItem,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
Radio,
|
||||||
|
Switch,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const PaySelectModal = ({ onOk, onCancel, ...rest }: PaySelectModalPropsType) => {
|
||||||
|
const [send, useSend] = useState(true);
|
||||||
|
|
||||||
|
const handleOk = () => {
|
||||||
|
const formState = form.getFormState();
|
||||||
|
onOk(formState.values);
|
||||||
|
};
|
||||||
|
const handleCancel = () => {
|
||||||
|
onCancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Modal title="选择方式" onOk={handleOk} onCancel={handleCancel} width={800} {...rest}>
|
||||||
|
<Form form={form} labelCol={4} wrapperCol={18}>
|
||||||
|
<SchemaField>
|
||||||
|
<SchemaField.String
|
||||||
|
name="type"
|
||||||
|
title="支付方式"
|
||||||
|
enum={[
|
||||||
|
{ label: '秘钥支付', value: 1 },
|
||||||
|
{ label: '小狐狸钱包支付', value: 2 },
|
||||||
|
]}
|
||||||
|
x-component="Select"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
/>
|
||||||
|
<SchemaField.String
|
||||||
|
name="input"
|
||||||
|
title="秘钥"
|
||||||
|
x-decorator="FormItem"
|
||||||
|
x-component="Input"
|
||||||
|
// x-component-props={{
|
||||||
|
// placeholder: '请输入秘钥,若使用小狐狸支付则不需要输入',
|
||||||
|
// }}
|
||||||
|
/>
|
||||||
|
</SchemaField>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PaySelectModal;
|
||||||
Loading…
Reference in New Issue