Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
V
V3-TailingPond
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
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
xinzhedeai
V3-TailingPond
Commits
83aacf1b
Commit
83aacf1b
authored
Oct 17, 2025
by
xinzhedeai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add: 新华 剖面 update from liqilin
parent
5afb27b3
Changes
15
Show whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
3952 additions
and
1118 deletions
+3952
-1118
.env.development
.env.development
+8
-0
.gitignore
.gitignore
+0
-1
index.html
public/model/index.html
+319
-321
init.js
public/model/init.js
+19
-20
shan.png
src/assets/images/jrx/shan.png
+0
-0
shui.png
src/assets/images/jrx/shui.png
+0
-0
index.vue
src/components/CenterViews/index.vue
+531
-235
index.vue
src/components/TableFilter/index.vue
+72
-66
request.js
src/utils/request.js
+15
-17
index.vue
src/views/Screen/index.vue
+125
-86
index copy.vue
src/views/dataMonitor/jrx/history/index copy.vue
+99
-146
index-剖面-old.vue
src/views/dataMonitor/jrx/history/index-剖面-old.vue
+958
-0
index.vue
src/views/dataMonitor/jrx/history/index.vue
+714
-222
index1.vue
src/views/dataMonitor/jrx/history/index1.vue
+1088
-0
vue.config.js
vue.config.js
+4
-4
No files found.
.env.development
0 → 100644
View file @
83aacf1b
ENV = 'development'
# 开发服务器端口配置
VUE_APP_LOCAL_PORT = 8080
VUE_APP_BASE_API = 'http://192.168.2.11:8080'
VUE_APP_LOCAL_API = 'http://192.168.2.37:9003'
\ No newline at end of file
.gitignore
View file @
83aacf1b
...
...
@@ -19,7 +19,6 @@ selenium-debug.log
*.njsproj
*.sln
*.local
*.env.development
*dist.rar
package-lock.json
...
...
public/model/index.html
View file @
83aacf1b
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<head>
<meta
charset=
"UTF-8"
/>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
/>
<!-- Cesium
1. CSS
2. JS
-->
<link
rel=
"stylesheet"
type=
"text/css"
href=
"./Cesium/Widgets/widgets.css"
/>
<link
rel=
"stylesheet"
type=
"text/css"
href=
"./Cesium/Widgets/widgets.css"
/>
<script
type=
"text/javascript"
src=
"./Cesium/Cesium.js"
></script>
<script
src=
"https://cdnjs.cloudflare.com/ajax/libs/proj4js/2.7.2/proj4.js"
></script>
...
...
@@ -194,14 +191,14 @@
border-radius
:
3px
;
}
.search_box
>
div
{
.search_box
>
div
{
display
:
flex
;
justify-content
:
start
;
color
:
#fff
;
align-items
:
center
;
}
.search_box
>
div
>
span
{
.search_box
>
div
>
span
{
display
:
flex
;
justify-content
:
start
;
margin
:
0
10px
;
...
...
@@ -234,9 +231,9 @@
display
:
none
!important
;
}
</style>
</head>
</head>
<body>
<body>
<div
id=
"cesiumcontainer"
>
<div></div>
</div>
...
...
@@ -332,5 +329,6 @@
}
})();
</script>
</body>
</body>
</html>
\ No newline at end of file
public/model/init.js
View file @
83aacf1b
...
...
@@ -367,8 +367,7 @@ const initCesiumpolyline = (
text
:
` 平距 :
${
distance
.
value
}
\n 空间距离 :
${
Math
.
sqrt
(
distance
.
value
*
distance
.
value
+
elevationDifference
.
value
*
elevationDifference
.
value
)}
\n 高差 :
${
elevationDifference
.
value
}
(米)\n 坡度 :
${
slopeDegrees
.
value
)}
\n 高差 :
${
elevationDifference
.
value
}
(米)\n 坡度 :
${
slopeDegrees
.
value
}
`
,
fillColor
:
Cesium
.
Color
.
GREEN
,
};
...
...
src/assets/images/jrx/shan.png
0 → 100644
View file @
83aacf1b
379 KB
src/assets/images/jrx/shui.png
0 → 100644
View file @
83aacf1b
278 KB
src/components/CenterViews/index.vue
View file @
83aacf1b
<!--
/**
* 表单通用组件
...
...
@@ -21,23 +20,26 @@
<
template
>
<div
class=
"center-flx"
>
<nav
v-if=
"list.length > 1"
>
<a
v-for=
"(child, i) in list"
:class=
"
{'actv': viewActive === i}" @click="navEvent(i, child.type)">
{{
child
.
sumtitle
}}
</a>
<a
v-for=
"(child, i) in list"
:class=
"
{ 'actv': viewActive === i }" @click="navEvent(i, child.type)">
{{
child
.
sumtitle
}}
</a>
</nav>
<div
class=
"b2a2_a"
id=
"agentFigure"
>
<div
class=
"list-wrap"
v-for=
"(child, i) in list"
:class=
"
{'show':viewActive === i
}">
<div
class=
"b2a2_a1"
v-if=
"child.type === 't_15'"
>
<div
class=
"list-wrap"
v-for=
"(child, i) in list"
:class=
"
{ 'show': viewActive === i
}">
<div
class=
"b2a2_a1"
v-if=
"child.type === 't_15'"
>
<div
id=
"figure"
class=
"figure"
>
<div
class=
"img-box"
id=
"pictureArea"
>
<img
id=
"drawingImg"
>
</div>
<div
id=
"pointsLayer"
class=
"cview_ctn wkk-ctn"
:data-index=
"i"
:class=
"child.className"
:data-item=
"JSON.stringify(child)"
:id=
"child.id"
>
<div
id=
"pointsLayer"
class=
"cview_ctn wkk-ctn"
:data-index=
"i"
:class=
"child.className"
:data-item=
"JSON.stringify(child)"
:id=
"child.id"
>
<ul></ul>
</div>
</div>
</div>
<div
v-else
>
<div
class=
"cview_ctn ctn-absfull"
:data-index=
"i"
:class=
"child.className"
:data-item=
"JSON.stringify(child)"
:id=
"child.id"
>
<EZUIKitJs
ref=
"EZUIKit"
selectSeat=
"none"
autoPlayer=
"false"
/>
<div
class=
"cview_ctn ctn-absfull"
:data-index=
"i"
:class=
"child.className"
:data-item=
"JSON.stringify(child)"
:id=
"child.id"
>
<EZUIKitJs
ref=
"EZUIKit"
selectSeat=
"none"
autoPlayer=
"false"
/>
</div>
</div>
</div>
...
...
@@ -53,34 +55,34 @@ export default {
components
:
{
EZUIKitJs
},
data
()
{
return
{
list
:
[],
Cache
:
{
list
:
[],
Cache
:
{
},
config
:
{
config
:
{
},
amapinfo
:
{
zoom
:
6
,
amapinfo
:
{
zoom
:
6
,
//longitude: 120.651884,
//latitude: 36.962533,
},
viewActive
:
0
,
viewActive
:
0
,
/* gis:{
isShow:0,
}, */
}
},
props
:
{
props
:
{
},
beforeCreate
()
{
beforeCreate
()
{
},
created
()
{
created
()
{
},
mounted
()
{
},
methods
:
{
createViews
(
item
)
{
createViews
(
item
)
{
var
that
=
this
;
this
.
list
=
item
.
children
;
this
.
config
.
interval
=
item
.
interval
;
this
.
list
=
item
.
children
;
this
.
config
.
interval
=
item
.
interval
;
var
carouselCtn
=
this
.
$el
.
firstElementChild
;
return
new
Promise
((
resolve
,
reject
)
=>
{
this
.
$nextTick
(()
=>
{
...
...
@@ -90,25 +92,25 @@ export default {
});
})
},
setAttribute
(
charts
)
{
setAttribute
(
charts
)
{
var
panelList
=
[];
for
(
var
el
of
charts
)
{
for
(
var
el
of
charts
)
{
var
item
=
JSON
.
parse
(
el
.
dataset
.
item
),
type
=
item
.
type
;
var
setData
=
type
===
'
t_15
'
?
this
.
showPointView
:
this
.
setPlayInfo
;
panelList
.
push
({
info
:
this
.
Cache
[
type
],
el
:
el
,
item
:
item
,
type
:
type
,
setData
:
setData
});
panelList
.
push
({
info
:
this
.
Cache
[
type
],
el
:
el
,
item
:
item
,
type
:
type
,
setData
:
setData
});
};
return
panelList
;
},
showPointView
(
data
,
Tools
,
pageApi
,
initModule
)
{
showPointView
(
data
,
Tools
,
pageApi
,
initModule
)
{
var
that
=
this
;
var
agentFigure
=
this
.
$el
.
querySelector
(
"
#agentFigure
"
);
this
.
mapWidget
=
new
qf
.
UI
.
pointCharts
({
chartsBox
:
this
.
$el
.
querySelector
(
"
#figure
"
),
width
:
agentFigure
.
offsetWidth
,
height
:
agentFigure
.
offsetHeight
,
isRelieveAlarm
:
true
,
itemClick
:
function
(
id
)
{
var
params
=
{
equipno
:
id
};
that
.
$parent
.
openRelieveAlarm
(
params
,
function
()
{
chartsBox
:
this
.
$el
.
querySelector
(
"
#figure
"
),
width
:
agentFigure
.
offsetWidth
,
height
:
agentFigure
.
offsetHeight
,
isRelieveAlarm
:
true
,
itemClick
:
function
(
id
)
{
var
params
=
{
equipno
:
id
};
that
.
$parent
.
openRelieveAlarm
(
params
,
function
()
{
initModule
()
});
},
...
...
@@ -116,48 +118,93 @@ export default {
this
.
mapWidget
.
setBackground
(
data
.
chart
.
picture
);
this
.
mapWidget
.
createPoints
(
data
.
points
,
data
.
chart
);
},
setPlayInfo
(
param
)
{
setPlayInfo
(
param
)
{
var
EZUIKit
=
this
.
$refs
.
EZUIKit
[
0
];
EZUIKit
.
playerToParam
(
param
);
},
navEvent
(
id
,
key
)
{
navEvent
(
id
,
key
)
{
this
.
viewActive
=
~~
id
;
},
},
}
</
script
>
<
style
lang=
"scss"
scope
>
.center-flx
{
height
:
100%
;
width
:
100%
;
display
:flex
;
flex-direction
:column
;
padding
:
.12rem
0
.12rem
0
.12rem
;
.center-flx
{
height
:
100%
;
width
:
100%
;
display
:
flex
;
flex-direction
:
column
;
padding
:
.12rem
0
.12rem
0
.12rem
;
/* padding:0 0.08rem 0.08rem; */
nav
{
height
:
.26rem
;
text-align
:center
;
color
:
#89B7C6
;
font-size
:
0
;
user-select
:none
;
margin-top
:
-0
.12rem
;
a
{
display
:inline-block
;
font-size
:
.15rem
;
line-height
:
.22rem
;
padding
:
0
.10rem
;
cursor
:pointer
;
border-radius
:
.05rem
.05rem
0
0
;
nav
{
height
:
.26rem
;
text-align
:
center
;
color
:
#89B7C6
;
font-size
:
0
;
user-select
:
none
;
margin-top
:
-0
.12rem
;
a
{
display
:
inline-block
;
font-size
:
.15rem
;
line-height
:
.22rem
;
padding
:
0
.10rem
;
cursor
:
pointer
;
border-radius
:
.05rem
.05rem
0
0
;
}
.actv
{
color
:
#0CE2CE
;
background-color
:
#2271C6
;};
.actv
{
color
:
#0CE2CE
;
background-color
:
#2271C6
;
}
.b2a2_a1
{
height
:
100%
;
width
:
100%
;
position
:relative
;
>
div
{
;
}
.b2a2_a1
{
height
:
100%
;
width
:
100%
;
position
:
relative
;
>
div
{
/* display:none; */
}
>
div
.show
{
display
:block
;}
>
div
:first-child
{}
>
div
:last-child
{}
.figure
{
position
:relative
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
user-select
:none
;
font-family
:serif
;
color
:
#444
;
>
div
.show
{
display
:
block
;
}
>
div
:first-child
{}
>
div
:last-child
{}
.figure
{
position
:
relative
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
user-select
:
none
;
font-family
:
serif
;
color
:
#444
;
}
.figure
{
.img-box
{
position
:
absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
z-index
:
10
;
img
{
display
:
block
;
border
:
0
;
max-height
:
100%
;
max-width
:
100%
;
}
.figure
{
.img-box
{
position
:absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
z-index
:
10
;
img
{
display
:block
;
border
:
0
;
max-height
:
100%
;
max-width
:
100%
;}
&
:before
{
position
:
absolute
;
...
...
@@ -166,96 +213,345 @@ export default {
height
:
100%
;
top
:
0
;
left
:
0
;
box-shadow
:
inset
0rem
0rem
0
.55rem
0
.20rem
rgba
(
0
,
31
,
60
,
.8
);
}
}
.wkk-ctn
{
position
:absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
z-index
:
20
;
}
}
.figure
.wkk-ctn
{
position
:absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;}
.figure
.wkk-ctn
li
{
position
:absolute
;}
.
figure
.
wkk-ctn
li
:
:
marker
{
content
:close-quote
;}
.figure
.wkk-ctn
li
i
{
position
:absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
background-repeat
:no-repeat
;
background-position
:center
bottom
;
background-size
:contain
;
}
.figure
.wkk-ctn
li
.d_01
i
{
background-image
:url
(
'~@/assets/images/icon/d_01.png'
)
;}
.figure
.wkk-ctn
li
.d_02
i
{
background-image
:url
(
'~@/assets/images/icon/d_02.png'
)
;}
.figure
.wkk-ctn
li
.d_03
i
{
background-image
:url
(
'~@/assets/images/icon/d_03.png'
)
;}
.figure
.wkk-ctn
li
.d_04
i
{
background-image
:url
(
'~@/assets/images/icon/d_04.png'
)
;}
.figure
.wkk-ctn
li
.d_05
i
{
background-image
:url
(
'~@/assets/images/icon/d_05.png'
)
;}
.figure
.wkk-ctn
li
.d_06
i
{
background-image
:url
(
'~@/assets/images/icon/d_06.png'
)
;}
.figure
.wkk-ctn
li
.d_07
i
{
background-image
:url
(
'~@/assets/images/icon/d_07.png'
)
;}
.figure
.wkk-ctn
li
.d_08
i
{
background-image
:url
(
'~@/assets/images/icon/d_08.png'
)
;}
.figure
.wkk-ctn
li
>
div
{
position
:absolute
;
display
:flex
;
align-items
:center
;
justify-content
:center
;}
.figure
.wkk-ctn
li
>
div
.text
{
position
:absolute
;
padding
:
0
.0402rem
;
background-color
:
#fff
;
border-radius
:
0
.0643rem
;
line-height
:
1
.2
;
color
:
#1A688C
;
font-weight
:bold
;
z-index
:
1
;}
.figure
.wkk-ctn
.text
h4
{
text-align
:center
;
color
:
#1284b3
;
font-weight
:normal
;}
.figure
.wkk-ctn
.text
dd
{
display
:block
;
line-height
:normal
;
margin-top
:
3px
;}
.figure
.wkk-ctn
.text
dd
:before
{
font-size
:
15px
;
margin-right
:
3px
;}
.figure
.wkk-ctn
.text
.normal
:before
{
font-size
:
13px
;
margin-right
:
1px
;}
.figure
.wkk-ctn
.text
.red
{
background-color
:red
;
color
:
#fff
;}
.figure
.wkk-ctn
.text
.orange
{
background-color
:orange
;
color
:
#fff
;}
.figure
.wkk-ctn
.text
.yellow
{
background-color
:
#e8cb08
;
color
:
#fff
;}
.figure
.wkk-ctn
.text
.blue
{
background-color
:
#0991FF
;
color
:
#fff
;}
.figure
.wkk-ctn
.text
.relieve
{
cursor
:pointer
;}
.figure
.wkk-ctn
.text
.offline
{
color
:
#aaa
;}
.figure
.wkk-ctn
.text
.online
{
color
:
#000
;}
box-shadow
:
inset
0rem
0rem
0
.55rem
0
.20rem
rgba
(
0
,
31
,
60
,
.8
);
}
}
.wkk-ctn
{
position
:
absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
z-index
:
20
;
}
}
.figure
.wkk-ctn
{
position
:
absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
}
.figure
.wkk-ctn
li
{
position
:
absolute
;
}
.
figure
.
wkk-ctn
li
:
:
marker
{
content
:
close-quote
;
}
.figure
.wkk-ctn
li
i
{
position
:
absolute
;
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
background-repeat
:
no-repeat
;
background-position
:
center
bottom
;
background-size
:
contain
;
}
.figure
.wkk-ctn
li
.d_01
i
{
background-image
:
url('~@/assets/images/icon/d_01.png')
;
}
.figure
.wkk-ctn
li
.d_02
i
{
background-image
:
url('~@/assets/images/icon/d_02.png')
;
}
.figure
.wkk-ctn
li
.d_03
i
{
background-image
:
url('~@/assets/images/icon/d_03.png')
;
}
.figure
.wkk-ctn
li
.d_04
i
{
background-image
:
url('~@/assets/images/icon/d_04.png')
;
}
.figure
.wkk-ctn
li
.d_05
i
{
background-image
:
url('~@/assets/images/icon/d_05.png')
;
}
.figure
.wkk-ctn
li
.d_06
i
{
background-image
:
url('~@/assets/images/icon/d_06.png')
;
}
.figure
.wkk-ctn
li
.d_07
i
{
background-image
:
url('~@/assets/images/icon/d_07.png')
;
}
.figure
.wkk-ctn
li
.d_08
i
{
background-image
:
url('~@/assets/images/icon/d_08.png')
;
}
.figure
.wkk-ctn
li
>
div
{
position
:
absolute
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
}
.figure
.wkk-ctn
li
>
div
.text
{
position
:
absolute
;
padding
:
0
.0402rem
;
background-color
:
#fff
;
border-radius
:
0
.0643rem
;
line-height
:
1
.2
;
color
:
#1A688C
;
font-weight
:
bold
;
z-index
:
1
;
}
.figure
.wkk-ctn
.text
h4
{
text-align
:
center
;
color
:
#1284b3
;
font-weight
:
normal
;
}
.figure
.wkk-ctn
.text
dd
{
display
:
block
;
line-height
:
normal
;
margin-top
:
3px
;
}
.figure
.wkk-ctn
.text
dd
:before
{
font-size
:
15px
;
margin-right
:
3px
;
}
.figure
.wkk-ctn
.text
.normal
:before
{
font-size
:
13px
;
margin-right
:
1px
;
}
.figure
.wkk-ctn
.text
.red
{
background-color
:
red
;
color
:
#fff
;
}
.figure
.wkk-ctn
.text
.orange
{
background-color
:
orange
;
color
:
#fff
;
}
.figure
.wkk-ctn
.text
.yellow
{
background-color
:
#e8cb08
;
color
:
#fff
;
}
.figure
.wkk-ctn
.text
.blue
{
background-color
:
#0991FF
;
color
:
#fff
;
}
.figure
.wkk-ctn
.text
.relieve
{
cursor
:
pointer
;
}
.figure
.wkk-ctn
.text
.offline
{
color
:
#aaa
;
}
.figure
.wkk-ctn
.text
.online
{
color
:
#000
;
}
/* .figure .wkk-ctn .text .el-icon-info{
animation:twinkle 1100ms infinite;
} */
.figure
.wkk-ctn
li
>
div
.text
:before
{
content
:
''
;
position
:absolute
;
height
:
0
;
width
:
0
;
border-style
:solid
;
border-width
:
0
.0643rem
;
border-color
:transparent
;}
.figure
.wkk-ctn
.up
{
top
:
0
;
left
:
0
;
height
:
0
;
width
:
100%
;}
.figure
.wkk-ctn
.up
.text
{
bottom
:
0
.0804rem
;
width
:max-content
;}
.figure
.wkk-ctn
.up
.text
:before
{
bottom
:
-0
.1287rem
;
left
:
50%
;
margin-left
:
-0
.0643rem
;
border-color
:
#fff
transparent
transparent
transparent
;}
.figure
.wkk-ctn
.down
{
bottom
:
0
;
left
:
0
;
height
:
0
;
width
:
100%
;}
.figure
.wkk-ctn
.down
.text
{
top
:
0
.0804rem
;
width
:max-content
;}
.figure
.wkk-ctn
.down
.text
:before
{
top
:
-0
.1287rem
;
left
:
50%
;
margin-left
:
-0
.0643rem
;
border-color
:transparent
transparent
#fff
transparent
;}
.figure
.wkk-ctn
.left
{
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
0
;}
.figure
.wkk-ctn
.left
.text
{
right
:
0
.0804rem
;
width
:max-content
;}
.figure
.wkk-ctn
.left
.text
:before
{
top
:
50%
;
right
:
-0
.1287rem
;
margin-top
:
-0
.0643rem
;
border-color
:transparent
transparent
transparent
#fff
;}
.figure
.wkk-ctn
.right
{
top
:
0
;
right
:
0
;
height
:
100%
;
width
:
0
;}
.figure
.wkk-ctn
.right
.text
{
left
:
0
.0804rem
;
width
:max-content
;}
.figure
.wkk-ctn
.right
.text
:before
{
top
:
50%
;
left
:
-0
.1287rem
;
margin-top
:
-0
.0643rem
;
border-color
:transparent
#fff
transparent
transparent
;}
.figure
.wkk-ctn
li
>
div
.text
:before
{
content
:
''
;
position
:
absolute
;
height
:
0
;
width
:
0
;
border-style
:
solid
;
border-width
:
0
.0643rem
;
border-color
:
transparent
;
}
.figure
.wkk-ctn
.up
{
top
:
0
;
left
:
0
;
height
:
0
;
width
:
100%
;
}
.figure
.wkk-ctn
.up
.text
{
bottom
:
0
.0804rem
;
width
:
max-content
;
}
.figure
.wkk-ctn
.up
.text
:before
{
bottom
:
-0
.1287rem
;
left
:
50%
;
margin-left
:
-0
.0643rem
;
border-color
:
#fff
transparent
transparent
transparent
;
}
.figure
.wkk-ctn
.down
{
bottom
:
0
;
left
:
0
;
height
:
0
;
width
:
100%
;
}
.figure
.wkk-ctn
.down
.text
{
top
:
0
.0804rem
;
width
:
max-content
;
}
.figure
.wkk-ctn
.down
.text
:before
{
top
:
-0
.1287rem
;
left
:
50%
;
margin-left
:
-0
.0643rem
;
border-color
:
transparent
transparent
#fff
transparent
;
}
.figure
.wkk-ctn
.left
{
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
0
;
}
.figure
.wkk-ctn
.left
.text
{
right
:
0
.0804rem
;
width
:
max-content
;
}
.figure
.wkk-ctn
.left
.text
:before
{
top
:
50%
;
right
:
-0
.1287rem
;
margin-top
:
-0
.0643rem
;
border-color
:
transparent
transparent
transparent
#fff
;
}
.figure
.wkk-ctn
.right
{
top
:
0
;
right
:
0
;
height
:
100%
;
width
:
0
;
}
.figure
.wkk-ctn
.right
.text
{
left
:
0
.0804rem
;
width
:
max-content
;
}
.figure
.wkk-ctn
.right
.text
:before
{
top
:
50%
;
left
:
-0
.1287rem
;
margin-top
:
-0
.0643rem
;
border-color
:
transparent
#fff
transparent
transparent
;
}
@keyframes
red
{
0
%
{
opacity
:
1
.0
;}
12
.5
%
{
opacity
:
0
.2
;}
25
%
{
opacity
:
1
.0
;}
0
%
{
opacity
:
1
.0
;
}
12
.5
%
{
opacity
:
0
.2
;
}
25
%
{
opacity
:
1
.0
;
}
}
@keyframes
orange
{
0
%
{
opacity
:
1
.0
;}
10
%
{
opacity
:
0
.2
;}
20
%
{
opacity
:
1
.0
;}
0
%
{
opacity
:
1
.0
;
}
10
%
{
opacity
:
0
.2
;
}
20
%
{
opacity
:
1
.0
;
}
}
@keyframes
yellow
{
0
%
{
opacity
:
1
.0
;}
9
%
{
opacity
:
0
.2
;}
18
%
{
opacity
:
1
.0
;}
0
%
{
opacity
:
1
.0
;
}
9
%
{
opacity
:
0
.2
;
}
18
%
{
opacity
:
1
.0
;
}
}
@keyframes
blue
{
0
%
{
opacity
:
1
.0
;}
7
.5
%
{
opacity
:
0
.2
;}
15
%
{
opacity
:
1
.0
;}
0
%
{
opacity
:
1
.0
;
}
7
.5
%
{
opacity
:
0
.2
;
}
15
%
{
opacity
:
1
.0
;
}
}
}
}
div
.screenAlart
{
.el-message-box__header
{
padding
:
10px
5px
5px
5px
;
.el-message-box__headerbtn
{
color
:
#eee
;
top
:
10px
;
right
:
10px
;
}
}
.kmb-message-box
{
background-color
:
rgba
(
0
,
0
,
0
,
.7
);
border
:
1px
solid
#00B2FC
;
.el-message-box__title
{
color
:
#eee
;
}
div
.screenAlart
{
.el-message-box__header
{
padding
:
10px
5px
5px
5px
;
.el-message-box__headerbtn
{
color
:
#eee
;
top
:
10px
;
right
:
10px
;}
.el-message-box__content
{
color
:
#ddd
;
}
.kmb-message-box
{
background-color
:rgba
(
0
,
0
,
0
,
.7
)
;
border
:
1px
solid
#00B2FC
;
.el-message-box__title
{
color
:
#eee
;}
.el-message-box__content
{
color
:
#ddd
;}
}
.alert-ctbox
{
.item
{
line-height
:
30px
;}
span
{
display
:inline-block
;
width
:
115px
;}
input
{
height
:
25px
;
line-height
:
25px
;
outline
:none
;
padding
:
5px
5px
;
background
:transparent
;
border
:
1px
solid
#aaa
;
color
:
#fff
;}
input
:
:-
webkit-input-placeholder
{
color
:
#888
;}
.alert-ctbox
{
.item
{
line-height
:
30px
;
}
span
{
display
:
inline-block
;
width
:
115px
;
}
input
{
height
:
25px
;
line-height
:
25px
;
outline
:
none
;
padding
:
5px
5px
;
background
:
transparent
;
border
:
1px
solid
#aaa
;
color
:
#fff
;
}
input
:
:-
webkit-input-placeholder
{
color
:
#888
;
}
}
}
</
style
>
src/components/TableFilter/index.vue
View file @
83aacf1b
<!--
/**
* 表单通用组件
...
...
@@ -57,34 +56,31 @@
<div
class=
"head-container"
v-if=
"form.config.search && form.config.search[0]"
>
<!-- 搜索 -->
<template
v-for=
"(item, index) in form.config.search"
>
<label
v-if=
"item.name"
class=
"el-form-item-label"
>
{{
item
.
name
}}
</label>
<template
v-if=
"item.type==='string'"
>
<el-input
v-model=
"form.query[item.word]"
clearable
:placeholder=
"'请输入'+item.name"
:style=
"'width:'+item.width"
@
clear=
"item.clear && item.clear.call(_self.$parent)"
/>
<label
v-if=
"item.name"
class=
"el-form-item-label"
>
{{
item
.
name
}}
</label>
<template
v-if=
"item.type === 'string'"
>
<el-input
v-model=
"form.query[item.word]"
clearable
:placeholder=
"'请输入' + item.name"
:style=
"'width:' + item.width"
@
clear=
"item.clear && item.clear.call(_self.$parent)"
/>
</
template
>
<
template
v-if=
"item.type==='select'"
>
<el-select
v-model=
"form.query[item.word]"
:placeholder=
"'请选择'+item.name"
size=
"small"
:style=
"'width:'+(item.width || 'auto')"
:disabled=
"item.disabled"
clearable
@
change=
"onEventInfos(item.change)"
@
clear=
"item.clear && item.clear.call(_self.$parent)"
>
<el-option
v-for=
"obj in Dict.selectList[item.word]"
:label=
"obj[item.key] || obj.name"
:value=
"obj[item.val] || obj.value"
></el-option>
<
template
v-if=
"item.type === 'select'"
>
<el-select
v-model=
"form.query[item.word]"
:placeholder=
"'请选择' + item.name"
size=
"small"
:style=
"'width:' + (item.width || 'auto')"
:disabled=
"item.disabled"
clearable
@
change=
"onEventInfos(item.change)"
@
clear=
"item.clear && item.clear.call(_self.$parent)"
>
<el-option
v-for=
"obj in Dict.selectList[item.word]"
:label=
"obj[item.key] || obj.name"
:value=
"obj[item.val] || obj.value"
></el-option>
</el-select>
</
template
>
<
template
v-else-if=
"item.type === 'checkbox'"
>
<el-checkbox
v-model=
"form.query[item.word]"
:label=
"item.label"
></el-checkbox>
</
template
>
<
template
v-else-if=
"item.type.indexOf('date') > -1"
>
<el-date-picker
v-model=
"form.query[item.word]"
:style=
"'width:'+item.width"
:type=
"item.type"
:value-format=
"item.format || 'yyyy-MM-dd'"
:default-time=
"item.defaultTime"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
clearable
@
change=
"item.change && item.change.call(_self, $event)"
>
<el-date-picker
v-model=
"form.query[item.word]"
:style=
"'width:' + item.width"
:type=
"item.type"
:value-format=
"item.format || 'yyyy-MM-dd'"
:default-time=
"item.defaultTime"
range-separator=
"至"
start-placeholder=
"开始日期"
end-placeholder=
"结束日期"
clearable
@
change=
"item.change && item.change.call(_self, $event)"
>
</el-date-picker>
</
template
>
<el-button
v-else-if=
"item.type==='button'"
size=
"mini"
:type=
"item.btntype || 'success'"
:icon=
"item.icon"
@
click=
"item.click && item.click.call(_self.$parent, $event)"
>
{{item.label}}
</el-button>
<el-button
v-else-if=
"item.type === 'button'"
size=
"mini"
:type=
"item.btntype || 'success'"
:icon=
"item.icon"
@
click=
"item.click && item.click.call(_self.$parent, $event)"
>
{{ item.label }}
</el-button>
</template>
</div>
</template>
...
...
@@ -94,7 +90,7 @@ export default {
return
{
}
},
props
:
{
props
:
{
form
:
{
type
:
Object
,
default
:
{},
...
...
@@ -104,24 +100,34 @@ export default {
default
:
{},
},
},
beforeCreate
()
{
beforeCreate
()
{
},
created
()
{
created
()
{
},
mounted
()
{
},
methods
:
{
onEventInfos
:
qf
.
vue
.
onEventInfos
,
onEventInfos
:
qf
.
vue
.
onEventInfos
,
},
}
</
script
>
<
style
lang=
"scss"
scope
>
.head-container
{
.el-form-item-label
{
font-weight
:
500
;
margin-left
:
15px
;
&
:first-child
{
margin-left
:
0
;}
.head-container
{
.el-form-item-label
{
font-weight
:
500
;
margin-left
:
15px
;
&
:first-child
{
margin-left
:
0
;
}
.el-button
{
margin-left
:
20px
;}
.el-checkbox
{
margin-right
:
5px
;}
}
.el-button
{
margin-left
:
20px
;
}
.el-checkbox
{
margin-right
:
5px
;
}
}
</
style
>
src/utils/request.js
View file @
83aacf1b
...
...
@@ -8,12 +8,10 @@ import Config from '@/settings'
axios
.
defaults
.
withCredentials
=
true
;
//var baseURL = (VUE_APP_API.ServiceURL || process.env.VUE_APP_LOCAL_API) + '/';
var
baseURL
=
process
.
env
.
NODE_ENV
===
'
development
'
?
process
.
env
.
VUE_APP_LOCAL_API
+
'
/
'
:
(
VUE_APP_API
.
ServiceURL
||
process
.
env
.
VUE_APP_LOCAL_API
)
+
'
/
'
;
var
baseURL
=
process
.
env
.
NODE_ENV
===
'
development
'
?
process
.
env
.
VUE_APP_LOCAL_API
+
'
/
'
:
(
process
.
env
.
VUE_APP_BASE_API
||
process
.
env
.
VUE_APP_LOCAL_API
)
+
'
/
'
;
// 创建axios实例
const
service
=
axios
.
create
({
baseURL
:
baseURL
,
baseURL
:
'
http://192.168.2.37:9003
'
,
timeout
:
Config
.
timeout
// 请求超时时间
})
...
...
src/views/Screen/index.vue
View file @
83aacf1b
...
...
@@ -60,12 +60,12 @@
import
{
Tools
}
from
"
@/assets/js/common.js
"
;
import
{
reqApi
,
Config
}
from
"
@/assets/js/httpApi.js
"
;
import
{
Highchart
}
from
"
@/assets/js/chartTemplates.js
"
;
//
import cesium from '@/components/Cesium';
import
cesium
from
'
@/components/Cesium
'
;
import
Carousel
from
"
@/components/Carousel
"
;
import
CenterViews
from
"
@/components/CenterViews
"
;
// style
//import '@/../static/js/Cesium/Widgets/widgets.css';
//
import '@/../static/js/Cesium/Widgets/widgets.css';
export
default
{
components
:
{
Carousel
,
CenterViews
},
data
()
{
...
...
@@ -88,17 +88,17 @@ export default {
var
nowTimeEl
=
this
.
$el
.
querySelector
(
"
#nowTime
"
);
var
Loop1
=
qf
.
Async
.
intervalLoop
(
1000
,
function
()
{
function
()
{
var
dateTime
=
Tools
.
Dates
.
format
(
"
yyyy年MM月dd日 HH:mm:ss
"
);
dateTime
=
dateTime
.
replace
(
/年|月|日/g
,
function
(
a
)
{
dateTime
=
dateTime
.
replace
(
/年|月|日/g
,
function
(
a
)
{
return
"
<span>
"
+
a
+
"
</span>
"
;
});
nowTimeEl
.
innerHTML
=
dateTime
;
//Loop1.clear();
},
function
()
{
function
()
{
var
dateTime
=
Tools
.
Dates
.
format
(
"
yyyy年MM月dd日 HH:mm:ss
"
);
dateTime
=
dateTime
.
replace
(
/年|月|日/g
,
function
(
a
)
{
dateTime
=
dateTime
.
replace
(
/年|月|日/g
,
function
(
a
)
{
return
"
<span>
"
+
a
+
"
</span>
"
;
});
nowTimeEl
.
innerHTML
=
dateTime
;
...
...
@@ -106,7 +106,7 @@ export default {
);
qf
(
function
()
{
function
()
{
this
.
initData
();
}.
bind
(
this
)
);
...
...
@@ -118,7 +118,7 @@ export default {
qf
.
Async
.
loopList
.
call
(
this
,
list
,
function
(
key
,
item
,
next
)
{
function
(
key
,
item
,
next
)
{
var
alarmDict
=
[
""
,
{
name
:
"
红色报警
"
,
color
:
"
red
"
},
...
...
@@ -146,12 +146,12 @@ export default {
"
)</div><div>时间:
"
+
item
.
time
+
'
</div><div class="btn-groub" style="margin-top:5px;display:flex;justify-content:center;"><button data-id="0">解除报警</button><button data-id="1" style="margin-left:30px;">关闭报警</button><button data-id="2" style="margin-left:30px;">不再提示</button></div></div>
'
,
onClose
:
function
(
v
)
{
setTimeout
(
function
()
{
onClose
:
function
(
v
)
{
setTimeout
(
function
()
{
next
();
},
~~
(
1
+
Math
.
random
()
*
3
)
*
1000
);
},
onClick
:
function
(
tag
)
{
onClick
:
function
(
tag
)
{
if
(
tag
.
nodeName
===
"
BUTTON
"
)
{
var
self
=
this
,
id
=
tag
.
dataset
.
id
;
...
...
@@ -160,11 +160,11 @@ export default {
Notify
.
pause
();
that
.
openRelieveAlarm
(
{
equipno
:
item
.
equipno
},
function
()
{
function
()
{
Notify
.
close
(
true
);
reqAlarmsPopup
();
},
function
()
{
function
()
{
Notify
.
recover
();
}
);
...
...
@@ -178,7 +178,7 @@ export default {
width
:
"
350px
"
,
html
:
"
点击确认后,该条数据仍会处于报警状态,但是不会再提示,您确认要这么做吗?
"
,
confirm
:
function
(
el
)
{
confirm
:
function
(
el
)
{
var
parm
=
{
id
:
item
.
id
};
that
.
pageApi
.
alterAbnormal
(
"
put
"
,
parm
).
then
(
res
=>
{
if
(
res
.
code
===
200
)
{
...
...
@@ -186,7 +186,7 @@ export default {
}
});
},
close
:
function
()
{
close
:
function
()
{
Notify
.
recover
();
}
});
...
...
@@ -199,8 +199,8 @@ export default {
}
});
},
function
()
{
setTimeout
(
function
()
{
function
()
{
setTimeout
(
function
()
{
reqAlarmsPopup
();
},
15000
);
}
...
...
@@ -223,7 +223,7 @@ export default {
// onload
this
.
$nextTick
(()
=>
{
new
qf
.
Async
.
intervalLoop
(
600000
,
function
()
{
new
qf
.
Async
.
intervalLoop
(
600000
,
function
()
{
// 加载数据
self
.
loadViewData
(
self
.
area
.
views
);
});
...
...
@@ -260,7 +260,7 @@ export default {
Tools
.
asyncLoop
.
call
(
this
,
panels
,
function
(
key
,
panel
,
next
)
{
function
(
key
,
panel
,
next
)
{
var
item
=
panel
.
item
,
param
=
{
range
:
item
.
range
,
...
...
@@ -347,7 +347,7 @@ export default {
}
}, */
tooltip
:
{
formatter
:
function
()
{
formatter
:
function
()
{
return
(
this
.
series
.
name
+
"
:
"
+
...
...
@@ -359,7 +359,7 @@ export default {
}
}
},
callback
:
function
(
key
,
extend
,
give
)
{
callback
:
function
(
key
,
extend
,
give
)
{
if
(
key
===
"
series
"
&&
give
[
key
].
constructor
.
name
===
"
Array
"
...
...
@@ -530,7 +530,7 @@ export default {
var
div
=
document
.
createElement
(
"
div
"
);
// 2024/8/10(周六) 为了缩减设备名称, 类型名称过长超出边界,添加对类型过滤
var
name
=
types
.
find
(
function
(
val
,
i
)
{
var
name
=
types
.
find
(
function
(
val
,
i
)
{
if
(
item
.
sensroname
.
includes
(
val
))
{
return
1
;
}
...
...
@@ -591,7 +591,7 @@ export default {
}
},
tooltip: {
formatter: function(e) {
formatter: function
(e) {
return this.key + ":" + this.y;
}
},
...
...
@@ -710,7 +710,7 @@ export default {
var
param
=
{
c
:
"
code
"
,
a
:
"
getcode
"
,
id
:
48
,
icon
:
1
,
py
:
city
};
reqApi
.
getWeather
(
param
).
then
(
res
=>
{
var
body
=
document
.
createElement
(
"
div
"
);
setTimeout
(
function
()
{
setTimeout
(
function
()
{
body
.
innerHTML
=
res
;
var
styles
=
body
.
querySelectorAll
(
"
link
"
);
for
(
var
style
of
styles
)
{
...
...
@@ -809,7 +809,7 @@ export default {
const
img
=
document
.
createElement
(
"
img
"
);
img
.
src
=
"
/static/jrx.png
"
;
img
.
style
.
cssText
=
"
width:
100%;height:100%;object-fit:contain;cursor:pointer
"
;
"
width:
95%;height:95%;object-fit:contain;cursor:pointer;margin: 10px 10px
"
;
img
.
addEventListener
(
"
click
"
,
()
=>
{
this
.
openImagePopup
(
imgId
,
img
.
src
);
});
...
...
@@ -818,7 +818,7 @@ export default {
}
next
();
},
function
()
{
}
function
()
{
}
);
},
// 点击图片方法
...
...
@@ -828,7 +828,7 @@ export default {
},
cuCharts
(
ctn
,
data
,
opts
)
{
//
var
cuCharts
=
function
(
ctn
,
data
,
opts
)
{
var
cuCharts
=
function
(
ctn
,
data
,
opts
)
{
var
ctn
=
(
this
.
ctn
=
typeof
element
===
"
string
"
?
document
.
getElementById
(
ctn
)
:
ctn
);
if
(
!
ctn
)
...
...
@@ -881,11 +881,11 @@ export default {
this
.
init
();
};
cuCharts
.
prototype
=
{
init
:
function
()
{
init
:
function
()
{
this
.
setModule
();
this
.
onresize
();
},
drawAxis
:
function
(
color
,
damHeight
)
{
drawAxis
:
function
(
color
,
damHeight
)
{
var
lw
=
this
.
options
.
axisLineWidth
;
var
wHalf
=
lw
/
2
;
var
initX
=
this
.
options
.
initX
;
...
...
@@ -924,7 +924,7 @@ export default {
color
:
color
});
},
drawSteps
:
function
(
ladders
)
{
drawSteps
:
function
(
ladders
)
{
ladders
=
ladders
||
[
0
];
var
initX
=
this
.
options
.
initX
,
initY
=
this
.
options
.
initY
;
...
...
@@ -1014,7 +1014,7 @@ export default {
var
damHeight
=
(
cumulationY
-
this
.
options
.
initY
)
/
pxRetioY
;
return
(
maxStepDepth
.
damHeight
=
damHeight
),
maxStepDepth
;
},
drawDevice
:
function
(
list
)
{
drawDevice
:
function
(
list
)
{
var
lineW
=
4
*
this
.
dpr
,
deviceW
=
6
*
this
.
dpr
,
deviceH
=
3
*
this
.
dpr
;
...
...
@@ -1078,7 +1078,7 @@ export default {
});
}
},
drawAlarmLine
:
function
(
alarms
,
Steps
)
{
drawAlarmLine
:
function
(
alarms
,
Steps
)
{
var
alarmValues
=
alarms
.
value
;
var
alarmLevel
=
alarms
.
alarmLevel
;
var
deviceCoords
=
this
.
options
.
deviceCoords
||
[];
...
...
@@ -1122,10 +1122,10 @@ export default {
}
}
},
getCirHeightDev
:
function
(
r
,
x
)
{
getCirHeightDev
:
function
(
r
,
x
)
{
return
r
-
Math
.
sqrt
(
Math
.
pow
(
r
,
2
)
-
Math
.
pow
(
x
,
2
));
},
drawWaterArea
:
function
(
depth
)
{
drawWaterArea
:
function
(
depth
)
{
depth
=
100
;
var
startAngle
=
this
.
options
.
waterArea
.
startAngle
;
var
radiusMultiple
=
this
.
options
.
waterArea
.
radius
;
...
...
@@ -1171,7 +1171,7 @@ export default {
ctx
.
fillStyle
=
"
#00A2E8
"
;
ctx
.
fill
();
},
byAngleAndHeightToCoord
:
function
(
angle
,
height
)
{
byAngleAndHeightToCoord
:
function
(
angle
,
height
)
{
var
devX
=
Math
.
tan
(
angle
*
0.017453293
)
*
height
;
var
xy
=
height
/
Math
.
cos
(
angle
*
0.017453293
);
var
devY
=
height
-
devX
;
...
...
@@ -1197,7 +1197,7 @@ export default {
var
averageHeight
=
(
damHeight
-
sum
)
/
not
;
return
{
averageHeight
:
averageHeight
,
damHeight
:
damHeight
};
},
setModule
:
function
()
{
setModule
:
function
()
{
this
.
ctx
.
clearRect
(
0
,
0
,
this
.
SumWidth
,
this
.
SumHeight
);
var
canvas
=
this
.
canvas
;
var
SumWidth
=
(
this
.
SumWidth
=
...
...
@@ -1230,7 +1230,7 @@ export default {
this
.
options
[
"
HWRation
"
]
=
(
endY
-
top
)
/
(
endX
-
left
);
this
.
drawChart
();
},
formatDeviceParam
:
function
(
devices
)
{
formatDeviceParam
:
function
(
devices
)
{
var
devices
=
devices
||
[];
var
arr
=
[];
for
(
var
item
of
devices
)
{
...
...
@@ -1244,7 +1244,7 @@ export default {
}
return
arr
;
},
getAlarmRealParam
:
function
(
aValues
)
{
getAlarmRealParam
:
function
(
aValues
)
{
var
aval
=
aValues
[
0
];
var
coords
=
this
.
options
.
deviceCoords
||
[];
var
valY
=
aval
*
this
.
options
.
pxRetioY
;
...
...
@@ -1259,7 +1259,7 @@ export default {
}
return
{
ratio
:
(
ey
-
sy
)
/
(
ex
-
sx
),
sy
:
sy
,
ey
:
ey
};
},
drawChart
:
function
()
{
drawChart
:
function
()
{
var
Steps
=
this
.
drawSteps
(
this
.
ladders
);
this
.
drawAxis
(
this
.
options
.
axisColor
,
Steps
.
damHeight
);
var
depth
=
55
;
...
...
@@ -1267,18 +1267,18 @@ export default {
this
.
drawDevice
(
this
.
devices
);
this
.
drawAlarmLine
(
this
.
options
.
alarm
,
Steps
);
},
onresize
:
function
()
{
onresize
:
function
()
{
qf
.
resize
(()
=>
{
this
.
setModule
();
});
},
updateData
:
function
(
data
)
{
updateData
:
function
(
data
)
{
data
=
data
||
{};
this
.
stations
=
data
.
stations
||
this
.
stations
;
this
.
points
=
data
.
points
||
this
.
points
;
this
.
draw
(
this
.
cacheX
+
this
.
destX
,
true
);
},
drawLiner
:
function
(
o
)
{
drawLiner
:
function
(
o
)
{
var
ctx
=
this
.
ctx
;
ctx
.
beginPath
();
ctx
.
moveTo
(
o
.
sx
,
o
.
sy
);
...
...
@@ -1287,7 +1287,7 @@ export default {
ctx
.
strokeStyle
=
o
.
color
;
ctx
.
stroke
();
},
drawText
:
function
(
o
)
{
drawText
:
function
(
o
)
{
var
ctx
=
this
.
ctx
;
var
fontSize
=
(
o
.
size
||
14
)
*
this
.
dpr
;
var
text
=
o
.
text
||
""
;
...
...
@@ -1339,21 +1339,21 @@ export default {
ctx
.
fillText
(
rows
[
b
],
~~
lsx
+
0.5
,
y
+
~~
lsy
+
0.5
);
}
},
getTextWidth
:
function
(
text
,
fontSize
)
{
getTextWidth
:
function
(
text
,
fontSize
)
{
return
(
(
this
.
ctx
.
measureText
(
text
).
width
/
parseInt
(
this
.
ctx
.
font
))
*
fontSize
);
},
drawImg
:
function
(
img
,
x
,
y
,
w
,
h
)
{
drawImg
:
function
(
img
,
x
,
y
,
w
,
h
)
{
x
=
x
-
w
/
2
;
y
=
y
-
h
;
ctx
.
drawImage
(
img
,
x
,
y
,
w
,
h
);
},
getRandomColor
:
function
()
{
getRandomColor
:
function
()
{
return
"
#
"
+
Math
.
floor
(
Math
.
random
()
*
16777215
).
toString
(
16
);
},
getEventTarget
:
function
(
x
,
y
)
{
getEventTarget
:
function
(
x
,
y
)
{
if
(
y
>
bottomReferY
-
imgA
.
height
-
1
&&
y
<
bottomReferY
+
1
)
{
var
arr
=
this
.
points
;
var
i
=
arr
.
length
-
1
,
...
...
@@ -1381,7 +1381,7 @@ export default {
}
}
},
xPixelToStepsYPixel
:
function
(
x
)
{
xPixelToStepsYPixel
:
function
(
x
)
{
var
ladders
=
this
.
Cache
.
ladders
||
[],
ladderSY
=
0
;
for
(
var
ladder
of
ladders
)
{
...
...
@@ -1402,7 +1402,7 @@ export default {
return
new
cuCharts
(
ctn
,
data
,
opts
);
},
mapOnload
()
{},
mapOnload
()
{
},
openRelieveAlarm
(
params
,
fn
,
close
)
{
var
self
=
this
;
...
...
@@ -1412,7 +1412,7 @@ export default {
closeBtnColor
:
"
#eee
"
,
html
:
'
<div class="item"><span>解除时长(小时):</span><input data-name="jchours" value=12 placeholder="请输入解除时长"/></div><div class="item"><span>报警原因:</span><input data-name="reason" placeholder="报警原因"/></div><div class="item"><span>解除报警原因:</span><input data-name="jcreason" placeholder="解除报警原因"/></div>
'
,
confirm
:
function
(
el
)
{
confirm
:
function
(
el
)
{
var
inputs
=
el
.
querySelectorAll
(
"
input
"
);
for
(
var
el
of
inputs
)
{
var
key
=
el
.
dataset
.
name
;
...
...
@@ -1431,7 +1431,7 @@ export default {
fn
&&
fn
();
});
},
close
:
function
()
{
close
:
function
()
{
close
&&
close
();
}
});
...
...
@@ -1445,6 +1445,7 @@ export default {
font-family
:
"diget year"
;
src
:
url("~@/assets/fonts/DS-Digital.ttf")
;
}
.font_digit
{
font-family
:
diget
year
;
}
...
...
@@ -1460,24 +1461,27 @@ export default {
.b_0
{
position
:
absolute
;
}
>
.actv
{
>
.actv
{
display
:
block
;
}
.a_0
{
top
:
0
;
left
:
0
;
height
:
100%
;
width
:
100%
;
background
:
no-repeat
center
center
url("~@/assets/images/layout/s_bg_min.png")
;
background
:
no-repeat
center
center
url("~@/assets/images/layout/s_bg_min.png")
;
background-size
:
100%
100%
;
}
.b_0
{
display
:
flex
;
width
:
100%
;
height
:
100%
;
padding-top
:
0
.65rem
;
background-color
:
rgba
(
0
,
0
,
0
,
0
.15
);
header
{
position
:
absolute
;
top
:
0
;
...
...
@@ -1487,32 +1491,32 @@ export default {
z-index
:
5
;
display
:
flex
;
user-select
:
none
;
.b1_a
{
position
:
absolute
;
top
:
0
;
left
:
0
;
height
:
0
.64rem
;
width
:
100%
;
background
:
no-repeat
top
left
url("~@/assets/images/layout/s_hd_min.png")
;
background
:
no-repeat
top
left
url("~@/assets/images/layout/s_hd_min.png")
;
background-size
:
100%
auto
;
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
h2
{
font-size
:
0
.32rem
;
line-height
:
1
;
margin-top
:
-0
.04rem
;
background-image
:
-webkit-linear-gradient
(
top
,
background-image
:
-webkit-linear-gradient
(
top
,
#fff
,
#d5f3fe
,
#7adbfe
);
#7adbfe
);
-webkit-background-clip
:
text
;
-webkit-text-fill-color
:
transparent
;
letter-spacing
:
0
.02rem
;
}
.b1_a1
{
position
:
absolute
;
top
:
0
;
...
...
@@ -1522,10 +1526,12 @@ export default {
display
:
flex
;
align-items
:
center
;
justify-content
:
left
;
.font_digit
{
margin-right
:
0
.2rem
;
font-size
:
0
.28rem
;
color
:
#2ef4ee
;
span
{
font-family
:
serif
;
font-size
:
0
.24rem
;
...
...
@@ -1533,6 +1539,7 @@ export default {
}
}
}
.b1_a2
{
position
:
absolute
;
top
:
0
;
...
...
@@ -1540,6 +1547,7 @@ export default {
height
:
100%
;
display
:
flex
;
align-items
:
center
;
&
:before
{
content
:
""
;
display
:
block
;
...
...
@@ -1556,6 +1564,7 @@ export default {
flex
:
1
;
position
:
relative
;
margin
:
0
0
.08rem
;
.b_2a
{
position
:
absolute
;
top
:
0
;
...
...
@@ -1572,17 +1581,20 @@ export default {
.b2_a1
,
.b2_a3
{
flex
:
1
;
>
div
{
>
div
{
//background-color:pink;
flex
:
1
;
}
}
.b2_a1
,
.b2_a2
,
.b2_a3
{
display
:
flex
;
flex-direction
:
column
;
>
div
{
>
div
{
margin-bottom
:
0
.08rem
;
}
}
...
...
@@ -1590,19 +1602,23 @@ export default {
.b2_a2
{
width
:
8
.84rem
;
margin
:
0
0
.08rem
;
>
div
:first-child
{
>
div
:first-child
{
height
:
7
.52rem
;
/* background-color:yellow; */
box-shadow
:
inset
0rem
0rem
0
.15rem
0
.24rem
rgba
(
2
,
43
,
80
,
0
.8
);
}
>
div
:last-child
{
>
div
:last-child
{
//height:2.46rem;
flex
:
1
;
display
:
flex
;
//height:22.777vh;
>
div
{
>
div
{
flex
:
1
;
margin-right
:
0
.08rem
;
//background-color:pink;
&
:last-child
{
margin-right
:
0
;
...
...
@@ -1613,8 +1629,9 @@ export default {
.b2a2_a
{
flex
:
1
;
position
:
relative
;
/* background:no-repeat center center url('~@/assets/images/layout/map_min.png');background-size:100% auto; */
>
div
{
>
div
{
display
:
none
;
position
:
absolute
;
top
:
0
;
...
...
@@ -1622,20 +1639,22 @@ export default {
height
:
100%
;
width
:
100%
;
}
>
div
.show
{
>
div
.show
{
display
:
block
;
}
>
div
:first-child
{
}
}
>
div
:first-child
{}
}
.b2_a3
{
}
.b2_a3
{}
.view-item
{
border
:
1px
solid
#004a8b
;
position
:
relative
;
box-shadow
:
inset
0rem
0rem
0
.15rem
0
.04rem
rgba
(
10
,
106
,
180
,
0
.8
);
&
:before
,
&
:after
,
.view-flx
:before
,
...
...
@@ -1648,18 +1667,22 @@ export default {
border-style
:
solid
;
border-color
:
#02f6ff
;
}
&
:before
,
&
:after
{
top
:
-1px
;
}
&
:before
{
left
:
-1px
;
border-width
:
0
.02rem
0
0
0
.02rem
;
}
&
:after
{
right
:
-1px
;
border-width
:
0
.02rem
0
.02rem
0
0
;
}
.view-flx
{
position
:
absolute
;
top
:
0
;
...
...
@@ -1667,14 +1690,17 @@ export default {
height
:
100%
;
width
:
100%
;
background-color
:
rgb
(
1
,
19
,
70
,
0
.3
);
&
:before
,
&
:after
{
bottom
:
-1px
;
}
&
:before
{
left
:
-1px
;
border-width
:
0
0
0
.02rem
0
.02rem
;
}
&
:after
{
right
:
-1px
;
border-width
:
0
0
.02rem
0
.02rem
0
;
...
...
@@ -1685,34 +1711,42 @@ export default {
.weather
{
font-size
:
11px
;
.mleft
{
display
:
none
;
}
.wtpath
{
display
:
none
;
}
.mright
{
flex
:
1
;
text-align
:
center
;
}
img
{
display
:
block
;
width
:
2vw
!
important
;
height
:
auto
!
important
;
margin
:
0
auto
;
}
ul
{
margin
:
5px
0
;
color
:
#d0d2ff
;
}
#mobile05
{
display
:
flex
;
position
:
relative
;
padding-top
:
5vh
!
important
;
}
#mobile05
>
div
:last-child
{
#mobile05
>
div
:last-child
{
display
:
none
;
}
#mright_1
{
position
:
absolute
;
top
:
0
;
...
...
@@ -1720,18 +1754,22 @@ export default {
height
:
auto
;
width
:
100%
;
display
:
flex
;
ul
{
margin
:
0
;
color
:
#03d3fe
;
}
.wt
{
display
:
flex
;
align-items
:
center
;
margin-left
:
140px
;
}
.day
{
display
:
none
;
}
span
:last-child
{
display
:
block
;
position
:
absolute
;
...
...
@@ -1740,6 +1778,7 @@ export default {
height
:
auto
;
font-size
:
26px
;
}
font
{
margin
:
6px
0
0
10px
;
color
:
#35ecfa
;
...
...
src/views/dataMonitor/jrx/history/index copy.vue
View file @
83aacf1b
<
template
>
<div
class=
"common-page qyzz page-t1"
>
<div
class=
"option page-row"
>
<table-filter
ref=
"filter"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:config=
"form.config"
:loadData=
"loadData"
/>
<table-filter
ref=
"filter"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
<div
class=
"new-container"
style=
"display: flex"
>
<div
class=
"canvas-wrapper"
style=
"width: 1000px;"
>
<!-- 替换为 Canvas 元素 -->
<canvas
ref=
"canvas"
id=
"mainCanvas"
width=
"1000"
style=
"background: #f0f0f0"
></canvas>
<canvas
ref=
"canvas"
id=
"mainCanvas"
width=
"1000"
style=
"background: #f0f0f0"
></canvas>
</div>
<div
class=
"chart-wrapper"
style=
"padding-left: 0px;"
>
<div
ref=
"chartContainer"
style=
"width: 870px; height: 550px; margin-bottom: 20px;border:1px solid gainsboro;"
></div>
<div
ref=
"chartContainer"
style=
"width: 870px; height: 550px; margin-bottom: 20px;border:1px solid gainsboro;"
>
</div>
<div
class=
"chart-btn-group"
>
<button
size=
"small"
:type=
"currentChartType === 'line' ? 'primary' : ''"
@
click=
"switchChartType('line')"
>
<button
size=
"small"
:type=
"currentChartType === 'line' ? 'primary' : ''"
@
click=
"switchChartType('line')"
>
折线图
</button>
<button
size=
"small"
:type=
"currentChartType === 'column' ? 'primary' : ''"
@
click=
"switchChartType('column')"
>
<button
size=
"small"
:type=
"currentChartType === 'column' ? 'primary' : ''"
@
click=
"switchChartType('column')"
>
柱状图
</button>
</div>
...
...
@@ -51,49 +30,24 @@
<div
class=
"content-fix"
>
<div
class=
"toolbar"
>
<div>
<el-button
v-for=
"(item, key) in form.config.otherBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button
>
<el-button
v-for=
"(item, key) in form.config.otherBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button>
</div>
<div>
<el-button
v-for=
"(item, key) in form.config.rightBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button
>
<el-button
v-for=
"(item, key) in form.config.rightBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref=
"cuTable"
:table=
"table"
:Dict=
"Dict"
:config=
"form.config"
:loadData=
"loadData"
/>
<cu-table
ref=
"cuTable"
:table=
"table"
:Dict=
"Dict"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref=
"cuForm"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:submit=
"submitForm"
:cancel=
"cancelForm"
:watchKeys=
"['paperfilename']"
/>
<cu-form
ref=
"cuForm"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:submit=
"submitForm"
:cancel=
"cancelForm"
:watchKeys=
"['paperfilename']"
/>
</div>
</
template
>
...
...
@@ -296,9 +250,9 @@ export default {
// 获取选择列表字典
var
selectList
=
this
.
Dict
.
selectList
;
Tools
.
asyncLoop
.
call
(
this
,
selectList
,
function
(
key
,
value
,
next
)
{
Tools
.
asyncLoop
.
call
(
this
,
selectList
,
function
(
key
,
value
,
next
)
{
if
(
typeof
value
===
"
function
"
)
{
value
.
call
(
this
.
Dict
).
then
(
function
(
res
)
{
value
.
call
(
this
.
Dict
).
then
(
function
(
res
)
{
selectList
[
key
]
=
res
;
next
();
});
...
...
@@ -318,7 +272,7 @@ export default {
},
methods
:
{
getCanvasData
(){
getCanvasData
()
{
const
params
=
{}
request
({
url
:
"
tab/jrx/dissect/visual-xinHua
"
,
...
...
@@ -418,7 +372,7 @@ export default {
for
(
let
index
=
0
;
index
<
tjNumber
;
index
++
)
{
canvasData
.
poConfigs
.
push
({
x
:
0
,
y
:
600
-
(
150
*
index
),
y
:
600
-
(
150
*
index
),
width
:
879
-
250
*
index
,
height
:
150
});
...
...
@@ -856,7 +810,7 @@ export default {
{
color
:
"
blue
"
,
name
:
"
蓝色报警线
"
}
],
alarmLine
=
{},
setAlarmSerie
=
function
(
value
,
name
,
color
)
{
setAlarmSerie
=
function
(
value
,
name
,
color
)
{
// 修改蓝色色值
color
===
"
blue
"
&&
(
color
=
"
#3BAFFB
"
);
var
sx
=
list
[
0
].
date
,
...
...
@@ -940,7 +894,7 @@ export default {
});
}
},
loadData
:
function
()
{
loadData
:
function
()
{
console
.
log
(
this
.
form
,
"
form
"
);
this
.
initChart1
();
...
...
@@ -956,6 +910,5 @@ export default {
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scope
>
.qyzz
{
}
.qyzz
{}
</
style
>
src/views/dataMonitor/jrx/history/index-剖面-old.vue
0 → 100644
View file @
83aacf1b
<
template
>
<div
class=
"common-page qyzz page-t1"
>
<div
class=
"option page-row"
>
<table-filter
ref=
"filter"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
<div
class=
"new-container"
style=
"display: flex"
>
<div
class=
"canvas-wrapper"
style=
"width: 1000px"
>
<!-- 替换为 Canvas 元素 -->
<canvas
ref=
"canvas"
id=
"mainCanvas"
width=
"1000"
style=
"background: #f0f0f0"
></canvas>
</div>
<div
class=
"chart-wrapper"
style=
"padding-left: 0px"
>
<div
ref=
"chartContainer"
style=
"
width: 870px;
height: 550px;
margin-bottom: 20px;
border: 1px solid gainsboro;
"
></div>
<div
class=
"chart-btn-group"
>
<button
size=
"small"
:type=
"currentChartType === 'line' ? 'primary' : ''"
@
click=
"switchChartType('line')"
>
折线图
</button>
<button
size=
"small"
:type=
"currentChartType === 'column' ? 'primary' : ''"
@
click=
"switchChartType('column')"
>
柱状图
</button>
</div>
</div>
</div>
<div
class=
"panel-bottom page-row"
>
<div
class=
"ctin-box"
>
<div
class=
"content-within"
>
<div
class=
"content-fix"
>
<div
class=
"toolbar"
>
<div>
<el-button
v-for=
"(item, key) in form.config.otherBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button
>
</div>
<div>
<el-button
v-for=
"(item, key) in form.config.rightBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button
>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref=
"cuTable"
:table=
"table"
:Dict=
"Dict"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref=
"cuForm"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:submit=
"submitForm"
:cancel=
"cancelForm"
:watchKeys=
"['paperfilename']"
/>
</div>
</
template
>
<
script
>
import
Highcharts
from
"
highcharts
"
;
import
{
reqApi
,
Config
}
from
"
@/assets/js/httpApi.js
"
;
import
{
Tools
}
from
"
@/assets/js/common.js
"
;
import
DateRangePicker
from
"
@/components/DateRangePicker
"
;
import
TableFilter
from
"
@/components/TableFilter
"
;
import
cuForm
from
"
@/components/cuForm
"
;
import
cuTable
from
"
@/components/cuTable
"
;
import
request
from
"
@/utils/request
"
;
export
default
{
name
:
"
Dashboard
"
,
components
:
{
DateRangePicker
,
TableFilter
,
cuForm
,
cuTable
,
},
data
()
{
return
{
chartDataEmpty
:
false
,
canvasDataEmpty
:
false
,
Dict
:
{
selectList
:
[]
},
table
:
{
page
:
1
,
size
:
10
,
total
:
0
,
loading
:
false
,
dataList
:
[],
},
rules
:
{},
form
:
{
title
:
""
,
visible
:
false
,
reqType
:
"
add
"
,
historyDialog
:
false
,
status
:
{
cu
:
0
},
query
:
{},
search
:
{},
item
:
{},
file
:
0
,
config
:
{},
},
// 新增图表相关数据
chartVisible
:
true
,
// 图表弹窗可见性
deviceList
:
[{
id
:
"
test001
"
,
name
:
"
测试设备1
"
}],
// 设备列表数据
selectedDevice
:
null
,
// 选中设备ID
dateRange
:
[
null
,
null
],
// 日期范围选择
currentChartType
:
"
line
"
,
// 当前图表类型(line/column)
chartLoading
:
false
,
// 图表加载状态
chartInstance
:
null
,
// Highcharts实例引用
// ...原有data属性保持不变...
canvas
:
null
,
// Canvas 实例
ctx
:
null
,
// 2D 上下文
bgImage
:
null
,
// 背景图对象
waterImage
:
null
,
// 新增:water.png 图片对象
poImage
:
null
,
// 新增:po.png 图片对象
canvasDataReal
:
{
// Canvas绘制配置(支持批量扩展)
poConfigs
:
[
{
x
:
0
,
y
:
null
,
width
:
879
,
height
:
150
},
// 第一张po.png配置
{
x
:
0
,
y
:
null
,
width
:
879
-
250
,
height
:
150
},
// 第二张po.png配置(宽度减少250px)
],
poConfigs
:
[
{
x
:
null
,
y
:
null
,
width
:
6
,
height
:
121
,
image
:
"
guanImage
"
},
// 第一张guan0.png
{
x
:
null
,
y
:
null
,
width
:
6
,
height
:
200
,
image
:
"
guanImage
"
},
// 第二张guan0.png(高度调整)
],
lineConfigs
:
[
{
points
:
[],
color
:
"
red
"
,
lineWidth
:
2
},
// 红色连接线配置
{
points
:
[],
color
:
"
yellow
"
,
lineWidth
:
2
},
// 黄色连接线配置
],
},
// canvasData: [
// {
// name: "剖面名称",
// height: "剖面高度",
// width: "剖面宽度",
// code: "剖面编号",
// sdeg: "水区扇形起始角度",
// diameter: "总直径",
// jrxStepsDtoList: [
// {
// name: "台阶名称",
// code: "台阶编号",
// height: "高度(米)",
// width: "宽度(米)",
// slope: "坡度(deg)"
// }
// ],
// equipmentDataList: [
// {
// sensorid: "设备id",
// sensorname: "设备名称",
// unit: "设备单位",
// stage: "水位(传感器到水面的距离)",
// depth: "浸润线埋深(水位到管口的距离)(m)",
// smhb: "// 水面海拔",
// time: "时间",
// holeDepth: "孔口高程",
// jrxTrepanning: "浸润线开口深度",
// redAlarm: "红色预警 此预警值针对的是depth 浸润线埋深",
// orangeAlarm: "橙色预警",
// yellowAlarm: "黄色预警",
// blueAlarm: "蓝色预警"
// }
// ]
// }
// ]
};
},
created
()
{
// 获取基本信息
this
.
pageApi
=
Config
.
getModuleInfo
(
this
);
this
.
Dict
=
this
.
pageApi
.
Dict
;
this
.
form
.
config
=
this
.
pageApi
.
config
;
this
.
rules
=
reqApi
.
getRules
(
this
.
Dict
.
baseInfo
)
||
this
.
Dict
.
rules
||
{};
this
.
pageApi
.
created
&&
this
.
pageApi
.
created
();
// 新增:获取地址栏deviceId参数并设置到form.query.code
const
deviceId
=
this
.
$route
.
query
.
deviceId
;
if
(
deviceId
)
{
this
.
form
.
query
.
sensorid
=
deviceId
;
// 将deviceId赋值到查询条件的code字段
}
// this.handleCanvasData(this.canvasData);
},
mounted
()
{
this
.
$nextTick
(()
=>
{
this
.
loadData
();
this
.
initChart1
()
this
.
getCanvasData
();
});
// 获取选择列表字典
var
selectList
=
this
.
Dict
.
selectList
;
Tools
.
asyncLoop
.
call
(
this
,
selectList
,
function
(
key
,
value
,
next
)
{
if
(
typeof
value
===
"
function
"
)
{
value
.
call
(
this
.
Dict
).
then
(
function
(
res
)
{
selectList
[
key
]
=
res
;
next
();
});
}
else
{
next
();
}
});
},
methods
:
{
/** 绘制文字标注 */
drawText
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系(左上角原点)
this
.
ctx
.
font
=
`10px Arial`
;
// 文字大小8px
this
.
ctx
.
fillStyle
=
"
#000
"
;
// 黄色
this
.
ctx
.
textAlign
=
"
center
"
;
// 水平居中
this
.
ctx
.
textBaseline
=
"
top
"
;
// 垂直顶部对齐
// 绘制文字(考虑Y轴方向转换)
const
drawY
=
this
.
canvas
.
height
-
config
.
y
;
// 转换为默认坐标系Y轴
this
.
ctx
.
fillText
(
config
.
text
,
config
.
x
,
drawY
+
5
);
// Y轴偏移5px避免重叠
this
.
ctx
.
restore
();
},
/** 清空画布内容及配置 */
clearCanvas
()
{
if
(
this
.
ctx
)
{
// 清除画布绘制内容(基于当前坐标系)
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系
this
.
ctx
.
clearRect
(
0
,
0
,
this
.
canvas
.
width
,
this
.
canvas
.
height
);
// 清空整个画布
this
.
ctx
.
restore
();
}
// 重置配置数据(避免残留)
this
.
canvasDataReal
.
poConfigs
=
[];
this
.
canvasDataReal
.
guanConfigs
=
[];
this
.
canvasDataReal
.
lineConfigs
=
[];
},
getCanvasData
()
{
const
params
=
{
...
this
.
form
.
query
};
request
({
url
:
"
tab/jrx/dissect/visual-xinHua
"
,
method
:
"
get
"
,
params
,
}).
then
(
async
(
res
)
=>
{
const
data
=
res
.
body
;
if
(
!
data
.
length
)
{
// 数据为空时清空画布
this
.
clearCanvas
();
return
;
}
// console.log("剖面接口数据", data);
// console.table(JSON.parse(JSON.stringify(data[0].jrxStepsDtoList)));
// console.table(JSON.parse(JSON.stringify(data[0].equipmentDataList)));
await
this
.
handleCanvasData
(
data
);
this
.
initCanvas
();
});
},
handleCanvasData
(
list
=
[])
{
return
new
Promise
((
resolve
)
=>
{
// 新增Promise封装
let
canvasWidth
=
1000
;
// 默认宽度
let
canvasHeight
=
600
;
// 默认高度
// 更新Canvas元素属性和样式
const
canvasEl
=
this
.
$refs
.
canvas
;
if
(
canvasEl
)
{
// 实际绘图区域尺寸(关键属性)
canvasEl
.
width
=
canvasWidth
;
canvasEl
.
height
=
canvasHeight
;
// 显示尺寸(与绘图区域保持一致)
canvasEl
.
style
.
width
=
`
${
canvasWidth
}
px`
;
canvasEl
.
style
.
height
=
`
${
canvasHeight
}
px`
;
}
// 数据清洗
const
poumian
=
list
[
0
];
// 坡面数据
const
poCount
=
poumian
.
jrxStepsDtoList
.
length
;
const
lineCount
=
5
;
const
po_pad_right
=
180
;
// poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const
poH
=
150
;
const
line_color
=
[
"
red
"
,
"
orange
"
,
"
yellow
"
,
"
blue
"
,
"
white
"
];
this
.
canvasDataReal
.
poConfigs
=
[];
this
.
canvasDataReal
.
guanConfigs
=
[];
this
.
canvasDataReal
.
lineConfigs
=
[];
//第一层台阶的开孔深度和设备图片相除的系数
const
sbHeightModulus
=
poumian
.
equipmentDataList
[
0
].
jrxTrepanning
/
130
;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡数据数据格式处理
poumian
.
jrxStepsDtoList
.
forEach
((
po
,
poIndex
)
=>
{
this
.
canvasDataReal
.
poConfigs
.
push
({
x
:
0
,
y
:
canvasHeight
-
(
poIndex
+
1
)
*
poH
,
width
:
canvasWidth
-
(
poIndex
+
1
)
*
po_pad_right
,
height
:
poH
,
});
});
// 管孔数据数据格式处理
poumian
.
equipmentDataList
.
forEach
((
equipment
,
equipIndex
)
=>
{
const
po
=
this
.
canvasDataReal
.
poConfigs
[
equipIndex
];
// 管孔数据数据格式处理
this
.
canvasDataReal
.
guanConfigs
.
push
({
x
:
po
.
width
*
0.75
+
50
,
y
:
canvasHeight
-
po
.
height
*
(
equipIndex
+
1
),
width
:
6
,
height
:
equipment
.
jrxTrepanning
/
sbHeightModulus
,
image
:
"
guanImage
"
,
});
});
// 警戒线逻辑- 初始话基本数据结构
for
(
let
index1
=
0
;
index1
<
lineCount
;
index1
++
)
{
this
.
canvasDataReal
.
lineConfigs
.
push
({
// 设置
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
20
*
index1
,
// 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
line
,
index
)
=>
{
let
lineValKey
=
line
.
color
==
"
white
"
?
"
depth
"
:
line
.
color
+
"
Alarm
"
;
// 几个管孔几个坐标点
poumian
.
equipmentDataList
.
forEach
((
equip
,
subindex
)
=>
{
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
,
y
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
equip
[
lineValKey
]
/
sbHeightModulus
,
// 管设备的y坐标+设备的警戒值*系数
});
});
});
// console.log("坡面处理完毕数据", this.canvasDataReal);
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.poConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.guanConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.lineConfigs))
// );
resolve
();
// 数据处理完成后触发resolve
});
},
/** 初始化 Canvas 画布及坐标系 */
initCanvas
()
{
// 获取 Canvas 元素和上下文
this
.
canvas
=
this
.
$refs
.
canvas
;
// document.getElementById('mainCanvas')
if
(
!
this
.
canvas
)
{
console
.
error
(
"
Canvas 元素未找到
"
);
return
;
}
// console.log(this.canvas, "canvas");
this
.
ctx
=
this
.
canvas
.
getContext
(
"
2d
"
);
// 坐标系变换:将原点移至左下角(默认原点在左上角)
this
.
ctx
.
translate
(
0
,
this
.
canvas
.
height
);
// 向下移动画布高度
this
.
ctx
.
scale
(
1
,
-
1
);
// 翻转 Y 轴方向(上为正)
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
this
.
loadAllImages
();
},
// 绘制单个po.png(支持配置参数)
drawPoImage
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 动态计算y坐标(若未指定则默认画布底部-高度)
this
.
ctx
.
drawImage
(
this
.
poImage
,
config
.
x
,
config
.
y
,
config
.
width
,
config
.
height
);
this
.
ctx
.
restore
();
},
// 绘制单个guan.png(支持不同图片类型)
drawGuanImage
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
const
targetImage
=
this
[
config
.
image
];
// 根据配置获取具体图片对象(如guanImage/guanImage1)
this
.
ctx
.
drawImage
(
targetImage
,
config
.
x
,
config
.
y
,
config
.
width
,
config
.
height
);
this
.
ctx
.
restore
();
},
// 绘制连接线(支持多坐标点)
drawLine
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
strokeStyle
=
config
.
color
;
this
.
ctx
.
lineWidth
=
config
.
lineWidth
;
this
.
ctx
.
beginPath
();
config
.
points
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
});
this
.
ctx
.
stroke
();
this
.
ctx
.
restore
();
},
// 绘制背景图(独立方法)
drawBackground
()
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
drawImage
(
this
.
bgImage
,
0
,
0
,
this
.
canvas
.
width
,
this
.
canvas
.
height
);
this
.
ctx
.
restore
();
},
// 绘制water.png(独立方法)
// drawWaterImage() {
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// this.ctx.drawImage(
// this.waterImage,
// 0,
// this.canvas.height - 255,
// 485,
// 255
// );
// this.ctx.restore();
// },
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages
()
{
// 1. 绘制背景图
this
.
drawBackground
();
// 2. 绘制po.png(遍历配置数组)
// console.log(this.canvasDataReal.poConfigs, "poConfigs");
this
.
canvasDataReal
.
poConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawPoImage
(
config
);
});
// 3. 绘制guan.png(遍历配置数组)
// console.log(this.canvasDataReal.guanConfigs, "guanConfigs");
this
.
canvasDataReal
.
guanConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawGuanImage
(
config
);
});
// 4. 绘制连接线(遍历配置数组)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawLine
(
config
);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>
0
)
{
// 添加可选链校验
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const
equipment
=
this
.
equipmentDataList
[
subindex
];
const
depth
=
equipment
.
depth
||
""
;
// 添加空值校验
// 绘制当前点的文字
this
.
drawText
({
x
:
point
.
x
,
y
:
this
.
canvas
.
height
-
point
.
y
,
text
:
`浸润线埋深:
${
depth
}
m`
,
});
});
}
});
// 新增:绘制白色警戒线下方海蓝色阴影
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
'
white
'
&&
lineConfig
.
points
.
length
>=
2
)
{
// 至少需要2个点构成直线
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系(左上角原点,Y轴向下)
// // 增加测试数据
// lineConfig.points.push({
// x: lineConfig.points[1].x - 150,
// y: lineConfig.points[1].y -150
// })
// 将警戒线坐标转换为默认坐标系(原坐标系Y轴向上)
const
canvasHeight
=
this
.
canvas
.
height
;
// 缓存画布高度
const
convertedPoints
=
lineConfig
.
points
.
map
(
point
=>
({
x
:
point
.
x
,
y
:
point
.
y
// 转换为默认Y轴向下的坐标
}));
// 遍历相邻点对,生成梯形
for
(
let
i
=
0
;
i
<
convertedPoints
.
length
-
1
;
i
++
)
{
const
start
=
convertedPoints
[
i
];
const
end
=
convertedPoints
[
i
+
1
];
// 构建当前线段对应的梯形四个顶点
const
trapezoid
=
[
start
,
// 顶部左端点
end
,
// 顶部右端点
{
x
:
end
.
x
,
y
:
canvasHeight
},
// 底部右端点(垂直投影到底边)
{
x
:
start
.
x
,
y
:
canvasHeight
},
// 底部左端点(垂直投影到底边)
];
// 绘制当前梯形
this
.
ctx
.
fillStyle
=
'
rgba(59, 175, 251, 0.3)
'
;
// 海蓝色,透明度30%
this
.
ctx
.
beginPath
();
trapezoid
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
});
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
}
this
.
ctx
.
restore
();
}
});
// 5. 绘制water.png
// this.drawWaterImage();
},
/** 加载所有图片并绘制 */
loadAllImages
()
{
// 加载背景图(原有)
this
.
bgImage
=
new
Image
();
this
.
bgImage
.
src
=
require
(
"
@/assets/images/jrx/bg.png
"
);
// // 加载 water.png
// this.waterImage = new Image();
// this.waterImage.src = require("@/assets/images/jrx/water.png");
// 加载 po.png
this
.
poImage
=
new
Image
();
this
.
poImage
.
src
=
require
(
"
@/assets/images/jrx/po.png
"
);
// 加载 guan.png
this
.
guanImage
=
new
Image
();
this
.
guanImage
.
src
=
require
(
"
@/assets/images/jrx/guan0.png
"
);
// 等待所有图片加载完成
Promise
.
all
([
new
Promise
((
resolve
)
=>
(
this
.
bgImage
.
onload
=
resolve
)),
// new Promise((resolve) => (this.waterImage.onload = resolve)),
new
Promise
((
resolve
)
=>
(
this
.
poImage
.
onload
=
resolve
)),
new
Promise
((
resolve
)
=>
(
this
.
guanImage
.
onload
=
resolve
)),
])
.
then
(()
=>
{
// 所有图片加载完成后绘制
this
.
drawAllImages
();
})
.
catch
(()
=>
{
console
.
error
(
"
部分图片加载失败
"
);
});
},
/** 初始化图表(关键修改:调整图例位置) */
initChart1
()
{
let
params
=
{
sort
:
"
date,desc
"
,
};
if
(
this
.
form
.
query
.
daterange
)
{
params
.
daterange
=
this
.
form
.
query
.
daterange
.
join
(
"
,
"
);
}
if
(
this
.
form
.
query
.
sensorid
)
{
params
.
code
=
this
.
form
.
query
.
sensorid
;
}
request
({
url
:
"
data/st/imghistory
"
,
method
:
"
get
"
,
params
,
}).
then
((
res
)
=>
{
const
data
=
res
.
body
;
// const data = this.getChartData().body
// console.log("data", data);
const
chartData
=
this
.
seriesDataFormat
(
data
,
{
datekey
:
"
date
"
});
var
warningLine
=
undefined
;
// this.form.config.warningLine;
var
option
=
{
valEnabled
:
true
,
opacity
:
1
,
lineWidth
:
3
,
};
var
alarmData
=
this
.
discernValidAlarmValue
(
data
.
alarm
,
data
.
lists
,
chartData
.
series
,
warningLine
,
option
);
// const chartData = data
// console.log("chartCData", chartData);
Highcharts
.
setOptions
({
global
:
{
useUTC
:
false
,
},
lang
:
{
resetZoom
:
"
重置缩放比例
"
,
},
});
this
.
chartInstance
=
new
Highcharts
.
chart
(
this
.
$refs
.
chartContainer
,
{
chart
:
{
//type: '',
backgroundColor
:
"
transparent
"
,
//marginTop:30,
//marginBottom:30,
//marginLeft:30,
zoomType
:
"
x
"
,
// xy
},
valEnabled
:
true
,
opacity
:
1
,
lineWidth
:
3
,
title
:
{
text
:
""
,
},
subtitle
:
{
text
:
""
,
},
tooltip
:
{
enabled
:
false
,
borderWidth
:
10
,
},
xAxis
:
{
type
:
"
datetime
"
,
// 最为关键的代码:如果为空数组,则导致日期格式化失效!!
categories
:
chartData
.
categories
[
0
]
&&
chartData
.
categories
,
lineWidth
:
0
,
//lineColor:'#ff0000',
gridLineColor
:
"
#aaa
"
,
dateTimeLabelFormats
:
{
millisecond
:
"
%H:%M:%S.%L
"
,
second
:
"
%H:%M:%S
"
,
minute
:
"
%H:%M
"
,
hour
:
"
%H:%M
"
,
day
:
"
%m-%d
"
,
week
:
"
%m-%d
"
,
month
:
"
%Y-%m
"
,
year
:
"
%Y
"
,
},
},
yAxis
:
{
title
:
{
text
:
""
,
},
labels
:
{
x
:
-
6
,
},
gridLineColor
:
"
#aaa
"
,
max
:
null
,
},
plotOptions
:
{
column
:
{
borderWidth
:
0
,
//y:50,
//itemMarginTop:50,
},
bar
:
{
borderWidth
:
0
,
},
},
tooltip
:
{
// {point.y:.4f} // 保留4位小数
//headerFormat: '
<
span
style
=
"
font-size:10px
"
>
{
point
.
key
}
<
/span><table>'
,
pointFormat
:
'
<tr><td style="color:{series.color};padding:0">{series.name}:</td>
'
+
'
<td style="padding:0"><b>{point.y}
'
+
data
.
danwei
+
"
</b> </td></tr>
"
,
footerFormat
:
"
</table>
"
,
shared
:
true
,
useHTML
:
true
,
dateTimeLabelFormats
:
{
millisecond
:
"
%H:%M:%S.%L
"
,
second
:
"
%H:%M:%S
"
,
minute
:
"
%H:%M
"
,
hour
:
"
%H:%M
"
,
day
:
"
%m-%d %H时
"
,
week
:
"
%m-%d
"
,
month
:
"
%Y-%m
"
,
year
:
"
%Y
"
,
},
},
legend
:
{
enabled
:
chartData
.
series
.
length
>
1
?
true
:
false
,
// 图例定位
layout
:
"
horizontal
"
,
// 水平布局:“horizontal”, 垂直布局:“vertical”
floating
:
false
,
// 图列是否浮动
align
:
"
right
"
,
// 图例容器
//width:'100%', // number || String
padding
:
2
,
// 内边距
margin
:
2
,
borderRadius
:
5
,
//borderWidth:1,
verticalAlign
:
"
top
"
,
// 图例项
//itemWidth:120, // 宽度
itemDistance
:
10
,
// 间距 20
y
:
-
10
,
itemMarginTop
:
2
,
itemStyle
:
{},
itemHoverStyle
:
{},
},
credits
:
{
enabled
:
false
,
},
series
:
chartData
.
series
,
});
});
},
seriesDataFormat
(
data
,
opts
)
{
var
names
=
data
.
names
||
[],
list
=
data
.
list
||
data
.
lists
,
series
=
[],
categories
=
[],
maxVal
=
0
;
if
(
names
[
0
]
&&
list
)
{
var
colors
=
[
"
#7CB5EC
"
,
"
#90ED7D
"
,
"
#F7A35C
"
,
"
#8085E9
"
,
"
#F15C80
"
,
"
#E4D354
"
,
"
#2B908F
"
,
"
#F45B5B
"
,
"
#91E8E1
"
,
"
#0769CB
"
,
"
#00ABBD
"
,
"
#ffd886
"
,
"
#9F2E61
"
,
"
#4D670C
"
,
];
var
len
=
names
.
length
;
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
var
item
=
names
[
i
];
var
serie
=
{
name
:
item
.
name
,
data
:
[],
key
:
item
.
key
,
type
:
data
.
chartType
,
color
:
colors
[
i
],
};
opts
&&
serie
.
type
&&
(
serie
.
type
=
opts
.
type
);
series
.
push
(
serie
);
}
for
(
var
item
of
list
)
{
var
values
=
item
.
values
;
//var datetime = item[opts.datekey || 'dateUnit'];
//var time = datetime.indexOf(' ') > 0 ? datetime.split(' ')[1] : datetime;
var
timestamp
=
item
[
"
date
"
];
//categories.push(timestamp);
for
(
var
serie
of
series
)
{
var
value
=
values
[
serie
.
key
]
*
1
;
Math
.
abs
(
value
)
>
maxVal
&&
(
maxVal
=
Math
.
abs
(
value
));
serie
.
data
.
push
([
timestamp
,
value
]);
}
}
}
return
{
series
:
series
,
categories
:
categories
,
maxVal
:
maxVal
};
},
discernValidAlarmValue
(
alarms
,
list
,
series
,
direction
,
opts
)
{
var
xLength
=
(
list
||
[]).
length
,
maxAlarm
=
0
,
opts
=
opts
||
{};
if
(
alarms
&&
xLength
)
{
var
value
=
alarms
.
value
;
// discern
var
levelDist
=
[
{
color
:
"
red
"
,
name
:
"
红色报警线
"
},
{
color
:
"
orange
"
,
name
:
"
橙色报警线
"
},
{
color
:
"
yellow
"
,
name
:
"
黄色报警线
"
},
{
color
:
"
blue
"
,
name
:
"
蓝色报警线
"
},
],
alarmLine
=
{},
setAlarmSerie
=
function
(
value
,
name
,
color
)
{
// 修改蓝色色值
color
===
"
blue
"
&&
(
color
=
"
#3BAFFB
"
);
var
sx
=
list
[
0
].
date
,
ex
=
list
[
xLength
-
1
].
date
;
var
serie
=
{
name
:
name
,
type
:
"
spline
"
,
data
:
[
{
x
:
sx
,
y
:
value
},
{
x
:
ex
,
y
:
value
},
],
color
:
color
,
enableMouseTracking
:
false
,
legend
:
false
,
showInLegend
:
false
,
dashStyle
:
"
ShortDot
"
,
lineWidth
:
opts
.
lineWidth
||
1
,
states
:
{
inactive
:
{
opacity
:
opts
.
opacity
,
},
},
dataLabels
:
{
enabled
:
opts
.
valEnabled
||
false
,
// 数据值, 2022/11/11(周五) 因多条报警线暂时关闭
//backgroundColor:'red',
verticalAlign
:
"
middle
"
,
padding
:
0
,
defer
:
false
,
allowOverlap
:
true
,
color
:
color
,
style
:
{
textOutline
:
"
none
"
,
},
},
tooltip
:
{
//footerFormat:'',
//pointFormat:'',
headerFormat
:
""
,
//nullFormat:'',
},
marker
:
{
enabled
:
false
,
},
zIndex
:
-
10
,
};
series
.
push
(
serie
);
};
/* 智能报警线
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
// 多条报警线
for
(
var
item
of
levelDist
)
{
item
.
value
=
value
[
item
.
color
];
alarmLine
[
item
.
color
]
=
item
;
}
// add
for
(
var
key
in
alarmLine
)
{
var
line
=
alarmLine
[
key
];
line
.
value
>
maxAlarm
&&
(
maxAlarm
=
line
.
value
);
setAlarmSerie
(
line
.
value
,
line
.
name
,
line
.
color
);
direction
&&
setAlarmSerie
(
0
-
line
.
value
,
line
.
name
,
line
.
color
);
}
}
return
{
series
,
maxAlarm
};
},
/** 切换图表类型 */
switchChartType
(
type
)
{
this
.
currentChartType
=
type
;
if
(
this
.
chartInstance
)
{
this
.
chartInstance
.
series
.
forEach
((
series
)
=>
{
series
.
update
({
type
:
this
.
currentChartType
});
});
}
},
// loadData: function () {
// // console.log(this.form, "form");
// // this.initChart1();
// // this.getCanvasData();
// return reqApi.common.getRequst;
// },
loadData
:
reqApi
.
common
.
getRequst
,
cancelForm
()
{
this
.
form
.
visible
=
false
;
},
submitForm
(
form
,
item
)
{
reqApi
.
common
.
submitForm
.
call
(
this
,
form
,
item
);
},
},
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scope
>
.qyzz
{
}
</
style
>
src/views/dataMonitor/jrx/history/index.vue
View file @
83aacf1b
<
template
>
<div
class=
"common-page qyzz page-t1"
>
<div
class=
"option page-row"
>
<table-filter
ref=
"filter"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:config=
"form.config"
:loadData=
"loadData"
/>
<table-filter
ref=
"filter"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
<div
class=
"new-container"
style=
"display: flex"
>
<div
class=
"canvas-wrapper"
style=
"width: 1000px"
>
<!-- 替换为 Canvas 元素 -->
<canvas
ref=
"canvas"
id=
"mainCanvas"
width=
"1000"
style=
"background: #f0f0f0"
></canvas>
<canvas
ref=
"canvas"
id=
"mainCanvas"
width=
"1000"
style=
"background: #f0f0f0"
></canvas>
</div>
<div
class=
"chart-wrapper"
style=
"padding-left: 0px"
>
<div
ref=
"chartContainer"
style=
"
width: 870px;
<div
ref=
"chartContainer"
style=
"
width: 850px;
height: 550px;
margin-bottom: 20px;
margin-left: 10px;
border: 1px solid gainsboro;
"
></div>
<div
class=
"chart-btn-group"
>
<button
size=
"small"
:type=
"currentChartType === 'line' ? 'primary' : ''"
@
click=
"switchChartType('line')"
>
"
></div>
<div
class=
"chart-btn-group"
style=
"margin-left: 10px;"
>
<button
size=
"small"
:type=
"currentChartType === 'line' ? 'primary' : ''"
@
click=
"switchChartType('line')"
>
折线图
</button>
<button
size=
"small"
:type=
"currentChartType === 'column' ? 'primary' : ''"
@
click=
"switchChartType('column')"
>
<button
size=
"small"
:type=
"currentChartType === 'column' ? 'primary' : ''"
@
click=
"switchChartType('column')"
>
柱状图
</button>
</div>
...
...
@@ -56,49 +35,24 @@
<div
class=
"content-fix"
>
<div
class=
"toolbar"
>
<div>
<el-button
v-for=
"(item, key) in form.config.otherBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button
>
<el-button
v-for=
"(item, key) in form.config.otherBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button>
</div>
<div>
<el-button
v-for=
"(item, key) in form.config.rightBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button
>
<el-button
v-for=
"(item, key) in form.config.rightBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref=
"cuTable"
:table=
"table"
:Dict=
"Dict"
:config=
"form.config"
:loadData=
"loadData"
/>
<cu-table
ref=
"cuTable"
:table=
"table"
:Dict=
"Dict"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref=
"cuForm"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:submit=
"submitForm"
:cancel=
"cancelForm"
:watchKeys=
"['paperfilename']"
/>
<cu-form
ref=
"cuForm"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:submit=
"submitForm"
:cancel=
"cancelForm"
:watchKeys=
"['paperfilename']"
/>
</div>
</
template
>
...
...
@@ -160,20 +114,41 @@ export default {
bgImage
:
null
,
// 背景图对象
waterImage
:
null
,
// 新增:water.png 图片对象
poImage
:
null
,
// 新增:po.png 图片对象
waterValue
:
0
,
// 新增:水位值
canvasDataReal
:
{
poConfigsWH
:
[{
// 基础信息配置对象 用于换算具体画布xy坐标点
xieMianW
:
0
,
// 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW
:
0
,
// 第一个坡平面距离平面宽度。
pingMianH
:
0
,
// 第一个坡平面距离平面高度。
kongW
:
0
,
// 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH
:
0
,
// 目前孔的深度
maishen
:
0
// 水位到管口的垂直距离
}],
otherConfig
:
{
gantanW
:
0
,
// 干滩距离水平面的宽度(根据最后一个坡平面坐标点计算xy。)
tuduiW
:
0
,
// 干滩距离水平面中间的土堆
shuiW
:
0
,
// 水平面的宽度
shuiH
:
0
,
// 水平面的高度
},
// Canvas绘制配置(支持批量扩展)
poConfigs
:
[
{
x
:
0
,
y
:
null
,
width
:
879
,
height
:
150
},
// 第一张po.png配置
{
x
:
0
,
y
:
null
,
width
:
879
-
250
,
height
:
150
},
// 第二张po.png配置(宽度减少250px)
poConfigsXY
:
[
// 根据poConfigsWH 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是斜面和平面点
],
guanConfigsXY
:
[
// 根据poConfigsXY和poConfigsWH的孔信息 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是孔起始坐标和结束坐标
],
gantanConfigsXY
:
[
],
jrxConfigsXY
:
[
],
shuiweiConfigsXY
:
[
],
poConfigs
:
[
{
x
:
null
,
y
:
null
,
width
:
6
,
height
:
121
,
image
:
"
guanImage
"
},
// 第一张guan0.png
{
x
:
null
,
y
:
null
,
width
:
6
,
height
:
200
,
image
:
"
guanImage
"
},
// 第二张guan0.png(高度调整)
tuduiConfigsXY
:
[
],
jingjiexianConfigsXY
:
[
],
lineConfigs
:
[
{
points
:
[],
color
:
"
red
"
,
lineWidth
:
2
},
// 红色连接线配置
{
points
:
[],
color
:
"
yellow
"
,
lineWidth
:
2
},
// 黄色连接线配置
//
{ points: [], color: "red", lineWidth: 2 }, // 红色连接线配置
//
{ points: [], color: "yellow", lineWidth: 2 }, // 黄色连接线配置
],
},
// canvasData: [
...
...
@@ -250,6 +225,28 @@ export default {
});
},
methods
:
{
// 最新
// calculateWidth(height, angleDegrees) {
// // 1. 将角度从度转换为弧度(JavaScript的Math.tan()使用弧度)
// const angleRadians = angleDegrees * Math.PI / 180;
// // 2. 计算角度的正切值
// const tanValue = Math.tan(angleRadians);
// // 3. 计算水平距离 L = H / tan(θ)
// const width = height / tanValue;
// return width;
// // 使用示例
// const height = 40; // 垂直高度
// const angle = 25; // 坡度角度(度)
// const result = calculateWidth(height, angle);
// console.log(`宽度 = ${result.toFixed(2)}`);
// // 输出:宽度 = 85.78
// },
/** 绘制文字标注 */
drawText
(
config
)
{
this
.
ctx
.
save
();
...
...
@@ -286,22 +283,18 @@ export default {
params
,
}).
then
(
async
(
res
)
=>
{
const
data
=
res
.
body
;
if
(
!
data
.
length
)
{
// 数据为空时清空画布
this
.
clearCanvas
();
return
;
}
// console.log("剖面接口数据", data);
// console.table(JSON.parse(JSON.stringify(data[0].jrxStepsDtoList)));
// console.table(JSON.parse(JSON.stringify(data[0].equipmentDataList)));
this
.
waterValue
=
data
[
0
].
wtValue
;
await
this
.
handleCanvasData
(
data
);
this
.
initCanvas
();
});
},
handleCanvasData
(
list
=
[])
{
handleCanvasData
New
(
list
=
[])
{
return
new
Promise
((
resolve
)
=>
{
// 新增Promise封装
let
canvasWidth
=
1000
;
// 默认宽度
...
...
@@ -324,6 +317,167 @@ export default {
const
po_pad_right
=
180
;
// poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const
poH
=
150
;
const
line_color
=
[
"
red
"
,
"
orange
"
,
"
yellow
"
,
"
blue
"
,
"
white
"
];
//第一层台阶的开孔深度和设备图片相除的系数
const
sbHeightModulus
=
poumian
.
equipmentDataList
[
0
].
jrxTrepanning
/
130
;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡面基本信息获取
for
(
let
index
=
0
;
index
<
poCount
;
index
++
)
{
this
.
poConfigsWH
.
push
({
xieMianW
:
10
+
index
,
// 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW
:
50
+
index
,
// 第一个坡平面距离平面宽度。
pingMianH
:
20
+
index
,
// 第一个坡平面距离平面高度。
kongW
:
10
+
index
,
// 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH
:
20
+
index
,
// 目前孔的深度
jrxTrepanning
:
10
+
index
,
// 浸润线开口深度
})
}
// 破平面xy计算
this
.
poConfigsXY
=
[{
x
:
0
,
y
:
0
}]
this
.
poConfigsWH
.
forEach
((
item
)
=>
{
this
.
poConfigsXY
.
push
({
// 斜坡点
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
+
item
.
xieMianW
,
// 每个斜平坡计算点都根据上一个前面已有的最后一个坐标点进行添加 第一个为x0y0
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
+
item
.
pingMianH
,
})
this
.
poConfigsXY
.
push
({
// 平坡点
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
+
item
.
pingMianW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
,
})
// 孔的xy计算
this
.
guanConfigsXY
.
push
({
// 管的起始点 -2是获取该斜坡点的结束坐标加上孔距离位置=孔在平坡上面的位置
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
x
+
item
.
kongW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
y
+
0
,
// 这里的0为了突出孔的仪器设备 突出坡平面距离。这里先放置0(方便后面浸润线水位的计算),等后面实际画管线的时候临时加上固定值。
})
this
.
guanConfigsXY
.
push
({
// 管的结束点
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
x
+
item
.
kongW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
y
-
item
.
kongH
,
maishen
:
item
.
depth
,
// 水位到管口的垂直距离
})
})
this
.
gantanConfigsXY
=
[
// 干滩的xy坐标点
{
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
},
// 干滩的起始点
{
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
+
this
.
otherConfig
.
gantanW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
-
this
.
otherConfig
.
shuiH
},
// 干滩的结束点 (最高平坡减去水位高度)
]
this
.
guanConfigsXY
.
forEach
((
item
,
index
)
=>
{
if
(
index
%
2
==
0
)
{
// 偶数为管的起始点
this
.
jrxConfigsXY
.
push
(
{
x
:
item
.
x
,
y
:
item
.
y
-
item
.
maishen
},
// 浸润线的坐标点是平坡y-埋深的值(水位到平坡的垂直距离)
)
}
})
this
.
shuiweiConfigsXY
=
[
// 水位的xy坐标点(画矩形)
{
x
:
this
.
gantanConfigsXY
[
1
].
x
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的起始点
{
x
:
this
.
gantanConfigsXY
[
1
].
x
+
this
.
otherConfig
.
tuduiW
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的结束点 (最高平坡减去水位高度)
]
this
.
tuduiConfigsXY
=
[
{
x
:
this
.
gantanConfigsXY
[
1
].
x
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的起始点
{
x
:
this
.
gantanConfigsXY
[
1
].
x
+
this
.
otherConfig
.
tuduiW
,
y
:
0
},
// 水位的结束点
]
this
.
jingjiexianConfigsXY
=
[
{
x
:
this
.
gantanConfigsXY
[
1
].
x
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的起始点
{
x
:
this
.
gantanConfigsXY
[
1
].
x
+
this
.
otherConfig
.
tuduiW
,
y
:
0
},
// 水位的结束点
]
// 警戒线逻辑- 初始话基本数据结构
for
(
let
index1
=
0
;
index1
<
lineCount
;
index1
++
)
{
this
.
jingjiexianConfigsXY
.
push
({
// 设置
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
4
*
index1
,
// 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
// this.jingjiexianConfigsXY.forEach((line, index) => {
// let lineValKey = line.color == "white" ? "depth" : line.color + "Alarm";
// // 几个管孔几个坐标点
// poumian.equipmentDataList.forEach((equip, subindex) => {
// line.points.push({
// x: this.canvasDataReal.guanConfigs[subindex].x + 1,
// y:
// this.canvasDataReal.guanConfigs[subindex].y +
// equip[lineValKey], // 管设备的y坐标+设备的警戒值*系数
// });
// });
// });
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
line
,
index
)
=>
{
let
lineValKey
=
line
.
color
==
"
white
"
?
"
depth
"
:
line
.
color
+
"
Alarm
"
;
// 几个管孔几个坐标点
poumian
.
equipmentDataList
.
forEach
((
equip
,
subindex
)
=>
{
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
,
y
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
equip
[
lineValKey
]
/
sbHeightModulus
,
});
});
});
// 4. 绘制连接线(遍历配置数组)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawLine
(
config
);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>
0
)
{
// 添加可选链校验
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const
equipment
=
this
.
equipmentDataList
[
subindex
];
const
depth
=
equipment
.
depth
||
""
;
// 添加空值校验
// 绘制当前点的文字
this
.
drawText
({
x
:
point
.
x
,
y
:
this
.
canvas
.
height
-
point
.
y
,
text
:
`浸润线埋深:
${
depth
}
m`
,
});
});
}
});
resolve
();
// 数据处理完成后触发resolve
});
},
handleCanvasData
(
list
=
[])
{
return
new
Promise
((
resolve
)
=>
{
// 新增Promise封装
let
canvasWidth
=
1000
;
// 默认宽度
let
canvasHeight
=
600
;
// 默认高度
// 更新Canvas元素属性和样式
const
canvasEl
=
this
.
$refs
.
canvas
;
if
(
canvasEl
)
{
// 实际绘图区域尺寸(关键属性)
canvasEl
.
width
=
canvasWidth
;
canvasEl
.
height
=
canvasHeight
;
// 显示尺寸(与绘图区域保持一致)
canvasEl
.
style
.
width
=
`
${
canvasWidth
}
px`
;
canvasEl
.
style
.
height
=
`
${
canvasHeight
}
px`
;
}
// 数据清洗
const
poumian
=
list
[
0
];
// 坡面数据
const
poCount
=
poumian
.
jrxStepsDtoList
.
length
;
const
lineCount
=
5
;
const
po_pad_right
=
-
140
;
// poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const
poH
=
450
;
const
line_color
=
[
"
red
"
,
"
orange
"
,
"
yellow
"
,
"
blue
"
,
"
white
"
];
this
.
canvasDataReal
.
poConfigs
=
[];
this
.
canvasDataReal
.
guanConfigs
=
[];
this
.
canvasDataReal
.
lineConfigs
=
[];
...
...
@@ -334,13 +488,12 @@ export default {
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡数据数据格式处理
poumian
.
jrxStepsDtoList
.
forEach
((
po
,
poIndex
)
=>
{
this
.
canvasDataReal
.
poConfigs
.
push
({
x
:
0
,
y
:
canvasHeight
-
(
poIndex
+
1
)
*
poH
,
width
:
canvasWidth
-
(
poIndex
+
1
)
*
po_pad_right
,
x
:
-
14
0
,
y
:
canvasHeight
-
(
poIndex
)
*
poH
,
width
:
canvasWidth
-
(
poIndex
)
*
po_pad_right
,
height
:
poH
,
});
});
...
...
@@ -348,13 +501,23 @@ export default {
poumian
.
equipmentDataList
.
forEach
((
equipment
,
equipIndex
)
=>
{
const
po
=
this
.
canvasDataReal
.
poConfigs
[
equipIndex
];
// 管孔数据数据格式处理
if
(
equipIndex
==
1
)
{
this
.
canvasDataReal
.
guanConfigs
.
push
({
x
:
po
.
width
*
0.75
+
50
,
y
:
canvasHeight
-
po
.
height
*
(
equipIndex
+
1
),
width
:
6
,
x
:
po
.
width
*
0.234
+
100
*
(
equipIndex
+
1
),
y
:
canvasHeight
-
po
.
height
+
133
,
width
:
7
,
// 可以设置不同的宽度
height
:
(
equipment
.
jrxTrepanning
/
sbHeightModulus
)
*
1.3
,
image
:
"
guanImage2
"
,
// 使用不同的图片
});
}
else
{
this
.
canvasDataReal
.
guanConfigs
.
push
({
x
:
po
.
width
*
0.234
+
100
*
(
equipIndex
+
1
),
y
:
canvasHeight
-
po
.
height
+
208
,
width
:
7
,
height
:
equipment
.
jrxTrepanning
/
sbHeightModulus
,
image
:
"
guanImage
"
,
});
}
});
// 警戒线逻辑- 初始话基本数据结构
...
...
@@ -364,36 +527,33 @@ export default {
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
20
*
index1
,
// 每条线之间的差值
cha
:
4
*
index1
,
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
line
,
index
)
=>
{
let
lineValKey
=
line
.
color
==
"
white
"
?
"
depth
"
:
line
.
color
+
"
Alarm
"
;
let
lineValKey
=
line
.
color
==
"
white
"
?
"
depth
"
:
line
.
color
+
"
Alarm
"
;
// 几个管孔几个坐标点
poumian
.
equipmentDataList
.
forEach
((
equip
,
subindex
)
=>
{
let
xOffset
=
0
;
let
baseY
=
0
;
// 对于彩色线(非白色),使用统一的计算方式,确保线条是直线
if
(
line
.
color
!==
"
white
"
)
{
// 对所有彩色线使用相同的计算逻辑,不使用不同的分母
xOffset
=
line
.
cha
/
20
;
// 使用统一的分母值
// 直接根据设备数据计算y坐标
baseY
=
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
equip
[
lineValKey
]
/
sbHeightModulus
;
}
else
{
baseY
=
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
height
;
}
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
,
y
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
equip
[
lineValKey
]
/
sbHeightModulus
,
// 管设备的y坐标+设备的警戒值*系数
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
+
xOffset
,
y
:
baseY
});
});
});
// console.log("坡面处理完毕数据", this.canvasDataReal);
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.poConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.guanConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.lineConfigs))
// );
resolve
();
// 数据处理完成后触发resolve
});
},
...
...
@@ -405,7 +565,6 @@ export default {
console
.
error
(
"
Canvas 元素未找到
"
);
return
;
}
// console.log(this.canvas, "canvas");
this
.
ctx
=
this
.
canvas
.
getContext
(
"
2d
"
);
// 坐标系变换:将原点移至左下角(默认原点在左上角)
...
...
@@ -418,6 +577,20 @@ export default {
this
.
loadAllImages
();
},
// 绘制water.png(独立方法)
drawWaterImage
()
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
drawImage
(
this
.
waterImage
,
500
,
this
.
canvas
.
height
-
(
180
+
this
.
waterValue
*
1.2
),
550
,
550
);
this
.
ctx
.
restore
();
},
// 绘制单个po.png(支持配置参数)
drawPoImage
(
config
)
{
this
.
ctx
.
save
();
...
...
@@ -448,18 +621,45 @@ export default {
this
.
ctx
.
restore
();
},
// 绘制连接线(支持多坐标点)
drawSecondPipeImage
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 可以使用不同的绘制逻辑
const
targetImage
=
this
[
config
.
image
]
||
this
.
guanImage
;
this
.
ctx
.
drawImage
(
targetImage
,
config
.
x
,
config
.
y
,
config
.
width
,
config
.
height
);
this
.
ctx
.
restore
();
},
// 绘制连接线(支持多坐标点)白色
drawLine
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
strokeStyle
=
config
.
color
;
this
.
ctx
.
lineWidth
=
config
.
lineWidth
;
this
.
ctx
.
beginPath
();
// 修复语法错误并改进白色线对齐逻辑
if
(
config
.
color
===
'
white
'
&&
this
.
canvasDataReal
.
guanConfigs
.
length
>
0
)
{
// 确保至少有两个点可以连接
if
(
config
.
points
&&
config
.
points
.
length
>=
2
)
{
config
.
points
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
});
}
}
else
{
config
.
points
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
// index === 0 ? this.ctx.moveTo(point.x - 400, point.y + 220) : this.ctx.lineTo(point.x, point.y);
// index === 0 ? this.ctx.moveTo(point.x - 400, point.y + 190) : this.ctx.lineTo(point.x, point.y);
});
}
this
.
ctx
.
stroke
();
this
.
ctx
.
restore
();
},
...
...
@@ -477,103 +677,219 @@ export default {
);
this
.
ctx
.
restore
();
},
// 绘制文字 箭头
createCustomLineWithText
(
config
)
{
// 配置参数默认值
const
defaultConfig
=
{
points
:
[],
color
:
'
#000000
'
,
lineWidth
:
2
,
showLine
:
true
,
text
:
''
,
textPosition
:
'
middle
'
,
textDirection
:
'
horizontal
'
,
textAngle
:
0
,
textOffset
:
10
,
textColor
:
'
#000000
'
,
fontSize
:
10
,
showArrow
:
false
,
showArrowAtStart
:
false
,
arrowSize
:
8
};
// 绘制water.png(独立方法)
// drawWaterImage() {
// this.ctx.save();
// this.ctx.setTransform(1, 0, 0, 1, 0, 0);
// this.ctx.drawImage(
// this.waterImage,
// 0,
// this.canvas.height - 255,
// 485,
// 255
// );
// this.ctx.restore();
// },
// 合并配置
const
finalConfig
=
{
...
defaultConfig
,
...
config
};
if
(
!
this
.
ctx
||
!
finalConfig
.
points
||
finalConfig
.
points
.
length
<
1
)
{
console
.
error
(
'
Canvas上下文或坐标点不足
'
);
return
;
}
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系
// 只有当showLine为true且lineWidth大于0时才绘制线条
if
(
finalConfig
.
showLine
&&
finalConfig
.
lineWidth
>
0
&&
finalConfig
.
points
.
length
>=
2
)
{
this
.
ctx
.
strokeStyle
=
finalConfig
.
color
;
this
.
ctx
.
lineWidth
=
finalConfig
.
lineWidth
;
this
.
ctx
.
beginPath
();
finalConfig
.
points
.
forEach
((
point
,
index
)
=>
{
if
(
index
==
0
)
{
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
);
}
else
{
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
}
});
this
.
ctx
.
stroke
();
// 新增:绘制箭头
if
(
finalConfig
.
showArrow
&&
finalConfig
.
points
.
length
>=
2
)
{
const
points
=
finalConfig
.
points
;
const
lastPoint
=
points
[
points
.
length
-
1
];
const
prevPoint
=
points
[
points
.
length
-
2
];
// 计算箭头方向
const
angle
=
Math
.
atan2
(
lastPoint
.
y
-
prevPoint
.
y
,
lastPoint
.
x
-
prevPoint
.
x
);
// 设置箭头样式
this
.
ctx
.
fillStyle
=
finalConfig
.
color
;
// 绘制箭头三角形
this
.
ctx
.
beginPath
();
this
.
ctx
.
moveTo
(
lastPoint
.
x
,
lastPoint
.
y
);
this
.
ctx
.
lineTo
(
lastPoint
.
x
-
finalConfig
.
arrowSize
*
Math
.
cos
(
angle
-
Math
.
PI
/
6
),
lastPoint
.
y
-
finalConfig
.
arrowSize
*
Math
.
sin
(
angle
-
Math
.
PI
/
6
)
);
this
.
ctx
.
lineTo
(
lastPoint
.
x
-
finalConfig
.
arrowSize
*
Math
.
cos
(
angle
+
Math
.
PI
/
6
),
lastPoint
.
y
-
finalConfig
.
arrowSize
*
Math
.
sin
(
angle
+
Math
.
PI
/
6
)
);
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
}
}
if
(
finalConfig
.
showArrowAtStart
&&
finalConfig
.
points
.
length
>=
2
)
{
const
points
=
finalConfig
.
points
;
const
firstPoint
=
points
[
0
];
const
secondPoint
=
points
[
1
];
// 计算起点箭头方向(与线段方向相反)
const
angle
=
Math
.
atan2
(
secondPoint
.
y
-
firstPoint
.
y
,
secondPoint
.
x
-
firstPoint
.
x
)
+
Math
.
PI
;
// 设置箭头样式
this
.
ctx
.
fillStyle
=
finalConfig
.
color
;
// 绘制起点箭头三角形
this
.
ctx
.
beginPath
();
this
.
ctx
.
moveTo
(
firstPoint
.
x
,
firstPoint
.
y
);
this
.
ctx
.
lineTo
(
firstPoint
.
x
-
finalConfig
.
arrowSize
*
Math
.
cos
(
angle
-
Math
.
PI
/
6
),
firstPoint
.
y
-
finalConfig
.
arrowSize
*
Math
.
sin
(
angle
-
Math
.
PI
/
6
)
);
this
.
ctx
.
lineTo
(
firstPoint
.
x
-
finalConfig
.
arrowSize
*
Math
.
cos
(
angle
+
Math
.
PI
/
6
),
firstPoint
.
y
-
finalConfig
.
arrowSize
*
Math
.
sin
(
angle
+
Math
.
PI
/
6
)
);
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
}
// 绘制文字
if
(
finalConfig
.
text
)
{
this
.
ctx
.
font
=
`
${
finalConfig
.
fontSize
}
px Arial`
;
this
.
ctx
.
fillStyle
=
finalConfig
.
textColor
;
// 计算文字位置
let
textX
,
textY
;
const
{
points
}
=
finalConfig
;
switch
(
finalConfig
.
textPosition
)
{
case
'
start
'
:
textX
=
points
[
0
].
x
;
textY
=
points
[
0
].
y
;
break
;
case
'
end
'
:
textX
=
points
[
points
.
length
-
1
].
x
;
textY
=
points
[
points
.
length
-
1
].
y
;
break
;
default
:
if
(
points
.
length
>=
2
)
{
const
midIndex
=
Math
.
floor
(
points
.
length
/
2
);
textX
=
(
points
[
midIndex
-
1
].
x
+
points
[
midIndex
].
x
)
/
2
;
textY
=
(
points
[
midIndex
-
1
].
y
+
points
[
midIndex
].
y
)
/
2
;
}
else
{
textX
=
points
[
0
].
x
;
textY
=
points
[
0
].
y
;
}
break
;
}
// 根据方向调整文字
switch
(
finalConfig
.
textDirection
)
{
case
'
vertical
'
:
this
.
ctx
.
save
();
this
.
ctx
.
translate
(
textX
,
textY
);
this
.
ctx
.
rotate
(
-
Math
.
PI
/
2
);
// 旋转90度
this
.
ctx
.
textAlign
=
'
center
'
;
this
.
ctx
.
textBaseline
=
'
middle
'
;
this
.
ctx
.
fillText
(
finalConfig
.
text
,
0
,
-
finalConfig
.
textOffset
);
this
.
ctx
.
restore
();
break
;
case
'
angle
'
:
const
angleRad
=
finalConfig
.
textAngle
*
Math
.
PI
/
180
;
this
.
ctx
.
save
();
this
.
ctx
.
translate
(
textX
,
textY
);
this
.
ctx
.
rotate
(
angleRad
);
this
.
ctx
.
textAlign
=
'
center
'
;
this
.
ctx
.
textBaseline
=
'
middle
'
;
this
.
ctx
.
fillText
(
finalConfig
.
text
,
0
,
-
finalConfig
.
textOffset
);
this
.
ctx
.
restore
();
break
;
default
:
// horizontal
this
.
ctx
.
textAlign
=
'
center
'
;
this
.
ctx
.
textBaseline
=
'
bottom
'
;
this
.
ctx
.
fillText
(
finalConfig
.
text
,
textX
,
textY
-
finalConfig
.
textOffset
);
break
;
}
}
this
.
ctx
.
restore
();
},
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages
()
{
// 1. 绘制背景图
this
.
drawBackground
();
// 绘制water.png
this
.
drawWaterImage
();
// 2. 绘制po.png(遍历配置数组)
// console.log(this.canvasDataReal.poConfigs, "poConfigs");
this
.
canvasDataReal
.
poConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawPoImage
(
config
);
});
// 3. 绘制guan.png(遍历配置数组)
// console.log(this.canvasDataReal.guanConfigs, "guanConfigs");
this
.
canvasDataReal
.
guanConfigs
.
forEach
((
config
,
index
)
=>
{
if
(
index
==
1
)
{
// 执行针对第二个管子的特殊绘制方法
this
.
drawSecondPipeImage
(
config
);
}
else
{
// 正常绘制其他管子
this
.
drawGuanImage
(
config
);
});
// 4. 绘制连接线(遍历配置数组)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawLine
(
config
);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>
0
)
{
// 添加可选链校验
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const
equipment
=
this
.
equipmentDataList
[
subindex
];
const
depth
=
equipment
.
depth
||
""
;
// 添加空值校验
// 绘制当前点的文字
this
.
drawText
({
x
:
point
.
x
,
y
:
this
.
canvas
.
height
-
point
.
y
,
text
:
`浸润线埋深:
${
depth
}
m`
,
});
});
}
});
// 新增:绘制白色警戒线下方海蓝色阴影
// 修改 drawAllImages 方法中的蓝色阴影绘制部分
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
'
white
'
&&
lineConfig
.
points
.
length
>=
2
)
{
// 至少需要2个点构成直线
if
(
lineConfig
.
color
===
'
white
'
&&
lineConfig
.
points
.
length
>=
2
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系(左上角原点,Y轴向下)
// // 增加测试数据
// lineConfig.points.push({
// x: lineConfig.points[1].x - 150,
// y: lineConfig.points[1].y -150
// })
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系
// 将警戒线坐标转换为默认坐标系(原坐标系Y轴向上)
const
canvasHeight
=
this
.
canvas
.
height
;
// 缓存画布高度
const
convertedPoints
=
lineConfig
.
points
.
map
(
point
=>
({
x
:
point
.
x
,
y
:
point
.
y
// 转换为默认Y轴向下的坐标
}));
// 直接使用白色线的原始坐标点,确保完全对齐
const
whiteLinePoints
=
lineConfig
.
points
;
const
canvasHeight
=
this
.
canvas
.
height
;
// 遍历相邻点对,生成梯形
for
(
let
i
=
0
;
i
<
converted
Points
.
length
-
1
;
i
++
)
{
const
start
=
converted
Points
[
i
];
const
end
=
converted
Points
[
i
+
1
];
// 遍历相邻点对,生成梯形阴影
for
(
let
i
=
0
;
i
<
whiteLine
Points
.
length
-
1
;
i
++
)
{
const
start
=
whiteLine
Points
[
i
];
const
end
=
whiteLine
Points
[
i
+
1
];
// 构建
当前线段对应的梯形四个顶点
// 构建
梯形四个顶点(确保与白色线完全重合)
const
trapezoid
=
[
start
,
// 顶部左端点
end
,
// 顶部右端点
{
x
:
end
.
x
,
y
:
canvasHeight
},
// 底部右端点
(垂直投影到底边)
{
x
:
start
.
x
,
y
:
canvasHeight
}
,
// 底部左端点(垂直投影到底边)
{
x
:
start
.
x
,
y
:
start
.
y
},
// 顶部左端点(与白色线起点完全对齐)
{
x
:
end
.
x
,
y
:
end
.
y
},
// 顶部右端点(与白色线终点完全对齐)
{
x
:
end
.
x
,
y
:
canvasHeight
},
// 底部右端点
{
x
:
start
.
x
,
y
:
canvasHeight
}
// 底部左端点
];
// 绘制
当前梯形
// 绘制
蓝色阴影
this
.
ctx
.
fillStyle
=
'
rgba(59, 175, 251, 0.3)
'
;
// 海蓝色,透明度30%
this
.
ctx
.
beginPath
();
trapezoid
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
});
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
...
...
@@ -583,8 +899,192 @@ export default {
}
});
// 5. 绘制water.png
// this.drawWaterImage();
// 确保在阴影绘制之后再绘制白色线条
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
config
)
=>
{
this
.
drawLine
(
config
);
});
const
colorsToConnect
=
[
'
red
'
,
'
orange
'
,
'
yellow
'
,
'
blue
'
];
// 为每种颜色定义对应的目标位置坐标
const
targetPoints
=
{
'
red
'
:
{
x
:
550
,
y
:
304
},
'
orange
'
:
{
x
:
560
,
y
:
307
},
'
yellow
'
:
{
x
:
570
,
y
:
310
},
'
blue
'
:
{
x
:
580
,
y
:
313
}
};
// 第二条 ....
colorsToConnect
.
forEach
(
color
=>
{
// 找到对应颜色的线配置
const
lineConfig
=
this
.
canvasDataReal
.
lineConfigs
.
find
(
config
=>
config
.
color
===
color
);
if
(
lineConfig
&&
lineConfig
.
points
.
length
>
0
)
{
const
lastPoint
=
lineConfig
.
points
[
lineConfig
.
points
.
length
-
1
];
// 获取该颜色对应的目标位置
const
targetPoint
=
targetPoints
[
color
];
// 绘制新的连接线,保持与原线相同的颜色和线宽
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
strokeStyle
=
color
;
this
.
ctx
.
lineWidth
=
lineConfig
.
lineWidth
||
2
;
this
.
ctx
.
beginPath
();
this
.
ctx
.
moveTo
(
lastPoint
.
x
-
500
,
lastPoint
.
y
+
300
);
this
.
ctx
.
lineTo
(
targetPoint
.
x
,
targetPoint
.
y
);
this
.
ctx
.
stroke
();
this
.
ctx
.
restore
();
}
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>
0
)
{
// 1. 收集所有设备信息,包括设备名称中的数字
const
deviceData
=
[];
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
const
equipment
=
this
.
equipmentDataList
[
subindex
];
if
(
equipment
)
{
// 提取设备名称中的数字
const
deviceNumber
=
equipment
.
sensorname
?
parseInt
(
equipment
.
sensorname
.
match
(
/
\d
+/
)[
0
]
||
'
0
'
)
:
0
;
deviceData
.
push
({
point
,
equipment
,
subindex
,
deviceNumber
,
isOdd
:
deviceNumber
%
2
===
1
});
}
});
// 2. 创建一个新的深度值数组,用于存放交换后的值
const
newDepths
=
new
Array
(
deviceData
.
length
).
fill
(
''
);
// 3. 实现相邻管子埋深值互换,根据设备名称中的数字奇偶性决定
for
(
let
i
=
0
;
i
<
deviceData
.
length
-
1
;
i
+=
2
)
{
// 检查当前两个设备
const
device1
=
deviceData
[
i
];
const
device2
=
deviceData
[
i
+
1
];
if
(
device1
&&
device2
)
{
// 如果第一个设备的编号是单数,则第一个管子的埋深值显示在第二个管子下面
if
(
device1
.
isOdd
)
{
newDepths
[
device1
.
subindex
]
=
device1
.
equipment
.
depth
||
''
;
newDepths
[
device2
.
subindex
]
=
device2
.
equipment
.
depth
||
''
;
}
else
if
(
!
device2
.
isOdd
)
{
newDepths
[
device1
.
subindex
]
=
device2
.
equipment
.
depth
||
''
;
newDepths
[
device2
.
subindex
]
=
device1
.
equipment
.
depth
||
''
;
}
}
}
// 处理可能的奇数个设备的最后一个设备
if
(
deviceData
.
length
%
2
===
1
)
{
const
lastDevice
=
deviceData
[
deviceData
.
length
-
1
];
newDepths
[
lastDevice
.
subindex
]
=
lastDevice
.
equipment
.
depth
||
''
;
}
// 4. 绘制文本,使用交换后的深度值
deviceData
.
forEach
(
device
=>
{
this
.
drawText
({
x
:
device
.
point
.
x
,
y
:
this
.
canvas
.
height
-
device
.
point
.
y
,
text
:
`浸润线埋深:
${
newDepths
[
device
.
subindex
]}
m`
,
});
});
}
});
// 浸润线
this
.
createCustomLineWithText
({
points
:
[
{
x
:
350
,
y
:
300
},
{
x
:
400
,
y
:
370
},
],
color
:
'
#000
'
,
lineWidth
:
1
,
text
:
'
浸润线
'
,
textPosition
:
'
start
'
,
// 文字位置:start、middle、end
textDirection
:
'
horizontal
'
,
// 文字方向:horizontal、vertical、angle
textOffset
:
9
,
textColor
:
'
#000
'
,
fontSize
:
14
,
showArrow
:
true
,
arrowSize
:
8
});
// 正常高水位
this
.
createCustomLineWithText
({
points
:
[
{
x
:
585
,
y
:
285
},
{
x
:
585
,
y
:
370
},
],
color
:
'
#000
'
,
lineWidth
:
1
,
text
:
'
正常高水位
'
,
textPosition
:
'
end
'
,
textDirection
:
'
horizontal
'
,
textOffset
:
-
20
,
textColor
:
'
#000
'
,
fontSize
:
14
});
// 平滩
this
.
createCustomLineWithText
({
points
:
[
{
x
:
587
,
y
:
285
},
{
x
:
520
,
y
:
285
},
],
color
:
'
#000
'
,
lineWidth
:
1
,
text
:
'
干滩
'
,
textPosition
:
'
middle
'
,
textDirection
:
'
horizontal
'
,
textOffset
:
20
,
textColor
:
'
orange
'
,
fontSize
:
15
,
showArrow
:
true
,
showArrowAtStart
:
true
,
arrowSize
:
7
});
// 大坝库
this
.
createCustomLineWithText
({
points
:
[
{
x
:
750
,
y
:
270
},
{
x
:
700
,
y
:
355
},
],
color
:
'
#000
'
,
lineWidth
:
1
,
text
:
'
大坝库
'
,
textPosition
:
'
start
'
,
textDirection
:
'
horizontal
'
,
textOffset
:
10
,
textColor
:
'
#2c4f7c
'
,
fontSize
:
15
});
// 传感器
this
.
createCustomLineWithText
({
points
:
[
{
x
:
300
,
y
:
480
},
{
x
:
400
,
y
:
370
},
],
text
:
'
渗压传感器
'
,
showLine
:
false
,
textPosition
:
'
start
'
,
textDirection
:
'
horizontal
'
,
textOffset
:
15
,
textColor
:
'
#000
'
,
fontSize
:
11
});
this
.
createCustomLineWithText
({
points
:
[
{
x
:
505
,
y
:
400
},
{
x
:
400
,
y
:
370
},
],
text
:
'
渗压传感器
'
,
showLine
:
false
,
textPosition
:
'
start
'
,
textDirection
:
'
horizontal
'
,
textOffset
:
15
,
textColor
:
'
#000
'
,
fontSize
:
11
});
},
/** 加载所有图片并绘制 */
loadAllImages
()
{
...
...
@@ -593,12 +1093,12 @@ export default {
this
.
bgImage
.
src
=
require
(
"
@/assets/images/jrx/bg.png
"
);
// // 加载 water.png
//
this.waterImage = new Image();
// this.waterImage.src = require("@/assets/images/jrx/water
.png");
this
.
waterImage
=
new
Image
();
this
.
waterImage
.
src
=
require
(
"
@/assets/images/jrx/shui
.png
"
);
// 加载
po
.png
// 加载
shan
.png
this
.
poImage
=
new
Image
();
this
.
poImage
.
src
=
require
(
"
@/assets/images/jrx/
po
.png
"
);
this
.
poImage
.
src
=
require
(
"
@/assets/images/jrx/
shan
.png
"
);
// 加载 guan.png
this
.
guanImage
=
new
Image
();
...
...
@@ -607,9 +1107,9 @@ export default {
// 等待所有图片加载完成
Promise
.
all
([
new
Promise
((
resolve
)
=>
(
this
.
bgImage
.
onload
=
resolve
)),
//
new Promise((resolve) => (this.waterImage.onload = resolve)),
new
Promise
((
resolve
)
=>
(
this
.
waterImage
.
onload
=
resolve
)),
new
Promise
((
resolve
)
=>
(
this
.
poImage
.
onload
=
resolve
)),
new
Promise
((
resolve
)
=>
(
this
.
guanImage
.
onload
=
resolve
))
,
new
Promise
((
resolve
)
=>
(
this
.
guanImage
.
onload
=
resolve
))
])
.
then
(()
=>
{
// 所有图片加载完成后绘制
...
...
@@ -845,7 +1345,7 @@ export default {
{
color
:
"
red
"
,
name
:
"
红色报警线
"
},
{
color
:
"
orange
"
,
name
:
"
橙色报警线
"
},
{
color
:
"
yellow
"
,
name
:
"
黄色报警线
"
},
{
color
:
"
blue
"
,
name
:
"
蓝色报警线
"
},
{
color
:
"
blue
"
,
name
:
"
蓝色报警线
"
}
],
alarmLine
=
{},
setAlarmSerie
=
function
(
value
,
name
,
color
)
{
...
...
@@ -935,14 +1435,7 @@ export default {
});
}
},
// loadData: function () {
// // console.log(this.form, "form");
// // this.initChart1();
// // this.getCanvasData();
// return reqApi.common.getRequst;
// },
loadData
:
reqApi
.
common
.
getRequst
,
loadData
:
reqApi
.
common
.
getRequst
,
cancelForm
()
{
this
.
form
.
visible
=
false
;
},
...
...
@@ -953,6 +1446,5 @@ export default {
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scope
>
.qyzz
{
}
.qyzz
{}
</
style
>
src/views/dataMonitor/jrx/history/index1.vue
0 → 100644
View file @
83aacf1b
<
template
>
<div
class=
"common-page qyzz page-t1"
>
<div
class=
"option page-row"
>
<table-filter
ref=
"filter"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
<div
class=
"new-container"
style=
"display: flex"
>
<div
class=
"canvas-wrapper"
style=
"width: 1000px"
>
<!-- 替换为 Canvas 元素 -->
<canvas
ref=
"canvas"
id=
"mainCanvas"
width=
"1000"
style=
"background: #f0f0f0"
></canvas>
</div>
<div
class=
"chart-wrapper"
style=
"padding-left: 0px"
>
<div
ref=
"chartContainer"
style=
"
width: 870px;
height: 550px;
margin-bottom: 20px;
border: 1px solid gainsboro;
"
></div>
<div
class=
"chart-btn-group"
>
<button
size=
"small"
:type=
"currentChartType === 'line' ? 'primary' : ''"
@
click=
"switchChartType('line')"
>
折线图
</button>
<button
size=
"small"
:type=
"currentChartType === 'column' ? 'primary' : ''"
@
click=
"switchChartType('column')"
>
柱状图
</button>
</div>
</div>
</div>
<div
class=
"panel-bottom page-row"
>
<div
class=
"ctin-box"
>
<div
class=
"content-within"
>
<div
class=
"content-fix"
>
<div
class=
"toolbar"
>
<div>
<el-button
v-for=
"(item, key) in form.config.otherBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button>
</div>
<div>
<el-button
v-for=
"(item, key) in form.config.rightBtn"
size=
"mini"
:type=
"item.type"
:icon=
"item.icon"
@
click=
"item.callback.call(_self, $event)"
>
{{
item
.
name
}}
</el-button>
</div>
</div>
<!-- 表格渲染 -->
<cu-table
ref=
"cuTable"
:table=
"table"
:Dict=
"Dict"
:config=
"form.config"
:loadData=
"loadData"
/>
</div>
</div>
</div>
</div>
<!-- 表单渲染 -->
<cu-form
ref=
"cuForm"
:form=
"form"
:Dict=
"Dict"
:rules=
"rules"
:submit=
"submitForm"
:cancel=
"cancelForm"
:watchKeys=
"['paperfilename']"
/>
</div>
</
template
>
<
script
>
import
Highcharts
from
"
highcharts
"
;
import
{
reqApi
,
Config
}
from
"
@/assets/js/httpApi.js
"
;
import
{
Tools
}
from
"
@/assets/js/common.js
"
;
import
DateRangePicker
from
"
@/components/DateRangePicker
"
;
import
TableFilter
from
"
@/components/TableFilter
"
;
import
cuForm
from
"
@/components/cuForm
"
;
import
cuTable
from
"
@/components/cuTable
"
;
import
request
from
"
@/utils/request
"
;
export
default
{
name
:
"
Dashboard
"
,
components
:
{
DateRangePicker
,
TableFilter
,
cuForm
,
cuTable
,
},
data
()
{
return
{
chartDataEmpty
:
false
,
canvasDataEmpty
:
false
,
Dict
:
{
selectList
:
[]
},
table
:
{
page
:
1
,
size
:
10
,
total
:
0
,
loading
:
false
,
dataList
:
[],
},
rules
:
{},
form
:
{
title
:
""
,
visible
:
false
,
reqType
:
"
add
"
,
historyDialog
:
false
,
status
:
{
cu
:
0
},
query
:
{},
search
:
{},
item
:
{},
file
:
0
,
config
:
{},
},
// 新增图表相关数据
chartVisible
:
true
,
// 图表弹窗可见性
deviceList
:
[{
id
:
"
test001
"
,
name
:
"
测试设备1
"
}],
// 设备列表数据
selectedDevice
:
null
,
// 选中设备ID
dateRange
:
[
null
,
null
],
// 日期范围选择
currentChartType
:
"
line
"
,
// 当前图表类型(line/column)
chartLoading
:
false
,
// 图表加载状态
chartInstance
:
null
,
// Highcharts实例引用
// ...原有data属性保持不变...
canvas
:
null
,
// Canvas 实例
ctx
:
null
,
// 2D 上下文
bgImage
:
null
,
// 背景图对象
waterImage
:
null
,
// 新增:water.png 图片对象
poImage
:
null
,
// 新增:po.png 图片对象
canvasDataReal
:
{
poConfigsWH
:
[{
// 基础信息配置对象 用于换算具体画布xy坐标点
xieMianW
:
50
,
// 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW
:
100
,
// 第一个坡平面距离平面宽度。
pingMianH
:
150
,
// 第一个坡平面距离平面高度。
kongW
:
150
,
// 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH
:
20
,
// 目前孔的深度
maishen
:
10
,
// 水位到管口的垂直距离
}],
otherConfig
:
{
gantanW
:
20
,
// 干滩距离水平面的宽度(根据最后一个坡平面坐标点计算xy。)
tuduiW
:
30
,
// 干滩距离水平面中间的土堆
shuiW
:
50
,
// 水平面的宽度
shuiH
:
30
,
// 水平面的高度
},
// Canvas绘制配置(支持批量扩展)
poConfigsXY
:
[
// 根据poConfigsWH 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是斜面和平面点
],
guanConfigsXY
:
[
// 根据poConfigsXY和poConfigsWH的孔信息 计算具体的xy坐标点,每个对象计算出两对坐标点。分别是孔起始坐标和结束坐标
],
gantanConfigsXY
:
[
],
jrxConfigsXY
:
[
],
shuiweiConfigsXY
:
[
],
tuduiConfigsXY
:
[
],
jingjiexianConfigsXY
:
[
],
lineConfigs
:
[
{
points
:
[],
color
:
"
red
"
,
lineWidth
:
2
},
// 红色连接线配置
{
points
:
[],
color
:
"
yellow
"
,
lineWidth
:
2
},
// 黄色连接线配置
],
},
// canvasData: [
// {
// name: "剖面名称",
// height: "剖面高度",
// width: "剖面宽度",
// code: "剖面编号",
// sdeg: "水区扇形起始角度",
// diameter: "总直径",
// jrxStepsDtoList: [
// {
// name: "台阶名称",
// code: "台阶编号",
// height: "高度(米)",
// width: "宽度(米)",
// slope: "坡度(deg)"
// }
// ],
// equipmentDataList: [
// {
// sensorid: "设备id",
// sensorname: "设备名称",
// unit: "设备单位",
// stage: "水位(传感器到水面的距离)",
// depth: "浸润线埋深(水位到管口的距离)(m)",
// smhb: "// 水面海拔",
// time: "时间",
// holeDepth: "孔口高程",
// jrxTrepanning: "浸润线开口深度",
// redAlarm: "红色预警 此预警值针对的是depth 浸润线埋深",
// orangeAlarm: "橙色预警",
// yellowAlarm: "黄色预警",
// blueAlarm: "蓝色预警"
// }
// ]
// }
// ]
};
},
created
()
{
// 获取基本信息
this
.
pageApi
=
Config
.
getModuleInfo
(
this
);
this
.
Dict
=
this
.
pageApi
.
Dict
;
this
.
form
.
config
=
this
.
pageApi
.
config
;
this
.
rules
=
reqApi
.
getRules
(
this
.
Dict
.
baseInfo
)
||
this
.
Dict
.
rules
||
{};
this
.
pageApi
.
created
&&
this
.
pageApi
.
created
();
// 新增:获取地址栏deviceId参数并设置到form.query.code
const
deviceId
=
this
.
$route
.
query
.
deviceId
;
if
(
deviceId
)
{
this
.
form
.
query
.
sensorid
=
deviceId
;
// 将deviceId赋值到查询条件的code字段
}
// this.handleCanvasData(this.canvasData);
},
mounted
()
{
this
.
$nextTick
(()
=>
{
this
.
loadData
();
this
.
initChart1
()
this
.
getCanvasData
();
});
// 获取选择列表字典
var
selectList
=
this
.
Dict
.
selectList
;
Tools
.
asyncLoop
.
call
(
this
,
selectList
,
function
(
key
,
value
,
next
)
{
if
(
typeof
value
===
"
function
"
)
{
value
.
call
(
this
.
Dict
).
then
(
function
(
res
)
{
selectList
[
key
]
=
res
;
next
();
});
}
else
{
next
();
}
});
},
methods
:
{
/** 绘制文字标注 */
drawText
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系(左上角原点)
this
.
ctx
.
font
=
`10px Arial`
;
// 文字大小8px
this
.
ctx
.
fillStyle
=
"
#000
"
;
// 黄色
this
.
ctx
.
textAlign
=
"
center
"
;
// 水平居中
this
.
ctx
.
textBaseline
=
"
top
"
;
// 垂直顶部对齐
// 绘制文字(考虑Y轴方向转换)
const
drawY
=
this
.
canvas
.
height
-
config
.
y
;
// 转换为默认坐标系Y轴
this
.
ctx
.
fillText
(
config
.
text
,
config
.
x
,
drawY
+
5
);
// Y轴偏移5px避免重叠
this
.
ctx
.
restore
();
},
/** 清空画布内容及配置 */
clearCanvas
()
{
if
(
this
.
ctx
)
{
// 清除画布绘制内容(基于当前坐标系)
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系
this
.
ctx
.
clearRect
(
0
,
0
,
this
.
canvas
.
width
,
this
.
canvas
.
height
);
// 清空整个画布
this
.
ctx
.
restore
();
}
// 重置配置数据(避免残留)
this
.
canvasDataReal
.
poConfigs
=
[];
this
.
canvasDataReal
.
guanConfigs
=
[];
this
.
canvasDataReal
.
lineConfigs
=
[];
},
getCanvasData
()
{
const
params
=
{
...
this
.
form
.
query
};
request
({
url
:
"
tab/jrx/dissect/visual-xinHua
"
,
method
:
"
get
"
,
params
,
}).
then
(
async
(
res
)
=>
{
const
data
=
res
.
body
;
if
(
!
data
.
length
)
{
// 数据为空时清空画布
this
.
clearCanvas
();
return
;
}
// console.log("剖面接口数据", data);
// console.table(JSON.parse(JSON.stringify(data[0].jrxStepsDtoList)));
// console.table(JSON.parse(JSON.stringify(data[0].equipmentDataList)));
await
this
.
handleCanvasData
(
data
);
this
.
initCanvas
();
});
},
handleCanvasDataNew
(
list
=
[])
{
return
new
Promise
((
resolve
)
=>
{
// 新增Promise封装
let
canvasWidth
=
1000
;
// 默认宽度
let
canvasHeight
=
600
;
// 默认高度
// 更新Canvas元素属性和样式
const
canvasEl
=
this
.
$refs
.
canvas
;
if
(
canvasEl
)
{
// 实际绘图区域尺寸(关键属性)
canvasEl
.
width
=
canvasWidth
;
canvasEl
.
height
=
canvasHeight
;
// 显示尺寸(与绘图区域保持一致)
canvasEl
.
style
.
width
=
`
${
canvasWidth
}
px`
;
canvasEl
.
style
.
height
=
`
${
canvasHeight
}
px`
;
}
// 数据清洗
const
poumian
=
list
[
0
];
// 坡面数据
const
poCount
=
poumian
.
jrxStepsDtoList
.
length
;
const
lineCount
=
5
;
const
po_pad_right
=
180
;
// poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const
poH
=
150
;
const
line_color
=
[
"
red
"
,
"
orange
"
,
"
yellow
"
,
"
blue
"
,
"
white
"
];
this
.
canvasDataReal
.
poConfigs
=
[];
this
.
canvasDataReal
.
guanConfigs
=
[];
this
.
canvasDataReal
.
lineConfigs
=
[];
//第一层台阶的开孔深度和设备图片相除的系数
const
sbHeightModulus
=
poumian
.
equipmentDataList
[
0
].
jrxTrepanning
/
130
;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡面基本信息获取
for
(
let
index
=
0
;
index
<
poCount
;
index
++
)
{
this
.
poConfigsWH
.
push
({
xieMianW
:
10
+
index
,
// 第一个坡斜面距离第一个坡平面的水平距离。
pingMianW
:
50
+
index
,
// 第一个坡平面距离平面宽度。
pingMianH
:
20
+
index
,
// 第一个坡平面距离平面高度。
kongW
:
10
+
index
,
// 目前设定打孔的位置在坡平面上距离左侧起始点的距离
kongH
:
20
+
index
,
// 目前孔的深度
jrxTrepanning
:
10
+
index
,
// 浸润线开口深度
})
}
// 破平面xy计算
this
.
poConfigsXY
=
[{
x
:
0
,
y
:
0
}]
this
.
poConfigsWH
.
forEach
((
item
)
=>
{
this
.
poConfigsXY
.
push
({
// 斜坡点
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
+
item
.
xieMianW
,
// 每个斜平坡计算点都根据上一个前面已有的最后一个坐标点进行添加 第一个为x0y0
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
+
item
.
pingMianH
,
})
this
.
poConfigsXY
.
push
({
// 平坡点
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
+
item
.
pingMianW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
,
})
// 孔的xy计算
this
.
guanConfigsXY
.
push
({
// 管的起始点 -2是获取该斜坡点的结束坐标加上孔距离位置=孔在平坡上面的位置
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
x
+
item
.
kongW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
y
+
0
,
// 这里的0为了突出孔的仪器设备 突出坡平面距离。这里先放置0(方便后面浸润线水位的计算),等后面实际画管线的时候临时加上固定值。
})
this
.
guanConfigsXY
.
push
({
// 管的结束点
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
x
+
item
.
kongW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
2
].
y
-
item
.
kongH
,
maishen
:
item
.
depth
,
// 水位到管口的垂直距离
})
})
this
.
gantanConfigsXY
=
[
// 干滩的xy坐标点
{
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
},
// 干滩的起始点
{
x
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
x
+
this
.
otherConfig
.
gantanW
,
y
:
this
.
poConfigsXY
[
this
.
poConfigsXY
.
length
-
1
].
y
-
this
.
otherConfig
.
shuiH
},
// 干滩的结束点 (最高平坡减去水位高度)
]
this
.
guanConfigsXY
.
forEach
((
item
,
index
)
=>
{
if
(
index
%
2
==
0
)
{
// 偶数为管的起始点
this
.
jrxConfigsXY
.
push
(
{
x
:
item
.
x
,
y
:
item
.
y
-
item
.
maishen
},
// 浸润线的坐标点是平坡y-埋深的值(水位到平坡的垂直距离)
)
}
})
this
.
shuiweiConfigsXY
=
[
// 水位的xy坐标点(画矩形)
{
x
:
this
.
gantanConfigsXY
[
1
].
x
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的起始点
{
x
:
this
.
gantanConfigsXY
[
1
].
x
+
this
.
otherConfig
.
tuduiW
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的结束点 (最高平坡减去水位高度)
]
this
.
tuduiConfigsXY
=
[
{
x
:
this
.
gantanConfigsXY
[
1
].
x
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的起始点
{
x
:
this
.
gantanConfigsXY
[
1
].
x
+
this
.
otherConfig
.
tuduiW
,
y
:
0
},
// 水位的结束点
]
this
.
jingjiexianConfigsXY
=
[
{
x
:
this
.
gantanConfigsXY
[
1
].
x
,
y
:
this
.
gantanConfigsXY
[
1
].
y
},
// 水位的起始点
{
x
:
this
.
gantanConfigsXY
[
1
].
x
+
this
.
otherConfig
.
tuduiW
,
y
:
0
},
// 水位的结束点
]
// 警戒线逻辑- 初始话基本数据结构
for
(
let
index1
=
0
;
index1
<
lineCount
;
index1
++
)
{
this
.
jingjiexianConfigsXY
.
push
({
// 设置
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
20
*
index1
,
// 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this
.
jingjiexianConfigsXY
.
forEach
((
line
,
index
)
=>
{
let
lineValKey
=
line
.
color
==
"
white
"
?
"
depth
"
:
line
.
color
+
"
Alarm
"
;
// 几个管孔几个坐标点
poumian
.
equipmentDataList
.
forEach
((
equip
,
subindex
)
=>
{
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
,
y
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
equip
[
lineValKey
]
/
sbHeightModulus
,
// 管设备的y坐标+设备的警戒值*系数
});
});
});
// 4. 绘制连接线(遍历配置数组)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawLine
(
config
);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>
0
)
{
// 添加可选链校验
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const
equipment
=
this
.
equipmentDataList
[
subindex
];
const
depth
=
equipment
.
depth
||
""
;
// 添加空值校验
// 绘制当前点的文字
this
.
drawText
({
x
:
point
.
x
,
y
:
this
.
canvas
.
height
-
point
.
y
,
text
:
`浸润线埋深:
${
depth
}
m`
,
});
});
}
});
resolve
();
// 数据处理完成后触发resolve
});
},
handleCanvasData
(
list
=
[])
{
return
new
Promise
((
resolve
)
=>
{
// 新增Promise封装
let
canvasWidth
=
1000
;
// 默认宽度
let
canvasHeight
=
600
;
// 默认高度
// 更新Canvas元素属性和样式
const
canvasEl
=
this
.
$refs
.
canvas
;
if
(
canvasEl
)
{
// 实际绘图区域尺寸(关键属性)
canvasEl
.
width
=
canvasWidth
;
canvasEl
.
height
=
canvasHeight
;
// 显示尺寸(与绘图区域保持一致)
canvasEl
.
style
.
width
=
`
${
canvasWidth
}
px`
;
canvasEl
.
style
.
height
=
`
${
canvasHeight
}
px`
;
}
// 数据清洗
const
poumian
=
list
[
0
];
// 坡面数据
const
poCount
=
poumian
.
jrxStepsDtoList
.
length
;
const
lineCount
=
5
;
const
po_pad_right
=
180
;
// poCount > 4 ? 130 : 180; // 第一个台阶距离画布的距离
const
poH
=
150
;
const
line_color
=
[
"
red
"
,
"
orange
"
,
"
yellow
"
,
"
blue
"
,
"
white
"
];
this
.
canvasDataReal
.
poConfigs
=
[];
this
.
canvasDataReal
.
guanConfigs
=
[];
this
.
canvasDataReal
.
lineConfigs
=
[];
//第一层台阶的开孔深度和设备图片相除的系数
const
sbHeightModulus
=
poumian
.
equipmentDataList
[
0
].
jrxTrepanning
/
130
;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡数据数据格式处理
poumian
.
jrxStepsDtoList
.
forEach
((
po
,
poIndex
)
=>
{
this
.
canvasDataReal
.
poConfigs
.
push
({
x
:
0
,
y
:
canvasHeight
-
(
poIndex
+
1
)
*
poH
,
width
:
canvasWidth
-
(
poIndex
+
1
)
*
po_pad_right
,
height
:
poH
,
});
});
// 管孔数据数据格式处理
poumian
.
equipmentDataList
.
forEach
((
equipment
,
equipIndex
)
=>
{
const
po
=
this
.
canvasDataReal
.
poConfigs
[
equipIndex
];
// 管孔数据数据格式处理
this
.
canvasDataReal
.
guanConfigs
.
push
({
x
:
po
.
width
*
0.75
+
50
,
y
:
canvasHeight
-
po
.
height
*
(
equipIndex
+
1
),
width
:
6
,
height
:
equipment
.
jrxTrepanning
/
sbHeightModulus
,
image
:
"
guanImage
"
,
});
});
// 警戒线逻辑- 初始话基本数据结构
for
(
let
index1
=
0
;
index1
<
lineCount
;
index1
++
)
{
this
.
canvasDataReal
.
lineConfigs
.
push
({
// 设置
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
20
*
index1
,
// 每条线之间的差值
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
line
,
index
)
=>
{
let
lineValKey
=
line
.
color
==
"
white
"
?
"
depth
"
:
line
.
color
+
"
Alarm
"
;
// 几个管孔几个坐标点
poumian
.
equipmentDataList
.
forEach
((
equip
,
subindex
)
=>
{
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
,
y
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
y
+
equip
[
lineValKey
]
/
sbHeightModulus
,
// 管设备的y坐标+设备的警戒值*系数
});
});
});
// console.log("坡面处理完毕数据", this.canvasDataReal);
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.poConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.guanConfigs))
// );
// console.table(
// JSON.parse(JSON.stringify(this.canvasDataReal.lineConfigs))
// );
resolve
();
// 数据处理完成后触发resolve
});
},
/** 初始化 Canvas 画布及坐标系 */
initCanvas
()
{
// 获取 Canvas 元素和上下文
this
.
canvas
=
this
.
$refs
.
canvas
;
// document.getElementById('mainCanvas')
if
(
!
this
.
canvas
)
{
console
.
error
(
"
Canvas 元素未找到
"
);
return
;
}
// console.log(this.canvas, "canvas");
this
.
ctx
=
this
.
canvas
.
getContext
(
"
2d
"
);
// 坐标系变换:将原点移至左下角(默认原点在左上角)
this
.
ctx
.
translate
(
0
,
this
.
canvas
.
height
);
// 向下移动画布高度
this
.
ctx
.
scale
(
1
,
-
1
);
// 翻转 Y 轴方向(上为正)
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
this
.
loadAllImages
();
},
// 绘制单个po.png(支持配置参数)
drawPoImage
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 动态计算y坐标(若未指定则默认画布底部-高度)
this
.
ctx
.
drawImage
(
this
.
poImage
,
config
.
x
,
config
.
y
,
config
.
width
,
config
.
height
);
this
.
ctx
.
restore
();
},
// 绘制单个guan.png(支持不同图片类型)
drawGuanImage
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
const
targetImage
=
this
[
config
.
image
];
// 根据配置获取具体图片对象(如guanImage/guanImage1)
this
.
ctx
.
drawImage
(
targetImage
,
config
.
x
,
config
.
y
,
config
.
width
,
config
.
height
);
this
.
ctx
.
restore
();
},
// 绘制连接线(支持多坐标点)
drawLine
(
config
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
strokeStyle
=
config
.
color
;
this
.
ctx
.
lineWidth
=
config
.
lineWidth
;
this
.
ctx
.
beginPath
();
config
.
points
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
});
this
.
ctx
.
stroke
();
this
.
ctx
.
restore
();
},
// 绘制背景图(独立方法)
drawBackground
()
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
drawImage
(
this
.
bgImage
,
0
,
0
,
this
.
canvas
.
width
,
this
.
canvas
.
height
);
this
.
ctx
.
restore
();
},
// 绘制water.png(独立方法)
drawWaterImage
()
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
0.7
,
0
,
0
,
1
,
0
,
0
);
this
.
ctx
.
drawImage
(
this
.
waterImage
,
0
,
this
.
canvas
.
height
-
255
,
485
,
255
);
this
.
ctx
.
restore
();
},
// 重构后的统一绘制入口(通过配置驱动)
drawAllImages
()
{
// 1. 绘制背景图
this
.
drawBackground
();
// 2. 绘制po.png(遍历配置数组)
// console.log(this.canvasDataReal.poConfigs, "poConfigs");
this
.
canvasDataReal
.
poConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawPoImage
(
config
);
});
// 3. 绘制guan.png(遍历配置数组)
// console.log(this.canvasDataReal.guanConfigs, "guanConfigs");
this
.
canvasDataReal
.
guanConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawGuanImage
(
config
);
});
// 4. 绘制连接线(遍历配置数组)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawLine
(
config
);
});
// 5. 绘制白色警戒线所有点的文字标注(修改部分)
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>
0
)
{
// 添加可选链校验
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
// 遍历所有坐标点
// 获取对应设备的深度值(通过索引对应)
const
equipment
=
this
.
equipmentDataList
[
subindex
];
const
depth
=
equipment
.
depth
||
""
;
// 添加空值校验
// 绘制当前点的文字
this
.
drawText
({
x
:
point
.
x
,
y
:
this
.
canvas
.
height
-
point
.
y
,
text
:
`浸润线埋深:
${
depth
}
m`
,
});
});
}
});
// 新增:绘制白色警戒线下方海蓝色阴影
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
lineConfig
)
=>
{
if
(
lineConfig
.
color
===
'
white
'
&&
lineConfig
.
points
.
length
>=
2
)
{
// 至少需要2个点构成直线
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系(左上角原点,Y轴向下)
// // 增加测试数据
// lineConfig.points.push({
// x: lineConfig.points[1].x - 150,
// y: lineConfig.points[1].y -150
// })
// 将警戒线坐标转换为默认坐标系(原坐标系Y轴向上)
const
canvasHeight
=
this
.
canvas
.
height
;
// 缓存画布高度
const
convertedPoints
=
lineConfig
.
points
.
map
(
point
=>
({
x
:
point
.
x
,
y
:
point
.
y
// 转换为默认Y轴向下的坐标
}));
// 遍历相邻点对,生成梯形
for
(
let
i
=
0
;
i
<
convertedPoints
.
length
-
1
;
i
++
)
{
const
start
=
convertedPoints
[
i
];
const
end
=
convertedPoints
[
i
+
1
];
// 构建当前线段对应的梯形四个顶点
const
trapezoid
=
[
start
,
// 顶部左端点
end
,
// 顶部右端点
{
x
:
end
.
x
,
y
:
canvasHeight
},
// 底部右端点(垂直投影到底边)
{
x
:
start
.
x
,
y
:
canvasHeight
},
// 底部左端点(垂直投影到底边)
];
// 绘制当前梯形
this
.
ctx
.
fillStyle
=
'
rgba(59, 175, 251, 0.3)
'
;
// 海蓝色,透明度30%
this
.
ctx
.
beginPath
();
trapezoid
.
forEach
((
point
,
index
)
=>
{
index
===
0
?
this
.
ctx
.
moveTo
(
point
.
x
,
point
.
y
)
:
this
.
ctx
.
lineTo
(
point
.
x
,
point
.
y
);
});
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
}
this
.
ctx
.
restore
();
}
});
// 5. 绘制water.png
// this.drawWaterImage();
},
/** 加载所有图片并绘制 */
loadAllImages
()
{
// 加载背景图(原有)
this
.
bgImage
=
new
Image
();
this
.
bgImage
.
src
=
require
(
"
@/assets/images/jrx/bg.png
"
);
// // 加载 water.png
this
.
waterImage
=
new
Image
();
this
.
waterImage
.
src
=
require
(
"
@/assets/images/jrx/water.png
"
);
// 加载 po.png
this
.
poImage
=
new
Image
();
this
.
poImage
.
src
=
require
(
"
@/assets/images/jrx/po.png
"
);
// 加载 guan.png
this
.
guanImage
=
new
Image
();
this
.
guanImage
.
src
=
require
(
"
@/assets/images/jrx/guan0.png
"
);
// 等待所有图片加载完成
Promise
.
all
([
new
Promise
((
resolve
)
=>
(
this
.
bgImage
.
onload
=
resolve
)),
new
Promise
((
resolve
)
=>
(
this
.
waterImage
.
onload
=
resolve
)),
new
Promise
((
resolve
)
=>
(
this
.
poImage
.
onload
=
resolve
)),
new
Promise
((
resolve
)
=>
(
this
.
guanImage
.
onload
=
resolve
)),
])
.
then
(()
=>
{
// 所有图片加载完成后绘制
this
.
drawAllImages
();
})
.
catch
(()
=>
{
console
.
error
(
"
部分图片加载失败
"
);
});
},
/** 初始化图表(关键修改:调整图例位置) */
initChart1
()
{
let
params
=
{
sort
:
"
date,desc
"
,
};
if
(
this
.
form
.
query
.
daterange
)
{
params
.
daterange
=
this
.
form
.
query
.
daterange
.
join
(
"
,
"
);
}
if
(
this
.
form
.
query
.
sensorid
)
{
params
.
code
=
this
.
form
.
query
.
sensorid
;
}
request
({
url
:
"
data/st/imghistory
"
,
method
:
"
get
"
,
params
,
}).
then
((
res
)
=>
{
const
data
=
res
.
body
;
// const data = this.getChartData().body
// console.log("data", data);
const
chartData
=
this
.
seriesDataFormat
(
data
,
{
datekey
:
"
date
"
});
var
warningLine
=
undefined
;
// this.form.config.warningLine;
var
option
=
{
valEnabled
:
true
,
opacity
:
1
,
lineWidth
:
3
,
};
var
alarmData
=
this
.
discernValidAlarmValue
(
data
.
alarm
,
data
.
lists
,
chartData
.
series
,
warningLine
,
option
);
// const chartData = data
// console.log("chartCData", chartData);
Highcharts
.
setOptions
({
global
:
{
useUTC
:
false
,
},
lang
:
{
resetZoom
:
"
重置缩放比例
"
,
},
});
this
.
chartInstance
=
new
Highcharts
.
chart
(
this
.
$refs
.
chartContainer
,
{
chart
:
{
//type: '',
backgroundColor
:
"
transparent
"
,
//marginTop:30,
//marginBottom:30,
//marginLeft:30,
zoomType
:
"
x
"
,
// xy
},
valEnabled
:
true
,
opacity
:
1
,
lineWidth
:
3
,
title
:
{
text
:
""
,
},
subtitle
:
{
text
:
""
,
},
tooltip
:
{
enabled
:
false
,
borderWidth
:
10
,
},
xAxis
:
{
type
:
"
datetime
"
,
// 最为关键的代码:如果为空数组,则导致日期格式化失效!!
categories
:
chartData
.
categories
[
0
]
&&
chartData
.
categories
,
lineWidth
:
0
,
//lineColor:'#ff0000',
gridLineColor
:
"
#aaa
"
,
dateTimeLabelFormats
:
{
millisecond
:
"
%H:%M:%S.%L
"
,
second
:
"
%H:%M:%S
"
,
minute
:
"
%H:%M
"
,
hour
:
"
%H:%M
"
,
day
:
"
%m-%d
"
,
week
:
"
%m-%d
"
,
month
:
"
%Y-%m
"
,
year
:
"
%Y
"
,
},
},
yAxis
:
{
title
:
{
text
:
""
,
},
labels
:
{
x
:
-
6
,
},
gridLineColor
:
"
#aaa
"
,
max
:
null
,
},
plotOptions
:
{
column
:
{
borderWidth
:
0
,
//y:50,
//itemMarginTop:50,
},
bar
:
{
borderWidth
:
0
,
},
},
tooltip
:
{
// {point.y:.4f} // 保留4位小数
//headerFormat: '
<
span
style
=
"
font-size:10px
"
>
{
point
.
key
}
<
/span><table>'
,
pointFormat
:
'
<tr><td style="color:{series.color};padding:0">{series.name}:</td>
'
+
'
<td style="padding:0"><b>{point.y}
'
+
data
.
danwei
+
"
</b> </td></tr>
"
,
footerFormat
:
"
</table>
"
,
shared
:
true
,
useHTML
:
true
,
dateTimeLabelFormats
:
{
millisecond
:
"
%H:%M:%S.%L
"
,
second
:
"
%H:%M:%S
"
,
minute
:
"
%H:%M
"
,
hour
:
"
%H:%M
"
,
day
:
"
%m-%d %H时
"
,
week
:
"
%m-%d
"
,
month
:
"
%Y-%m
"
,
year
:
"
%Y
"
,
},
},
legend
:
{
enabled
:
chartData
.
series
.
length
>
1
?
true
:
false
,
// 图例定位
layout
:
"
horizontal
"
,
// 水平布局:“horizontal”, 垂直布局:“vertical”
floating
:
false
,
// 图列是否浮动
align
:
"
right
"
,
// 图例容器
//width:'100%', // number || String
padding
:
2
,
// 内边距
margin
:
2
,
borderRadius
:
5
,
//borderWidth:1,
verticalAlign
:
"
top
"
,
// 图例项
//itemWidth:120, // 宽度
itemDistance
:
10
,
// 间距 20
y
:
-
10
,
itemMarginTop
:
2
,
itemStyle
:
{},
itemHoverStyle
:
{},
},
credits
:
{
enabled
:
false
,
},
series
:
chartData
.
series
,
});
});
},
seriesDataFormat
(
data
,
opts
)
{
var
names
=
data
.
names
||
[],
list
=
data
.
list
||
data
.
lists
,
series
=
[],
categories
=
[],
maxVal
=
0
;
if
(
names
[
0
]
&&
list
)
{
var
colors
=
[
"
#7CB5EC
"
,
"
#90ED7D
"
,
"
#F7A35C
"
,
"
#8085E9
"
,
"
#F15C80
"
,
"
#E4D354
"
,
"
#2B908F
"
,
"
#F45B5B
"
,
"
#91E8E1
"
,
"
#0769CB
"
,
"
#00ABBD
"
,
"
#ffd886
"
,
"
#9F2E61
"
,
"
#4D670C
"
,
];
var
len
=
names
.
length
;
for
(
var
i
=
0
;
i
<
len
;
i
++
)
{
var
item
=
names
[
i
];
var
serie
=
{
name
:
item
.
name
,
data
:
[],
key
:
item
.
key
,
type
:
data
.
chartType
,
color
:
colors
[
i
],
};
opts
&&
serie
.
type
&&
(
serie
.
type
=
opts
.
type
);
series
.
push
(
serie
);
}
for
(
var
item
of
list
)
{
var
values
=
item
.
values
;
//var datetime = item[opts.datekey || 'dateUnit'];
//var time = datetime.indexOf(' ') > 0 ? datetime.split(' ')[1] : datetime;
var
timestamp
=
item
[
"
date
"
];
//categories.push(timestamp);
for
(
var
serie
of
series
)
{
var
value
=
values
[
serie
.
key
]
*
1
;
Math
.
abs
(
value
)
>
maxVal
&&
(
maxVal
=
Math
.
abs
(
value
));
serie
.
data
.
push
([
timestamp
,
value
]);
}
}
}
return
{
series
:
series
,
categories
:
categories
,
maxVal
:
maxVal
};
},
discernValidAlarmValue
(
alarms
,
list
,
series
,
direction
,
opts
)
{
var
xLength
=
(
list
||
[]).
length
,
maxAlarm
=
0
,
opts
=
opts
||
{};
if
(
alarms
&&
xLength
)
{
var
value
=
alarms
.
value
;
// discern
var
levelDist
=
[
{
color
:
"
red
"
,
name
:
"
红色报警线
"
},
{
color
:
"
orange
"
,
name
:
"
橙色报警线
"
},
{
color
:
"
yellow
"
,
name
:
"
黄色报警线
"
},
{
color
:
"
blue
"
,
name
:
"
蓝色报警线
"
},
],
alarmLine
=
{},
setAlarmSerie
=
function
(
value
,
name
,
color
)
{
// 修改蓝色色值
color
===
"
blue
"
&&
(
color
=
"
#3BAFFB
"
);
var
sx
=
list
[
0
].
date
,
ex
=
list
[
xLength
-
1
].
date
;
var
serie
=
{
name
:
name
,
type
:
"
spline
"
,
data
:
[
{
x
:
sx
,
y
:
value
},
{
x
:
ex
,
y
:
value
},
],
color
:
color
,
enableMouseTracking
:
false
,
legend
:
false
,
showInLegend
:
false
,
dashStyle
:
"
ShortDot
"
,
lineWidth
:
opts
.
lineWidth
||
1
,
states
:
{
inactive
:
{
opacity
:
opts
.
opacity
,
},
},
dataLabels
:
{
enabled
:
opts
.
valEnabled
||
false
,
// 数据值, 2022/11/11(周五) 因多条报警线暂时关闭
//backgroundColor:'red',
verticalAlign
:
"
middle
"
,
padding
:
0
,
defer
:
false
,
allowOverlap
:
true
,
color
:
color
,
style
:
{
textOutline
:
"
none
"
,
},
},
tooltip
:
{
//footerFormat:'',
//pointFormat:'',
headerFormat
:
""
,
//nullFormat:'',
},
marker
:
{
enabled
:
false
,
},
zIndex
:
-
10
,
};
series
.
push
(
serie
);
};
/* 智能报警线
var level = (~~alarms.alarmLevel || levelDist.length+1) - 1;
var nearLevel = level ? level - 1 : level;
var alarm = levelDist[level];
var nearAlarm = levelDist[nearLevel];
nearAlarm.value = value[nearAlarm.color];
alarmLine[nearAlarm.color] = nearAlarm;
if(alarm){
alarm.value = value[alarm.color];
alarmLine[alarm.color] = alarm;
}; */
// 多条报警线
for
(
var
item
of
levelDist
)
{
item
.
value
=
value
[
item
.
color
];
alarmLine
[
item
.
color
]
=
item
;
}
// add
for
(
var
key
in
alarmLine
)
{
var
line
=
alarmLine
[
key
];
line
.
value
>
maxAlarm
&&
(
maxAlarm
=
line
.
value
);
setAlarmSerie
(
line
.
value
,
line
.
name
,
line
.
color
);
direction
&&
setAlarmSerie
(
0
-
line
.
value
,
line
.
name
,
line
.
color
);
}
}
return
{
series
,
maxAlarm
};
},
/** 切换图表类型 */
switchChartType
(
type
)
{
this
.
currentChartType
=
type
;
if
(
this
.
chartInstance
)
{
this
.
chartInstance
.
series
.
forEach
((
series
)
=>
{
series
.
update
({
type
:
this
.
currentChartType
});
});
}
},
// loadData: function () {
// // console.log(this.form, "form");
// // this.initChart1();
// // this.getCanvasData();
// return reqApi.common.getRequst;
// },
loadData
:
reqApi
.
common
.
getRequst
,
cancelForm
()
{
this
.
form
.
visible
=
false
;
},
submitForm
(
form
,
item
)
{
reqApi
.
common
.
submitForm
.
call
(
this
,
form
,
item
);
},
},
};
</
script
>
<
style
rel=
"stylesheet/scss"
lang=
"scss"
scope
>
.qyzz
{}
</
style
>
vue.config.js
View file @
83aacf1b
...
...
@@ -12,8 +12,8 @@ function resolve(dir) {
};
const
name
=
defaultSettings
.
title
;
// 网址标题
const
port
=
process
.
env
.
VUE_APP_LOCAL_PORT
;
// 端口配置
const
VUE_APP_BASE_API
=
process
.
env
.
VUE_APP_BASE_API
;
const
port
=
9527
;
// 端口配置
const
VUE_APP_BASE_API
=
'
http://192.168.2.37:9003
'
;
// All configuration item explanations can be find in https://cli.vuejs.org/config/
module
.
exports
=
{
...
...
@@ -63,14 +63,14 @@ module.exports = {
},
proxy
:
{
'
/api
'
:
{
target
:
process
.
env
.
VUE_APP_BASE_API
,
target
:
VUE_APP_BASE_API
,
changeOrigin
:
true
,
pathRewrite
:
{
'
^/api
'
:
'
api
'
}
},
'
/auth
'
:
{
target
:
process
.
env
.
VUE_APP_BASE_API
,
target
:
VUE_APP_BASE_API
,
changeOrigin
:
true
,
pathRewrite
:
{
'
^/auth
'
:
'
auth
'
...
...
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