Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
I
Iot_mobile
Project
Project
Details
Activity
Releases
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
wuhao
Iot_mobile
Commits
5e47b27f
Commit
5e47b27f
authored
Feb 23, 2023
by
wuhao
🎯
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
common
parent
1ac6b91f
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
1046 additions
and
28 deletions
+1046
-28
authRoutes.js
config/authRoutes.js
+5
-2
BasicLayout.jsx
src/layouts/BasicLayout.jsx
+3
-2
columns.js
src/pages/alarm/columns.js
+41
-0
detail.jsx
src/pages/alarm/detail.jsx
+712
-0
index.jsx
src/pages/alarm/index.jsx
+202
-0
detail.jsx
src/pages/home/detail.jsx
+79
-24
index.jsx
src/pages/login/index.jsx
+4
-0
No files found.
config/authRoutes.js
View file @
5e47b27f
...
...
@@ -16,13 +16,16 @@ export default [
name
:
'设备'
,
path
:
'/home'
,
component
:
'./home'
,
icon
:
'HomeOutlined'
,
},
{
name
:
'设备详情'
,
path
:
'/home/detail'
,
component
:
'./home/detail'
,
icon
:
'HomeOutlined'
,
},
{
name
:
'告警'
,
path
:
'/alarm'
,
component
:
'./alarm'
,
},
],
},
...
...
src/layouts/BasicLayout.jsx
View file @
5e47b27f
...
...
@@ -26,7 +26,7 @@ menulist 中的表示主路由菜单上左上角是打开 drawer 否则为返回
*/
const
menulist
=
[
'/home'
];
const
menulist
=
[
'/home'
,
'/alarm'
];
function
BasicLayout
()
{
const
setRouteActive
=
(
value
)
=>
{
...
...
@@ -44,7 +44,7 @@ function BasicLayout() {
icon
:
<
IconFont
type=
"icon-pintu"
/>,
},
{
key
:
'/
todo
'
,
key
:
'/
alarm
'
,
title
:
'告警'
,
icon
:
<
IconFont
type=
"icon-bell"
/>,
},
...
...
@@ -315,6 +315,7 @@ function BasicLayout() {
danger
:
true
,
bold
:
true
,
onClick
:
()
=>
{
localStorage
.
clear
();
history
.
replace
(
'/login'
);
handler
.
current
.
close
();
},
...
...
src/pages/alarm/columns.js
0 → 100644
View file @
5e47b27f
function
getcolumns
(
setdrawer
)
{
return
{
columns
:
[
{
title
:
'设备名称'
,
dataIndex
:
'deviceName'
,
key
:
'deviceName'
,
hidetitle
:
true
,
},
{
title
:
'设备状态'
,
dataIndex
:
'deviceStatusName'
,
key
:
'deviceStatusName'
,
hidetitle
:
true
,
render
:
(
text
,
record
)
=>
{
return
<
div
style
=
{{
color
:
record
?.
statusColorList
?.
filter
(
it
=>
it
.
type
===
record
.
deviceStatus
)[
0
].
color
}}
>
{
text
}
<
/div
>
}
},
{
title
:
'活跃时间'
,
dataIndex
:
'lastActivityTime'
,
key
:
'lastActivityTime'
,
},
{
title
:
'日均开动率'
,
dataIndex
:
'powerOnRate'
,
key
:
'powerOnRate'
,
},
],
pathconfig
:
{
enableadd
:
true
,
enableedit
:
true
,
enabledelete
:
true
,
enabledetail
:
true
,
},
};
}
export
default
getcolumns
;
src/pages/alarm/detail.jsx
0 → 100644
View file @
5e47b27f
/* eslint-disable eqeqeq */
import
*
as
React
from
'react'
;
import
{
useState
,
useMemo
,
useRef
}
from
'react'
;
import
DrawerPro
from
'@/components/DrawerPro'
;
import
AutoTable
from
'@/components/AutoTable'
;
import
{
Badge
,
Skeleton
,
Row
,
Col
}
from
'antd'
;
import
getcolumns
from
'./columns'
;
import
{
useAsyncEffect
,
useRequest
}
from
'ahooks'
;
import
{
doFetch
}
from
'@/utils/doFetch'
;
import
ReactECharts
from
'echarts-for-react'
;
import
*
as
echarts
from
'echarts'
;
import
Settings
from
'../../../config/defaultSettings'
;
import
{
useLocation
}
from
'@umijs/max'
;
import
{
FloatingPanel
,
List
}
from
'antd-mobile'
;
const
{
proxypath
}
=
Settings
;
function
cropImage
(
url
)
{
return
new
Promise
((
resolve
)
=>
{
const
img
=
new
Image
();
img
.
crossOrigin
=
'Anonymous'
;
img
.
src
=
url
;
img
.
onload
=
()
=>
{
const
canvas
=
document
.
createElement
(
'canvas'
);
const
ctx
=
canvas
.
getContext
(
'2d'
);
const
size
=
Math
.
min
(
img
.
width
,
img
.
height
);
canvas
.
width
=
size
;
canvas
.
height
=
size
;
ctx
.
beginPath
();
ctx
.
arc
(
size
/
2
,
size
/
2
,
size
/
2
,
0
,
2
*
Math
.
PI
);
ctx
.
clip
();
ctx
.
drawImage
(
img
,
(
img
.
width
-
size
)
/
2
,
(
img
.
height
-
size
)
/
2
,
size
,
size
,
0
,
0
,
size
,
size
,
);
canvas
.
toBlob
((
blob
)
=>
{
const
reader
=
new
FileReader
();
reader
.
readAsDataURL
(
blob
);
reader
.
onloadend
=
()
=>
{
resolve
(
reader
.
result
);
};
},
'image/png'
);
};
});
}
let
gradientColor
=
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
'rgba(33, 89, 81, 1)'
},
{
offset
:
1
,
color
:
'rgba(33, 89, 81, 0.1)'
},
]);
let
gradientColors
=
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
'rgba(24, 70, 114, 1)'
},
{
offset
:
1
,
color
:
'rgba(24, 70, 114, 0.1)'
},
]);
const
Cards
=
({
item
,
columns
,
loading
})
=>
{
const
[
option
,
setoption
]
=
useState
({});
const
{
statusColorList
,
deviceStatusDurationList
}
=
item
??
{
statusColorList
:
[],
deviceStatusDurationList
:
[],
};
useAsyncEffect
(
async
()
=>
{
let
img
=
item
?.
image
?.
length
>
0
?
proxypath
+
item
.
image
?.[
0
]?.
url
:
require
(
'@/assets/default.png'
);
const
image
=
await
cropImage
(
img
);
let
normalColor
=
statusColorList
?.
filter
((
el
)
=>
el
.
type
==
3
)?.[
0
]?.
color
??
''
;
let
data
=
deviceStatusDurationList
?.
map
((
it
)
=>
{
let
label
=
statusColorList
?.
filter
((
el
)
=>
el
.
type
==
it
.
name
)?.[
0
]?.
name
??
''
,
itemColor
=
statusColorList
?.
filter
((
el
)
=>
el
.
type
==
it
.
name
)?.[
0
]?.
color
??
''
;
return
{
...
it
,
label
,
itemStyle
:
{
color
:
itemColor
,
},
};
})
??
[
{
name
:
'关机'
,
value
:
1
,
itemStyle
:
{
color
:
normalColor
,
},
},
];
const
options
=
{
series
:
[
{
type
:
'pie'
,
radius
:
[
'85%'
,
'95%'
],
avoidLabelOverlap
:
false
,
label
:
{
show
:
false
,
position
:
'center'
,
},
data
,
},
],
graphic
:
{
elements
:
[
{
type
:
'image'
,
style
:
{
image
:
image
,
width
:
88
,
height
:
88
,
},
left
:
'center'
,
top
:
'center'
,
},
],
},
};
setoption
(
options
);
},
[
item
]);
return
(
<
div
className=
"split"
style=
{
{
backgroundColor
:
'rgba(255,255,255,0.2)'
,
padding
:
12
,
borderRadius
:
12
,
minHeight
:
130
,
marginBottom
:
30
,
}
}
>
<
Skeleton
loading=
{
loading
}
active
>
<
div
className=
"spread"
style=
{
{
justifyContent
:
'flex-start'
}
}
>
<
Badge
count=
{
item
.
alarmNum
}
overflowCount=
{
99
}
offset=
{
[
-
10
,
10
]
}
color=
"red"
>
<
div
style=
{
{
width
:
120
,
height
:
120
,
flexShrink
:
0
}
}
>
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
'100%'
}
}
/>
</
div
>
</
Badge
>
<
div
style=
{
{
flex
:
1
,
margin
:
'8px 0'
}
}
className=
"rightsection"
>
{
columns
?.
filter
((
it
)
=>
!
(
it
.
valueType
===
'split'
||
it
?.
hideInTable
))
?.
map
((
it
,
i
)
=>
{
const
Bod
=
({
children
})
=>
i
==
0
?
(
<
h2
>
{
children
}
</
h2
>
)
:
i
==
1
?
(
<
h3
>
{
children
}
</
h3
>
)
:
(
<
p
>
{
children
}
</
p
>
);
return
(
<
Bod
key=
{
it
?.
dataIndex
}
>
{
it
?.
hidetitle
?
''
:
`${it?.title}: `
}
{
it
.
render
?
it
.
render
(
item
[
it
?.
dataIndex
],
item
)
:
item
[
it
?.
dataIndex
]
}
</
Bod
>
);
})
}
</
div
>
</
div
>
</
Skeleton
>
</
div
>
);
};
const
Kai
=
({
item
,
loading
})
=>
{
const
[
option
,
setoption
]
=
useState
({});
useAsyncEffect
(
async
()
=>
{
const
options
=
{
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'line'
,
lineStyle
:
{
color
:
'#999999'
,
},
},
backgroundColor
:
'rgba(255,255,255,0.7)'
,
textStyle
:
{
color
:
'#333333'
,
fontSize
:
12
,
},
padding
:
[
8
,
12
],
},
grid
:
{
top
:
10
,
bottom
:
20
,
left
:
40
,
right
:
10
,
},
xAxis
:
{
show
:
false
,
data
:
item
?.
map
?.((
it
)
=>
it
.
name
)
??
[],
},
yAxis
:
{
type
:
'value'
,
axisLine
:
{
show
:
false
,
},
axisTick
:
{
show
:
false
,
},
splitLine
:
{
lineStyle
:
{
color
:
[
'rgba(255,255,255,0.1)'
],
},
},
axisLabel
:
{
color
:
'#fff'
,
fontSize
:
12
,
formatter
:
'{value}'
,
},
},
series
:
[
{
name
:
'时间开动率'
,
type
:
'line'
,
smooth
:
true
,
symbol
:
'circle'
,
symbolSize
:
0
,
lineStyle
:
{
normal
:
{
width
:
2
,
color
:
'#3881e2'
,
},
},
data
:
item
?.
map
?.((
it
)
=>
it
.
value
)
??
[],
},
],
};
setoption
(
options
);
},
[
item
]);
return
(
<
div
style=
{
{
borderRadius
:
12
,
height
:
180
,
}
}
>
<
Skeleton
loading=
{
loading
}
active
>
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
'100%'
}
}
/>
</
Skeleton
>
</
div
>
);
};
const
Mttr
=
({
item
,
loading
})
=>
{
const
[
option
,
setoption
]
=
useState
({});
useAsyncEffect
(
async
()
=>
{
const
options
=
{
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'line'
,
lineStyle
:
{
color
:
'#999999'
,
},
},
backgroundColor
:
'rgba(255,255,255,0.7)'
,
textStyle
:
{
color
:
'#333333'
,
fontSize
:
12
,
},
padding
:
[
8
,
12
],
},
grid
:
{
top
:
10
,
bottom
:
20
,
left
:
40
,
right
:
10
,
},
xAxis
:
{
show
:
false
,
data
:
item
?.
map
?.((
it
)
=>
it
.
name
)
??
[],
},
yAxis
:
{
type
:
'value'
,
axisLine
:
{
show
:
false
,
},
axisTick
:
{
show
:
false
,
},
splitLine
:
{
lineStyle
:
{
type
:
'dashed'
,
color
:
[
'rgba(255,255,255,0.1)'
],
},
},
axisLabel
:
{
color
:
'#fff'
,
fontSize
:
12
,
formatter
:
'{value}'
,
},
},
series
:
[
{
name
:
'MTTR'
,
type
:
'line'
,
smooth
:
true
,
symbol
:
'circle'
,
symbolSize
:
0
,
lineStyle
:
{
normal
:
{
width
:
2
,
color
:
'#9af5ed'
,
},
},
areaStyle
:
{
color
:
gradientColor
,
opacity
:
0.8
,
},
data
:
item
?.
map
?.((
it
)
=>
it
.
value
)
??
[],
},
],
};
setoption
(
options
);
},
[
item
]);
return
(
<
div
style=
{
{
borderRadius
:
12
,
height
:
180
,
}
}
>
<
Skeleton
loading=
{
loading
}
active
>
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
'100%'
}
}
/>
</
Skeleton
>
</
div
>
);
};
const
Mtbf
=
({
item
,
loading
})
=>
{
const
[
option
,
setoption
]
=
useState
({});
useAsyncEffect
(
async
()
=>
{
const
options
=
{
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'line'
,
lineStyle
:
{
color
:
'#999999'
,
},
},
backgroundColor
:
'rgba(255,255,255,0.7)'
,
textStyle
:
{
color
:
'#333333'
,
fontSize
:
12
,
},
padding
:
[
8
,
12
],
},
grid
:
{
top
:
10
,
bottom
:
20
,
left
:
40
,
right
:
10
,
},
xAxis
:
{
show
:
false
,
data
:
item
?.
map
?.((
it
)
=>
it
.
name
)
??
[],
},
yAxis
:
{
type
:
'value'
,
axisLine
:
{
show
:
false
,
},
axisTick
:
{
show
:
false
,
},
splitLine
:
{
lineStyle
:
{
type
:
'dashed'
,
color
:
[
'rgba(255,255,255,0.1)'
],
},
},
axisLabel
:
{
color
:
'#fff'
,
fontSize
:
12
,
formatter
:
'{value}'
,
},
},
series
:
[
{
name
:
'MTBF'
,
type
:
'line'
,
smooth
:
true
,
symbol
:
'circle'
,
symbolSize
:
0
,
lineStyle
:
{
normal
:
{
width
:
2
,
color
:
'#3f98f6'
,
},
},
areaStyle
:
{
color
:
gradientColors
,
opacity
:
0.8
,
},
data
:
item
?.
map
?.((
it
)
=>
it
.
value
)
??
[],
},
],
};
setoption
(
options
);
},
[
item
]);
return
(
<
div
style=
{
{
borderRadius
:
12
,
height
:
180
,
}
}
>
<
Skeleton
loading=
{
loading
}
active
>
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
'100%'
}
}
/>
</
Skeleton
>
</
div
>
);
};
const
DeviceIdAlarmList
=
({
item
,
loading
})
=>
{
const
[
option
,
setoption
]
=
useState
({});
useAsyncEffect
(
async
()
=>
{
const
options
=
{
tooltip
:
{
trigger
:
'axis'
,
axisPointer
:
{
type
:
'line'
,
lineStyle
:
{
color
:
'#999999'
,
},
},
backgroundColor
:
'rgba(255,255,255,0.7)'
,
textStyle
:
{
color
:
'#333333'
,
fontSize
:
12
,
},
padding
:
[
8
,
12
],
},
grid
:
{
top
:
10
,
bottom
:
20
,
left
:
40
,
right
:
10
,
},
xAxis
:
{
show
:
false
,
data
:
item
?.
map
?.((
it
)
=>
it
.
label
)
??
[],
},
yAxis
:
{
type
:
'value'
,
axisLine
:
{
show
:
false
,
},
axisTick
:
{
show
:
false
,
},
splitLine
:
{
lineStyle
:
{
type
:
'dashed'
,
color
:
[
'rgba(255,255,255,0.1)'
],
},
},
axisLabel
:
{
color
:
'#fff'
,
fontSize
:
12
,
formatter
:
'{value}'
,
},
},
series
:
[
{
name
:
'告警统计分析'
,
type
:
'bar'
,
itemStyle
:
{
borderRadius
:
[
50
,
50
,
0
,
0
],
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
'rgba(130,186,254,1)'
},
{
offset
:
1
,
color
:
'rgba(130,186,254,0.2)'
},
]),
},
data
:
item
?.
map
?.((
it
)
=>
it
.
value
)
??
[],
},
],
};
setoption
(
options
);
},
[
item
]);
return
(
<
div
style=
{
{
borderRadius
:
12
,
height
:
180
,
}
}
>
<
Skeleton
loading=
{
loading
}
active
>
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
'100%'
}
}
/>
</
Skeleton
>
</
div
>
);
};
function
Detail
(
props
)
{
const
actionRef
=
useRef
();
const
location
=
useLocation
();
const
{
id
,
deviceId
}
=
location
.
state
;
const
{
run
,
loading
}
=
useRequest
(
doFetch
,
{
manual
:
true
,
onSuccess
:
(
res
,
params
)
=>
{
if
(
res
?.
code
===
'0000'
)
{
actionRef
?.
current
?.
reload
();
}
},
});
const
columns
=
useMemo
(()
=>
{
let
defcolumn
=
getcolumns
()?.
columns
;
return
defcolumn
;
},
[]);
const
info
=
useRequest
(
async
()
=>
{
let
res
=
await
doFetch
({
url
:
'/app/device/info'
,
params
:
{
deviceId
},
});
return
res
?.
data
?.
data
;
},
{
debounceWait
:
300
,
},
);
const
kai
=
useRequest
(
async
()
=>
{
let
res
=
await
doFetch
({
url
:
'/app/device/onLineRate'
,
params
:
{
deviceId
},
});
return
res
?.
data
?.
data
??
[];
},
{
debounceWait
:
300
,
},
);
const
mttr
=
useRequest
(
async
()
=>
{
let
res
=
await
doFetch
({
url
:
'/app/device/mttr'
,
params
:
{
deviceId
},
});
return
res
?.
data
?.
dataList
??
[];
},
{
debounceWait
:
300
,
},
);
const
mtbf
=
useRequest
(
async
()
=>
{
let
res
=
await
doFetch
({
url
:
'/app/device/mtbf'
,
params
:
{
deviceId
},
});
return
res
?.
data
?.
dataList
??
[];
},
{
debounceWait
:
300
,
},
);
const
deviceIdAlarmList
=
useRequest
(
async
()
=>
{
let
res
=
await
doFetch
({
url
:
'/app/device/deviceIdAlarmList'
,
params
:
{
deviceId
},
});
return
res
?.
data
?.
dataList
??
[];
},
{
debounceWait
:
300
,
},
);
const
datalist
=
useRequest
(
async
()
=>
{
let
res
=
await
doFetch
({
url
:
'/app/device/timeseries'
,
params
:
{
deviceId
},
});
return
res
?.
data
?.
dataList
??
[];
},
{
debounceWait
:
300
,
},
);
const
anchors
=
[
70
,
window
.
innerHeight
*
0.4
,
window
.
innerHeight
-
230
];
return
(
<
div
style=
{
{
position
:
'relative'
}
}
>
<
Cards
item=
{
info
?.
data
??
{}
}
columns=
{
columns
}
loading=
{
info
?.
loading
}
/>
<
div
style=
{
{
padding
:
'0 12px'
}
}
>
<
h3
>
时间开动率
</
h3
>
<
Kai
item=
{
kai
?.
data
??
{}
}
loading=
{
kai
?.
loading
}
/>
<
h3
>
MTTR
</
h3
>
<
Mttr
item=
{
mttr
?.
data
??
{}
}
loading=
{
mttr
?.
loading
}
/>
<
h3
>
MTBF
</
h3
>
<
Mtbf
item=
{
mtbf
?.
data
??
{}
}
loading=
{
mtbf
?.
loading
}
/>
<
h3
>
告警统计分析
</
h3
>
<
DeviceIdAlarmList
item=
{
deviceIdAlarmList
?.
data
??
{}
}
loading=
{
deviceIdAlarmList
?.
loading
}
/>
</
div
>
<
FloatingPanel
anchors=
{
anchors
}
>
<
div
style=
{
{
padding
:
12
}
}
>
<
Row
style=
{
{
position
:
"absolute"
,
width
:
"calc(100% - 24px)"
,
top
:
20
,
backgroundColor
:
"#546e84"
,
left
:
12
,
zIndex
:
9999
,
padding
:
"12px 0"
}
}
>
<
Col
span=
{
24
}
style=
{
{
paddingLeft
:
12
,
alignItems
:
"baseline"
}
}
className=
"spread"
>
<
h3
style=
{
{
marginTop
:
0
}
}
>
实时数据
</
h3
>
<
b
>
共
{
datalist
?.
data
?.
length
}
条
</
b
>
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
}
}
>
参数
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
}
}
>
数据
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
}
}
>
时间
</
Col
>
</
Row
>
<
div
style=
{
{
paddingTop
:
68
}
}
>
{
datalist
?.
data
?.
map
?.((
it
,
i
)
=>
{
return
(
<
Row
key=
{
it
?.
id
}
style=
{
{
padding
:
'8px 0'
,
backgroundColor
:
'rgba(0,0,0,0.1)'
,
marginTop
:
2
,
borderRadius
:
8
,
}
}
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
,
wordBreak
:
'break-all'
}
}
>
{
it
?.
key
}
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
,
wordBreak
:
'break-all'
}
}
>
{
it
?.
value
}
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
,
wordBreak
:
'break-all'
}
}
>
{
it
?.
time
}
</
Col
>
</
Row
>
);
})
}
</
div
>
</
div
>
</
FloatingPanel
>
</
div
>
);
}
export
default
Detail
;
src/pages/alarm/index.jsx
0 → 100644
View file @
5e47b27f
/* eslint-disable eqeqeq */
import
*
as
React
from
'react'
;
import
{
useState
,
useMemo
,
useRef
}
from
'react'
;
import
DrawerPro
from
'@/components/DrawerPro'
;
import
AutoTable
from
'@/components/AutoTable'
;
import
{
Badge
,
Skeleton
}
from
'antd'
;
import
getcolumns
from
'./columns'
;
import
{
useAsyncEffect
,
useRequest
}
from
'ahooks'
;
import
{
doFetch
}
from
'@/utils/doFetch'
;
import
ReactECharts
from
'echarts-for-react'
;
import
Settings
from
'../../../config/defaultSettings'
;
import
{
history
}
from
'@umijs/max'
;
const
{
proxypath
}
=
Settings
;
function
cropImage
(
url
)
{
return
new
Promise
((
resolve
)
=>
{
const
img
=
new
Image
();
img
.
crossOrigin
=
'Anonymous'
;
img
.
src
=
url
;
img
.
onload
=
()
=>
{
const
canvas
=
document
.
createElement
(
'canvas'
);
const
ctx
=
canvas
.
getContext
(
'2d'
);
const
size
=
Math
.
min
(
img
.
width
,
img
.
height
);
canvas
.
width
=
size
;
canvas
.
height
=
size
;
ctx
.
beginPath
();
ctx
.
arc
(
size
/
2
,
size
/
2
,
size
/
2
,
0
,
2
*
Math
.
PI
);
ctx
.
clip
();
ctx
.
drawImage
(
img
,
(
img
.
width
-
size
)
/
2
,
(
img
.
height
-
size
)
/
2
,
size
,
size
,
0
,
0
,
size
,
size
,
);
canvas
.
toBlob
((
blob
)
=>
{
const
reader
=
new
FileReader
();
reader
.
readAsDataURL
(
blob
);
reader
.
onloadend
=
()
=>
{
resolve
(
reader
.
result
);
};
},
'image/png'
);
};
});
}
const
Cards
=
({
item
,
columns
})
=>
{
const
[
option
,
setoption
]
=
useState
({});
const
{
statusColorList
,
deviceStatusDurationList
}
=
item
;
const
[
loading
,
setloading
]
=
useState
(
false
);
useAsyncEffect
(
async
()
=>
{
setloading
(
true
)
let
img
=
item
?.
image
?.
length
>
0
?
proxypath
+
item
.
image
?.[
0
]?.
url
:
require
(
'@/assets/default.png'
);
const
image
=
await
cropImage
(
img
);
let
normalColor
=
statusColorList
.
filter
((
el
)
=>
el
.
type
==
3
)?.[
0
]?.
color
??
''
;
let
data
=
deviceStatusDurationList
?.
map
((
it
)
=>
{
let
label
=
statusColorList
.
filter
((
el
)
=>
el
.
type
==
it
.
name
)?.[
0
]?.
name
??
''
,
itemColor
=
statusColorList
.
filter
((
el
)
=>
el
.
type
==
it
.
name
)?.[
0
]?.
color
??
''
;
return
{
...
it
,
label
,
itemStyle
:
{
color
:
itemColor
,
},
};
})
??
[
{
name
:
'关机'
,
value
:
1
,
itemStyle
:
{
color
:
normalColor
,
},
},
];
const
options
=
{
series
:
[
{
type
:
'pie'
,
radius
:
[
'85%'
,
'95%'
],
avoidLabelOverlap
:
false
,
label
:
{
show
:
false
,
position
:
'center'
,
},
data
,
},
],
graphic
:
{
elements
:
[
{
type
:
'image'
,
style
:
{
image
:
image
,
width
:
88
,
height
:
88
,
},
left
:
'center'
,
top
:
'center'
,
},
],
},
};
await
setoption
(
options
);
setloading
(
false
)
},
[
item
]);
return
(
<
div
className=
"split"
onClick=
{
()
=>
{
history
.
push
(
'/home/detail'
,
{
id
:
item
.
id
,
deviceId
:
item
.
deviceId
});
}
}
style=
{
{
minHeight
:
169
}
}
>
<
Skeleton
loading=
{
loading
}
active
>
<
div
className=
"spread"
style=
{
{
justifyContent
:
'flex-start'
}
}
>
<
Badge
count=
{
item
.
alarmNum
}
overflowCount=
{
99
}
offset=
{
[
-
10
,
10
]
}
color=
"red"
>
<
div
style=
{
{
width
:
120
,
height
:
120
,
flexShrink
:
0
}
}
>
<
ReactECharts
option=
{
option
}
style=
{
{
height
:
'100%'
}
}
/>
</
div
>
</
Badge
>
<
div
style=
{
{
flex
:
1
}
}
className=
"rightsection"
>
{
columns
?.
filter
((
it
)
=>
!
(
it
.
valueType
===
'split'
||
it
?.
hideInTable
))
?.
map
((
it
,
i
)
=>
{
const
Bod
=
({
children
})
=>
i
==
0
?
(
<
h2
>
{
children
}
</
h2
>
)
:
i
==
1
?
(
<
h3
>
{
children
}
</
h3
>
)
:
(
<
p
>
{
children
}
</
p
>
);
return
(
<
Bod
key=
{
it
?.
dataIndex
}
>
{
it
?.
hidetitle
?
''
:
`${it?.title}: `
}
{
it
.
render
?
it
.
render
(
item
[
it
?.
dataIndex
],
item
)
:
item
[
it
?.
dataIndex
]
}
</
Bod
>
);
})
}
</
div
>
</
div
>
</
Skeleton
>
</
div
>
);
};
function
Home
(
props
)
{
const
actionRef
=
useRef
();
const
{
run
,
loading
}
=
useRequest
(
doFetch
,
{
manual
:
true
,
onSuccess
:
(
res
,
params
)
=>
{
if
(
res
?.
code
===
'0000'
)
{
actionRef
?.
current
?.
reload
();
}
},
});
const
columns
=
useMemo
(()
=>
{
let
defcolumn
=
getcolumns
()?.
columns
;
return
defcolumn
;
},
[]);
return
(
<
div
style=
{
{
position
:
'relative'
}
}
>
<
AutoTable
columns=
{
columns
}
path=
{
'/app/device/index'
}
actionRef=
{
actionRef
}
>
<
Cards
/>
</
AutoTable
>
</
div
>
);
}
export
default
Home
;
src/pages/home/detail.jsx
View file @
5e47b27f
...
...
@@ -3,7 +3,7 @@ import * as React from 'react';
import
{
useState
,
useMemo
,
useRef
}
from
'react'
;
import
DrawerPro
from
'@/components/DrawerPro'
;
import
AutoTable
from
'@/components/AutoTable'
;
import
{
Badge
,
Skeleton
}
from
'antd'
;
import
{
Badge
,
Skeleton
,
Row
,
Col
}
from
'antd'
;
import
getcolumns
from
'./columns'
;
import
{
useAsyncEffect
,
useRequest
}
from
'ahooks'
;
import
{
doFetch
}
from
'@/utils/doFetch'
;
...
...
@@ -11,7 +11,7 @@ import ReactECharts from 'echarts-for-react';
import
*
as
echarts
from
'echarts'
;
import
Settings
from
'../../../config/defaultSettings'
;
import
{
useLocation
}
from
'@umijs/max'
;
import
{
FloatingPanel
,
List
}
from
'antd-mobile'
import
{
FloatingPanel
,
List
}
from
'antd-mobile'
;
const
{
proxypath
}
=
Settings
;
...
...
@@ -491,13 +491,10 @@ const DeviceIdAlarmList = ({ item, loading }) => {
type
:
'bar'
,
itemStyle
:
{
borderRadius
:
[
50
,
50
,
0
,
0
],
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
'rgba(130,186,254,1)'
},
{
offset
:
1
,
color
:
'rgba(130,186,254,0.2)'
}
]
)
color
:
new
echarts
.
graphic
.
LinearGradient
(
0
,
0
,
0
,
1
,
[
{
offset
:
0
,
color
:
'rgba(130,186,254,1)'
},
{
offset
:
1
,
color
:
'rgba(130,186,254,0.2)'
},
]),
},
data
:
item
?.
map
?.((
it
)
=>
it
.
value
)
??
[],
},
...
...
@@ -520,7 +517,6 @@ const DeviceIdAlarmList = ({ item, loading }) => {
);
};
function
Detail
(
props
)
{
const
actionRef
=
useRef
();
const
location
=
useLocation
();
...
...
@@ -616,9 +612,9 @@ function Detail(props) {
{
debounceWait
:
300
,
},
);
);
const
anchors
=
[
100
,
window
.
innerHeight
*
0.4
,
window
.
innerHeight
*
0.8
]
const
anchors
=
[
70
,
window
.
innerHeight
*
0.4
,
window
.
innerHeight
-
230
];
return
(
<
div
style=
{
{
position
:
'relative'
}
}
>
...
...
@@ -635,20 +631,79 @@ function Detail(props) {
<
h3
>
MTBF
</
h3
>
<
Mtbf
item=
{
mtbf
?.
data
??
{}
}
loading=
{
mtbf
?.
loading
}
/>
<
h3
>
告警统计分析
</
h3
>
<
DeviceIdAlarmList
item=
{
deviceIdAlarmList
?.
data
??
{}
}
loading=
{
deviceIdAlarmList
?.
loading
}
/>
<
DeviceIdAlarmList
item=
{
deviceIdAlarmList
?.
data
??
{}
}
loading=
{
deviceIdAlarmList
?.
loading
}
/>
</
div
>
<
FloatingPanel
anchors=
{
anchors
}
>
{
datalist
?.
data
?.
map
?.((
it
,
i
)
=>
{
return
<
div
key=
{
it
?.
id
}
>
{}
</
div
>
})
}
<
div
style=
{
{
padding
:
12
}
}
>
<
Row
style=
{
{
position
:
"absolute"
,
width
:
"calc(100% - 24px)"
,
top
:
20
,
backgroundColor
:
"#546e84"
,
left
:
12
,
zIndex
:
9999
,
padding
:
"12px 0"
}
}
>
<
Col
span=
{
24
}
style=
{
{
paddingLeft
:
12
,
alignItems
:
"baseline"
}
}
className=
"spread"
>
<
h3
style=
{
{
marginTop
:
0
}
}
>
实时数据
</
h3
>
<
b
>
共
{
datalist
?.
data
?.
length
}
条
</
b
>
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
}
}
>
参数
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
}
}
>
数据
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
}
}
>
时间
</
Col
>
</
Row
>
<
div
style=
{
{
paddingTop
:
68
}
}
>
{
datalist
?.
data
?.
map
?.((
it
,
i
)
=>
{
return
(
<
Row
key=
{
it
?.
id
}
style=
{
{
padding
:
'8px 0'
,
backgroundColor
:
'rgba(0,0,0,0.1)'
,
marginTop
:
2
,
borderRadius
:
8
,
}
}
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
,
wordBreak
:
'break-all'
}
}
>
{
it
?.
key
}
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
,
wordBreak
:
'break-all'
}
}
>
{
it
?.
value
}
</
Col
>
<
Col
span=
{
8
}
style=
{
{
paddingLeft
:
12
,
wordBreak
:
'break-all'
}
}
>
{
it
?.
time
}
</
Col
>
</
Row
>
);
})
}
</
div
>
</
div
>
</
FloatingPanel
>
</
div
>
);
...
...
src/pages/login/index.jsx
View file @
5e47b27f
...
...
@@ -56,6 +56,10 @@ export default () => {
history
.
push
(
'/'
);
});
}
}
initialValues=
{
{
username
:
"root"
,
password
:
"Nangao@2022"
}
}
>
{
loginType
===
'account'
&&
(
<>
...
...
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