Browse Source

凡米游加口子相关功能

fanmiyou
nili 9 months ago
parent
commit
63a8a998cb
  1. 130
      src/pages/AppManagement.tsx
  2. 19
      src/pages/Bind.tsx
  3. 261
      src/pages/DeviceOwnerApp.tsx
  4. 33
      src/services/matrix/device.ts

130
src/pages/AppManagement.tsx

@ -0,0 +1,130 @@
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
import { useModel } from '@umijs/max';
import { Button, Form, Input, Modal, Popover, QRCode } from 'antd';
import { useEffect, useState } from 'react';
import { appList, saveApp } from '../services/matrix/admin';
const AppManagement = () => {
const [visible, setVisible] = useState(false);
const [form] = Form.useForm();
const [appArr, setAppArr] = useState<API.MatrixApp[]>([]);
const { initialState } = useModel('@@initialState');
const currentUser = initialState?.currentUser;
const canUpdate = currentUser && currentUser.role && currentUser.role < 2;
const handleEdit = (record: API.MatrixApp) => {
form.setFieldsValue(record);
setVisible(true);
};
const columns: ProColumns<API.MatrixApp>[] = [
{
title: '应用名',
dataIndex: 'name',
},
{
title: 'code',
dataIndex: 'code',
},
{
title: '下载地址',
dataIndex: 'url',
renderText: (url: string) => (
<Popover
overlayInnerStyle={{ padding: 0 }}
content={<QRCode value={url || ''} bordered={false} />}
>
<a>{url}</a>
</Popover>
),
},
];
const columnsWithOperation: ProColumns<API.MatrixApp>[] = [
...columns,
{
title: 'secret',
dataIndex: 'secret',
ellipsis: true,
copyable: true,
},
{
title: '操作',
width: 80,
renderText: (record: API.MatrixApp) => (
<a key="edit" onClick={() => handleEdit(record)}>
</a>
),
},
];
const handleOk = () => {
form.submit();
};
const handleCancel = () => {
setVisible(false);
};
const fetchApp = async () => {
const res = await appList();
if (res.data) {
setAppArr(res.data);
}
};
useEffect(() => {
fetchApp();
}, []);
const handleNew = () => {
form.resetFields(); // 重置表单字段
setVisible(true);
};
const handleSaveApp = async (values: API.MatrixApp) => {
try {
await saveApp(values);
} catch (e) {
return;
}
setVisible(false);
fetchApp();
};
return (
<PageContainer>
{currentUser && currentUser.role && currentUser.role < 2 && (
<Button style={{ marginBottom: '20px' }} onClick={handleNew}>
</Button>
)}
<ProTable
search={false}
columns={canUpdate ? columnsWithOperation : columns}
dataSource={appArr}
/>
<Modal title="编辑" visible={visible} onOk={handleOk} onCancel={handleCancel}>
<Form form={form} onFinish={handleSaveApp}>
<Form.Item name="id" style={{ display: 'none' }}>
<Input type="hidden" />
</Form.Item>
<Form.Item name="code" style={{ display: 'none' }}>
<Input type="hidden" />
</Form.Item>
<Form.Item label="应用名" name="name">
<Input />
</Form.Item>
<Form.Item label="下载地址" name="url">
<Input />
</Form.Item>
</Form>
</Modal>
</PageContainer>
);
};
export default AppManagement;

19
src/pages/Bind.tsx

@ -0,0 +1,19 @@
import { PageContainer } from '@ant-design/pro-components';
import { useModel } from '@umijs/max';
import { Card, QRCode } from 'antd';
const Bind: React.FC = () => {
const { initialState } = useModel('@@initialState');
const currentUser = initialState?.currentUser;
return (
<PageContainer>
<Card>
<QRCode style={{ margin: 'auto' }} value={currentUser?.name || ''} />
<p style={{ textAlign: 'center', marginTop: '20px' }}>使app扫码绑定设备</p>
</Card>
</PageContainer>
);
};
export default Bind;

261
src/pages/DeviceOwnerApp.tsx

@ -0,0 +1,261 @@
import { advList } from '@/services/matrix/admin';
import { PageContainer, ProColumns, ProTable } from '@ant-design/pro-components';
import { useIntl, useModel } from '@umijs/max';
import { Tabs } from 'antd';
import TabPane from 'antd/es/tabs/TabPane';
import React, { useEffect, useRef, useState } from 'react';
import { useParams } from 'react-router-dom';
// import { RequestOptionsType, ProFieldRequestData } from "@ant-design/pro-utils";
import { deviceList, offline } from '@/services/matrix/device';
import type { ActionType } from '@ant-design/pro-components';
const DeviceOwnerApp: React.FC = () => {
const actionRef = useRef<ActionType>();
const deviceRef = useRef<ActionType>();
const [usedDeviceCnt, setUsedDeviceCnt] = useState(0);
/**
* @en-US International configuration
* @zh-CN
* */
const intl = useIntl();
const { code } = useParams();
const { initialState } = useModel('@@initialState');
const currentUser = initialState?.currentUser;
const fetchDevice = async () => {
const res = await deviceList({ appCode: code ? code : '' });
if (res.data) {
setUsedDeviceCnt(res.data?.filter((device) => device.status === 0).length);
}
return {
data: res.data,
total: res.data?.length,
success: true,
};
};
const handleSetOffline = async (deviceId: string | undefined) => {
if (!deviceId) {
return;
}
await offline({ deviceId: deviceId });
deviceRef.current?.reload();
};
const columns: ProColumns<API.MatrixAdvRecordBo>[] = [
{
title: '设备id',
dataIndex: 'deviceId',
valueType: 'textarea',
ellipsis: true,
copyable: true,
},
{
title: '应用名称',
hideInSearch: true,
dataIndex: 'appName',
valueType: 'textarea',
},
{
title: '平台',
dataIndex: 'platform',
valueEnum: {
1: {
text: '穿山甲',
},
2: {
text: '腾讯',
},
3: {
text: '百度联盟',
},
4: {
text: 'Mintegral',
},
5: {
text: '快手',
},
6: {
text: '游可赢',
},
7: {
text: 'Sigmob',
},
8: {
text: 'Admob',
},
},
},
{
title: '广告类型',
dataIndex: 'advType',
valueEnum: {
1: {
text: '横幅',
status: 'Default',
},
2: {
text: '插页',
status: 'Processing',
},
3: {
text: '激励视频',
status: 'Success',
},
},
},
{
title: 'ecpm(元)',
dataIndex: 'ecpm',
hideInSearch: true,
renderText: (x) => {
return x / 100;
},
},
{
title: 'ecpm-抽成后(元)',
dataIndex: 'deductEcpm',
hideInSearch: true,
renderText: (x, record) => {
if (currentUser?.incomeRate && record.ecpm) {
return Math.floor((record.ecpm * currentUser.incomeRate) / 100) / 100;
}
return '-';
},
},
{
title: '设备品牌',
dataIndex: 'deviceBrand',
hideInSearch: true,
valueType: 'textarea',
},
{
title: '设备名',
dataIndex: 'deviceName',
hideInSearch: true,
valueType: 'textarea',
},
{
title: 'ip',
dataIndex: 'ip',
hideInSearch: true,
valueType: 'textarea',
},
{
title: '时间',
hideInSearch: true,
dataIndex: 'createdAt',
valueType: 'dateTime',
},
{
title: '时间',
hideInTable: true,
dataIndex: 'createdAt',
valueType: 'dateRange',
},
// {
// title: "应用名称",
// hideInTable: true,
// dataIndex: 'appId',
// valueType: "select",
// request: appNameMap
// }
];
const deviceColumns: ProColumns<API.MatrixAdminDevice>[] = [
{
title: '设备id',
dataIndex: 'deviceId',
valueType: 'text',
ellipsis: true,
width: 400,
copyable: true,
},
{
title: '状态',
dataIndex: 'status',
valueEnum: {
0: {
text: '正常',
},
'-1': {
text: '已下线',
},
},
filters: true,
onFilter: true,
},
{
title: '绑定时间',
hideInSearch: true,
dataIndex: 'createdAt',
valueType: 'dateTime',
},
{
title: '操作',
dataIndex: 'operation',
hideInSearch: true,
render: (_, record) => {
if (record.status === 0) {
return <a onClick={() => handleSetOffline(record.deviceId)}>线</a>;
}
return null;
},
},
];
const fetchData = async (params: any) => {
const res = await advList({ ...params, code: code });
return {
data: res.data?.data,
total: res.data?.total,
success: true,
};
};
useEffect(() => {
actionRef.current?.reload();
deviceRef.current?.reload();
}, [code]);
return (
<PageContainer>
<Tabs defaultActiveKey="1" centered style={{ backgroundColor: 'white', padding: '20px' }}>
<TabPane tab="设备列表" key="1">
<p style={{ textAlign: 'center' }}>
{'正常使用设备数:' +
usedDeviceCnt +
',剩余可绑定设备数:' +
Math.max(0, (currentUser?.deviceCnt ? currentUser.deviceCnt : 0) - usedDeviceCnt)}
</p>
<ProTable<API.MatrixAdminDevice>
actionRef={deviceRef}
rowKey="id"
search={false}
request={fetchDevice}
columns={deviceColumns}
/>
</TabPane>
<TabPane tab="广告详情" key="2">
<ProTable<API.MatrixAdvRecordBo, API.AdvRecordQuery>
headerTitle={intl.formatMessage({
id: 'pages.searchTable.title',
defaultMessage: 'Enquiry form',
})}
actionRef={actionRef}
rowKey="id"
search={{
labelWidth: 120,
}}
request={fetchData}
columns={columns}
/>
</TabPane>
</Tabs>
</PageContainer>
);
};
export default DeviceOwnerApp;

33
src/services/matrix/device.ts

@ -0,0 +1,33 @@
// @ts-ignore
/* eslint-disable */
import { request } from '@umijs/max';
/** 此处后端没有提供注释 GET /api/admin/device/list */
export async function deviceList(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.deviceListParams,
options?: { [key: string]: any },
) {
return request<API.RListMatrixAdminDevice>('/api/admin/device/list', {
method: 'GET',
params: {
...params,
},
...(options || {}),
});
}
/** 此处后端没有提供注释 POST /api/admin/device/offline */
export async function offline(
// 叠加生成的Param类型 (非body参数swagger默认没有生成对象)
params: API.offlineParams,
options?: { [key: string]: any },
) {
return request<API.RString>('/api/admin/device/offline', {
method: 'POST',
params: {
...params,
},
...(options || {}),
});
}
Loading…
Cancel
Save