Commit e4002b20 by zhaochengxiang

资产运营

parent db73475b
......@@ -386,4 +386,28 @@ export function* listDistributeAbleUsersByName(payload) {
export function* getMetadataColumns(payload) {
return yield call(metadataService.getMetadataColumns, payload)
}
export function* operationOverview() {
return yield call(service.operationOverview)
}
export function* getOperationSupportDataAssetStatisticsObject() {
return yield call(service.getOperationSupportDataAssetStatisticsObject)
}
export function* getOperationSupportResourceStatisticsObject() {
return yield call(service.getOperationSupportResourceStatisticsObject)
}
export function* operationCountByStatisticsObject(payload) {
return yield call(service.operationCountByStatisticsObject, payload)
}
export function* getOperationPopularDataAssetRanking() {
return yield call(service.getOperationPopularDataAssetRanking)
}
export function* getOperationLatestDataAssetRanking() {
return yield call(service.getOperationLatestDataAssetRanking)
}
\ No newline at end of file
......@@ -374,4 +374,28 @@ export function getPreviewRangeByDirId(payload) {
export function listDistributeAbleUsersByName(payload) {
return GetJSON("/dataassetmanager/userApi/listDistributeAbleUsersByName", payload)
}
\ No newline at end of file
}
export function operationOverview() {
return GetJSON("/dataassetmanager/operationApi/statisticalOverview")
}
export function getOperationSupportDataAssetStatisticsObject() {
return GetJSON("/dataassetmanager/operationApi/listSupportDataAssetStatisticsObject")
}
export function getOperationSupportResourceStatisticsObject() {
return GetJSON("/dataassetmanager/operationApi/listSupportResourceStatisticsObject")
}
export function operationCountByStatisticsObject(payload) {
return PostJSON("/dataassetmanager/operationApi/countByStatisticsObject", payload)
}
export function getOperationPopularDataAssetRanking() {
return GetJSON("/dataassetmanager/operationApi/getPopularDataAssetRanking")
}
export function getOperationLatestDataAssetRanking() {
return GetJSON("/dataassetmanager/operationApi/getLatestDataAssetRanking")
}
\ No newline at end of file
import React from 'react'
import * as echarts from 'echarts'
import ResizeObserver from 'rc-resize-observer'
import { Row, Col, Card, Space, Divider, Badge, Select, DatePicker } from 'antd'
import { Row, Col, Card, Space, Divider, Badge, Select, DatePicker, Spin, Tabs } from 'antd'
import produce from 'immer'
import Table from '../../../util/Component/Table'
import { dispatch } from '../../../model'
import './index.less'
const mockStatisticInfo = [
{ title: '内部资源', value: 12112 },
{ title: '外部资源', value: 5609 },
{ title: '已发布资产', value: 7174 },
{ title: '未发布资产', value: 1309 },
{ title: '梳理任务', value: 122 },
const overviewInformations = [
{ title: '内部资源', key: 'innerResourceCount'},
{ title: '外部资源', key: 'outerResourceCount'},
{ title: '已发布资产', key: 'publishedDataAssetCount'},
{ title: '未发布资产', key: 'unPublishedDataAssetCount'},
{ title: '梳理任务', key: 'taskCount'},
]
const FC = (props) => {
return (
<div className='asset-operation p-3'>
<Summary data={mockStatisticInfo} />
<div className='my-3'>
<div className='asset-operation'>
<Overview />
<div className='my-3' style={{ overflow: 'hidden' }}>
<Row gutter={10}>
<Col span={12}>
<ResourceStatistic />
<Statistic type='resource' />
</Col>
<Col span={12}>
<AssetStatistic />
<Statistic />
</Col>
</Row>
</div>
<div className='my-3'>
<div style={{ overflow: 'hidden' }}>
<Row gutter={10}>
<Col span={12}>
<AssetBrowseRank />
<PopularAssetRank />
</Col>
<Col span={12}>
<AssetNewest />
<LatestAssetRank />
</Col>
</Row>
</div>
......@@ -53,118 +54,209 @@ export const Header = ({ title }) => (
</Space>
)
const Summary = ({ data }) => {
const Overview = () => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const [contentWidth, setContentWidth] = React.useState()
React.useEffect(() => {
getOverview()
}, [])
const colWidth = React.useMemo(() => {
const len = (data??[]).length
const len = (overviewInformations??[]).length
if (contentWidth && len>0) {
const len = (data??[]).length
return (contentWidth - (len-1)*10)/len
}
return 0
}, [contentWidth, data])
}, [contentWidth])
const getOverview = () => {
setLoading(true)
dispatch({
type: 'assetmanage.operationOverview',
callback: data => {
setLoading(false)
setData(data)
},
error: () => {
setLoading(false)
}
})
}
return (
<Card size='small'>
<Header title='资产数据概览' />
<ResizeObserver
onResize={({ width }) => {
setContentWidth(width)
}}
>
<div className='flex' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
{
data?.map((item, index) => {
return (
<div key={index} style={{ width: colWidth }}>
<Card>
<div
className='flex'
style={{
justifyContent: 'space-between',
alignItems: 'center'
}}
>
<span style={{ color: 'rgba(0, 0, 0, 0.45)' }}>{item.title}</span>
<span style={{ color: 'rgba(0, 0, 0, 0.85)', fontSize: 24 }}>{item.value||0}</span>
</div>
</Card>
</div>
);
})
}
</div>
</ResizeObserver>
</Card>
<Spin spinning={loading}>
<Card size='small'>
<Header title='资产数据概览' />
<ResizeObserver
onResize={({ width }) => {
setContentWidth(width)
}}
>
<div className='flex' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
{
(overviewInformations??[]).map((item, index) => {
return (
<div key={item.key} style={{ width: colWidth }}>
<Card>
<div
className='flex'
style={{
justifyContent: 'space-between',
alignItems: 'center'
}}
>
<span style={{ color: 'rgba(0, 0, 0, 0.45)' }}>{item.title}</span>
<span style={{ color: 'rgba(0, 0, 0, 0.85)', fontSize: 24 }}>{data?.[item.key]}</span>
</div>
</Card>
</div>
);
})
}
</div>
</ResizeObserver>
</Card>
</Spin>
)
}
const ResourceStatistic = () => {
const mockOptions = [
'按资源状态',
]
const Statistic = ({ type = 'dataAsset' }) => {
const [loading, setLoading] = React.useState(false)
const [loadingStatisticsObject, setLoadingStatisticsObject] = React.useState(false)
const [statisticsObject, setStatisticsObject] = React.useState()
const [currentStatisticObject, setCurrentStatisticObject] = React.useState()
const [startTime, setStartTime] = React.useState()
const [endTime, setEndTime] = React.useState()
const [operationType, setOperationType] = React.useState()
const [data, setData] = React.useState()
React.useEffect(() => {
getStatisticsObject()
}, [])
React.useEffect(() => {
if (currentStatisticObject
&& (
(currentStatisticObject.groupByOperateTypes??[]).length===0
|| ((currentStatisticObject.groupByOperateTypes??[]).length>0&&operationType)
)
) {
getCount()
}
}, [currentStatisticObject, operationType, startTime, endTime])
const getStatisticsObject = () => {
setLoadingStatisticsObject(true)
dispatch({
type: (type==='dataAsset')?'assetmanage.getOperationSupportDataAssetStatisticsObject':'assetmanage.getOperationSupportResourceStatisticsObject',
callback: data => {
setLoadingStatisticsObject(false)
setStatisticsObject(data)
if ((data??[]).length > 0) {
const newCurrentStatisticObject = data[0]
setCurrentStatisticObject(newCurrentStatisticObject)
if ((newCurrentStatisticObject?.groupByOperateTypes??[]).length > 0) {
setOperationType(newCurrentStatisticObject?.groupByOperateTypes[0].type)
} else {
setOperationType()
}
}
},
error: () => {
setLoadingStatisticsObject(false)
}
})
}
const getCount = () => {
const newCurrentStatisticObject = produce(currentStatisticObject, (draft) => {
draft.beingTime = startTime
draft.endTime = endTime
for (let item of (draft.groupByOperateTypes??[])) {
item.selected = (item.type===operationType)
}
})
setLoading(true)
dispatch({
type: 'assetmanage.operationCountByStatisticsObject',
payload: {
data: newCurrentStatisticObject
},
callback: data => {
setLoading(false)
setData(data)
},
error: () => {
setLoading(false)
}
})
}
return (
<Card size='small'>
<Header title='数据资源统计' />
<div className='flex mb-3' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Header title={type==='dataAsset'?'数据资产统计':'数据资源统计'} />
<div className='flex' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Select
loading={loadingStatisticsObject}
onChange={(value) => {
const index = (statisticsObject??[]).findIndex(item => item.statisticsById===value)
if (index !== -1) {
const newCurrentStatisticObject = statisticsObject[index]
setCurrentStatisticObject(newCurrentStatisticObject)
if ((newCurrentStatisticObject?.groupByOperateTypes??[]).length > 0) {
setOperationType(newCurrentStatisticObject?.groupByOperateTypes[0].type)
} else {
setOperationType()
}
}
}}
value={currentStatisticObject?.statisticsById}
style={{ width: 140 }}
>
{
(mockOptions??[]).map((item, index) => <Select.Option key={index} value={item}>{item}</Select.Option>)
(statisticsObject??[]).map((item, index) => <Select.Option key={item.statisticsById} value={item.statisticsById}>{item.statisticsByName}</Select.Option>)
}
</Select>
<DatePicker.RangePicker
format="YYYY-MM-DD"
onChange={(values) => {
// setArgsAndPage({ startTime: (values??[]).length>0?values[0].valueOf():'', endTime: (values??[]).length>1?values[1].valueOf():'' })
setStartTime((values??[]).length>0?values[0].valueOf():'')
setEndTime((values??[]).length>1?values[1].valueOf():'')
}}
style={{ width: 240 }}
/>
</div>
<StackedLine />
</Card>
)
}
const AssetStatistic = () => {
const mockOptions = [
'按资源状态',
]
return (
<Card size='small'>
<Header title='数据资产统计' />
<div className='flex mb-3' style={{ justifyContent: 'space-between', alignItems: 'center' }}>
<Select
onChange={(value) => {
<div className='mb-3' style={{ height: 38 }}>
{
(currentStatisticObject?.groupByOperateTypes??[]).length > 0 && <Tabs
size='small'
activeKey={operationType}
onChange={(val) => {
setOperationType(val)
}}
style={{ width: 140 }}
>
{
(mockOptions??[]).map((item, index) => <Select.Option key={index} value={item}>{item}</Select.Option>)
(currentStatisticObject?.groupByOperateTypes??[]).map((item, index) => {
return <Tabs.TabPane tab={item.name} key={item.type}></Tabs.TabPane>
})
}
</Select>
<DatePicker.RangePicker
format="YYYY-MM-DD"
onChange={(values) => {
// setArgsAndPage({ startTime: (values??[]).length>0?values[0].valueOf():'', endTime: (values??[]).length>1?values[1].valueOf():'' })
}}
style={{ width: 240 }}
/>
</Tabs>
}
</div>
<StackedLine />
<Spin spinning={loading}>
<StackedLine data={data} />
</Spin>
</Card>
)
}
const AssetBrowseRank = () => {
const PopularAssetRank = () => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const cols = [
......@@ -188,7 +280,7 @@ const AssetBrowseRank = () => {
},
{
title: '英文名',
dataIndex: 'name',
dataIndex: 'enName',
ellipsis: true,
},
{
......@@ -198,7 +290,7 @@ const AssetBrowseRank = () => {
},
{
title: '浏览次数',
dataIndex: 'count',
dataIndex: 'visitCount',
ellipsis: true,
},
]
......@@ -209,12 +301,16 @@ const AssetBrowseRank = () => {
const getRanks = () => {
setLoading(true)
setTimeout(() => {
setLoading(false)
setData(Array.from({ length: 10 }).map((_, i) => ({
})))
}, 1000)
dispatch({
type: 'assetmanage.getOperationPopularDataAssetRanking',
callback: data => {
setLoading(false)
setData(data)
},
error: () => {
setLoading(false)
}
})
}
return (
......@@ -231,7 +327,7 @@ const AssetBrowseRank = () => {
)
}
const AssetNewest = () => {
const LatestAssetRank = () => {
const [loading, setLoading] = React.useState(false)
const [data, setData] = React.useState()
const cols = [
......@@ -255,7 +351,7 @@ const AssetNewest = () => {
},
{
title: '英文名',
dataIndex: 'name',
dataIndex: 'enName',
ellipsis: true,
},
{
......@@ -265,7 +361,7 @@ const AssetNewest = () => {
},
{
title: '发布时间',
dataIndex: 'time',
dataIndex: 'createTime',
ellipsis: true,
},
]
......@@ -276,12 +372,16 @@ const AssetNewest = () => {
const getRanks = () => {
setLoading(true)
setTimeout(() => {
setLoading(false)
setData(Array.from({ length: 10 }).map((_, i) => ({
})))
}, 1000)
dispatch({
type: 'assetmanage.getOperationLatestDataAssetRanking',
callback: data => {
setLoading(false)
setData(data)
},
error: () => {
setLoading(false)
}
})
}
return (
......@@ -311,13 +411,23 @@ const StackedLine = ({ data }) => {
}, [data])
const setOption = () => {
let serieNames = []
if ((data??[]).length === 0) {
echartsRef.current?.clear()
return
}
if ((data??[]).length > 0) {
serieNames = Object.keys(data[0]).filter(item => item !== 'date')
}
let option = {
tooltip: {
trigger: 'axis'
},
legend: {
bottom: 0,
data: ['Email', 'Union Ads', 'Video Ads', 'Direct', 'Search Engine']
data: serieNames
},
grid: {
left: '3%',
......@@ -328,44 +438,20 @@ const StackedLine = ({ data }) => {
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
boundaryGap: true,
data: (data??[]).map(item => item.date)
},
yAxis: {
type: 'value'
},
series: [
{
name: 'Email',
series: (serieNames??[]).map(name => {
return ({
name,
type: 'line',
stack: 'Total',
data: [120, 132, 101, 134, 90, 230, 210]
},
{
name: 'Union Ads',
type: 'line',
stack: 'Total',
data: [220, 182, 191, 234, 290, 330, 310]
},
{
name: 'Video Ads',
type: 'line',
stack: 'Total',
data: [150, 232, 201, 154, 190, 330, 410]
},
{
name: 'Direct',
type: 'line',
stack: 'Total',
data: [320, 332, 301, 334, 390, 330, 320]
},
{
name: 'Search Engine',
type: 'line',
stack: 'Total',
data: [820, 932, 901, 934, 1290, 1330, 1320]
}
]
data: (data??[]).map(item => item[`${name}`])
})
})
}
echartsRef.current?.setOption(option)
}
......
.asset-operation {
height: 100%;
// background-color: white;
overflow: auto;
.yy-tabs-nav::before {
border: none;
}
.yy-tabs-nav-wrap {
justify-content: flex-end;
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment