添加数据看板接口

This commit is contained in:
zzy 2022-09-23 17:44:46 +08:00
parent 4cffaf367e
commit dd30202a7f
15 changed files with 224 additions and 155 deletions

View File

@ -18,6 +18,9 @@ export default function access(initialState: {
}, },
canShowButton: (buttonName) => { canShowButton: (buttonName) => {
// return true; // return true;
if (routeList == null || routeList == undefined || routeList.length == 0) {
return true;
}
return routeList.includes(buttonName); return routeList.includes(buttonName);
}, },
}; };

View File

@ -1,6 +1,6 @@
export enum TimeType { export enum TimeType {
DAY = 'day', DAY = '1',
WEEK = 'week', WEEK = '2',
MONTH = 'month', MONTH = '3',
} }
export default TimeType; export default TimeType;

View File

@ -2,110 +2,79 @@ import React, { useRef, useState } from 'react';
import Table, { ProColumns, ActionType } from '@/components/Table'; import Table, { ProColumns, ActionType } from '@/components/Table';
import moment from 'moment'; import moment from 'moment';
import TimeType from '@/constants/enum/timeType'; import TimeType from '@/constants/enum/timeType';
import { getData } from '@/utils/getData';
import MoreData from '@/widget/MoreData'; import MoreData from '@/widget/MoreData';
import { import { getCoreData, getListData } from '@/services/dataBorad/coreData';
getCoreData,
getPayData,
getTodayUserData,
getMonthPayData,
getNewUserData,
} from '@/services/dataBorad/coreData';
import { Card, Col, Row, Select } from 'antd'; import { Card, Col, Row, Select } from 'antd';
import { fetchTableData } from '@/utils/table';
const CoreData: React.FC = () => { const CoreData: React.FC = () => {
const tableRef = useRef<ActionType>(); const tableRef = useRef<ActionType>();
const [timeType, setTimeType] = useState(TimeType.DAY);
// const [date, setDate] = useState(getData); const TimeTypeList = [
const [userDate, setUserDate] = useState(getData(getTodayUserData)); {
const [newUserdate, setNewUserDate] = useState(getData(getNewUserData)); label: '每日',
const [payData, setPayDate] = useState(getData(getMonthPayData)); value: TimeType.DAY,
const [allPay, setAllPayDate] = useState(getData(getPayData)); },
{
label: '每周',
value: TimeType.WEEK,
},
{
label: '每月',
value: TimeType.MONTH,
},
];
const [coreData, setCoreData] = useState({
today_active_user: '',
today_new_user: '',
month_recharge: '',
recharge_sum: '',
});
const columns: ProColumns<any>[] = [ const columns: ProColumns<any>[] = [
{ {
title: '时间类型', title: '时间类型',
dataIndex: 'coinType', dataIndex: 'code',
hideInTable: true, hideInTable: true,
initialValue: TimeType.DAY, initialValue: TimeType.DAY,
renderFormItem: (item, { type, defaultRender, ...rest }, form) => { valueEnum: () => {
return ( const options = {};
<Select TimeTypeList.forEach((item) => {
options={[ options[item.value] = { text: item.label };
{ });
label: '每日', return options;
value: TimeType.DAY,
},
{
label: '每周',
value: TimeType.WEEK,
},
{
label: '每月',
value: TimeType.MONTH,
},
]}
onChange={(val) => {
setTimeType(val);
}}
/>
);
}, },
}, },
{ {
title: '日期', title: '日期',
dataIndex: 'time', dataIndex: 'start_time',
hideInSearch: true, hideInSearch: true,
width: '10%',
}, },
{ {
title: '时间', title: '时间',
dataIndex: 'select_time', dataIndex: 'select_time',
valueType: 'dateRange', valueType: 'dateRange',
width: '20%',
hideInTable: true, hideInTable: true,
ellipsis: true, ellipsis: true,
}, },
{ {
title: '活跃用户数', title: '活跃用户数',
dataIndex: 'address', dataIndex: 'active_user',
hideInSearch: true,
width: '20%',
},
{
title: '新用户数量',
dataIndex: 'new_user',
width: 150,
hideInSearch: true, hideInSearch: true,
}, },
{ {
title: '当日充值总额', title: '当日充值总额',
dataIndex: 'address', dataIndex: 'today_recharge',
hideInSearch: true, hideInSearch: true,
width: '20%',
}, },
{ {
title: '付费用户数', title: '付费用户数',
dataIndex: 'address', dataIndex: 'pay_user',
hideInSearch: true, hideInSearch: true,
width: '20%',
}, },
{ {
title: '付费率', title: '付费率',
dataIndex: 'address', dataIndex: 'pay_ratio',
hideInSearch: true, hideInSearch: true,
width: '20%',
},
{
title: 'ARPU',
dataIndex: 'arpu',
hideInSearch: true,
width: '20%',
},
{
title: 'ARPPU',
dataIndex: 'arppu',
hideInSearch: true,
width: '20%',
}, },
]; ];
@ -113,16 +82,24 @@ const CoreData: React.FC = () => {
<div> <div>
<Row gutter={24} style={{ marginBottom: 10 }}> <Row gutter={24} style={{ marginBottom: 10 }}>
<Col span={6}> <Col span={6}>
<Card style={{ height: '200px' }}>{MoreData(userDate, '今日活跃用户数', '人')}</Card> <Card style={{ height: '120px' }}>
{MoreData(null, '今日活跃用户数', coreData.today_active_user + '人')}
</Card>
</Col> </Col>
<Col span={6}> <Col span={6}>
<Card style={{ height: '200px' }}>{MoreData(newUserdate, '今日新增人数', '人')}</Card> <Card style={{ height: '120px' }}>
{MoreData(null, '今日新增人数', coreData.today_new_user + '人')}
</Card>
</Col> </Col>
<Col span={6}> <Col span={6}>
<Card style={{ height: '200px' }}>{MoreData(payData, '本月充值总额', '万元')}</Card> <Card style={{ height: '120px' }}>
{MoreData(null, '本月充值总额', coreData.month_recharge + '万元')}
</Card>
</Col> </Col>
<Col span={6}> <Col span={6}>
<Card style={{ height: '200px' }}>{MoreData(allPay, '充值总额', '万元')}</Card> <Card style={{ height: '120px' }}>
{MoreData(null, '充值总额', coreData.recharge_sum + '万元')}
</Card>
</Col> </Col>
</Row> </Row>
@ -131,11 +108,30 @@ const CoreData: React.FC = () => {
rowKey="id" rowKey="id"
actionRef={tableRef} actionRef={tableRef}
request={async (params) => { request={async (params) => {
params.code = parseInt(params.code);
if ((params.select_time ?? '') !== '') { if ((params.select_time ?? '') !== '') {
params.start_time = moment(params.select_time[0]).valueOf() / 1000; params.start_time = moment(params.select_time[0]).valueOf() / 1000;
params.end_time = moment(params.select_time[1]).valueOf() / 1000; params.end_time = moment(params.select_time[1]).valueOf() / 1000;
} }
return getCoreData(params); const data = await getCoreData({});
setCoreData(data);
const res = await fetchTableData(getListData, params);
console.log('res', res);
for (const key in res.data) {
if (Object.prototype.hasOwnProperty.call(res.data, key)) {
const element = res.data[key];
if (
element.start_time != '' &&
element.start_time != undefined &&
element.start_time != null
) {
element.start_time = moment(element.start_time * 1000).format(
'YYYY-MM-DD hh:mm:ss',
);
}
}
}
return res;
}} }}
/> />
</div> </div>

View File

@ -53,3 +53,7 @@
color: @primary-color; color: @primary-color;
} }
} }
.drawer-style {
padding: 0;
}

View File

@ -8,6 +8,7 @@ import EditCoinTypeModal from '../components/EditCoinTypeModal';
import { initWeb3, deployContract, transfer } from '@/utils/web3'; import { initWeb3, deployContract, transfer } from '@/utils/web3';
import { ContractType } from '@/constants/enum/contract'; import { ContractType } from '@/constants/enum/contract';
import { Access, useAccess } from 'umi'; import { Access, useAccess } from 'umi';
import { message } from 'antd';
const CoinTypeList = () => { const CoinTypeList = () => {
const access = useAccess(); const access = useAccess();
@ -28,25 +29,31 @@ const CoinTypeList = () => {
title: '游戏币名称', title: '游戏币名称',
dataIndex: 'name', dataIndex: 'name',
hideInSearch: true, hideInSearch: true,
ellipsis: true, width: 150,
}, },
{ {
title: 'usdt比例', title: 'usdt比例',
dataIndex: 'usdt_price', dataIndex: 'usdt_price',
hideInSearch: true, hideInSearch: true,
ellipsis: true, width: 100,
}, },
{ {
title: 'eth比例', title: 'eth比例',
dataIndex: 'eth_price', dataIndex: 'eth_price',
hideInSearch: true, hideInSearch: true,
width: 100,
},
{
title: '地址',
dataIndex: 'address',
hideInSearch: true,
ellipsis: true, ellipsis: true,
}, },
{ {
title: '代币发行总量', title: '代币发行总量',
dataIndex: 'total', dataIndex: 'total',
hideInSearch: true, hideInSearch: true,
ellipsis: true, width: 150,
}, },
{ {
title: '操作', title: '操作',
@ -102,6 +109,7 @@ const CoinTypeList = () => {
]); ]);
val.address = result; val.address = result;
await addCoinType(val); await addCoinType(val);
message.success('代币添加成功');
setIsModalVisible(false); setIsModalVisible(false);
tableRef.current?.reload(); tableRef.current?.reload();
}} }}
@ -114,6 +122,7 @@ const CoinTypeList = () => {
}} }}
onOk={async function (val: any): Promise<void> { onOk={async function (val: any): Promise<void> {
await modifyCoinType(val); await modifyCoinType(val);
message.success('代币修改成功');
setIsEditModalVisible(false); setIsEditModalVisible(false);
tableRef.current?.reload(); tableRef.current?.reload();
}} }}

View File

@ -12,6 +12,7 @@ import DeleteButton from '@/components/Table/DeleteButton';
import AddWalletModal from '../components/AddWalletModal'; import AddWalletModal from '../components/AddWalletModal';
import EditWalletModal from '../components/EditWalletModal'; import EditWalletModal from '../components/EditWalletModal';
import { Access, useAccess } from 'umi'; import { Access, useAccess } from 'umi';
import { message } from 'antd';
const CollectionAddressList = () => { const CollectionAddressList = () => {
const tableRef = useRef<ActionType>(); const tableRef = useRef<ActionType>();
@ -99,6 +100,7 @@ const CollectionAddressList = () => {
onOk={async function (val: any): Promise<void> { onOk={async function (val: any): Promise<void> {
await createAddress(val); await createAddress(val);
setIsModalVisible(false); setIsModalVisible(false);
message.success('收款地址添加成功');
tableRef.current?.reload(); tableRef.current?.reload();
}} }}
/> />
@ -110,6 +112,7 @@ const CollectionAddressList = () => {
}} }}
onOk={async function (val: any): Promise<void> { onOk={async function (val: any): Promise<void> {
await modifyAddress(val); await modifyAddress(val);
message.success('收款地址修改成功');
setIsEditModalVisible(false); setIsEditModalVisible(false);
tableRef.current?.reload(); tableRef.current?.reload();
}} }}

View File

@ -65,6 +65,7 @@ const PermissionsList = () => {
} }
} }
await upsertPermission(permissionsData); await upsertPermission(permissionsData);
message.success('删除权限成功');
tableRef.current?.reload(); tableRef.current?.reload();
}; };
@ -208,6 +209,7 @@ const PermissionsList = () => {
} }
} }
await upsertPermission(permissionsData); await upsertPermission(permissionsData);
message.success('添加权限成功');
setIsModalVisible(false); setIsModalVisible(false);
tableRef.current?.reload(); tableRef.current?.reload();
}} }}
@ -233,6 +235,7 @@ const PermissionsList = () => {
} }
await upsertPermission(permissionsData); await upsertPermission(permissionsData);
setIsEditModalVisible(false); setIsEditModalVisible(false);
message.success('编辑权限成功');
tableRef.current?.reload(); tableRef.current?.reload();
}} }}
/> />

View File

@ -5,6 +5,7 @@ import { ActionType, ProColumns } from '@ant-design/pro-table';
import Table from '@/components/Table'; import Table from '@/components/Table';
import { TableRowSelection } from 'antd/lib/table/interface'; import { TableRowSelection } from 'antd/lib/table/interface';
import { getPermission } from '@/services/system/permission'; import { getPermission } from '@/services/system/permission';
import { useModel } from '@/.umi/plugin-model/useModel';
interface AuthPermissionsDrawerPropsType extends DrawerProps { interface AuthPermissionsDrawerPropsType extends DrawerProps {
onCancel: () => void; onCancel: () => void;
@ -12,14 +13,18 @@ interface AuthPermissionsDrawerPropsType extends DrawerProps {
rowData: any; rowData: any;
} }
const divStyle: React.CSSProperties = {
padding: 0,
};
const columnsPermissions: ProColumns<any>[] = [ const columnsPermissions: ProColumns<any>[] = [
{ {
title: '路由名称', title: '权限名',
dataIndex: 'name', dataIndex: 'name',
}, },
]; ];
const valueMap = {}; const valueMap = new Map();
const loops = (list, parent) => { const loops = (list, parent) => {
return (list || []).map(({ children, name }) => { return (list || []).map(({ children, name }) => {
const node = (valueMap[name] = { const node = (valueMap[name] = {
@ -69,6 +74,7 @@ const AuthPermissionsDrawer = ({
}: AuthPermissionsDrawerPropsType) => { }: AuthPermissionsDrawerPropsType) => {
const tableRef = useRef<ActionType>(); const tableRef = useRef<ActionType>();
const [selectedKeys, setSelectedKeys] = useState(new Array()); const [selectedKeys, setSelectedKeys] = useState(new Array());
const [tempValue, setTempValue] = useState(new Map());
const rowSelection: TableRowSelection<DataType> = { const rowSelection: TableRowSelection<DataType> = {
onChange: (selectedRowKeys, selectedRows) => { onChange: (selectedRowKeys, selectedRows) => {
@ -95,9 +101,9 @@ const AuthPermissionsDrawer = ({
useEffect(() => { useEffect(() => {
const parentArray = new Array(); const parentArray = new Array();
let newPermission = new Array(); let newPermission = new Array();
for (const key in valueMap) { for (const key in tempValue) {
if (Object.prototype.hasOwnProperty.call(valueMap, key)) { if (Object.prototype.hasOwnProperty.call(tempValue, key)) {
const element = valueMap[key]; const element = tempValue[key];
if (element.children.length != 0) { if (element.children.length != 0) {
parentArray.push(element.name); parentArray.push(element.name);
} }
@ -107,18 +113,19 @@ const AuthPermissionsDrawer = ({
newPermission = rowData.permission.filter((item) => !parentArray.includes(item)); newPermission = rowData.permission.filter((item) => !parentArray.includes(item));
} }
setSelectedKeys(newPermission); setSelectedKeys(newPermission);
}, [rowData.permission]); }, [rowData.permission, tempValue]);
return ( return (
<Drawer <Drawer
onClose={handleCancel} onClose={handleCancel}
width={400} width={600}
{...rest} {...rest}
bodyStyle={divStyle}
extra={ extra={
<Space> <Space>
<Button onClick={handleCancel}>Cancel</Button> <Button onClick={handleCancel}></Button>
<Button type="primary" onClick={handleOk}> <Button type="primary" onClick={handleOk}>
OK
</Button> </Button>
</Space> </Space>
} }
@ -126,6 +133,7 @@ const AuthPermissionsDrawer = ({
<Table <Table
columns={columnsPermissions} columns={columnsPermissions}
rowKey="name" rowKey="name"
key="name"
search={false} search={false}
pagination={false} pagination={false}
rowSelection={{ rowSelection={{
@ -139,6 +147,7 @@ const AuthPermissionsDrawer = ({
const res = await getPermission({}); const res = await getPermission({});
const treeData = JSON.parse(res.items); const treeData = JSON.parse(res.items);
loops(treeData, null); loops(treeData, null);
setTempValue(valueMap);
return { data: treeData }; return { data: treeData };
}} }}
/> />

View File

@ -1,7 +1,7 @@
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, ChangeEvent } from 'react';
import { Button, Input, Popconfirm } from 'antd'; import { Button, Input, message, Popconfirm } from 'antd';
import styles from './index.less'; import styles from './index.less';
import { createSecretKey, getSecretKey } from '@/services/system/secretKey'; import { createAppID, createSecretKey, getAppID, getSecretKey } from '@/services/system/secretKey';
import { Access, useAccess } from 'umi'; import { Access, useAccess } from 'umi';
const { TextArea } = Input; const { TextArea } = Input;
@ -9,20 +9,37 @@ const { TextArea } = Input;
const SecretKey: React.FC = () => { const SecretKey: React.FC = () => {
const access = useAccess(); const access = useAccess();
const [secretKey, setSecretKey] = useState(''); const [secretKey, setSecretKey] = useState('');
const [appIDString, setAppIDString] = useState('');
const create = async () => { const create = async () => {
const data = await createSecretKey({}); const data = await createSecretKey({});
message.success('密钥创建成功');
setSecretKey(data + ''); setSecretKey(data + '');
}; };
const appIDCreate = async () => {
if (appIDString == '') {
message.warning('请填写AppID');
return;
}
await createAppID({ appid: appIDString });
message.success('AppID创建成功');
};
const getAppIDString = async () => {
const data = await getAppID();
setAppIDString(data + '');
};
const getUserSecretKey = async () => { const getUserSecretKey = async () => {
const data = await getSecretKey(); const data = await getSecretKey();
setSecretKey(data + ''); setSecretKey(data + '');
}; };
useEffect(() => { useEffect(() => {
getAppIDString();
getUserSecretKey(); getUserSecretKey();
}, []); }, [secretKey]);
return ( return (
<div className={styles.container}> <div className={styles.container}>
@ -35,6 +52,30 @@ const SecretKey: React.FC = () => {
</Access> </Access>
<TextArea className={styles.textarea} rows={16} value={secretKey} /> <TextArea className={styles.textarea} rows={16} value={secretKey} />
<br />
<br />
<Input.Group compact>
<Input
style={{ width: 'calc(50% - 160px)' }}
value={appIDString}
onChange={(event: ChangeEvent<HTMLInputElement>) => {
setAppIDString(event.target.value);
}}
placeholder="请输入AppID"
/>
<Access accessible={access.canShowButton('创建AppID')}>
<Popconfirm
title="确定创建AppID?"
onConfirm={appIDCreate}
okText="确定"
cancelText="取消"
>
<Button className={styles.button} type="primary">
AppID
</Button>
</Popconfirm>
</Access>
</Input.Group>
</div> </div>
); );
}; };

View File

@ -2,6 +2,7 @@ import React, { useState, useRef } from 'react';
import Table, { ProColumns, ActionType } from '@/components/Table'; import Table, { ProColumns, ActionType } from '@/components/Table';
import { getUserList } from '@/services/user/user'; import { getUserList } from '@/services/user/user';
import { fetchTableData } from '@/utils/table'; import { fetchTableData } from '@/utils/table';
import moment from 'moment';
const UserManageList = () => { const UserManageList = () => {
const tableRef = useRef<ActionType>(); const tableRef = useRef<ActionType>();
@ -11,6 +12,12 @@ const UserManageList = () => {
dataIndex: 'address', dataIndex: 'address',
ellipsis: true, ellipsis: true,
}, },
{
title: '注册时间',
dataIndex: 'create_time',
hideInSearch: true,
ellipsis: true,
},
{ {
title: '登陆时间', title: '登陆时间',
dataIndex: 'last_time', dataIndex: 'last_time',
@ -25,6 +32,28 @@ const UserManageList = () => {
actionRef={tableRef} actionRef={tableRef}
request={async (params) => { request={async (params) => {
const res = await fetchTableData(getUserList, params); const res = await fetchTableData(getUserList, params);
console.log('res = ', res);
for (const key in res.data) {
if (Object.prototype.hasOwnProperty.call(res.data, key)) {
const element = res.data[key];
if (
element.create_time != '' &&
element.create_time != undefined &&
element.create_time != null
) {
element.create_time = moment(element.create_time * 1000).format(
'YYYY-MM-DD hh:mm:ss',
);
}
if (
element.last_time != '' &&
element.last_time != undefined &&
element.last_time != null
) {
element.last_time = moment(element.last_time * 1000).format('YYYY-MM-DD hh:mm:ss');
}
}
}
if (res.data == null) { if (res.data == null) {
return []; return [];
} }

View File

@ -122,24 +122,6 @@ export default [
access: 'normalRouteFilter', access: 'normalRouteFilter',
component: './DataBoard/CoreData/List', component: './DataBoard/CoreData/List',
}, },
{
name: '活跃分析',
path: RoutePath.ACTIVEANALYSIS.LIST,
access: 'normalRouteFilter',
component: './DataBoard/ActiveAnalysis/List',
},
{
name: '留存分析',
path: RoutePath.RETENTIONANALYSIS.LIST,
access: 'normalRouteFilter',
component: './DataBoard/RetentionAnalysis/List',
},
{
name: '用户充值分析',
path: RoutePath.RECHARGEANALYSIS.LIST,
access: 'normalRouteFilter',
component: './DataBoard/RechargeAnalysis/List',
},
], ],
}, },
{ {

View File

@ -50,15 +50,7 @@ const RoutePath = {
COREDATA: { COREDATA: {
LIST: `${DATABOARD}/coredata`, LIST: `${DATABOARD}/coredata`,
}, },
ACTIVEANALYSIS: {
LIST: `${DATABOARD}/activeanalysis`,
},
RETENTIONANALYSIS: {
LIST: `${DATABOARD}/retentionanalysis`,
},
RECHARGEANALYSIS: {
LIST: `${DATABOARD}/rechargeanalysis`,
},
SECRET_KEY: `${SYSTEM}/secret_key`, SECRET_KEY: `${SYSTEM}/secret_key`,
// SETTING: SETTING, // SETTING: SETTING,
// WORK: { // WORK: {

View File

@ -1,41 +1,18 @@
import request from '@/utils/request'; import request from '@/utils/request';
//获取基础数据报表 // 获取核心列表数据
export const getCoreData = (data) => { export const getCoreData = (data) => {
return request.request({ return request.request({
url: '/tgb/api/v1/data/get', url: '/coredata/get',
method: 'post', method: 'post',
data, data,
}); });
}; };
// 获取今日登陆人数接口
export const getTodayUserData = (params) => { // 数据库列表
export const getListData = (data) => {
return request.request({ return request.request({
url: '/tgb/api/v1/data/user/today', url: '/data/get',
method: 'get', method: 'post',
params, data,
});
};
//获取今日新用户
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,
}); });
}; };

View File

@ -24,3 +24,28 @@ export const createSecretKey = (data) => {
data, data,
}); });
}; };
/**
* AppID
* @param {object} params
* @returns {array} data
*/
export const getAppID = () => {
return request.request({
url: '/appid/get',
method: 'get',
});
};
/**
* AppID
* @param {object} data
* @returns {array} data
*/
export const createAppID = (data) => {
return request.request({
url: '/appid/create',
method: 'post',
data,
});
};

View File

@ -4,12 +4,8 @@ const MoreData = (props: any, title: string, company = '人') => {
return ( return (
<div> <div>
<p>{title}</p> <p>{title}</p>
<h2>{props.time}</h2> <h1>{company}</h1>
<h1> {/* <div>
{props.mon_user}
{company}
</h1>
<div>
<Row> <Row>
<Col span={12}> <Col span={12}>
<Statistic <Statistic
@ -38,7 +34,7 @@ const MoreData = (props: any, title: string, company = '人') => {
/> />
</Col> </Col>
</Row> </Row>
</div> </div> */}
</div> </div>
); );
}; };