nili
6 months ago
26 changed files with 678 additions and 255 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -1 +0,0 @@ |
|||
!function(){"use strict";var t="/".replace(/([^/])$/,"$1/"),e=location.pathname,n=e.startsWith(t)&&decodeURI("/".concat(e.slice(t.length)));if(n){var a=document,c=a.head,r=a.createElement.bind(a),i=function(t,e,n){var a,c=e.r[t]||(null===(a=Object.entries(e.r).find((function(e){var n=e[0];return new RegExp("^".concat(n.replace(/\/:[^/]+/g,"/[^/]+").replace("/*","/.+"),"$")).test(t)})))||void 0===a?void 0:a[1]);return null==c?void 0:c.map((function(t){var a=e.f[t][1],c=e.f[t][0];return{type:c.split(".").pop(),url:"".concat(n.publicPath).concat(c),attrs:[["data-".concat(e.b),"".concat(e.p,":").concat(a)]]}}))}(n,{"p":"ant-design-pro","b":"webpack","f":[["51.a2ea1b3b.async.js",51],["63.86ff1d28.async.js",63],["134.6fc81d91.async.js",134],["169.57647c7d.async.js",169],["p__Welcome.61596037.async.js",185],["235.ac8537cc.async.js",235],["247.3fe8fb10.async.js",247],["t__plugin-layout__Layout.6cae69f5.chunk.css",301],["t__plugin-layout__Layout.4594a64b.async.js",301],["335.fcb437d3.async.js",335],["p__User__Login__index.9d3ab92e.async.js",366],["p__DeviceOwnerApp.1442f75c.async.js",371],["390.41467286.async.js",390],["393.38316f72.async.js",393],["397.fb5f72c1.async.js",397],["p__SuperAdmin.2c0b0908.async.js",455],["531.3d4ec55a.async.js",531],["p__Bind.b6ee068f.async.js",557],["559.016bfdbb.async.js",559],["p__404.0c100574.async.js",571],["635.20e45f05.async.js",635],["p__App__AppManagement.10ce4bad.async.js",731],["p__AdminManagement.4b0ea38b.async.js",816],["841.2ae59567.async.js",841],["848.32a73e48.async.js",848],["p__AdvRecordList.957040e5.async.js",857],["905.6e225d1b.async.js",905],["930.fca7adbf.async.js",930]],"r":{"/*":[19,26],"/":[2,7,8,18,20,26],"/welcome":[2,3,4,13,18,27,7,8,20,26],"/super":[0,1,2,3,5,6,15,27,7,8,18,20,26],"/adminList":[0,3,5,22,24,2,7,8,18,20,26],"/bind":[2,3,13,14,17,18,27,7,8,20,26],"/appList":[0,1,2,3,5,6,9,14,16,21,24,26,27,7,8,18,20],"/advList/:code":[0,1,2,3,5,9,16,18,23,24,25,26,27,7,8,20],"/app/:code":[0,1,2,3,5,9,11,16,18,23,24,26,27,7,8,20],"/user/login":[1,2,3,5,10,16,24]}},{publicPath:"/"});null==i||i.forEach((function(t){var e,n=t.type,a=t.url;if("js"===n)(e=r("script")).src=a,e.async=!0;else{if("css"!==n)return;(e=r("link")).href=a,e.rel="preload",e.as="style"}t.attrs.forEach((function(t){e.setAttribute(t[0],t[1]||"")})),c.appendChild(e)}))}}(); |
@ -0,0 +1 @@ |
|||
!function(){"use strict";var t="/".replace(/([^/])$/,"$1/"),e=location.pathname,n=e.startsWith(t)&&decodeURI("/".concat(e.slice(t.length)));if(n){var a=document,c=a.head,r=a.createElement.bind(a),i=function(t,e,n){var a,c=e.r[t]||(null===(a=Object.entries(e.r).find((function(e){var n=e[0];return new RegExp("^".concat(n.replace(/\/:[^/]+/g,"/[^/]+").replace("/*","/.+"),"$")).test(t)})))||void 0===a?void 0:a[1]);return null==c?void 0:c.map((function(t){var a=e.f[t][1],c=e.f[t][0];return{type:c.split(".").pop(),url:"".concat(n.publicPath).concat(c),attrs:[["data-".concat(e.b),"".concat(e.p,":").concat(a)]]}}))}(n,{"p":"ant-design-pro","b":"webpack","f":[["51.a2ea1b3b.async.js",51],["63.86ff1d28.async.js",63],["134.6fc81d91.async.js",134],["169.57647c7d.async.js",169],["p__Welcome.61596037.async.js",185],["p__MoneyManagement.79d40f90.async.js",190],["235.ac8537cc.async.js",235],["247.3fe8fb10.async.js",247],["t__plugin-layout__Layout.6cae69f5.chunk.css",301],["t__plugin-layout__Layout.4594a64b.async.js",301],["335.fcb437d3.async.js",335],["p__User__Login__index.9d3ab92e.async.js",366],["p__DeviceOwnerApp.1442f75c.async.js",371],["390.41467286.async.js",390],["393.38316f72.async.js",393],["397.fb5f72c1.async.js",397],["p__SuperAdmin.9634e267.async.js",455],["531.3d4ec55a.async.js",531],["p__AdvRecordListV2.30086e42.async.js",542],["p__Bind.b6ee068f.async.js",557],["559.016bfdbb.async.js",559],["p__404.0c100574.async.js",571],["635.20e45f05.async.js",635],["p__App__AppManagement.37218ab6.async.js",731],["p__AdminManagement.4b0ea38b.async.js",816],["841.614ef4c0.async.js",841],["848.32a73e48.async.js",848],["p__AdvRecordList.957040e5.async.js",857],["p__UserManagement.6aa3da9c.async.js",903],["905.6e225d1b.async.js",905],["930.fca7adbf.async.js",930]],"r":{"/*":[21,29],"/":[2,8,9,20,22,29],"/welcome":[2,3,4,14,20,30,8,9,22,29],"/super":[0,1,2,3,6,7,16,30,8,9,20,22,29],"/adminList":[0,3,6,24,26,2,8,9,20,22,29],"/bind":[2,3,14,15,19,20,30,8,9,22,29],"/appList":[0,1,2,3,6,7,10,15,17,23,26,29,30,8,9,20,22],"/advList/:code":[0,1,2,3,6,10,17,20,25,26,27,29,30,8,9,22],"/advListV2/:code":[0,1,2,3,6,10,17,18,20,25,26,29,30,8,9,22],"/user/:code":[2,3,28,30,8,9,20,22,29],"/money/:code":[2,3,5,30,8,9,20,22,29],"/app/:code":[0,1,2,3,6,10,12,17,20,25,26,29,30,8,9,22],"/user/login":[1,2,3,6,11,17,26]}},{publicPath:"/"});null==i||i.forEach((function(t){var e,n=t.type,a=t.url;if("js"===n)(e=r("script")).src=a,e.async=!0;else{if("css"!==n)return;(e=r("link")).href=a,e.rel="preload",e.as="style"}t.attrs.forEach((function(t){e.setAttribute(t[0],t[1]||"")})),c.appendChild(e)}))}}(); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@ |
|||
"use strict";(self.webpackChunkant_design_pro=self.webpackChunkant_design_pro||[]).push([[190],{3295:function(s,e,n){n.r(e);var t=n(90930),_=n(85893),a=function(){return(0,_.jsx)(t._z,{children:(0,_.jsx)("p",{children:"TODO"})})};e.default=a}}]); |
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -0,0 +1 @@ |
|||
"use strict";(self.webpackChunkant_design_pro=self.webpackChunkant_design_pro||[]).push([[903],{47989:function(a,e,n){n.r(e);var _=n(90930),s=n(85893),t=function(){return(0,s.jsx)(_._z,{children:(0,s.jsx)("p",{children:"TODO"})})};e.default=t}}]); |
File diff suppressed because one or more lines are too long
@ -0,0 +1,347 @@ |
|||
import { advList, incomeDaily, incomeOverview } from '@/services/matrix/admin'; |
|||
import { Column } from '@ant-design/charts'; |
|||
import { |
|||
ColumnsState, |
|||
PageContainer, |
|||
ProColumns, |
|||
ProFormDateRangePicker, |
|||
ProFormSelect, |
|||
ProTable, |
|||
QueryFilter, |
|||
StatisticCard, |
|||
} from '@ant-design/pro-components'; |
|||
import { Avatar, Row, Tabs } from 'antd'; |
|||
import TabPane from 'antd/es/tabs/TabPane'; |
|||
import moment from 'moment'; |
|||
import RcResizeObserver from 'rc-resize-observer'; |
|||
import React, { useEffect, useRef, useState } from 'react'; |
|||
import { useParams } from 'react-router-dom'; |
|||
|
|||
// import { RequestOptionsType, ProFieldRequestData } from "@ant-design/pro-utils";
|
|||
|
|||
import { formatIncome } from '@/utils/numberUtils'; |
|||
import type { ActionType } from '@ant-design/pro-components'; |
|||
const AdvRecordListV2: React.FC = () => { |
|||
const actionRef = useRef<ActionType>(); |
|||
const [income, setIncome] = useState<number | undefined>(undefined); |
|||
|
|||
const isMobile = () => { |
|||
return window.innerWidth <= 768; |
|||
}; |
|||
|
|||
const [columnsState, setColumnsState] = useState<Record<string, ColumnsState>>({ |
|||
deviceId: { show: !isMobile() }, |
|||
appName: { show: !isMobile() }, |
|||
platform: { show: !isMobile() }, |
|||
deviceBrand: { show: !isMobile() }, |
|||
deviceName: { show: !isMobile() }, |
|||
ip: { show: !isMobile() }, |
|||
advType: { show: !isMobile() }, |
|||
}); |
|||
|
|||
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', |
|||
width: 80, |
|||
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: '设备', |
|||
dataIndex: 'device', |
|||
hideInSearch: true, |
|||
renderText: (_, record) => { |
|||
return ( |
|||
<> |
|||
<p>{record.deviceBrand}</p> |
|||
<p>{record.deviceName}</p> |
|||
</> |
|||
); |
|||
}, |
|||
}, |
|||
{ |
|||
title: 'ip', |
|||
dataIndex: 'ip', |
|||
hideInSearch: true, |
|||
valueType: 'textarea', |
|||
}, |
|||
{ |
|||
title: '用户', |
|||
dataIndex: 'user', |
|||
hideInSearch: true, |
|||
renderText: (_, record) => { |
|||
if (!record.user) { |
|||
return; |
|||
} |
|||
return ( |
|||
<Row> |
|||
<Avatar src={record.user?.avatar} /> |
|||
<p style={{ fontSize: 12 }}> |
|||
id:{record.user.id} |
|||
<br /> |
|||
{record.user?.nickname || record.user?.mobile} |
|||
</p> |
|||
</Row> |
|||
); |
|||
}, |
|||
}, |
|||
{ |
|||
title: '时间', |
|||
hideInSearch: true, |
|||
dataIndex: 'createdAt', |
|||
valueType: 'dateTime', |
|||
}, |
|||
{ |
|||
title: '时间', |
|||
hideInTable: true, |
|||
dataIndex: 'createdAt', |
|||
valueType: 'dateRange', |
|||
}, |
|||
// {
|
|||
// title: "应用名称",
|
|||
// hideInTable: true,
|
|||
// dataIndex: 'appId',
|
|||
// valueType: "select",
|
|||
// request: appNameMap
|
|||
// }
|
|||
]; |
|||
|
|||
const { code } = useParams(); |
|||
|
|||
const [overview, setOverview] = useState<API.OverviewBo>(); |
|||
const [daily, setDaily] = useState<API.DateIncome[]>([]); |
|||
const { Divider } = StatisticCard; |
|||
const [responsive, setResponsive] = useState(false); |
|||
|
|||
const fetchOverview = async (param: string | undefined) => { |
|||
const res = await incomeOverview({ appCode: param }); |
|||
if (res.data) { |
|||
setOverview(res.data); |
|||
} |
|||
}; |
|||
|
|||
const fetchDaily = async (params: API.IncomeQuery) => { |
|||
const res = await incomeDaily({ ...params, code: code }); |
|||
if (res.data) { |
|||
setDaily(res.data); |
|||
} |
|||
}; |
|||
|
|||
useEffect(() => { |
|||
actionRef.current?.reload(); |
|||
fetchOverview(code); |
|||
fetchDaily({ code: code }); |
|||
}, [code]); |
|||
|
|||
const processedChartData: { date: string | number; income: number }[] = daily.map((item) => ({ |
|||
date: (() => { |
|||
const inputDateStr = item.date + ''; |
|||
const year: string = inputDateStr.slice(0, 4); |
|||
const month: string = inputDateStr.slice(4, 6); |
|||
const day: string = inputDateStr.slice(6, 8); |
|||
|
|||
return `${year}-${month}-${day}`; |
|||
})(), |
|||
income: formatIncome(item.income), |
|||
})); |
|||
|
|||
const config = { |
|||
data: processedChartData, |
|||
xField: 'date', |
|||
yField: 'income', |
|||
tooltip: { |
|||
name: '收入', |
|||
field: 'income', |
|||
}, |
|||
axis: { |
|||
date: { |
|||
title: '日期', |
|||
}, |
|||
}, |
|||
title: |
|||
'累计' + |
|||
formatIncome(daily.reduce((acc, data) => acc + (data.income ? data.income : 0), 0)) + |
|||
'元', |
|||
height: 400, |
|||
label: { |
|||
text: (d: any) => (d.income > 0 ? d.income : ''), |
|||
textBaseline: 'bottom', |
|||
}, |
|||
}; |
|||
|
|||
return ( |
|||
<PageContainer> |
|||
<Tabs defaultActiveKey="1" centered style={{ backgroundColor: 'white', padding: '20px' }}> |
|||
<TabPane tab="广告详情" key="1"> |
|||
<ProTable<API.MatrixAdvRecordBo, API.AdvRecordQuery> |
|||
headerTitle={income ? '表格累计:' + formatIncome(income) + '元' : ''} |
|||
actionRef={actionRef} |
|||
rowKey="key" |
|||
search={{ |
|||
labelWidth: 120, |
|||
}} |
|||
request={async (params: API.AdvRecordQuery) => { |
|||
const res = await advList({ ...params, code: code }); |
|||
if (params.current === 1) { |
|||
setIncome(res.data?.sum); |
|||
} |
|||
return { |
|||
data: res.data?.data, |
|||
total: res.data?.total, |
|||
success: true, |
|||
}; |
|||
}} |
|||
columns={columns} |
|||
columnsState={{ |
|||
value: columnsState, |
|||
onChange: (newState) => { |
|||
setColumnsState(newState); |
|||
}, |
|||
}} |
|||
/> |
|||
</TabPane> |
|||
<TabPane tab="数据总览" key="2"> |
|||
<RcResizeObserver |
|||
key="resize-observer" |
|||
onResize={(offset) => { |
|||
setResponsive(offset.width < 596); |
|||
}} |
|||
> |
|||
<StatisticCard> |
|||
<StatisticCard.Group direction={responsive ? 'column' : 'row'}> |
|||
<StatisticCard |
|||
statistic={{ |
|||
title: '上月收入(元)', |
|||
value: formatIncome(overview?.lastMonthIncome), |
|||
}} |
|||
/> |
|||
<Divider type={responsive ? 'horizontal' : 'vertical'} /> |
|||
<StatisticCard |
|||
statistic={{ |
|||
title: '本月收入(元)', |
|||
value: formatIncome(overview?.thisMonthIncome), |
|||
}} |
|||
/> |
|||
<Divider type={responsive ? 'horizontal' : 'vertical'} /> |
|||
<StatisticCard |
|||
statistic={{ |
|||
title: '今日收入(元)', |
|||
value: formatIncome(overview?.todayIncome), |
|||
}} |
|||
/> |
|||
<Divider type={responsive ? 'horizontal' : 'vertical'} /> |
|||
<StatisticCard |
|||
statistic={{ |
|||
title: '昨日收入(元)', |
|||
value: formatIncome(overview?.yesterdayIncome), |
|||
}} |
|||
/> |
|||
</StatisticCard.Group> |
|||
</StatisticCard> |
|||
</RcResizeObserver> |
|||
|
|||
<QueryFilter defaultCollapsed split onFinish={fetchDaily}> |
|||
<ProFormSelect |
|||
label="平台" |
|||
name="platform" |
|||
valueEnum={{ |
|||
1: '穿山甲', |
|||
2: '腾讯', |
|||
3: '百度联盟', |
|||
4: 'Mintegral', |
|||
5: '快手', |
|||
6: '游可赢', |
|||
7: 'Sigmob', |
|||
8: 'Admob', |
|||
}} |
|||
/> |
|||
<ProFormSelect |
|||
name="advType" |
|||
label="广告类型" |
|||
valueEnum={{ |
|||
1: '横幅', |
|||
2: '插页', |
|||
3: '激励视频', |
|||
}} |
|||
/> |
|||
<ProFormDateRangePicker |
|||
fieldProps={{ |
|||
disabledDate: (current: any) => current && current >= moment().startOf('day'), |
|||
}} |
|||
name="date" |
|||
label="时间" |
|||
/> |
|||
</QueryFilter> |
|||
{/* <Line {...config} /> */} |
|||
<Column {...config} /> |
|||
</TabPane> |
|||
</Tabs> |
|||
</PageContainer> |
|||
); |
|||
}; |
|||
|
|||
export default AdvRecordListV2; |
@ -0,0 +1,11 @@ |
|||
import { PageContainer } from '@ant-design/pro-components'; |
|||
|
|||
const MoneyManagement: React.FC = () => { |
|||
return ( |
|||
<PageContainer> |
|||
<p>TODO</p> |
|||
</PageContainer> |
|||
); |
|||
}; |
|||
|
|||
export default MoneyManagement; |
@ -0,0 +1,11 @@ |
|||
import { PageContainer } from '@ant-design/pro-components'; |
|||
|
|||
const UserManagement: React.FC = () => { |
|||
return ( |
|||
<PageContainer> |
|||
<p>TODO</p> |
|||
</PageContainer> |
|||
); |
|||
}; |
|||
|
|||
export default UserManagement; |
@ -0,0 +1,8 @@ |
|||
const channelList = () => { |
|||
return [ |
|||
{ label: '凡米游', value: 'fanmiyou' }, |
|||
{ label: '奇迹', value: 'qiji' }, |
|||
]; |
|||
}; |
|||
|
|||
export { channelList }; |
@ -0,0 +1,8 @@ |
|||
const formatIncome = (v: number | undefined) => { |
|||
if (!v) { |
|||
return 0; |
|||
} |
|||
return parseFloat((v / 1000_00).toFixed(2)); |
|||
}; |
|||
|
|||
export { formatIncome }; |
Loading…
Reference in new issue