Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
C
CivWeb
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ReactWeb5
CivWeb
Commits
5ed65178
Commit
5ed65178
authored
Mar 03, 2022
by
崔佳豪
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: 添加平台使用分析
parent
cf5d7c6e
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1840 additions
and
0 deletions
+1840
-0
index.js
src/pages/cloudOMS/usingAnalysis/index.js
+1664
-0
index.less
src/pages/cloudOMS/usingAnalysis/index.less
+171
-0
config.js
src/routes/config.js
+5
-0
No files found.
src/pages/cloudOMS/usingAnalysis/index.js
0 → 100644
View file @
5ed65178
/**
* 云平台使用分析
*/
import
React
,
{
useCallback
,
useEffect
,
useState
,
useRef
}
from
'react'
;
import
{
connect
}
from
'react-redux'
;
import
{
Card
,
DatePicker
,
Radio
,
Select
,
Statistic
,
Input
,
Button
,
Modal
,
Form
,
Space
,
Spin
,
ConfigProvider
,
notification
,
}
from
'antd'
;
import
ReactECharts
from
'echarts-for-react'
;
import
zhCN
from
'antd/lib/locale/zh_CN'
;
import
{
LeftOutlined
}
from
'@ant-design/icons'
;
import
{
cloudService
}
from
'@/api'
;
import
SecurityLayout
from
'../../../layouts/SecurityLayout'
;
import
Basictable
from
'@wisdom-components/basictable'
;
import
{
actionCreators
}
from
'../../../containers/App/store'
;
import
styles
from
'./index.less'
;
import
_
from
'lodash'
;
import
moment
from
'moment'
;
const
dateForModel
=
(
model
,
date
=
moment
())
=>
{
let
result
=
{
dateFrom
:
null
,
dateTo
:
null
};
switch
(
model
)
{
case
'day'
:
result
=
{
dateFrom
:
date
.
clone
().
startOf
(
'day'
),
dateTo
:
date
.
clone
().
endOf
(
'day'
),
};
break
;
case
'week'
:
result
=
{
dateFrom
:
date
.
clone
().
startOf
(
'week'
),
dateTo
:
date
.
clone
().
endOf
(
'week'
),
};
break
;
case
'month'
:
result
=
{
dateFrom
:
date
.
clone
().
startOf
(
'month'
),
dateTo
:
date
.
clone
().
endOf
(
'month'
),
};
break
;
case
'quarter'
:
result
=
{
dateFrom
:
date
.
clone
().
startOf
(
'quarter'
),
dateTo
:
date
.
clone
().
endOf
(
'quarter'
),
};
break
;
case
'year'
:
result
=
{
dateFrom
:
date
.
clone
().
startOf
(
'year'
),
dateTo
:
date
.
clone
().
endOf
(
'year'
),
};
break
;
case
'all'
:
default
:
result
=
{
dateFrom
:
null
,
dateTo
:
null
};
break
;
}
return
result
;
};
const
textForModel
=
model
=>
{
switch
(
model
)
{
case
'day'
:
return
'天'
;
case
'week'
:
return
'周'
;
case
'month'
:
return
'月'
;
case
'quarter'
:
return
'季度'
;
case
'year'
:
return
'年'
;
case
'all'
:
return
'全部'
;
case
'custom'
:
return
'自定义'
;
default
:
return
model
;
}
};
const
defaultFormat
=
'YYYY-MM-DD HH:mm:ss'
;
const
defaultShowModels
=
[
'all'
,
'week'
,
'month'
,
'quarter'
,
'year'
,
'custom'
];
const
DatePickerGroup
=
({
onChange
,
format
=
defaultFormat
,
showModels
=
defaultShowModels
,
defaultModel
=
'all'
,
defaultDate
,
value
,
dateModel
,
})
=>
{
const
[
model
,
setModel
]
=
useState
(
defaultModel
);
const
[
dateValue
,
setDateValue
]
=
useState
(()
=>
dateForModel
(
defaultModel
,
defaultDate
),
);
useEffect
(()
=>
{
if
(
value
||
dateModel
)
{
setModel
(
dateModel
);
setDateValue
(
value
);
}
},
[
value
,
dateModel
]);
// 切换类型
const
changeModel
=
e
=>
{
const
_model
=
e
.
target
.
value
;
const
_dateValue
=
dateForModel
(
_model
);
if
(
!
value
&&
!
dateModel
)
{
setModel
(
_model
);
setDateValue
(
_dateValue
);
if
(
_model
===
'custom'
)
return
;
}
const
_dateFrom
=
_dateValue
&&
_dateValue
.
dateFrom
?
_dateValue
.
dateFrom
.
format
(
format
)
:
''
;
const
_dateTo
=
_dateValue
&&
_dateValue
.
dateTo
?
_dateValue
.
dateTo
.
format
(
format
)
:
''
;
onChange
&&
onChange
(
{
dateFrom
:
_dateFrom
,
dateTo
:
_dateTo
,
},
_model
,
);
};
// 切换时间
const
changeDate
=
(
date
,
dateString
)
=>
{
const
_dateValue
=
dateForModel
(
model
,
date
);
const
_dateFrom
=
_dateValue
&&
_dateValue
.
dateFrom
?
_dateValue
.
dateFrom
.
format
(
format
)
:
''
;
const
_dateTo
=
_dateValue
&&
_dateValue
.
dateTo
?
_dateValue
.
dateTo
.
format
(
format
)
:
''
;
if
(
!
value
&&
!
dateModel
)
{
setDateValue
(
_dateValue
);
}
onChange
&&
onChange
(
{
dateFrom
:
_dateFrom
,
dateTo
:
_dateTo
,
},
model
,
);
};
// 切换范围时间
const
changeRangeDate
=
(
dates
,
dateStrings
)
=>
{
const
_dateValue
=
{
dateFrom
:
dates
?.[
0
],
dateTo
:
dates
?.[
1
]
};
const
_dateFrom
=
_dateValue
&&
_dateValue
.
dateFrom
?
_dateValue
.
dateFrom
.
format
(
format
)
:
''
;
const
_dateTo
=
_dateValue
&&
_dateValue
.
dateTo
?
_dateValue
.
dateTo
.
format
(
format
)
:
''
;
if
(
!
value
&&
!
dateModel
)
{
setDateValue
(
_dateValue
);
}
onChange
&&
onChange
(
{
dateFrom
:
_dateFrom
,
dateTo
:
_dateTo
,
},
model
,
);
};
// 渲染时间选择器
const
renderDatePicker
=
()
=>
{
let
_result
=
null
;
switch
(
model
)
{
case
'day'
:
_result
=
(
<
DatePicker
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/
>
);
break
;
case
'week'
:
_result
=
(
<
DatePicker
picker
=
"week"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/
>
);
break
;
case
'month'
:
_result
=
(
<
DatePicker
picker
=
"month"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/
>
);
break
;
case
'quarter'
:
_result
=
(
<
DatePicker
picker
=
"quarter"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/
>
);
break
;
case
'year'
:
_result
=
(
<
DatePicker
picker
=
"year"
onChange
=
{
changeDate
}
value
=
{
dateValue
.
dateFrom
}
/
>
);
break
;
case
'custom'
:
_result
=
(
<
DatePicker
.
RangePicker
onChange
=
{
changeRangeDate
}
value
=
{[
dateValue
.
dateFrom
,
dateValue
.
dateTo
]}
/
>
);
break
;
case
'all'
:
default
:
_result
=
null
;
break
;
}
return
_result
;
};
return
(
<
Space
size
=
{
8
}
>
<
Radio
.
Group
value
=
{
model
}
onChange
=
{
changeModel
}
style
=
{{
whiteSpace
:
'nowrap'
}}
>
{
showModels
.
map
(
item
=>
(
<
Radio
.
Button
value
=
{
item
}
key
=
{
item
}
>
{
textForModel
(
item
)}
<
/Radio.Button
>
))}
<
/Radio.Group
>
{
renderDatePicker
()}
<
/Space
>
);
};
const
LoginStatisticModal
=
({
visible
,
setVisible
,
date
,
// 查询日期,如:2021-11 2021-11-01
timeMode
,
})
=>
{
const
[
pageIndex
,
setPageIndex
]
=
useState
(
1
);
const
[
pageSize
,
setPageSize
]
=
useState
(
20
);
const
[
totalNum
,
setTotalNum
]
=
useState
(
0
);
const
[
searchInfo
,
setSearchInfo
]
=
useState
(
''
);
const
[
tableData
,
setTableData
]
=
useState
([]);
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
searchInput
=
useRef
();
const
getAccountData
=
()
=>
{
let
stime
,
etime
,
timeModeTemp
;
if
(
timeMode
===
'月'
)
{
timeModeTemp
=
'month'
;
}
else
{
timeModeTemp
=
'day'
;
}
stime
=
moment
(
new
Date
(
date
))
.
startOf
(
timeModeTemp
)
.
format
(
'YYYY-MM-DD HH:mm:ss'
);
etime
=
moment
(
new
Date
(
date
))
.
endOf
(
timeModeTemp
)
.
format
(
'YYYY-MM-DD HH:mm:ss'
);
setLoading
(
true
);
cloudService
.
getAccountPageList
({
pageSize
:
pageSize
,
pageIndex
:
pageIndex
,
sortFields
:
'登录时间'
,
direction
:
'desc'
,
accountName
:
'用户登录台账'
,
info
:
searchInfo
,
queryWhere
:
" and (登录时间 >= '"
+
stime
+
"' and 登录时间 <= '"
+
etime
+
"')"
,
ignoreSite
:
true
,
})
.
then
(
res
=>
{
setLoading
(
false
);
const
data1
=
JSON
.
parse
(
res
?.
jsonData
??
'[]'
);
const
_tableData
=
data1
.
map
((
item
,
index
)
=>
({
...
item
,
key
:
index
,
}));
setTableData
(
_tableData
);
setTotalNum
(
res
?.
totalRcdNum
??
0
);
})
.
catch
(
err
=>
{
setLoading
(
false
);
notification
.
error
({
message
:
err
.
message
,
});
});
};
useEffect
(()
=>
{
if
(
visible
)
{
getAccountData
();
}
},
[
searchInfo
,
visible
,
date
,
pageIndex
]);
const
columns
=
[
{
title
:
'序号'
,
key
:
'序号'
,
render
:
(
text
,
record
,
index
)
=>
(
pageIndex
-
1
)
*
pageSize
+
index
+
1
,
align
:
'center'
,
width
:
80
,
},
{
title
:
'client'
,
key
:
'client'
,
dataIndex
:
'client'
,
align
:
'center'
,
},
{
title
:
'origin'
,
key
:
'site'
,
dataIndex
:
'site'
,
align
:
'center'
,
},
{
title
:
'登录名'
,
key
:
'登录名'
,
dataIndex
:
'登录名'
,
align
:
'center'
,
},
{
title
:
'登录时间'
,
key
:
'登录时间'
,
dataIndex
:
'登录时间'
,
align
:
'center'
,
},
];
return
(
<
Modal
title
=
{
`用户登录台账
${
date
}
`
}
visible
=
{
visible
}
onCancel
=
{()
=>
setVisible
(
false
)}
footer
=
{
null
}
wrapClassName
=
{
styles
[
'login-log-modal'
]}
width
=
{
'60%'
}
>
<
Spin
spinning
=
{
loading
}
>
<
div
className
=
"login-log-modal-header"
>
<
Form
.
Item
label
=
"快速索引"
>
<
Input
.
Search
ref
=
{
searchInput
}
placeholder
=
"请输入关键字"
style
=
{{
width
:
400
}}
onSearch
=
{
value
=>
{
setSearchInfo
(
value
);
setPageIndex
(
1
);
}}
/
>
<
/Form.Item
>
<
Button
onClick
=
{
e
=>
{
setSearchInfo
(
''
);
searchInput
.
current
.
state
.
value
=
''
;
searchInput
.
current
.
input
.
value
=
''
;
setPageIndex
(
1
);
}}
>
重置
<
/Button
>
<
/div
>
<
div
className
=
"login-log-modal-content"
>
<
Basictable
bordered
dataSource
=
{
tableData
}
columns
=
{
columns
}
pagination
=
{{
showSizeChanger
:
true
,
showQuickJumper
:
true
,
total
:
totalNum
,
pageSize
:
pageSize
,
current
:
pageIndex
,
onChange
:
(
page
,
pageSize
)
=>
{
setPageIndex
(
page
);
setPageSize
(
pageSize
);
},
}}
/
>
<
/div
>
<
/Spin
>
<
/Modal
>
);
};
const
initIndustries
=
[
'供水'
,
'排水'
,
'能源'
,
'农饮水'
,
'直饮水'
,
'大数据'
,
'实验室'
,
'项目案例'
,
];
const
industryColors
=
{
供水
:
'rgb(38,150,250)'
,
农饮水
:
'rgb(23,198,149)'
,
排水
:
'rgb(246,171,37)'
,
能源
:
'rgb(113,183,62)'
,
直饮水
:
'rgb(84,189,204)'
,
大数据
:
'rgb(116,87,232)'
,
实验室
:
'rgb(96,154,232)'
,
项目案例
:
'rgb(141,74,210)'
,
设备管理
:
'rgb(141,74,210)'
,
};
const
myColor
=
[
'#008EFE'
,
'#39DDD1'
,
'#FF9700'
,
'#844BF0'
,
'#625ba1'
,
'#898989'
,
'#9c9800'
,
'#007f54'
,
'#a195c5'
,
'#103667'
,
'#f19272'
,
];
const
initCounterData
=
[
{
title
:
'环境数量'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'总功能数量'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'常用功能数量'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'新增功能数量'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'总用户数'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'活跃用户数'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'当期访问量'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'当期点击量'
,
value
:
'--'
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
];
const
defaultPickeDate
=
moment
().
add
(
-
1
,
'month'
);
const
defaultPickModel
=
'month'
;
const
CloudUsingAnalysis
=
()
=>
{
const
[
loading
,
setLoading
]
=
useState
(
false
);
const
[
industries
,
setIndustries
]
=
useState
(
initIndustries
);
// 行业列表
const
[
industry
,
setindustry
]
=
useState
();
// 条件:行业类型
const
[
type
,
setType
]
=
useState
(
''
);
// 条件:环境类型 1 -> 客户环境,2 -> 演示环境
const
[
dateFrom
,
setDateFrom
]
=
useState
(
defaultPickeDate
.
startOf
(
defaultPickModel
).
format
(
defaultFormat
),
);
const
[
dateTo
,
setDateTo
]
=
useState
(
defaultPickeDate
.
endOf
(
defaultPickModel
).
format
(
defaultFormat
),
);
const
[
timeMode
,
setTimeMode
]
=
useState
(
'日'
);
const
[
limitNum
,
steLimitNum
]
=
useState
(
20
);
const
[
countersData
,
setCountersData
]
=
useState
(
initCounterData
);
// 统计总览数据
const
[
loginsOption
,
setLoginsOption
]
=
useState
(
null
);
// loigns chart option
const
[
loginDate
,
setLoginDate
]
=
useState
(
''
);
const
[
loginModalVisible
,
setLoginModalVisible
]
=
useState
(
false
);
const
[
industriesChartData
,
setIndustriesChartData
]
=
useState
([]);
const
[
levelType
,
setLevelType
]
=
useState
(
'all'
);
const
[
industryOption
,
setIndustryOption
]
=
useState
(
null
);
// industry proportion chart option
const
[
hotsOption
,
setHotsOption
]
=
useState
(
null
);
// hots enviroment chart option
const
[
productsOption
,
setProdutsOption
]
=
useState
(
null
);
const
[
cusViewData
,
setCusViewData
]
=
useState
([]);
const
[
cusViewTableData
,
setCusViewTableData
]
=
useState
([]);
// 用户访问统计
const
cusViewInput
=
useRef
();
// 登录量统计,查看详情
const
showLoginDetails
=
useCallback
(
event
=>
{
setLoginDate
(
event
.
name
);
setLoginModalVisible
(
true
);
},
[]);
// 行业占比分析,查看下一级
const
showIndustryLevel
=
useCallback
(
event
=>
{
const
pieName
=
event
.
name
;
const
_chartData
=
industriesChartData
.
find
(
item
=>
item
.
name
===
pieName
);
if
(
!
_chartData
)
return
;
const
_chartOption
=
buildIndustryOption
(
_chartData
?
_chartData
.
data
:
[]);
setLevelType
(
pieName
);
setIndustryOption
(
_chartOption
);
},
[]);
const
fetchIndustries
=
()
=>
{
cloudService
.
getDataDictionaryList
({
nodeNameArr
:
'行业'
,
ignoreSite
:
true
,
})
.
then
(
res
=>
{
if
(
res
.
data
&&
res
.
data
.
length
)
{
const
_industries
=
res
.
data
[
0
].
childList
.
map
(
item
=>
item
.
NODEVALUE
);
setIndustries
(
_industries
);
}
});
};
const
buildCounterOptions
=
(
custResult
,
funcResult
,
loginResult
)
=>
{
const
funcNum
=
funcResult
.
total
||
0
;
const
usefuncNum
=
funcResult
.
currentNum
||
0
;
const
usefuncPercent
=
funcNum
==
0
?
0
:
((
usefuncNum
/
funcNum
)
*
100
).
toFixed
(
0
);
const
_counterOptions
=
[
{
title
:
'环境数量'
,
value
:
custResult
.
total
||
0
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'总功能数量'
,
value
:
funcNum
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'常用功能数量'
,
value
:
funcResult
.
currentNum
||
0
,
icon
:
''
,
suffix
:
<
span
style
=
{{
color
:
'orange'
}}
>
/ {usefuncPercent}%</
span
>
,
prefix
:
''
,
},
{
title
:
'新增功能数量'
,
value
:
funcResult
.
addNum
||
0
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'总用户数'
,
value
:
loginResult
.
total
||
0
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'活跃用户数'
,
value
:
loginResult
.
currentNum
||
0
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'当期访问量'
,
value
:
loginResult
.
loginNum
||
0
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
{
title
:
'当期点击量'
,
value
:
funcResult
.
visitTotal
||
0
,
icon
:
''
,
suffix
:
''
,
prefix
:
''
,
},
];
return
_counterOptions
;
};
// 登录量统计图表(统计:移动端、PC、全部登录人次)
const
buildLoginsOption
=
(
loginResult
,
mobilelogin
)
=>
{
const
xCategories
=
[],
loginData
=
[],
mobileldata
=
[],
pcdata
=
[];
if
(
loginResult
.
datas
&&
loginResult
.
datas
.
length
)
{
loginResult
.
datas
.
forEach
(
d
=>
{
xCategories
.
push
(
d
.
time
);
loginData
.
push
(
d
.
num
);
const
mData
=
mobilelogin
.
datas
.
find
(
m
=>
{
return
m
.
time
==
d
.
time
;
});
if
(
mData
&&
mData
.
num
)
{
mobileldata
.
push
(
mData
.
num
);
pcdata
.
push
(
d
.
num
-
mData
.
num
);
}
else
{
mobileldata
.
push
(
0
);
pcdata
.
push
(
d
.
num
);
}
});
}
return
{
grid
:
{
top
:
30
,
bottom
:
30
,
left
:
50
,
right
:
10
,
},
legend
:
{
show
:
true
,
top
:
-
10
,
padding
:
20
,
itemWidth
:
14
,
itemHeight
:
6
,
itemGap
:
20
,
textStyle
:
{
padding
:
[
0
,
0
,
0
,
8
],
fontSize
:
14
,
color
:
'#00000065'
,
},
},
xAxis
:
{
type
:
'category'
,
data
:
xCategories
,
splitLine
:
{
show
:
false
,
},
axisLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#DBE8EF'
,
},
},
axisTick
:
{
show
:
false
,
},
axisLabel
:
{
color
:
'#808080'
,
},
},
yAxis
:
[
{
type
:
'value'
,
minInterval
:
1
,
name
:
'登录人次'
,
nameGap
:
10
,
nameTextStyle
:
{
color
:
'#808080'
,
align
:
'right'
,
padding
:
[
0
,
0
,
0
,
8
],
},
splitLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#DBE8EF'
,
type
:
'dashed'
,
},
},
axisLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#DBE8EF'
,
},
},
axisLabel
:
{
color
:
'#808080'
,
},
formatter
:
function
(
value
,
index
)
{
// value大于1000时除以1000并拼接k,小于1000按原格式显示
if
(
value
>=
1000
)
{
value
=
value
/
1000
+
'k'
;
}
else
if
(
value
<
1000
)
{
value
;
}
return
value
;
},
},
],
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
,
},
},
series
:
[
{
name
:
'移动端'
,
type
:
'bar'
,
stack
:
'客户端'
,
barMaxWidth
:
'40'
,
yAxisIndex
:
0
,
data
:
mobileldata
,
itemStyle
:
{
color
:
'#39DDD1'
,
},
},
{
name
:
'PC'
,
type
:
'bar'
,
stack
:
'客户端'
,
barMaxWidth
:
'40'
,
yAxisIndex
:
0
,
data
:
pcdata
,
itemStyle
:
{
color
:
'#008EFE'
,
},
},
{
name
:
'总登录人次'
,
type
:
'line'
,
smooth
:
true
,
yAxisIndex
:
0
,
data
:
loginData
,
itemStyle
:
{
color
:
'#FFAE00'
,
},
},
],
};
};
// 行业占比分析图表(统计:行业点击量占比)
const
buildIndustryOption
=
chartdata
=>
{
return
{
title
:
{
show
:
false
,
text
:
''
,
},
color
:
[
'#008EFE'
,
'#39DDD1'
,
'#FF9700'
,
'#844BF0'
,
'#625ba1'
,
'#898989'
,
'#9c9800'
,
'#007f54'
,
'#a195c5'
,
'#103667'
,
'#f19272'
,
],
tooltip
:
{
trigger
:
'item'
,
animation
:
false
,
formatter
(
params
)
{
return
`<div style="display:inline-block;margin-right:7px;margin-bottom:2px;border-radius:5px;width:5px;height:5px;background-color:
${
params
.
color
.
length
>
7
?
params
.
color
.
slice
(
0
,
-
2
)
:
params
.
color
}
"></div>
${
params
.
name
}
<div style="display:inline-block;">:</div><span style="color:
${
params
.
color
.
length
>
7
?
params
.
color
.
slice
(
0
,
-
2
)
:
params
.
color
}
;margin-left:10px">
${
params
.
value
}
</span>`
;
},
},
legend
:
{
show
:
false
,
top
:
'bottom'
,
// right: '10%',
// left: '15%',
// borderColor: '#DBE8EF',
// borderWidth: 1,
// orient: 'horizontal',
padding
:
20
,
itemWidth
:
14
,
itemHeight
:
6
,
itemGap
:
20
,
textStyle
:
{
padding
:
[
0
,
0
,
0
,
8
],
fontSize
:
14
,
color
:
'#00000065'
,
},
itemStyle
:
{},
},
series
:
[
{
name
:
'行业统计'
,
type
:
'pie'
,
center
:
[
'50%'
,
'50%'
],
// radius: ['55%', '70%'],
avoidLabelOverlap
:
false
,
animation
:
true
,
hoverAnimation
:
true
,
itemStyle
:
{
opacity
:
0.8
,
},
label
:
{
normal
:
{
formatter
(
params
)
{
return
`{name|
${
params
.
name
}
}:{value|
${
params
.
value
}
}个 {value|
${
Number
(
params
.
percent
).
toFixed
(
1
)}
}{unit| %}`
;
},
rich
:
{
name
:
{
fontSize
:
14
,
color
:
'#333333'
,
fontFamily
:
'DINPro'
,
lineHeight
:
20
,
opacity
:
0.85
,
},
value
:
{
fontSize
:
14
,
// color: '#333333',
fontFamily
:
'DINPro'
,
lineHeight
:
20
,
fontWeight
:
'bold'
,
opacity
:
0.85
,
},
unit
:
{
color
:
'#333333'
,
},
},
},
},
emphasis
:
{
label
:
{
show
:
true
,
},
},
labelLine
:
{
show
:
true
,
lineStyle
:
{
cap
:
'round'
,
},
// length: 10,
// length2: 40,
},
data
:
chartdata
,
},
],
};
};
const
buildIndustryData
=
datas
=>
{
let
industrydata
=
[],
moredata
=
[],
cIndex
=
0
;
datas
.
length
&&
datas
.
forEach
(
d
=>
{
industrydata
.
push
({
name
:
d
.
aindustry
,
value
:
d
.
count
,
drilldown
:
d
.
aindustry
,
color
:
industryColors
[
d
.
aindustry
]
?
industryColors
[
d
.
aindustry
]
:
myColor
[
cIndex
++
],
});
var
mData
=
{
id
:
d
.
aindustry
,
name
:
d
.
aindustry
,
data
:
[],
};
d
.
details
&&
d
.
details
.
length
&&
d
.
details
.
forEach
(
i
=>
{
mData
.
data
.
push
({
name
:
i
.
environmentName
,
value
:
i
.
num
,
});
});
moredata
.
push
(
mData
);
});
moredata
.
unshift
({
id
:
'all'
,
name
:
'all'
,
data
:
industrydata
});
return
moredata
;
};
// 环境热度分析图表(统计:环境功能点击量分布)
const
buildHotsOption
=
datas
=>
{
let
chartDatas
=
[],
cIndex
=
0
;
chartDatas
=
datas
.
map
(
d
=>
{
// 预处理,将d.enviromentTypes 下的 functionInfos 提取出来
const
enterprises
=
[];
d
.
environmentTypes
.
forEach
(
e
=>
{
e
.
functionInfos
.
forEach
(
f
=>
{
// 所有的functionsInfo 根据 enterpriseName 分类
let
enterprise
=
enterprises
.
find
(
ent
=>
ent
.
enterpriseName
===
f
.
enterpriseName
,
);
let
_functionInfos
=
[];
if
(
!
enterprise
)
{
_functionInfos
=
[];
enterprises
.
push
({
enterpriseName
:
f
.
enterpriseName
,
functionInfos
:
_functionInfos
,
});
}
else
{
_functionInfos
=
enterprise
.
functionInfos
;
}
_functionInfos
.
push
({
...
f
});
});
});
// 对提取后的分类统计
const
dChildren
=
enterprises
.
map
(
e
=>
{
const
eChildren
=
e
.
functionInfos
.
map
(
f
=>
({
name
:
f
.
functionName
,
value
:
f
.
functionVisNum
,
}));
return
{
name
:
e
.
enterpriseName
,
children
:
eChildren
,
};
});
return
{
name
:
d
.
aindustry
,
children
:
dChildren
,
};
});
return
{
title
:
{
text
:
null
,
},
tooltip
:
{},
series
:
[
{
name
:
'平台环境'
,
type
:
'treemap'
,
// visibleMin: 300,
data
:
chartDatas
,
leafDepth
:
2
,
levels
:
[
{
itemStyle
:
{
borderColor
:
'#555'
,
borderWidth
:
4
,
gapWidth
:
4
,
},
},
{
colorSaturation
:
[
0.3
,
0.6
],
itemStyle
:
{
borderColorSaturation
:
0.7
,
gapWidth
:
2
,
borderWidth
:
2
,
},
},
{
colorSaturation
:
[
0.3
,
0.5
],
itemStyle
:
{
borderColorSaturation
:
0.6
,
gapWidth
:
1
,
},
},
{
colorSaturation
:
[
0.3
,
0.5
],
},
],
},
],
};
return
{
title
:
{
text
:
null
,
},
credits
:
{
enabled
:
false
},
series
:
[
{
type
:
'treemap'
,
layoutAlgorithm
:
'squarified'
,
allowDrillToNode
:
true
,
dataLabels
:
{
enabled
:
false
,
},
levelIsConstant
:
false
,
levels
:
[
{
level
:
1
,
dataLabels
:
{
enabled
:
true
,
},
borderWidth
:
2
,
},
],
data
:
chartDatas
,
},
],
};
};
// 环境使用次数统计图表(统计:各环境下产品功能使用次数)
const
buildProductsOption
=
funcResult
=>
{
var
funcs
=
[],
types
=
[];
funcResult
.
length
&&
funcResult
.
forEach
(
i
=>
{
if
(
!
i
.
environmentTypes
||
!
_
.
isArray
(
i
.
environmentTypes
))
return
void
0
;
i
.
environmentTypes
.
forEach
(
e
=>
{
if
(
!
e
.
functionInfos
||
!
e
.
functionInfos
.
length
)
return
void
0
;
e
.
functionInfos
.
forEach
(
f
=>
{
if
(
!
f
.
functionName
||
f
.
functionName
==
''
)
return
void
0
;
var
funcItem
=
funcs
.
find
(
_f
=>
{
return
_f
.
fName
==
f
.
functionName
;
});
if
(
!
funcItem
)
{
funcItem
=
{
fName
:
f
.
functionName
,
总和
:
f
.
functionVisNum
,
};
funcItem
[
i
.
aindustry
]
=
f
.
functionVisNum
;
funcs
.
push
(
funcItem
);
}
else
{
funcItem
[
'总和'
]
+=
f
.
functionVisNum
;
funcItem
[
i
.
aindustry
]
=
f
.
functionVisNum
;
}
});
});
if
(
types
.
indexOf
(
i
.
aindustry
)
<
0
)
types
.
push
(
i
.
aindustry
);
});
funcs
=
funcs
.
sort
(
function
(
a
,
b
)
{
return
b
[
'总和'
]
-
a
[
'总和'
];
});
var
products
=
[],
totalData
=
[],
eData
=
[],
cIndex
=
0
;
types
.
forEach
(
t
=>
{
eData
.
push
({
name
:
t
,
type
:
'bar'
,
barMaxWidth
:
'40'
,
stack
:
'环境功能'
,
yAxisIndex
:
0
,
data
:
[],
itemStyle
:
{
color
:
industryColors
[
t
.
aindustry
]
?
industryColors
[
t
.
aindustry
]
:
myColor
[
cIndex
++
%
myColor
.
length
],
},
});
});
funcs
.
forEach
(
funcItem
=>
{
products
.
push
(
funcItem
.
fName
);
totalData
.
push
(
funcItem
[
'总和'
]);
eData
.
forEach
(
data
=>
{
if
(
funcItem
.
hasOwnProperty
(
data
.
name
))
{
data
.
data
.
push
(
funcItem
[
data
.
name
]);
}
else
{
data
.
data
.
push
(
0
);
}
});
});
return
{
grid
:
{
top
:
30
,
bottom
:
30
,
left
:
50
,
right
:
10
,
},
legend
:
{
show
:
true
,
top
:
-
8
,
padding
:
[
20
,
0
,
20
,
80
],
itemWidth
:
14
,
itemHeight
:
6
,
itemGap
:
10
,
textStyle
:
{
padding
:
[
0
,
0
,
0
,
8
],
fontSize
:
14
,
color
:
'#00000065'
,
},
},
xAxis
:
{
type
:
'category'
,
data
:
products
,
splitLine
:
{
show
:
false
,
},
axisLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#DBE8EF'
,
},
},
axisTick
:
{
show
:
false
,
},
axisLabel
:
{
color
:
'#808080'
,
},
},
yAxis
:
[
{
type
:
'value'
,
minInterval
:
1
,
name
:
'访问量 (人·次)'
,
nameGap
:
10
,
nameTextStyle
:
{
color
:
'#808080'
,
align
:
'middle'
,
padding
:
[
0
,
-
10
,
0
,
0
],
},
splitLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#DBE8EF'
,
type
:
'dashed'
,
},
},
axisLine
:
{
show
:
true
,
lineStyle
:
{
color
:
'#DBE8EF'
,
},
},
axisLabel
:
{
color
:
'#808080'
,
formatter
:
function
(
value
,
index
)
{
// value大于1000时除以1000并拼接k,小于1000按原格式显示
if
(
value
>=
1000
)
{
value
=
value
/
1000
+
'k'
;
}
else
if
(
value
<
1000
)
{
value
;
}
return
value
;
},
},
},
],
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'shadow'
,
},
},
series
:
[
...
eData
,
{
name
:
'总访问量'
,
type
:
'line'
,
stack
:
'环境功能'
,
smooth
:
true
,
yAxisIndex
:
0
,
data
:
totalData
,
itemStyle
:
{
color
:
'#FFAE00'
,
},
},
],
};
};
const
buildCusViewsData
=
userTableData
=>
{
let
list
=
[],
datas
=
userTableData
;
datas
=
datas
.
sort
(
function
(
a
,
b
)
{
return
b
.
num
-
a
.
num
;
});
datas
.
length
&&
datas
.
forEach
(
d
=>
{
const
productData
=
{};
d
.
userLoginDetails
.
forEach
(
f
=>
{
if
(
!
productData
.
hasOwnProperty
(
f
.
projectName
))
{
productData
[
f
.
projectName
]
=
[];
}
if
(
f
.
projectNum
>=
limitNum
)
productData
[
f
.
projectName
].
push
(
f
.
functionName
);
});
list
.
push
({
userName
:
d
.
userName
,
count
:
d
.
num
,
products
:
productData
,
key
:
d
.
userName
,
});
});
return
list
;
};
const
getDatas
=
()
=>
{
setLoading
(
true
);
const
req0
=
cloudService
.
getLoginStatistic
({
dateFrom
:
dateFrom
,
dateTo
:
dateTo
,
mode
:
timeMode
,
industryType
:
industry
,
enviromentType
:
type
,
client
:
''
,
ignoreSite
:
true
,
});
const
req1
=
cloudService
.
getFunctionsStatistic
({
dateFrom
:
dateFrom
,
dateTo
:
dateTo
,
industryType
:
industry
,
enviromentType
:
type
,
client
:
''
,
visitNum
:
limitNum
,
ignoreSite
:
true
,
});
const
req2
=
cloudService
.
getEnviromentStatistic
({
industryType
:
industry
,
enviromentType
:
type
,
ignoreSite
:
true
,
});
const
req3
=
cloudService
.
getUserLoginStatistic
({
dateFrom
:
dateFrom
,
dateTo
:
dateTo
,
industryType
:
industry
,
enviromentType
:
type
,
client
:
''
,
visitNum
:
limitNum
,
ignoreSite
:
true
,
});
const
req4
=
cloudService
.
getLoginStatistic
({
dateFrom
:
dateFrom
,
dateTo
:
dateTo
,
mode
:
timeMode
,
industryType
:
industry
,
enviromentType
:
type
,
client
:
'miniapp'
,
ignoreSite
:
true
,
});
Promise
.
all
([
req0
,
req1
,
req2
,
req3
,
req4
])
.
then
(
results
=>
{
setLoading
(
false
);
const
loginResult
=
results
&&
results
[
0
]
&&
results
[
0
].
say
&&
results
[
0
].
say
.
statusCode
==
'0000'
&&
results
[
0
].
getMe
.
length
?
results
[
0
].
getMe
[
0
]
:
{};
const
funcResult
=
results
&&
results
[
1
]
&&
results
[
1
].
say
&&
results
[
1
].
say
.
statusCode
==
'0000'
&&
results
[
1
].
getMe
.
length
?
results
[
1
].
getMe
[
0
]
:
{};
const
custResult
=
results
&&
results
[
2
]
&&
results
[
2
].
say
&&
results
[
2
].
say
.
statusCode
==
'0000'
&&
results
[
2
].
getMe
.
length
?
results
[
2
].
getMe
[
0
]
:
{};
const
viewResult
=
results
&&
results
[
3
]
&&
results
[
3
].
say
&&
results
[
3
].
say
.
statusCode
==
'0000'
&&
results
[
3
].
getMe
.
length
?
results
[
3
].
getMe
[
0
]
:
{};
const
mobilelogin
=
results
&&
results
[
4
]
&&
results
[
4
].
say
&&
results
[
4
].
say
.
statusCode
==
'0000'
&&
results
[
4
].
getMe
.
length
?
results
[
4
].
getMe
[
0
]
:
{};
// build counters data
const
_countersData
=
buildCounterOptions
(
custResult
,
funcResult
,
loginResult
,
);
setCountersData
(
_countersData
);
// build logins chart option
const
_loginsOption
=
buildLoginsOption
(
loginResult
,
mobilelogin
);
setLoginsOption
(
_loginsOption
);
// build industry chart option
const
_industriesData
=
buildIndustryData
(
custResult
.
environmentInfos
&&
custResult
.
environmentInfos
.
length
?
custResult
.
environmentInfos
:
[],
);
const
_chartData
=
_industriesData
.
find
(
item
=>
item
.
id
===
levelType
);
const
_industryOption
=
buildIndustryOption
(
_chartData
?
_chartData
.
data
:
[],
);
setIndustriesChartData
(
_industriesData
);
setIndustryOption
(
_industryOption
);
// build hots enviroment chart option
const
_hotsOption
=
buildHotsOption
(
funcResult
.
datas
&&
funcResult
.
datas
.
length
?
funcResult
.
datas
:
[],
);
setHotsOption
(
_hotsOption
);
const
_productsOption
=
buildProductsOption
(
funcResult
.
datas
&&
funcResult
.
datas
.
length
?
funcResult
.
datas
:
[],
);
setProdutsOption
(
_productsOption
);
const
_cusViewData
=
buildCusViewsData
(
viewResult
.
userLoginStatistics
&&
viewResult
.
userLoginStatistics
.
length
?
viewResult
.
userLoginStatistics
:
[],
);
setCusViewData
(
_cusViewData
);
const
_newData
=
_cusViewData
.
filter
(
item
=>
item
.
userName
&&
item
.
userName
.
includes
(
cusViewInput
?.
current
?.
input
?.
value
??
''
),
);
setCusViewTableData
(
_newData
);
})
.
catch
(
err
=>
{
setLoading
(
false
);
notification
.
error
({
message
:
err
.
message
,
});
});
};
useEffect
(()
=>
{
fetchIndustries
();
getDatas
();
},
[
dateFrom
,
dateTo
,
industry
,
type
]);
const
columns
=
[
{
title
:
'序号'
,
key
:
'序号'
,
render
:
(
text
,
record
,
index
)
=>
index
+
1
,
align
:
'center'
,
width
:
100
,
},
{
title
:
'账号名称'
,
key
:
'账号名称'
,
dataIndex
:
'userName'
,
align
:
'center'
,
width
:
200
,
},
{
title
:
'访问次数'
,
key
:
'访问次数'
,
dataIndex
:
'count'
,
align
:
'center'
,
width
:
150
,
},
{
title
:
'常用环境及功能'
,
key
:
'常用环境及功能'
,
render
:
(
text
,
record
,
index
)
=>
{
let
temp
=
[];
record
.
products
&&
_
.
isObject
(
record
.
products
)
&&
Object
.
keys
(
record
.
products
).
forEach
(
key
=>
{
temp
.
push
(
<>
<
span
className
=
"table-cell-bold"
>
{
key
}
<
/span
>
<
span
>
:
{
record
.
products
[
key
]
&&
_
.
isArray
(
record
.
products
[
key
])
?
record
.
products
[
key
].
join
(
','
)
:
''
}
<
/span
>
<
br
/>
<
/>
,
);
});
return
temp
;
},
},
];
const
dateChange
=
({
dateFrom
,
dateTo
},
model
)
=>
{
setDateFrom
(
dateFrom
);
setDateTo
(
dateTo
);
if
(
moment
(
dateTo
).
diff
(
moment
(
dateFrom
),
'days'
)
>
362
)
{
setTimeMode
(
'月'
);
}
else
{
setTimeMode
(
'日'
);
}
};
const
onSearch
=
value
=>
{
if
(
!
cusViewData
)
return
;
const
_newData
=
cusViewData
.
filter
(
item
=>
item
.
userName
&&
item
.
userName
.
includes
(
value
),
);
setCusViewTableData
(
_newData
);
};
const
backToBootPage
=
e
=>
{
window
.
history
.
back
();
};
return
(
<
SecurityLayout
>
<
ConfigProvider
locale
=
{
zhCN
}
>
<
div
className
=
{
styles
.
usingAnalysis
}
>
<
Spin
spinning
=
{
loading
}
>
<
div
className
=
"cua-content"
>
<
div
className
=
"cua-header"
>
<
div
className
=
"back-btn"
onClick
=
{
backToBootPage
}
>
<
LeftOutlined
/>
返回
<
/div
>
<
div
className
=
"filter-item"
>
<
span
className
=
"filter-item-label"
>
统计时间:
<
/span
>
<
DatePickerGroup
showModels
=
{[
'day'
,
'week'
,
'month'
,
'quarter'
,
'year'
,
'custom'
,
]}
onChange
=
{
dateChange
}
defaultModel
=
"month"
defaultDate
=
{
moment
().
add
(
-
1
,
'month'
)}
/
>
<
/div
>
<
div
className
=
"filter-item"
>
<
span
className
=
"filter-item-label"
>
行业切换:
<
/span
>
<
Select
placeholder
=
"请选择行业"
allowClear
value
=
{
industry
}
onChange
=
{
value
=>
setindustry
(
value
)}
>
{
industries
.
map
(
item
=>
(
<
Select
.
Option
value
=
{
item
}
key
=
{
item
}
>
{
item
}
<
/Select.Option
>
))}
<
/Select
>
<
/div
>
<
div
className
=
"filter-item"
>
<
span
className
=
"filter-item-label"
>
环境类型:
<
/span
>
<
Radio
.
Group
value
=
{
type
}
onChange
=
{
e
=>
setType
(
e
.
target
.
value
)}
>
<
Radio
value
=
""
>
全部
<
/Radio
>
<
Radio
value
=
"2"
>
演示环境
<
/Radio
>
<
Radio
value
=
"1"
>
客户环境
<
/Radio
>
<
/Radio.Group
>
<
/div
>
<
div
className
=
"sub-title"
>
数据来源
:
Panda
-
Water
.
cn
<
/div
>
<
/div
>
<
div
className
=
"counter-list"
>
{
countersData
&&
countersData
.
map
((
item
,
n
)
=>
(
<
Card
key
=
{
n
}
bordered
=
{
false
}
>
<
Statistic
title
=
{
item
.
title
}
value
=
{
item
.
value
}
// precision={2}
// prefix={<ArrowUpOutlined />}
suffix
=
{
item
.
suffix
}
/
>
<
/Card
>
))}
<
/div
>
<
div
className
=
"cua-main"
>
<
div
className
=
"cua-main-middle"
>
<
div
className
=
"cua-chart-box"
>
<
div
className
=
"cua-chart-header"
>
<
div
className
=
"cua-chart-title"
>
登录量统计
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-content"
>
{
loginsOption
?
(
<
ReactECharts
className
=
"po-type-hour-chart"
style
=
{{
width
:
'100%'
,
height
:
'100%'
}}
opts
=
{{
renderer
:
'svg'
}}
option
=
{
loginsOption
}
onEvents
=
{{
click
:
showLoginDetails
,
}}
/
>
)
:
null
}
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-box"
>
<
div
className
=
"cua-chart-header"
>
<
div
className
=
"cua-chart-title"
>
行业占比分析
<
/div
>
<
div
className
=
"cua-chart-subtitle"
>
{
levelType
===
'all'
?
null
:
(
<
Button
onClick
=
{
e
=>
{
const
_industryData
=
industriesChartData
.
find
(
item
=>
item
.
name
===
'all'
,
);
const
_industryOption
=
buildIndustryOption
(
_industryData
?
_industryData
.
data
:
[],
);
setLevelType
(
'all'
);
setIndustryOption
(
_industryOption
);
}}
>
返回
<
/Button
>
)}
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-content"
>
{
industryOption
?
(
<
ReactECharts
className
=
"po-type-hour-chart"
style
=
{{
width
:
'100%'
,
height
:
'100%'
}}
opts
=
{{
renderer
:
'svg'
}}
option
=
{
industryOption
}
onEvents
=
{{
click
:
showIndustryLevel
,
}}
/
>
)
:
null
}
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-box"
>
<
div
className
=
"cua-chart-header"
>
<
div
className
=
"cua-chart-title"
>
环境热度分析
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-content"
>
{
hotsOption
?
(
<
ReactECharts
className
=
"po-type-hour-chart"
style
=
{{
width
:
'100%'
,
height
:
'100%'
}}
opts
=
{{
renderer
:
'svg'
}}
option
=
{
hotsOption
}
/
>
)
:
null
}
<
/div
>
<
/div
>
<
/div
>
<
div
className
=
"cua-main-bottom"
>
<
div
className
=
"cua-chart-box"
style
=
{{
overflow
:
'hidden'
}}
>
<
div
className
=
"cua-chart-header"
>
<
div
className
=
"cua-chart-title"
>
用户访问统计
<
/div
>
<
div
className
=
"cua-chart-subtitle"
>
<
Input
.
Search
ref
=
{
cusViewInput
}
placeholder
=
"搜索用户名称"
onSearch
=
{
onSearch
}
style
=
{{
width
:
300
}}
/
>
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-content cua-customer-view"
>
<
Basictable
bordered
columns
=
{
columns
}
dataSource
=
{
cusViewTableData
}
pagination
=
{
false
}
/
>
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-box enviromentusing-chart-box"
>
<
div
className
=
"cua-chart-header"
>
<
div
className
=
"cua-chart-title"
>
环境使用统计
<
/div
>
<
/div
>
<
div
className
=
"cua-chart-content"
>
{
productsOption
?
(
<
ReactECharts
className
=
"po-type-hour-chart"
style
=
{{
width
:
'100%'
,
height
:
'100%'
}}
opts
=
{{
renderer
:
'svg'
}}
option
=
{
productsOption
}
/
>
)
:
null
}
<
/div
>
<
/div
>
<
/div
>
<
/div
>
<
/div
>
{
loginModalVisible
?
(
<
LoginStatisticModal
visible
=
{
loginModalVisible
}
setVisible
=
{
setLoginModalVisible
}
date
=
{
loginDate
}
timeMode
=
{
timeMode
}
/
>
)
:
null
}
<
/Spin
>
<
/div
>
<
/ConfigProvider
>
<
/SecurityLayout
>
);
};
const
mapStateToProps
=
state
=>
({
global
:
state
.
getIn
([
'global'
,
'globalConfig'
]),
instance
:
state
.
getIn
([
'global'
,
'instance'
]),
});
const
mapDispatchToProps
=
dispatch
=>
({
updateConfig
(
config
)
{
dispatch
(
actionCreators
.
getConfig
(
config
));
},
createContext
(
data
)
{
dispatch
(
actionCreators
.
createContext
(
data
));
},
updateCurrentIndex
(
index
)
{
dispatch
(
actionCreators
.
updateCurrentIndex
(
index
));
},
});
export
default
connect
(
mapStateToProps
,
mapDispatchToProps
,
)(
CloudUsingAnalysis
);
src/pages/cloudOMS/usingAnalysis/index.less
0 → 100644
View file @
5ed65178
@import '~antd/es/style/themes/default.less';
@background-color-container: #f5f5f5;
@border-radius: 2px;
.usingAnalysis {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
background-color: @background-color-container;
:global {
.@{ant-prefix}-spin-nested-loading,
.@{ant-prefix}-spin-container {
height: 100%;
}
.anticon {
vertical-align: 0.125em;
}
.back-btn {
font-size: 16px;
opacity: 0.75;
cursor: pointer;
line-height: 32px;
user-select: none;
.anticon {
transform: translateX(0px);
transition: transform 0.3s;
}
&:hover {
.anticon {
transform: translateX(-4px);
}
}
}
.cua-content {
width: 100%;
height: 100%;
min-width: 1150px;
// padding: 5px 8px;
// 顶部筛选条件
.cua-header {
background-color: #FFF;
border-radius: @border-radius;
padding: 8px;
display: flex;
align-items: center;
gap: 20px;
.filter-item {
min-width: 220px;
.@{ant-prefix}-select {
width: 140px;
}
}
.sub-title {
margin-left: auto;
font-size: 12px;
color: #aaa;
}
}
.counter-list {
margin-top: 4px;
display: flex;
gap: 4px;
.@{ant-prefix}-card {
flex: 1 1;
.@{ant-prefix}-card-body {
padding: 8px;
}
}
}
.cua-main {
height: calc(100% - 136px);
margin-top: 4px;
display: flex;
flex-direction: column;
.cua-main-middle {
flex: 1;
overflow: hidden;
width: 100%;
min-height: 200px;
margin-bottom: 5px;
display: flex;
justify-content: space-between;
gap: 4px;
}
.cua-main-bottom {
flex: none;
height: 50%;
width: 100%;
min-height: 320px;
display: flex;
justify-content: space-between;
gap: 4px;
.cua-customer-view {
padding: 10px;
.table-cell-bold {
font-weight: bold;
}
.@{ant-prefix}-table-thead th {
text-align: center;
}
}
}
.cua-chart-box {
flex: 1;
background-color: #FFF;
padding: 4px 8px 8px 8px;
display: flex;
flex-direction: column;
.cua-chart-header {
flex: none;
display: flex;
align-items: center;
.cua-chart-title {
font-weight: bold;
line-height: 32px;
&::before {
content: "";
display: inline-block;
width: 3px;
height: 14px;
background-color: #1890ff;
vertical-align: -0.125em;
margin-right: 8px;
}
}
.cua-chart-subtitle {
margin-left: auto;
}
}
.cua-chart-content {
flex: 1;
overflow: hidden;
}
&.enviromentusing-chart-box {
.cua-chart-content {
overflow: visible;
}
}
}
}
}
}
}
.login-log-modal {
:global {
.login-log-modal-header {
display: flex;
margin-bottom: 16px;
.@{ant-prefix}-form-item {
margin-bottom: 0;
margin-right: 8px;
}
}
.login-log-modal-content {
height: 500px;
}
}
}
\ No newline at end of file
src/routes/config.js
View file @
5ed65178
...
...
@@ -8,6 +8,7 @@ import Iframe from '../pages/iframe';
import
Login
from
'../pages/user/login'
;
import
CommonMenu
from
'../pages/commonMenu'
;
import
NoSecret
from
'../pages/user/login/noSecret'
;
import
UsingAnalysis
from
'../pages/cloudOMS/usingAnalysis'
;
export
const
dyRoutes
=
(
routes
,
layout
)
=>
{
// eslint-disable-next-line no-shadow
...
...
@@ -34,6 +35,10 @@ export const dyRoutes = (routes, layout) => {
path
:
'/industry'
,
component
:
BootPage
,
},
{
path
:
'/usingAnalysis'
,
component
:
UsingAnalysis
,
},
{
path
:
'/'
,
component
:
BasicLayout
,
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment