448 lines
12 KiB
JavaScript
448 lines
12 KiB
JavaScript
import React, { useState, useEffect } from "react";
|
||
import baseRequest from "../../utils/baseRequest";
|
||
import { DatePicker, Table, Image } from "antd";
|
||
|
||
export default function Data() {
|
||
const { RangePicker } = DatePicker;
|
||
const [data, setData] = useState();
|
||
const [order, setOrder] = useState();
|
||
const [notFinishOrder, setNotFinishOrder] = useState();
|
||
const [zoneData, setZoneData] = useState();
|
||
|
||
// 获取当前时间戳
|
||
const currentTimestamp = Date.now();
|
||
// 获取前2个小时的时间戳
|
||
const oneHourAgoTimestamp = currentTimestamp - 7200000; // 1小时 = 60分钟 * 60秒 * 1000毫秒
|
||
const [selectTime, setSelectTime] = useState({
|
||
ct_lower_bound: oneHourAgoTimestamp,
|
||
ct_upper_bound: currentTimestamp,
|
||
});
|
||
|
||
useEffect(() => {
|
||
const getData = async () => {
|
||
try {
|
||
const base = baseRequest();
|
||
const response = await fetch(`/op/daily_statement/list`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
ct_lower_bound: Math.floor(selectTime.ct_lower_bound / 1000),
|
||
ct_upper_bound: Math.floor(selectTime.ct_upper_bound / 1000),
|
||
offset: 0,
|
||
limit: 100,
|
||
...base,
|
||
}),
|
||
});
|
||
const _data = await response.json();
|
||
if (_data.ret === -1) {
|
||
alert(_data.msg);
|
||
return;
|
||
}
|
||
const structedData = _data.data.list.map((item, index) => {
|
||
return {
|
||
key: index,
|
||
time: {
|
||
start: new Date(item.start_time * 1000).toLocaleString(),
|
||
end: new Date(item.end_time * 1000).toLocaleString(),
|
||
},
|
||
h5_call_count: item.h5_call_count,
|
||
zone_list_from_outside_count: item.zone_list_from_outside_count,
|
||
last_hour_new_user_form: {
|
||
ios: item.last_hour_new_user_count_from_ios,
|
||
android: item.last_hour_new_user_count_from_android,
|
||
h5: item.last_hour_new_user_count_from_h5,
|
||
},
|
||
registered_user_count: item.registered_user_count,
|
||
order_created_count: item.order_created_count,
|
||
order_finished_count: item.order_finished_count,
|
||
};
|
||
});
|
||
setData(structedData);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
const getOrderData = async () => {
|
||
try {
|
||
const base = baseRequest();
|
||
const response = await fetch(`/op/vas/coin_order_list`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
st: Math.floor(selectTime.ct_lower_bound / 1000),
|
||
et: Math.floor(selectTime.ct_upper_bound / 1000),
|
||
offset: 0,
|
||
limit: 10000,
|
||
...base,
|
||
}),
|
||
});
|
||
const _data = await response.json();
|
||
if (_data.ret === -1) {
|
||
alert(_data.msg);
|
||
return;
|
||
}
|
||
const structedData = _data.data.list.map((item, index) => {
|
||
return {
|
||
key: index,
|
||
time: new Date(item.ct * 1000).toLocaleString(),
|
||
user: item.user_user_id,
|
||
streamer: item.streamer_user_id,
|
||
price: item.coins / 10,
|
||
order_detail: {
|
||
order_id: item.order_id,
|
||
order_status_desc: item.order_status_desc,
|
||
},
|
||
};
|
||
});
|
||
setOrder(structedData);
|
||
//查询所有未处理的订单
|
||
const response2 = await fetch(`/op/vas/coin_order_list`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
st: Math.floor(Date.now() / 1000) - 60 * 60 * 24 * 8, //往前推8天
|
||
et: Math.floor(Date.now() / 1000),
|
||
offset: 0,
|
||
limit: 10000,
|
||
...base,
|
||
}),
|
||
});
|
||
const _data2 = await response2.json();
|
||
if (_data2.ret === -1) {
|
||
alert(_data2.msg);
|
||
return;
|
||
}
|
||
const structedData2 = _data2.data.list
|
||
.filter((item, index) => item.order_status === 3)
|
||
.map((item, index) => {
|
||
return {
|
||
key: index,
|
||
time: new Date(item.ct * 1000).toLocaleString(),
|
||
user: item.user_user_id,
|
||
streamer: item.streamer_user_id,
|
||
price: item.coins / 10,
|
||
order_detail: {
|
||
order_id: item.order_id,
|
||
order_status_desc: item.order_status_desc,
|
||
},
|
||
};
|
||
});
|
||
setNotFinishOrder(structedData2);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
const getZoneData = async () => {
|
||
try {
|
||
const base = baseRequest();
|
||
const response = await fetch(`/op/daily_statement_zone_info/list`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
st: Math.floor(selectTime.ct_lower_bound / 1000),
|
||
et: Math.floor(selectTime.ct_upper_bound / 1000),
|
||
offset: 0,
|
||
limit: 100,
|
||
...base,
|
||
}),
|
||
});
|
||
const _data = await response.json();
|
||
if (_data.ret === -1) {
|
||
alert(_data.msg);
|
||
return;
|
||
}
|
||
const structedData = _data.data.list.map((item, index) => {
|
||
return {
|
||
key: index,
|
||
time: {
|
||
start: new Date(item.start_time * 1000).toLocaleString(),
|
||
end: new Date(item.end_time * 1000).toLocaleString(),
|
||
},
|
||
streamer: item.streamer_ext,
|
||
entrant_num: item.entrant_num,
|
||
earn_amount: {
|
||
total_amount: item.total_amount,
|
||
admission_amount: item.admission_amount,
|
||
zone_moment_amount: item.zone_moment_amount,
|
||
superfanship_amount: item.superfanship_amount,
|
||
},
|
||
refund: {
|
||
refund_amount: item.refund_amount,
|
||
refunder_amount: item.refunder_amount,
|
||
},
|
||
};
|
||
});
|
||
setZoneData(structedData);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
getData();
|
||
getOrderData();
|
||
getZoneData();
|
||
}, [selectTime]);
|
||
|
||
const onOk = (value) => {
|
||
const startTimeStamp = value[0] && value[0].valueOf() - 60000; // 起始时间的时间戳
|
||
const endTimeStamp = value[1] && value[1].valueOf() + 60000; // 结束时间的时间戳
|
||
setSelectTime({
|
||
ct_lower_bound: startTimeStamp,
|
||
ct_upper_bound: endTimeStamp,
|
||
});
|
||
};
|
||
|
||
//表头
|
||
const columns = [
|
||
{
|
||
title: "时段",
|
||
dataIndex: "time",
|
||
key: "time",
|
||
render: (data) => {
|
||
return (
|
||
<div>
|
||
<p>
|
||
<span className="text-green-400">开始时间:</span>
|
||
{data.start}
|
||
</p>
|
||
<p>
|
||
<span className="text-red-400">结束时间:</span>
|
||
{data.end}
|
||
</p>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
title: "当日主播页面访问",
|
||
dataIndex: "h5_call_count",
|
||
key: "h5_call_count",
|
||
},
|
||
{
|
||
title: "当日空间页面访问",
|
||
dataIndex: "zone_list_from_outside_count",
|
||
key: "zone_list_from_outside_count",
|
||
},
|
||
{
|
||
title: "总注册",
|
||
dataIndex: "registered_user_count",
|
||
key: "registered_user_count",
|
||
},
|
||
{
|
||
title: "注册来源",
|
||
dataIndex: "last_hour_new_user_form",
|
||
key: "last_hour_new_user_form",
|
||
render: (data) => {
|
||
return (
|
||
<div>
|
||
<p>
|
||
<span className="text-green-400">ios:</span>
|
||
{data.ios}
|
||
</p>
|
||
<p>
|
||
<span className="text-green-400">安卓:</span>
|
||
{data.android}
|
||
</p>
|
||
<p>
|
||
<span className="text-green-400">h5:</span>
|
||
{data.h5}
|
||
</p>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
title: "总订单创建",
|
||
dataIndex: "order_created_count",
|
||
key: "order_created_count",
|
||
},
|
||
{
|
||
title: "总订单完成",
|
||
dataIndex: "order_finished_count",
|
||
key: "order_finished_count",
|
||
},
|
||
];
|
||
|
||
//订单表头
|
||
const orderColumns = [
|
||
{
|
||
title: "订单时间",
|
||
dataIndex: "time",
|
||
key: "time",
|
||
},
|
||
{
|
||
title: "用户",
|
||
dataIndex: "user",
|
||
key: "user",
|
||
},
|
||
{
|
||
title: "主播",
|
||
dataIndex: "streamer",
|
||
key: "streamer",
|
||
},
|
||
{
|
||
title: "价格",
|
||
dataIndex: "price",
|
||
key: "price",
|
||
render: (data) => {
|
||
return <p>¥{data}</p>;
|
||
},
|
||
},
|
||
{
|
||
title: "订单详情",
|
||
dataIndex: "order_detail",
|
||
key: "order_detail",
|
||
render: (data) => {
|
||
return (
|
||
<div>
|
||
<p>订单号:{data.order_id}</p>
|
||
<p>订单状态:{data.order_status_desc}</p>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
];
|
||
|
||
//空间数据表头
|
||
const zoneColumns = [
|
||
{
|
||
title: "时段",
|
||
dataIndex: "time",
|
||
key: "time",
|
||
render: (data) => {
|
||
return (
|
||
<div>
|
||
<p>
|
||
<span className="text-green-400">开始时间:</span>
|
||
{data.start}
|
||
</p>
|
||
<p>
|
||
<span className="text-red-400">结束时间:</span>
|
||
{data.end}
|
||
</p>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
title: "发帖人",
|
||
dataIndex: "streamer",
|
||
key: "streamer",
|
||
render: (data) => (
|
||
<div>
|
||
<Image src={data.avatar.images[0].urls[0]} width={50} />
|
||
<p>
|
||
ID:<span className="text-red-400">{data.user_id}</span>
|
||
</p>
|
||
<p>
|
||
昵称:<span className="text-red-400">{data.name}</span>
|
||
</p>
|
||
</div>
|
||
),
|
||
},
|
||
{
|
||
title: "上小时空间新增人数",
|
||
dataIndex: "entrant_num",
|
||
key: "entrant_num",
|
||
},
|
||
{
|
||
title: "营收情况",
|
||
dataIndex: "earn_amount",
|
||
key: "earn_amount",
|
||
render: (data) => {
|
||
return (
|
||
<div>
|
||
<p>
|
||
<span className="text-red-400">总营收:</span>¥
|
||
{data?.total_amount / 100}
|
||
</p>
|
||
<p>
|
||
<span className="text-red-400">解锁空间:</span>¥
|
||
{data?.admission_amount / 100}
|
||
</p>
|
||
<p>
|
||
<span className="text-red-400">空间动态:</span>¥
|
||
{data?.zone_moment_amount / 100}
|
||
</p>
|
||
<p>
|
||
<span className="text-red-400">超粉:</span>¥
|
||
{data?.superfanship_amount / 100}
|
||
</p>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
{
|
||
title: "退款情况",
|
||
dataIndex: "refund",
|
||
key: "refund",
|
||
render: (data) => {
|
||
return (
|
||
<div>
|
||
<p>
|
||
<span className="text-red-400">退款人数:</span>
|
||
{data?.refunder_amount}
|
||
</p>
|
||
<p>
|
||
<span className="text-red-400">退款金额:</span>¥
|
||
{data?.refund_amount / 100}
|
||
</p>
|
||
</div>
|
||
);
|
||
},
|
||
},
|
||
];
|
||
|
||
return (
|
||
<div className="px-4">
|
||
<h1>数据统计</h1>
|
||
<p>请选择时段</p>
|
||
<RangePicker
|
||
showTime={{
|
||
format: "HH:mm",
|
||
}}
|
||
showNow
|
||
format="YYYY-MM-DD HH:mm"
|
||
onOk={onOk}
|
||
/>
|
||
<p>全部未处理订单</p>
|
||
<Table
|
||
columns={orderColumns}
|
||
dataSource={notFinishOrder}
|
||
pagination={{ pageSize: 20 }}
|
||
scroll={{ y: window.innerHeight - 300 }}
|
||
/>
|
||
<p>时段订单</p>
|
||
<Table
|
||
columns={orderColumns}
|
||
dataSource={order}
|
||
pagination={{ pageSize: 20 }}
|
||
scroll={{ y: window.innerHeight - 300 }}
|
||
/>
|
||
<p>时段数据</p>
|
||
<Table
|
||
columns={columns}
|
||
dataSource={data}
|
||
pagination={{ pageSize: 20 }}
|
||
scroll={{ y: window.innerHeight - 300 }}
|
||
/>
|
||
<Table
|
||
columns={zoneColumns}
|
||
dataSource={zoneData}
|
||
pagination={{ pageSize: 20 }}
|
||
scroll={{ y: window.innerHeight - 300 }}
|
||
/>
|
||
</div>
|
||
);
|
||
}
|