初步完成人工充值页面;完成数据统计页面
This commit is contained in:
parent
fce15a60d7
commit
99c6f600a8
Binary file not shown.
After Width: | Height: | Size: 4.9 KiB |
|
@ -1,7 +1,6 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Form, Input, Table, Image, Space, Button, Modal, Radio } from "antd";
|
import { Form, Input, Table, Image, Space, Button, Modal, Radio } from "antd";
|
||||||
import baseRequest from "../../utils/baseRequest";
|
import baseRequest from "../../utils/baseRequest";
|
||||||
import { generateSignature } from "../../utils/crypto";
|
|
||||||
|
|
||||||
const ManualRechargeAndWithdrawalContent = (props) => {
|
const ManualRechargeAndWithdrawalContent = (props) => {
|
||||||
const { TextArea } = Input;
|
const { TextArea } = Input;
|
||||||
|
@ -134,20 +133,16 @@ const ManualRechargeAndWithdrawalContent = (props) => {
|
||||||
const modalSearch = async (value) => {
|
const modalSearch = async (value) => {
|
||||||
try {
|
try {
|
||||||
const base = baseRequest();
|
const base = baseRequest();
|
||||||
const signature = generateSignature();
|
const response = await fetch(`/op/account/list_by_user_id`, {
|
||||||
const response = await fetch(
|
method: "POST",
|
||||||
`/op/account/list_by_user_id?signature=${signature}`,
|
headers: {
|
||||||
{
|
"Content-Type": "application/json",
|
||||||
method: "POST",
|
},
|
||||||
headers: {
|
body: JSON.stringify({
|
||||||
"Content-Type": "application/json",
|
user_id: parseInt(value.userId, 10),
|
||||||
},
|
...base,
|
||||||
body: JSON.stringify({
|
}),
|
||||||
user_id: parseInt(value.userId, 10),
|
});
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
if (data.ret === -1) {
|
if (data.ret === -1) {
|
||||||
alert(data.msg);
|
alert(data.msg);
|
||||||
|
@ -177,34 +172,23 @@ const ManualRechargeAndWithdrawalContent = (props) => {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const base = baseRequest();
|
const base = baseRequest();
|
||||||
const signature = generateSignature({
|
const response = await fetch(`/op/vas/create_order`, {
|
||||||
mid: selectedUser,
|
method: "POST",
|
||||||
coins: parseInt(value.num, 10),
|
headers: {
|
||||||
operator: base.b_mid.toString(),
|
"Content-Type": "application/json",
|
||||||
...base,
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
mid: selectedUser,
|
||||||
|
coins: parseInt(value.num, 10),
|
||||||
|
operator: value.password,
|
||||||
|
...base,
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
const response = await fetch(
|
|
||||||
`/op/vas/create_order?signature=${signature}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
mid: selectedUser,
|
|
||||||
coins: parseInt(value.num, 10),
|
|
||||||
operator: base.b_mid.toString(),
|
|
||||||
...base,
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
console.log(data);
|
|
||||||
if (data.ret === -1) {
|
if (data.ret === -1) {
|
||||||
alert(data.msg);
|
alert(data.msg);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
setUserInfo(data.data.account);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
}
|
}
|
||||||
|
@ -342,6 +326,19 @@ const ManualRechargeAndWithdrawalContent = (props) => {
|
||||||
>
|
>
|
||||||
<Input className="w-32" type="number" min={0} max={10000} />
|
<Input className="w-32" type="number" min={0} max={10000} />
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
|
<Form.Item
|
||||||
|
label="支付密码"
|
||||||
|
name="password"
|
||||||
|
rules={[
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: "未填写",
|
||||||
|
},
|
||||||
|
]}
|
||||||
|
style={{ margin: 0 }}
|
||||||
|
>
|
||||||
|
<Input className="w-32" type="password" min={0} max={10000} />
|
||||||
|
</Form.Item>
|
||||||
<Button className="ml-8" type="primary" htmlType="submit">
|
<Button className="ml-8" type="primary" htmlType="submit">
|
||||||
确认
|
确认
|
||||||
</Button>
|
</Button>
|
||||||
|
|
|
@ -0,0 +1,133 @@
|
||||||
|
import React, { useState, useEffect } from "react";
|
||||||
|
import baseRequest from "../../utils/baseRequest";
|
||||||
|
import { DatePicker, Table } from "antd";
|
||||||
|
|
||||||
|
export default function Data() {
|
||||||
|
const { RangePicker } = DatePicker;
|
||||||
|
const [data, setData] = 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();
|
||||||
|
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,
|
||||||
|
registered_user_count: item.registered_user_count,
|
||||||
|
order_created_count: item.order_created_count,
|
||||||
|
order_finished_count: item.order_finished_count,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
setData(structedData);
|
||||||
|
if (_data.ret === -1) {
|
||||||
|
alert(_data.msg);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getData();
|
||||||
|
}, [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: "registered_user_count",
|
||||||
|
key: "registered_user_count",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "总订单创建",
|
||||||
|
dataIndex: "order_created_count",
|
||||||
|
key: "order_created_count",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: "总订单完成",
|
||||||
|
dataIndex: "order_finished_count",
|
||||||
|
key: "order_finished_count",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="px-4">
|
||||||
|
<h1>数据统计</h1>
|
||||||
|
<p>请选择时段</p>
|
||||||
|
<RangePicker
|
||||||
|
showTime={{
|
||||||
|
format: "HH:mm",
|
||||||
|
}}
|
||||||
|
showNow
|
||||||
|
format="YYYY-MM-DD HH:mm"
|
||||||
|
onOk={onOk}
|
||||||
|
/>
|
||||||
|
<Table
|
||||||
|
columns={columns}
|
||||||
|
dataSource={data}
|
||||||
|
pagination={{ pageSize: 20 }}
|
||||||
|
scroll={{ y: window.innerHeight - 300 }}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
|
@ -16,6 +16,7 @@ import {
|
||||||
import { Menu, Layout } from "antd";
|
import { Menu, Layout } from "antd";
|
||||||
import { Outlet, useNavigate, useLocation } from "react-router-dom";
|
import { Outlet, useNavigate, useLocation } from "react-router-dom";
|
||||||
import { checkAuth, signOut } from "../../utils/auth";
|
import { checkAuth, signOut } from "../../utils/auth";
|
||||||
|
import Data from "./data";
|
||||||
|
|
||||||
export default function Op() {
|
export default function Op() {
|
||||||
const { Content, Sider } = Layout;
|
const { Content, Sider } = Layout;
|
||||||
|
@ -92,11 +93,8 @@ export default function Op() {
|
||||||
zIndex: 999,
|
zIndex: 999,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="op-logo">
|
<div onClick={() => navigate("/")} className="op-logo">
|
||||||
<img
|
<img src="/images/icon_border.png" alt="" />
|
||||||
src="https://s2.loli.net/2023/08/03/mu51haYNUOPXkqR.png"
|
|
||||||
alt=""
|
|
||||||
/>
|
|
||||||
<h2>铁粉空间运营</h2>
|
<h2>铁粉空间运营</h2>
|
||||||
</div>
|
</div>
|
||||||
<Menu
|
<Menu
|
||||||
|
@ -118,7 +116,7 @@ export default function Op() {
|
||||||
overflow: "initial",
|
overflow: "initial",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{location.pathname === "/" && <h1>好兄弟,辛苦了!加油!奥利给!</h1>}
|
{location.pathname === "/" && <Data />}
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</Content>
|
</Content>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
Loading…
Reference in New Issue