Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
P
pdczt_qd
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zhaopanyu
pdczt_qd
Commits
b52c00b8
Commit
b52c00b8
authored
Nov 20, 2025
by
zhaopanyu
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
zpy
parent
a930ca57
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
352 additions
and
209 deletions
+352
-209
src/views/efficiencyAnalysis/djxx/detail/components/HistogramGraph.vue
+157
-208
src/views/efficiencyAnalysis/djxx/index.vue
+18
-0
src/views/wellDesign/components/WellStructure.vue
+177
-1
No files found.
src/views/efficiencyAnalysis/djxx/detail/components/HistogramGraph.vue
View file @
b52c00b8
<
template
>
<div
class=
"chart-container"
>
<div
id=
"mainzftdj"
class=
"chart"
ref=
"chartRef"
></div>
<div
class=
"chart-wrapper"
>
<div
id=
"mainzftdj"
class=
"chart"
ref=
"chartRef"
></div>
<div
v-if=
"legendItems.length"
class=
"legend-panel"
>
<div
class=
"legend-title"
>
层位图例
</div>
<div
class=
"legend-scroll"
>
<div
v-for=
"(item, index) in legendItems"
:key=
"getLegendKey(item, index)"
class=
"legend-item"
>
<span
class=
"legend-swatch"
>
<img
v-if=
"hasLegendSvg(item)"
:src=
"getLegendSvgSrc(item)"
alt=
""
class=
"legend-swatch-img"
/>
<span
v-else
class=
"legend-swatch-color"
:style=
"
{ backgroundColor: getLegendColor(index) }"
>
</span>
</span>
<span
class=
"legend-label"
>
{{
formatLegendName
(
item
)
}}
</span>
</div>
</div>
</div>
</div>
<div
v-if=
"loading"
class=
"loading-overlay"
>
<div
class=
"loading-spinner"
></div>
<span>
加载中...
</span>
...
...
@@ -45,6 +72,7 @@ export default {
lastXAxisLabels
:
null
,
lastDepthIntervals
:
null
,
currentGraphicElements
:
[],
tlList
:
[],
};
},
computed
:
{
...
...
@@ -89,6 +117,9 @@ export default {
}
};
return
schemes
[
this
.
theme
];
},
legendItems
()
{
return
Array
.
isArray
(
this
.
tlList
)
?
this
.
tlList
:
[];
}
},
watch
:
{
...
...
@@ -231,6 +262,7 @@ export default {
jhs
:
`
${
this
.
jh
}
,
${
this
.
jhs
}
`
});
this
.
mockData
=
res
?.
mockData
||
{};
this
.
tlList
=
res
?.
tlList
||
res
?.
mockData
?.
tlList
||
[];
return
this
.
mockData
;
}
catch
(
error
)
{
console
.
error
(
"获取数据失败:"
,
error
);
...
...
@@ -883,215 +915,11 @@ export default {
});
},
//
使用像素坐标绘制地层标签(每口井的每个地层都标注
名称)
//
清空地层标签(暂不在图内展示层位
名称)
drawStratumLabels
(
stackedAreas
,
chartConfig
,
xAxisLabels
)
{
if
(
!
this
.
myChart
||
!
stackedAreas
)
return
;
// 清空当前 graphic
if
(
!
this
.
myChart
)
return
;
this
.
currentGraphicElements
=
[];
this
.
myChart
.
setOption
({
graphic
:
{
elements
:
[]
}
});
const
graphics
=
[];
const
depthIntervals
=
this
.
mockData
?.
wellData
?.
depthIntervals
||
[];
// 如果为老格式(全局数组),保持原有从右侧标注的策略
if
(
Array
.
isArray
(
stackedAreas
))
{
if
(
stackedAreas
.
length
===
0
)
return
;
let
currentDepth
=
chartConfig
.
yAxis
.
min
;
const
lastXIndex
=
Math
.
max
(
0
,
(
xAxisLabels
?.
length
||
1
)
-
1
);
const
xOffset
=
16
;
stackedAreas
.
forEach
((
area
)
=>
{
if
(
!
area
||
!
area
.
points
||
area
.
points
.
length
===
0
)
return
;
let
thickness
;
let
centerDepth
;
if
(
area
.
sjdjsd
!=
null
&&
area
.
sjhd
!=
null
)
{
// 业务规则:当 sjdjsd 等于 sjhd 时,厚度即为 sjdjsd 本身,从 0 到 sjdjsd
if
(
Number
(
area
.
sjdjsd
)
===
Number
(
area
.
sjhd
))
{
thickness
=
Number
(
area
.
sjdjsd
);
centerDepth
=
thickness
/
2
;
}
else
{
thickness
=
Math
.
abs
(
Number
(
area
.
sjdjsd
)
-
Number
(
area
.
sjhd
));
centerDepth
=
(
Number
(
area
.
sjdjsd
)
+
Number
(
area
.
sjhd
))
/
2
;
}
}
else
{
const
p0
=
area
.
points
[
0
];
const
y
=
Number
(
p0
?.
y
);
const
y2
=
p0
?.
y2
!=
null
?
Number
(
p0
.
y2
)
:
null
;
if
(
y2
!=
null
&&
y2
===
y
)
{
// y2 即为厚度,从 0 到 y2
thickness
=
y2
;
centerDepth
=
thickness
/
2
;
}
else
if
(
y2
!=
null
&&
!
Number
.
isNaN
(
y
))
{
thickness
=
Math
.
abs
(
y2
-
y
);
centerDepth
=
(
y2
+
y
)
/
2
;
}
else
if
(
!
Number
.
isNaN
(
y
))
{
thickness
=
y
;
centerDepth
=
thickness
/
2
;
}
else
{
thickness
=
0
;
centerDepth
=
chartConfig
?.
yAxis
?.
min
||
0
;
}
}
const
pixelRight
=
this
.
myChart
.
convertToPixel
({
xAxisIndex
:
0
,
yAxisIndex
:
0
},
[
lastXIndex
,
centerDepth
]);
if
(
!
pixelRight
||
!
Array
.
isArray
(
pixelRight
)
||
pixelRight
.
length
<
2
)
return
;
const
[
pxRight
,
py
]
=
pixelRight
;
graphics
.
push
({
type
:
'text'
,
position
:
[
pxRight
+
xOffset
,
py
],
style
:
{
text
:
area
.
name
,
fontSize
:
12
,
fontWeight
:
600
,
fill
:
'#333'
,
stroke
:
'#fff'
,
lineWidth
:
2
,
backgroundColor
:
'transparent'
,
align
:
'left'
,
verticalAlign
:
'middle'
},
z
:
10
,
zlevel
:
30
,
bounding
:
'raw'
,
silent
:
true
});
currentDepth
+=
thickness
;
});
this
.
currentGraphicElements
=
graphics
;
this
.
myChart
.
setOption
({
graphic
:
{
elements
:
graphics
}
});
return
;
}
// 新格式:按井号分组对象。先按 depthIntervals 顺序识别每口井对应的 x 轴段
const
segments
=
[];
let
currentJh
=
null
;
let
currentMin
=
Infinity
;
let
currentMax
=
-
Infinity
;
let
started
=
false
;
for
(
let
i
=
0
;
i
<
depthIntervals
.
length
;
i
++
)
{
const
{
jh
}
=
depthIntervals
[
i
]
||
{};
const
idx
=
i
;
// 使用 depthIntervals 顺序索引作为 x 轴位置
if
(
!
started
)
{
currentJh
=
jh
;
currentMin
=
currentMax
=
idx
;
started
=
true
;
continue
;
}
if
(
jh
===
currentJh
)
{
currentMin
=
Math
.
min
(
currentMin
,
idx
);
currentMax
=
Math
.
max
(
currentMax
,
idx
);
}
else
{
segments
.
push
({
jh
:
currentJh
,
startIdx
:
Math
.
min
(
currentMin
,
currentMax
),
endIdx
:
Math
.
max
(
currentMin
,
currentMax
)
});
currentJh
=
jh
;
currentMin
=
currentMax
=
idx
;
}
}
if
(
started
)
{
segments
.
push
({
jh
:
currentJh
,
startIdx
:
Math
.
min
(
currentMin
,
currentMax
),
endIdx
:
Math
.
max
(
currentMin
,
currentMax
)
});
}
// 记录每口井的最后一列索引
const
lastIndexByJh
=
new
Map
();
(
depthIntervals
||
[]).
forEach
((
di
,
idx
)
=>
{
if
(
di
&&
di
.
jh
!=
null
)
{
lastIndexByJh
.
set
(
di
.
jh
,
idx
);
}
});
// 对每个井段,遍历该井的每个地层,按其 points 的实际 x 位置放置标签
// 将相同 x 标签的所有全局索引都存储起来,便于按井段范围内精确匹配
const
xIndexMap
=
new
Map
();
// key: x 标签, value: 索引数组
(
xAxisLabels
||
[]).
forEach
((
x
,
idx
)
=>
{
const
key
=
String
(
x
);
if
(
!
xIndexMap
.
has
(
key
))
xIndexMap
.
set
(
key
,
[]);
xIndexMap
.
get
(
key
).
push
(
idx
);
});
segments
.
forEach
(
seg
=>
{
const
layers
=
stackedAreas
[
seg
.
jh
]
||
[];
if
(
!
Array
.
isArray
(
layers
)
||
layers
.
length
===
0
)
return
;
layers
.
forEach
(
area
=>
{
if
(
!
area
)
return
;
// 选取该层的第一个点(通常为该井的首个测点,如 HT2465)用于横向定位
let
pointForX
=
null
;
if
(
Array
.
isArray
(
area
.
points
)
&&
area
.
points
.
length
>
0
)
{
// 优先选择在本井段 [startIdx, endIdx] 范围内能匹配到的 x
pointForX
=
area
.
points
.
find
(
p
=>
{
const
arr
=
xIndexMap
.
get
(
String
(
p
?.
x
));
if
(
!
arr
||
arr
.
length
===
0
)
return
false
;
return
arr
.
some
(
ix
=>
ix
>=
seg
.
startIdx
&&
ix
<=
seg
.
endIdx
);
})
||
area
.
points
[
0
];
}
// 计算中心深度(厚度规则:当 y2==y 或 sjdjsd==sjhd 时,厚度= y2,从 0 到 y2)
let
centerDepth
;
if
(
area
.
sjdjsd
!=
null
&&
area
.
sjhd
!=
null
)
{
if
(
Number
(
area
.
sjdjsd
)
===
Number
(
area
.
sjhd
))
{
centerDepth
=
Number
(
area
.
sjdjsd
)
/
2
;
}
else
{
centerDepth
=
(
Number
(
area
.
sjdjsd
)
+
Number
(
area
.
sjhd
))
/
2
;
}
}
else
if
(
pointForX
)
{
const
py1
=
Number
(
pointForX
.
y
);
const
py2
=
pointForX
.
y2
!=
null
?
Number
(
pointForX
.
y2
)
:
null
;
if
(
py2
!=
null
&&
py2
===
py1
)
{
centerDepth
=
py2
/
2
;
}
else
if
(
py2
!=
null
)
{
centerDepth
=
(
py1
+
py2
)
/
2
;
}
else
if
(
!
Number
.
isNaN
(
py1
))
{
centerDepth
=
py1
/
2
;
}
else
{
centerDepth
=
chartConfig
?.
yAxis
?.
min
||
0
;
}
}
else
{
centerDepth
=
chartConfig
?.
yAxis
?.
min
||
0
;
}
// 计算横向像素:若能找到该点的 x 在 xAxis 中的索引,就用该索引;否则退回到该井段的中点
let
xIndex
=
null
;
if
(
pointForX
&&
xIndexMap
.
has
(
String
(
pointForX
.
x
)))
{
const
candidates
=
xIndexMap
.
get
(
String
(
pointForX
.
x
))
||
[];
// 找到位于当前井段范围内的索引;如没有则回退到第一个
const
inSeg
=
candidates
.
find
(
ix
=>
ix
>=
seg
.
startIdx
&&
ix
<=
seg
.
endIdx
);
xIndex
=
inSeg
!=
null
?
inSeg
:
candidates
[
0
];
}
else
{
xIndex
=
(
seg
.
startIdx
+
seg
.
endIdx
)
/
2
;
}
// 仅在该井最后一列显示地层名
const
lastIdxForJh
=
lastIndexByJh
.
get
(
seg
.
jh
);
if
(
!
Number
.
isInteger
(
xIndex
)
||
lastIdxForJh
===
undefined
||
lastIdxForJh
!==
xIndex
)
{
return
;
}
const
pixel
=
this
.
myChart
.
convertToPixel
({
xAxisIndex
:
0
,
yAxisIndex
:
0
},
[
xIndex
,
centerDepth
]);
if
(
!
pixel
||
!
Array
.
isArray
(
pixel
)
||
pixel
.
length
<
2
)
return
;
const
[
px
,
py
]
=
pixel
;
graphics
.
push
({
type
:
'text'
,
position
:
[
px
+
120
,
py
],
style
:
{
text
:
area
.
name
||
''
,
fontSize
:
12
,
fontWeight
:
600
,
fill
:
'#111827'
,
stroke
:
'rgba(255,255,255,0.9)'
,
lineWidth
:
3
,
backgroundColor
:
'transparent'
,
align
:
'left'
,
verticalAlign
:
'middle'
},
z
:
10
,
zlevel
:
30
,
bounding
:
'raw'
,
silent
:
true
});
});
});
this
.
currentGraphicElements
=
graphics
;
this
.
myChart
.
setOption
({
graphic
:
{
elements
:
graphics
}
});
},
// 根据 depthIntervals 的顺序按 jh 分段,绘制虚线与顶部井号
...
...
@@ -1497,6 +1325,40 @@ export default {
const
merged
=
kept
.
concat
(
graphics
);
this
.
currentGraphicElements
=
merged
;
this
.
myChart
.
setOption
({
graphic
:
{
elements
:
merged
}
});
},
svgToDataUrl
(
svgString
)
{
if
(
!
svgString
)
return
null
;
try
{
const
encoded
=
encodeURIComponent
(
svgString
)
.
replace
(
/'/g
,
"%27"
)
.
replace
(
/"/g
,
"%22"
);
return
`data:image/svg+xml,
${
encoded
}
`
;
}
catch
(
error
)
{
console
.
warn
(
"SVG 转 dataUrl 失败:"
,
error
);
return
null
;
}
},
getLegendColor
(
index
)
{
const
palette
=
[
"#6B7280"
,
"#9CA3AF"
,
"#F59E0B"
,
"#F97316"
,
"#EF4444"
,
"#10B981"
,
"#14B8A6"
,
"#3B82F6"
,
"#6366F1"
,
"#8B5CF6"
,
"#EC4899"
,
"#0EA5E9"
,
"#84CC16"
,
"#D97706"
,
"#A16207"
];
return
palette
[
index
%
palette
.
length
];
},
hasLegendSvg
(
item
)
{
return
Boolean
(
item
&&
typeof
item
.
svg
===
"string"
&&
item
.
svg
.
trim
().
length
>
0
);
},
getLegendSvgSrc
(
item
)
{
if
(
!
this
.
hasLegendSvg
(
item
))
return
""
;
return
this
.
svgToDataUrl
(
item
.
svg
);
},
formatLegendName
(
item
)
{
return
item
&&
item
.
name
?
item
.
name
:
'-'
;
},
getLegendKey
(
item
,
index
)
{
return
`
${
this
.
formatLegendName
(
item
)}
-
${
index
}
`
;
}
},
};
...
...
@@ -1515,6 +1377,81 @@ export default {
position
:
relative
;
}
.chart-wrapper
{
flex
:
1
;
display
:
flex
;
flex-direction
:
row
;
align-items
:
stretch
;
gap
:
16px
;
position
:
relative
;
}
.legend-panel
{
width
:
220px
;
min-width
:
200px
;
max-height
:
100%
;
padding
:
16px
;
border-radius
:
16px
;
background
:
linear-gradient
(
135deg
,
#ffffff
0%
,
#f8fafc
100%
);
box-shadow
:
0
8px
24px
rgba
(
15
,
23
,
42
,
0.08
);
border
:
1px
solid
rgba
(
226
,
232
,
240
,
0.8
);
display
:
flex
;
flex-direction
:
column
;
gap
:
12px
;
}
.legend-title
{
font-size
:
15px
;
font-weight
:
600
;
color
:
#111827
;
letter-spacing
:
0.5px
;
}
.legend-scroll
{
flex
:
1
;
overflow-y
:
auto
;
padding-right
:
4px
;
}
.legend-item
{
display
:
flex
;
align-items
:
center
;
gap
:
10px
;
padding
:
6px
4px
;
}
.legend-swatch
{
width
:
32px
;
height
:
18px
;
border-radius
:
4px
;
border
:
1px
solid
rgba
(
148
,
163
,
184
,
0.6
);
flex-shrink
:
0
;
overflow
:
hidden
;
display
:
inline-flex
;
align-items
:
center
;
justify-content
:
center
;
background
:
#fff
;
}
.legend-swatch-img
{
width
:
100%
;
height
:
100%
;
object-fit
:
cover
;
border-radius
:
2px
;
}
.legend-swatch-color
{
width
:
100%
;
height
:
100%
;
border-radius
:
2px
;
}
.legend-label
{
font-size
:
13px
;
font-weight
:
500
;
color
:
#374151
;
}
/* 井号显示样式 */
.well-number-display
{
position
:
absolute
;
...
...
@@ -1612,10 +1549,22 @@ export default {
padding
:
0
10px
;
}
.chart-wrapper
{
flex-direction
:
column
;
}
.chart
{
min-height
:
300px
;
border-radius
:
12px
;
}
.legend-panel
{
width
:
100%
;
min-width
:
auto
;
flex-direction
:
row
;
flex-wrap
:
wrap
;
max-height
:
220px
;
}
}
/* 深色模式支持 */
...
...
src/views/efficiencyAnalysis/djxx/index.vue
View file @
b52c00b8
...
...
@@ -88,6 +88,18 @@
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"开次"
prop=
"kc"
>
<el-input
v-model=
"formData.kc"
placeholder=
"请输入开次"
/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col
:span=
"12"
>
<el-form-item
label=
"井眼尺寸"
prop=
"jycc"
>
<el-input
v-model=
"formData.jycc"
placeholder=
"请输入井眼尺寸"
/>
</el-form-item>
</el-col>
<el-col
:span=
"12"
>
<el-form-item
label=
"选择邻井"
prop=
"jhs"
>
<div
style=
"cursor: pointer;"
@
click=
"handleSelectAdjacentWell"
>
<el-input
v-model=
"formData.jhs"
placeholder=
"请点击选择邻井"
readonly
...
...
@@ -197,6 +209,8 @@ export default {
famc
:
''
,
qk
:
''
,
jhs
:
''
,
kc
:
''
,
jycc
:
''
,
jl
:
'10000'
,
// 距离默认值10000
wjsjks
:
null
,
// 完井时间开始默认五年前的今天
wjsjjs
:
null
,
// 完井时间结束默认今天
...
...
@@ -310,6 +324,8 @@ export default {
famc
:
''
,
qk
:
''
,
jhs
:
''
,
kc
:
''
,
jycc
:
''
,
jl
:
'10000'
,
// 距离默认值10000
wjsjks
:
this
.
getFiveYearsAgoDate
(),
// 完井时间开始默认五年前的今天
wjsjjs
:
this
.
getCurrentDate
(),
// 完井时间结束默认今天
...
...
@@ -445,6 +461,8 @@ export default {
famc
:
''
,
qk
:
''
,
jhs
:
''
,
kc
:
''
,
jycc
:
''
,
jl
:
'10000'
,
// 距离默认值10000
wjsjks
:
this
.
getFiveYearsAgoDate
(),
// 完井时间开始默认五年前的今天
wjsjjs
:
this
.
getCurrentDate
(),
// 完井时间结束默认今天
...
...
src/views/wellDesign/components/WellStructure.vue
View file @
b52c00b8
...
...
@@ -442,7 +442,7 @@ export default {
svg2
.
append
(
"rect"
)
.
attr
(
"width"
,
this
.
width
)
.
attr
(
"height"
,
this
.
height
)
.
style
(
"fill"
,
"
rgb(38,42,50)"
);
.
style
(
"fill"
,
"
transparent"
);
// 设置背景色为浅灰色
svg2
.
append
(
"g"
)
.
attr
(
"transform"
,
`translate(0,
${
this
.
marginTop
}
)`
)
...
...
@@ -491,6 +491,20 @@ export default {
.
y0
(
d
=>
y
(
d
.
depth1
))
.
y1
(
d
=>
y
(
d
.
depth2
));
// 深色填充区域(例如井筒内部)
if
(
Array
.
isArray
(
res
.
svg2ConstructFillDark
))
{
for
(
let
k
=
0
;
k
<
res
.
svg2ConstructFillDark
.
length
;
k
++
)
{
const
item
=
res
.
svg2ConstructFillDark
[
k
];
if
(
!
item
||
!
item
.
fill
)
continue
;
svg2
.
append
(
"path"
)
.
attr
(
"transform"
,
`translate(0,0)`
)
.
datum
(
item
.
fill
)
.
attr
(
"class"
,
"area-dark"
)
.
attr
(
"d"
,
area
)
.
attr
(
"fill"
,
"rgb(60,60,60)"
);
}
}
if
(
Array
.
isArray
(
res
.
svg2ConstructFillGrey
))
{
for
(
let
k
=
0
;
k
<
res
.
svg2ConstructFillGrey
.
length
;
k
++
)
{
const
item
=
res
.
svg2ConstructFillGrey
[
k
];
...
...
@@ -552,6 +566,127 @@ export default {
}
}
}
// 标注用的直线生成器(左右说明箭头)
const
arrowLine
=
d3
.
line
()
.
x
(
d
=>
x
(
d
[
0
]))
.
y
(
d
=>
y
(
d
[
1
]))
.
curve
(
d3
.
curveLinear
);
// 左侧标注点与文字
if
(
Array
.
isArray
(
res
.
svg2ConstructPointLeft
))
{
for
(
let
i
=
0
;
i
<
res
.
svg2ConstructPointLeft
.
length
;
i
++
)
{
const
item
=
res
.
svg2ConstructPointLeft
[
i
];
if
(
!
item
||
!
Array
.
isArray
(
item
.
point
)
||
item
.
point
.
length
<
2
)
continue
;
// 箭头线
svg2
.
append
(
"path"
)
.
attr
(
"d"
,
arrowLine
(
item
.
point
))
.
attr
(
"stroke"
,
"#ffffff"
)
.
attr
(
"fill"
,
"none"
)
.
attr
(
"stroke-width"
,
1
)
.
attr
(
"stroke-linecap"
,
"round"
);
// 起点实心圆
const
circleX
=
x
(
item
.
point
[
0
][
0
]);
const
circleY
=
y
(
item
.
point
[
0
][
1
]);
svg2
.
append
(
"circle"
)
.
attr
(
"cx"
,
circleX
)
.
attr
(
"cy"
,
circleY
)
.
attr
(
"r"
,
3
)
.
attr
(
"fill"
,
"#ffffff"
)
.
attr
(
"stroke"
,
"none"
);
// 文本位置在箭头起点右侧稍上
const
textX
=
x
(
item
.
point
[
0
][
0
]
+
20
);
const
textY
=
y
(
item
.
point
[
0
][
1
]
-
3
);
const
group
=
svg2
.
append
(
"g"
)
.
attr
(
"transform"
,
"translate(0,0)"
);
const
text
=
group
.
append
(
"text"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
)
.
attr
(
"fill"
,
"#ffffff"
)
.
attr
(
"font-size"
,
"12px"
);
if
(
item
.
describe1
)
{
text
.
append
(
"tspan"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
)
.
attr
(
"font-weight"
,
"bold"
)
.
text
(
item
.
describe1
);
}
if
(
item
.
describe2
)
{
text
.
append
(
"tspan"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
+
16
)
.
attr
(
"font-weight"
,
"bold"
)
.
text
(
item
.
describe2
);
}
if
(
item
.
describe3
)
{
text
.
append
(
"tspan"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
+
32
)
.
attr
(
"font-weight"
,
"bold"
)
.
text
(
item
.
describe3
);
}
}
}
// 右侧标注点与文字
if
(
Array
.
isArray
(
res
.
svg2ConstructPointRight
))
{
for
(
let
i
=
0
;
i
<
res
.
svg2ConstructPointRight
.
length
;
i
++
)
{
const
item
=
res
.
svg2ConstructPointRight
[
i
];
if
(
!
item
||
!
Array
.
isArray
(
item
.
point
)
||
item
.
point
.
length
<
2
)
continue
;
svg2
.
append
(
"path"
)
.
attr
(
"d"
,
arrowLine
(
item
.
point
))
.
attr
(
"stroke"
,
"#ffffff"
)
.
attr
(
"fill"
,
"none"
)
.
attr
(
"stroke-width"
,
1
)
.
attr
(
"stroke-linecap"
,
"round"
);
const
circleX
=
x
(
item
.
point
[
0
][
0
]);
const
circleY
=
y
(
item
.
point
[
0
][
1
]);
svg2
.
append
(
"circle"
)
.
attr
(
"cx"
,
circleX
)
.
attr
(
"cy"
,
circleY
)
.
attr
(
"r"
,
3
)
.
attr
(
"fill"
,
"#ffffff"
)
.
attr
(
"stroke"
,
"none"
);
const
textX
=
x
(
item
.
point
[
0
][
0
]
+
20
);
const
textY
=
y
(
item
.
point
[
0
][
1
]
-
3
);
const
group
=
svg2
.
append
(
"g"
)
.
attr
(
"transform"
,
"translate(0,0)"
);
const
text
=
group
.
append
(
"text"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
)
.
attr
(
"fill"
,
"#ffffff"
)
.
attr
(
"font-size"
,
"12px"
);
if
(
item
.
describe1
)
{
text
.
append
(
"tspan"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
)
.
attr
(
"font-weight"
,
"bold"
)
.
text
(
item
.
describe1
);
}
if
(
item
.
describe2
)
{
text
.
append
(
"tspan"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
+
16
)
.
attr
(
"font-weight"
,
"bold"
)
.
text
(
item
.
describe2
);
}
if
(
item
.
describe3
)
{
text
.
append
(
"tspan"
)
.
attr
(
"x"
,
textX
+
10
)
.
attr
(
"y"
,
textY
+
32
)
.
attr
(
"font-weight"
,
"bold"
)
.
text
(
item
.
describe3
);
}
}
}
},
drawTriangle
(
triangle
)
{
return
"M"
+
triangle
.
x1
+
","
+
triangle
.
y1
+
...
...
@@ -678,6 +813,47 @@ export default {
margin
:
5px
;
}
.content-row
{
height
:
100%
;
}
.jsjgt-wrapper
{
height
:
calc
(
100vh
-
260px
);
border
:
1px
solid
#e4e7ed
;
border-radius
:
4px
;
display
:
flex
;
flex-direction
:
column
;
background-color
:
#262a32
;
overflow
:
hidden
;
}
.jsjgt-title
{
padding
:
6px
12px
;
font-size
:
14px
;
font-weight
:
600
;
color
:
#ffffff
;
border-bottom
:
1px
solid
#3c3f45
;
}
.jsjgt-body
{
flex
:
1
;
display
:
flex
;
align-items
:
stretch
;
justify-content
:
center
;
}
.jsjgt-body
.svg2
{
flex
:
1
;
}
.jsjgt-empty
{
position
:
absolute
;
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
color
:
#c0c4cc
;
}
::v-deep
.el-table__cell
>
.cell
{
font-weight
:
normal
;
}
...
...
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