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
ecd1a93d
Commit
ecd1a93d
authored
Nov 03, 2025
by
xinzhedeai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add:浸润线坡面动态绘制埋深数据显示问题排查处理。无用代码移除
parent
83aacf1b
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
3240 additions
and
193 deletions
+3240
-193
index-lql.vue
src/views/dataMonitor/jrx/history/index-lql.vue
+1920
-0
index-zjunb.vue
src/views/dataMonitor/jrx/history/index-zjunb.vue
+1318
-0
index.vue
src/views/dataMonitor/jrx/history/index.vue
+2
-193
No files found.
src/views/dataMonitor/jrx/history/index-lql.vue
0 → 100644
View file @
ecd1a93d
<
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: 850px;
height: 550px;
margin-bottom: 20px;
margin-left: 10px;
border: 1px solid gainsboro;
"
></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>
</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 图片对象
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绘制配置(支持批量扩展)
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
:
{
// 最新
// 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
();
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
=>
{
var
data
=
res
.
body
;
if
(
!
data
.
length
)
{
// 数据为空时清空画布
this
.
clearCanvas
();
return
;
}
this
.
waterValue
=
data
[
0
].
wtValue
;
let
data1
=
[
{
code
:
"
001
"
,
diameter
:
2
,
drys
:
[],
equipmentDataList
:
[
{
blueAlarm
:
"
6.5
"
,
depth
:
"
7.730
"
,
holeDepth
:
"
88.5
"
,
jrxTrepanning
:
"
8.55
"
,
orangeAlarm
:
"
5.5
"
,
redAlarm
:
"
5.0
"
,
sensorid
:
"
42022210030502
"
,
sensorname
:
"
浸润线 ZQ2
"
,
smhb
:
"
80.770
"
,
stage
:
"
0.820
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
6.0
"
},
{
blueAlarm
:
"
3.3
"
,
depth
:
"
4.770
"
,
holeDepth
:
"
84.5
"
,
jrxTrepanning
:
"
6.2
"
,
orangeAlarm
:
"
2.8
"
,
redAlarm
:
"
2.5
"
,
sensorid
:
"
42022210030501
"
,
sensorname
:
"
浸润线 ZQ1
"
,
smhb
:
"
79.730
"
,
stage
:
"
1.430
"
,
time
:
"
2025-10-29 10:45:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
3.1
"
}
],
height
:
null
,
id
:
1
,
jrxStepsDtoList
:
[
{
code
:
1
,
height
:
null
,
id
:
null
,
name
:
"
1
"
,
slope
:
null
,
width
:
10
},
{
code
:
2
,
height
:
null
,
id
:
null
,
name
:
"
2
"
,
slope
:
null
,
width
:
10
}
],
name
:
"
三号副坝
"
,
pondid
:
""
,
sdeg
:
10
,
type
:
""
,
width
:
null
,
wtValue
:
84.5
},
{
code
:
"
3
"
,
diameter
:
2
,
drys
:
[],
equipmentDataList
:
[
{
blueAlarm
:
"
3.3
"
,
depth
:
"
7.280
"
,
holeDepth
:
"
84.5
"
,
jrxTrepanning
:
"
7.36
"
,
orangeAlarm
:
"
2.8
"
,
redAlarm
:
"
2.5
"
,
sensorid
:
"
42022210030503
"
,
sensorname
:
"
浸润线 ZQ3
"
,
smhb
:
"
77.220
"
,
stage
:
"
0.080
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
3.1
"
},
{
blueAlarm
:
"
6.5
"
,
depth
:
"
8.060
"
,
holeDepth
:
"
88.5
"
,
jrxTrepanning
:
"
8.06
"
,
orangeAlarm
:
"
5.5
"
,
redAlarm
:
"
5.0
"
,
sensorid
:
"
42022210030504
"
,
sensorname
:
"
浸润线 ZQ4
"
,
smhb
:
"
80.440
"
,
stage
:
"
0.000
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
6.0
"
}
],
height
:
null
,
id
:
2
,
jrxStepsDtoList
:
[
{
code
:
1
,
height
:
null
,
id
:
null
,
name
:
"
1
"
,
slope
:
null
,
width
:
10
},
{
code
:
2
,
height
:
null
,
id
:
null
,
name
:
"
2
"
,
slope
:
null
,
width
:
10
}
],
name
:
"
3
"
,
pondid
:
""
,
sdeg
:
10
,
type
:
""
,
width
:
null
,
wtValue
:
84.5
},
{
code
:
"
4
"
,
diameter
:
2
,
drys
:
[],
equipmentDataList
:
[
{
blueAlarm
:
"
6.5
"
,
depth
:
"
8.710
"
,
holeDepth
:
"
88.5
"
,
jrxTrepanning
:
"
9.0
"
,
orangeAlarm
:
"
5.5
"
,
redAlarm
:
"
5.0
"
,
sensorid
:
"
42022210030507
"
,
sensorname
:
"
浸润线 ZQ6
"
,
smhb
:
"
79.790
"
,
stage
:
"
0.290
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
6.0
"
},
{
blueAlarm
:
"
3.3
"
,
depth
:
"
6.980
"
,
holeDepth
:
"
84.5
"
,
jrxTrepanning
:
"
7.5
"
,
orangeAlarm
:
"
2.8
"
,
redAlarm
:
"
2.5
"
,
sensorid
:
"
42022210030505
"
,
sensorname
:
"
浸润线 ZQ5
"
,
smhb
:
"
77.520
"
,
stage
:
"
0.520
"
,
time
:
"
2025-10-29 10:45:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
3.1
"
}
],
height
:
null
,
id
:
4
,
jrxStepsDtoList
:
[
{
code
:
1
,
height
:
null
,
id
:
null
,
name
:
"
1
"
,
slope
:
null
,
width
:
10
},
{
code
:
2
,
height
:
null
,
id
:
null
,
name
:
"
2
"
,
slope
:
null
,
width
:
10
}
],
name
:
"
65
"
,
pondid
:
""
,
sdeg
:
10
,
type
:
""
,
width
:
null
,
wtValue
:
84.5
},
{
code
:
"
5
"
,
diameter
:
2
,
drys
:
[],
equipmentDataList
:
[
{
blueAlarm
:
"
6.5
"
,
depth
:
"
7.340
"
,
holeDepth
:
"
88.5
"
,
jrxTrepanning
:
"
8.0
"
,
orangeAlarm
:
"
5.5
"
,
redAlarm
:
"
5.0
"
,
sensorid
:
"
42022210030509
"
,
sensorname
:
"
浸润线 ZQ8
"
,
smhb
:
"
81.160
"
,
stage
:
"
0.660
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
6.0
"
},
{
blueAlarm
:
"
3.3
"
,
depth
:
"
6.330
"
,
holeDepth
:
"
84.5
"
,
jrxTrepanning
:
"
6.5
"
,
orangeAlarm
:
"
2.8
"
,
redAlarm
:
"
2.5
"
,
sensorid
:
"
42022210030508
"
,
sensorname
:
"
浸润线 ZQ7
"
,
smhb
:
"
78.170
"
,
stage
:
"
0.170
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
3.1
"
}
],
height
:
null
,
id
:
5
,
jrxStepsDtoList
:
[
{
code
:
1
,
height
:
null
,
id
:
null
,
name
:
"
1
"
,
slope
:
null
,
width
:
10
},
{
code
:
2
,
height
:
null
,
id
:
null
,
name
:
"
2
"
,
slope
:
null
,
width
:
10
}
],
name
:
"
87
"
,
pondid
:
""
,
sdeg
:
10
,
type
:
""
,
width
:
null
,
wtValue
:
84.5
},
{
code
:
"
6
"
,
diameter
:
2
,
drys
:
[],
equipmentDataList
:
[
{
blueAlarm
:
"
3.3
"
,
depth
:
"
4.160
"
,
holeDepth
:
"
84.5
"
,
jrxTrepanning
:
"
6.5
"
,
orangeAlarm
:
"
2.8
"
,
redAlarm
:
"
2.5
"
,
sensorid
:
"
420222100305010
"
,
sensorname
:
"
浸润线 ZQ9
"
,
smhb
:
"
80.340
"
,
stage
:
"
2.340
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
3.1
"
},
{
blueAlarm
:
"
6.0
"
,
depth
:
"
6.900
"
,
holeDepth
:
"
88.5
"
,
jrxTrepanning
:
"
8.0
"
,
orangeAlarm
:
"
5.5
"
,
redAlarm
:
"
5.0
"
,
sensorid
:
"
420222100305011
"
,
sensorname
:
"
浸润线 ZQ10
"
,
smhb
:
"
81.600
"
,
stage
:
"
1.100
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
5.8
"
}
],
height
:
null
,
id
:
6
,
jrxStepsDtoList
:
[
{
code
:
1
,
height
:
null
,
id
:
null
,
name
:
"
1
"
,
slope
:
null
,
width
:
10
},
{
code
:
2
,
height
:
null
,
id
:
null
,
name
:
"
2
"
,
slope
:
null
,
width
:
10
}
],
name
:
"
109
"
,
pondid
:
""
,
sdeg
:
10
,
type
:
""
,
width
:
null
,
wtValue
:
84.5
},
{
code
:
"
7
"
,
diameter
:
2
,
drys
:
[],
equipmentDataList
:
[
{
blueAlarm
:
"
6.5
"
,
depth
:
"
7.180
"
,
holeDepth
:
"
88.5
"
,
jrxTrepanning
:
"
8.0
"
,
orangeAlarm
:
"
5.5
"
,
redAlarm
:
"
5.0
"
,
sensorid
:
"
420222100305013
"
,
sensorname
:
"
浸润线 ZQ12
"
,
smhb
:
"
81.320
"
,
stage
:
"
0.820
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
6.0
"
},
{
blueAlarm
:
"
3.3
"
,
depth
:
"
4.330
"
,
holeDepth
:
"
84.5
"
,
jrxTrepanning
:
"
7.2
"
,
orangeAlarm
:
"
2.8
"
,
redAlarm
:
"
2.5
"
,
sensorid
:
"
420222100305012
"
,
sensorname
:
"
浸润线 ZQ11
"
,
smhb
:
"
80.170
"
,
stage
:
"
2.870
"
,
time
:
"
2025-10-29 10:46:10
"
,
unit
:
"
m
"
,
yellowAlarm
:
"
3.1
"
}
],
height
:
null
,
id
:
7
,
jrxStepsDtoList
:
[
{
code
:
1
,
height
:
null
,
id
:
null
,
name
:
"
1
"
,
slope
:
null
,
width
:
10
},
{
code
:
2
,
height
:
null
,
id
:
null
,
name
:
"
2
"
,
slope
:
null
,
width
:
10
}
],
name
:
"
1211
"
,
pondid
:
""
,
sdeg
:
10
,
type
:
""
,
width
:
null
,
wtValue
:
84.5
}
];
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
"
];
//第一层台阶的开孔深度和设备图片相除的系数
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. 绘制白色警戒线所有点的文字标注(修改部分)
console
.
log
(
this
.
canvasDataReal
.
lineConfig
,
"
lineconfig
"
);
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
=
[];
//第一层台阶的开孔深度和设备图片相除的系数
const
sbHeightModulus
=
poumian
.
equipmentDataList
[
0
].
jrxTrepanning
/
130
;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡数据数据格式处理
poumian
.
jrxStepsDtoList
.
forEach
((
po
,
poIndex
)
=>
{
this
.
canvasDataReal
.
poConfigs
.
push
({
x
:
-
140
,
y
:
canvasHeight
-
poIndex
*
poH
,
width
:
canvasWidth
-
poIndex
*
po_pad_right
,
height
:
poH
});
});
// 管孔数据数据格式处理
poumian
.
equipmentDataList
.
forEach
((
equipment
,
equipIndex
)
=>
{
const
po
=
this
.
canvasDataReal
.
poConfigs
[
equipIndex
];
// 管孔数据数据格式处理
if
(
equipIndex
==
1
)
{
this
.
canvasDataReal
.
guanConfigs
.
push
({
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
"
});
}
});
// 警戒线逻辑- 初始话基本数据结构
for
(
let
index1
=
0
;
index1
<
lineCount
;
index1
++
)
{
this
.
canvasDataReal
.
lineConfigs
.
push
({
// 设置
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
4
*
index1
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
line
,
index
)
=>
{
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
;
}
console
.
log
(
equip
,
"
equip
"
);
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
+
xOffset
,
y
:
baseY
,
depth
:
equip
[
"
depth
"
]
});
});
});
resolve
();
// 数据处理完成后触发resolve
});
},
/** 初始化 Canvas 画布及坐标系 */
initCanvas
()
{
// 获取 Canvas 元素和上下文
this
.
canvas
=
this
.
$refs
.
canvas
;
// document.getElementById('mainCanvas')
if
(
!
this
.
canvas
)
{
console
.
error
(
"
Canvas 元素未找到
"
);
return
;
}
this
.
ctx
=
this
.
canvas
.
getContext
(
"
2d
"
);
// 坐标系变换:将原点移至左下角(默认原点在左上角)
this
.
ctx
.
translate
(
0
,
this
.
canvas
.
height
);
// 向下移动画布高度
this
.
ctx
.
scale
(
1
,
-
1
);
// 翻转 Y 轴方向(上为正)
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
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
();
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
();
},
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 - 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
();
},
// 绘制背景图(独立方法)
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
();
},
// 绘制文字 箭头
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
};
// 合并配置
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(遍历配置数组)
this
.
canvasDataReal
.
poConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawPoImage
(
config
);
});
// 3. 绘制guan.png(遍历配置数组)
this
.
canvasDataReal
.
guanConfigs
.
forEach
((
config
,
index
)
=>
{
if
(
index
==
1
)
{
// 执行针对第二个管子的特殊绘制方法
this
.
drawSecondPipeImage
(
config
);
}
else
{
// 正常绘制其他管子
this
.
drawGuanImage
(
config
);
}
});
// 修改 drawAllImages 方法中的蓝色阴影绘制部分
this
.
canvasDataReal
.
lineConfigs
.
forEach
(
lineConfig
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>=
2
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系
// 直接使用白色线的原始坐标点,确保完全对齐
const
whiteLinePoints
=
lineConfig
.
points
;
const
canvasHeight
=
this
.
canvas
.
height
;
// 遍历相邻点对,生成梯形阴影
for
(
let
i
=
0
;
i
<
whiteLinePoints
.
length
-
1
;
i
++
)
{
const
start
=
whiteLinePoints
[
i
];
const
end
=
whiteLinePoints
[
i
+
1
];
// 构建梯形四个顶点(确保与白色线完全重合)
const
trapezoid
=
[
{
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
);
});
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
}
this
.
ctx
.
restore
();
}
});
// 确保在阴影绘制之后再绘制白色线条
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
(
""
);
console
.
log
(
deviceData
,
"
deviceData
"
);
// 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
||
""
;
}
// else {
// // 针对第一个设备编号不是奇数,且第二个设备编号是奇数,导致前面两个判断漏掉的问题
// newDepths[i] = deviceData[i].equipment.depth || "";
// }
// newDepths[i] = deviceData[i].equipment.depth || "";
}
}
console
.
log
(
newDepths
,
"
newDepths
"
);
// 处理可能的奇数个设备的最后一个设备
if
(
deviceData
.
length
%
2
===
1
)
{
const
lastDevice
=
deviceData
[
deviceData
.
length
-
1
];
newDepths
[
lastDevice
.
subindex
]
=
lastDevice
.
equipment
.
depth
||
""
;
}
// 4. 绘制文本,使用交换后的深度值
deviceData
.
forEach
(
device
=>
{
console
.
log
(
"
newDepths[device.subindex
"
,
newDepths
,
device
.
subindex
,
newDepths
[
device
.
subindex
]
);
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
()
{
// 加载背景图(原有)
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/shui.png
"
);
// 加载 shan.png
this
.
poImage
=
new
Image
();
this
.
poImage
.
src
=
require
(
"
@/assets/images/jrx/shan.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
:
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-zjunb.vue
0 → 100644
View file @
ecd1a93d
<
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: 850px;
height: 550px;
margin-bottom: 20px;
margin-left: 10px;
border: 1px solid gainsboro;
"
></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>
</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 图片对象
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绘制配置(支持批量扩展)
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
:
{
// 最新
// 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
();
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
=>
{
var
data
=
res
.
body
;
if
(
!
data
.
length
)
{
// 数据为空时清空画布
this
.
clearCanvas
();
return
;
}
this
.
waterValue
=
data
[
0
].
wtValue
;
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
=
-
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
=
[];
//第一层台阶的开孔深度和设备图片相除的系数
const
sbHeightModulus
=
poumian
.
equipmentDataList
[
0
].
jrxTrepanning
/
130
;
// 存储设备数据列表(关键新增,用于后续获取depth值)
this
.
equipmentDataList
=
poumian
.
equipmentDataList
||
[];
// 坡数据数据格式处理
poumian
.
jrxStepsDtoList
.
forEach
((
po
,
poIndex
)
=>
{
this
.
canvasDataReal
.
poConfigs
.
push
({
x
:
-
140
,
y
:
canvasHeight
-
poIndex
*
poH
,
width
:
canvasWidth
-
poIndex
*
po_pad_right
,
height
:
poH
});
});
// 管孔数据数据格式处理
poumian
.
equipmentDataList
.
forEach
((
equipment
,
equipIndex
)
=>
{
const
po
=
this
.
canvasDataReal
.
poConfigs
[
equipIndex
];
// 管孔数据数据格式处理
if
(
equipIndex
==
1
)
{
this
.
canvasDataReal
.
guanConfigs
.
push
({
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
"
});
}
});
// 警戒线逻辑- 初始话基本数据结构
for
(
let
index1
=
0
;
index1
<
lineCount
;
index1
++
)
{
this
.
canvasDataReal
.
lineConfigs
.
push
({
// 设置
points
:
[],
color
:
line_color
[
index1
],
lineWidth
:
2
,
cha
:
4
*
index1
});
}
// 警戒线种类下,根据管孔设备个数,设定对应的坐标点point
this
.
canvasDataReal
.
lineConfigs
.
forEach
((
line
,
index
)
=>
{
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
;
}
console
.
log
(
equip
,
"
equip
"
);
line
.
points
.
push
({
x
:
this
.
canvasDataReal
.
guanConfigs
[
subindex
].
x
+
1
+
xOffset
,
y
:
baseY
,
depth
:
equip
[
"
depth
"
]
});
});
});
resolve
();
// 数据处理完成后触发resolve
});
},
/** 初始化 Canvas 画布及坐标系 */
initCanvas
()
{
// 获取 Canvas 元素和上下文
this
.
canvas
=
this
.
$refs
.
canvas
;
// document.getElementById('mainCanvas')
if
(
!
this
.
canvas
)
{
console
.
error
(
"
Canvas 元素未找到
"
);
return
;
}
this
.
ctx
=
this
.
canvas
.
getContext
(
"
2d
"
);
// 坐标系变换:将原点移至左下角(默认原点在左上角)
this
.
ctx
.
translate
(
0
,
this
.
canvas
.
height
);
// 向下移动画布高度
this
.
ctx
.
scale
(
1
,
-
1
);
// 翻转 Y 轴方向(上为正)
// // 加载背景图并绘制
// this.loadBackgroundImage();
// 加载所有图片并绘制
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
();
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
();
},
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 - 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
();
},
// 绘制背景图(独立方法)
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
();
},
// 绘制文字 箭头
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
};
// 合并配置
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(遍历配置数组)
this
.
canvasDataReal
.
poConfigs
.
forEach
((
config
,
index
)
=>
{
this
.
drawPoImage
(
config
);
});
// 3. 绘制guan.png(遍历配置数组)
this
.
canvasDataReal
.
guanConfigs
.
forEach
((
config
,
index
)
=>
{
if
(
index
==
1
)
{
// 执行针对第二个管子的特殊绘制方法
this
.
drawSecondPipeImage
(
config
);
}
else
{
// 正常绘制其他管子
this
.
drawGuanImage
(
config
);
}
});
// 修改 drawAllImages 方法中的蓝色阴影绘制部分
this
.
canvasDataReal
.
lineConfigs
.
forEach
(
lineConfig
=>
{
if
(
lineConfig
.
color
===
"
white
"
&&
lineConfig
.
points
.
length
>=
2
)
{
this
.
ctx
.
save
();
this
.
ctx
.
setTransform
(
1
,
0
,
0
,
1
,
0
,
0
);
// 恢复默认坐标系
// 直接使用白色线的原始坐标点,确保完全对齐
const
whiteLinePoints
=
lineConfig
.
points
;
const
canvasHeight
=
this
.
canvas
.
height
;
// 遍历相邻点对,生成梯形阴影
for
(
let
i
=
0
;
i
<
whiteLinePoints
.
length
-
1
;
i
++
)
{
const
start
=
whiteLinePoints
[
i
];
const
end
=
whiteLinePoints
[
i
+
1
];
// 构建梯形四个顶点(确保与白色线完全重合)
const
trapezoid
=
[
{
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
);
});
this
.
ctx
.
closePath
();
this
.
ctx
.
fill
();
}
this
.
ctx
.
restore
();
}
});
// 确保在阴影绘制之后再绘制白色线条
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
)
{
deviceData
.
push
({
point
,
equipment
,
subindex
,
});
}
});
// 4. 绘制文本,使用交换后的深度值
deviceData
.
forEach
(
device
=>
{
this
.
drawText
({
x
:
device
.
point
.
x
,
y
:
this
.
canvas
.
height
-
device
.
point
.
y
,
text
:
`浸润线埋深:
${
device
.
equipment
.
depth
||
""
}
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
()
{
// 加载背景图(原有)
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/shui.png
"
);
// 加载 shan.png
this
.
poImage
=
new
Image
();
this
.
poImage
.
src
=
require
(
"
@/assets/images/jrx/shan.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
:
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 @
ecd1a93d
...
@@ -294,167 +294,6 @@ export default {
...
@@ -294,167 +294,6 @@ export default {
this
.
initCanvas
();
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
"
];
//第一层台阶的开孔深度和设备图片相除的系数
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
=
[])
{
handleCanvasData
(
list
=
[])
{
return
new
Promise
((
resolve
)
=>
{
return
new
Promise
((
resolve
)
=>
{
// 新增Promise封装
// 新增Promise封装
...
@@ -945,50 +784,20 @@ export default {
...
@@ -945,50 +784,20 @@ export default {
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
lineConfig
.
points
.
forEach
((
point
,
subindex
)
=>
{
const
equipment
=
this
.
equipmentDataList
[
subindex
];
const
equipment
=
this
.
equipmentDataList
[
subindex
];
if
(
equipment
)
{
if
(
equipment
)
{
// 提取设备名称中的数字
const
deviceNumber
=
equipment
.
sensorname
?
parseInt
(
equipment
.
sensorname
.
match
(
/
\d
+/
)[
0
]
||
'
0
'
)
:
0
;
deviceData
.
push
({
deviceData
.
push
({
point
,
point
,
equipment
,
equipment
,
subindex
,
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. 绘制文本,使用交换后的深度值
// 4. 绘制文本,使用交换后的深度值
deviceData
.
forEach
(
device
=>
{
deviceData
.
forEach
(
device
=>
{
this
.
drawText
({
this
.
drawText
({
x
:
device
.
point
.
x
,
x
:
device
.
point
.
x
,
y
:
this
.
canvas
.
height
-
device
.
point
.
y
,
y
:
this
.
canvas
.
height
-
device
.
point
.
y
,
text
:
`浸润线埋深:
${
newDepths
[
device
.
subindex
]
}
m`
,
text
:
`浸润线埋深:
${
device
.
equipment
.
depth
}
m`
,
});
});
});
});
}
}
...
...
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