Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
SatelliteDigital
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
nijiawen
SatelliteDigital
Commits
b548a9ad
提交
b548a9ad
authored
3月 17, 2026
作者:
汪雄
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
完成曲线模板配置流程
上级
3b22b605
隐藏空白字符变更
内嵌
并排
正在显示
12 个修改的文件
包含
1014 行增加
和
868 行删除
+1014
-868
Zodiac.js
src/api/Zodiac.js
+96
-3
cdfCurve.vue
src/pages/all/components/cdf/cdfCurve.vue
+69
-68
childrenCdfCurve.vue
src/pages/all/components/cdf/childrenCdfCurve.vue
+87
-91
index.vue
src/pages/all/components/cdf/index.vue
+39
-41
hotMap.vue
src/pages/all/components/hotMapComponents/hotMap.vue
+56
-375
index.vue
src/pages/all/components/hotMapComponents/index.vue
+35
-29
testMap.vue
src/pages/all/components/hotMapComponents/testMap.vue
+227
-104
index.vue
src/pages/all/components/instant/index.vue
+35
-31
timers.vue
src/pages/footer/component/timers.vue
+1
-1
screenConfigCase.vue
src/pages/header/component/screenConfigCase.vue
+190
-75
screenConfigeDialog.vue
src/pages/header/component/screenConfigeDialog.vue
+178
-49
index.vue
src/pages/header/index.vue
+1
-1
没有找到文件。
src/api/Zodiac.js
浏览文件 @
b548a9ad
...
...
@@ -118,9 +118,56 @@ export function getCapacityAndTraffic(data) {
granularity
:
data
.
granularity
,
startTime
:
data
.
startTime
,
endTime
:
data
.
endTime
,
regionName
:
data
.
regionName
||
null
,
regionName
:
data
.
regionName
||
null
,
signalSiteCode
:
data
.
signalSiteCode
||
null
,
},
});
}
//规划可用性
export
function
getAvailability
(
data
)
{
return
request
({
url
:
"/commPanel/getAvailability"
,
method
:
"get"
,
params
:
{
gridCodes
:
data
.
gridCodes
||
null
,
granularity
:
data
.
granularity
,
startTime
:
data
.
startTime
,
endTime
:
data
.
endTime
,
regionName
:
data
.
regionName
||
null
,
signalSiteCode
:
data
.
signalSiteCode
||
null
,
},
});
}
//接入时延(搜星)
export
function
getDelay
(
data
)
{
return
request
({
url
:
"/commPanel/getDelay"
,
method
:
"get"
,
params
:
{
gridCodes
:
data
.
gridCodes
||
null
,
granularity
:
data
.
granularity
,
startTime
:
data
.
startTime
,
endTime
:
data
.
endTime
,
regionName
:
data
.
regionName
||
null
,
signalSiteCode
:
data
.
signalSiteCode
||
null
,
},
});
}
//丢包率获取
export
function
getLossRate
(
data
)
{
return
request
({
url
:
"/commPanel/getLossRate"
,
method
:
"get"
,
params
:
{
gridCodes
:
data
.
gridCodes
||
null
,
granularity
:
data
.
granularity
,
startTime
:
data
.
startTime
,
endTime
:
data
.
endTime
,
regionName
:
data
.
regionName
||
null
,
signalSiteCode
:
data
.
signalSiteCode
||
null
,
},
});
}
...
...
@@ -131,4 +178,51 @@ export function getGridInfoList() {
url
:
"/GridInfo/list"
,
method
:
"get"
,
});
}
\ No newline at end of file
}
//模板配置列表
export
function
getTemplateList
()
{
return
request
({
url
:
"/templateApi/list"
,
method
:
"get"
,
});
}
//模板配置新增
export
function
templateAdd
(
data
)
{
return
request
({
url
:
"/templateApi/add"
,
method
:
"post"
,
data
,
});
}
//模板配置删除
export
function
templateDel
({
data
})
{
return
request
({
url
:
"/templateApi/delete"
,
method
:
"get"
,
params
:
{
templateId
:
data
.
templateId
,
},
});
}
//模板配置详情
export
function
templateDetail
({
data
})
{
return
request
({
url
:
"/templateApi/detail"
,
method
:
"get"
,
params
:
{
templateId
:
data
.
templateId
,
},
});
}
//模板配置修改
export
function
templateuUpdate
({
data
})
{
return
request
({
url
:
"/templateApi/update"
,
method
:
"POST"
,
data
,
});
}
src/pages/all/components/cdf/cdfCurve.vue
浏览文件 @
b548a9ad
<
template
>
<!--
C
DF曲线图 -->
<!--
P
DF曲线图 -->
<div
class=
"container"
>
<div
class=
"main"
>
<div
:id=
"idName"
class=
"cdfCurve"
></div>
<div
class=
"showDetial"
@
click=
"showViewClick"
v-if=
"isShowDetial"
>
<el-icon
v-if=
"showView"
class=
"icon"
><View
/></el-icon>
<el-icon
v-else
class=
"icon"
><Hide
/></el-icon>
<el-icon
v-if=
"showView"
class=
"icon"
>
<View
/>
</el-icon>
<el-icon
v-else
class=
"icon"
>
<Hide
/>
</el-icon>
<span>
详情
</span>
</div>
<div
class=
"showValue"
>
<div
v-for=
"(item, index) in markLineData"
:key=
"index"
>
<span
style=
"font-weight: 700;font-size: 10px; padding: 0 5.5px;"
:style=
"
{ color: item.color }">--
</span>
{{
item
.
descript
}}
<span
style=
"font-weight: 700;font-size: 10px; padding: 0 5.5px;"
:style=
"
{ color: item.color }">--
</span>
{{
item
.
descript
}}
</div>
</div>
</div>
<el-dialog
v-model=
"isDetialDialogVisible"
:show-close=
"false"
:modal=
"false"
custom-class=
"custom-cdf-dialog"
width=
"200"
height=
"100"
:destroy-on-close=
"true"
:before-close=
"isDetialDialogVisibleHandleClose"
style=
"margin: 0;padding: 0; background-color: rgba(0, 0, 0, 0);"
>
<childrenCdfCurve
ref=
"childrenCdfRef"
:propsDate=
"propsDate"
@
isDetialDialogVisibleHandleClose=
"isDetialDialogVisibleHandleClose"
/>
</el-dialog>
<el-dialog
v-model=
"isDetialDialogVisible"
:show-close=
"false"
:modal=
"false"
custom-class=
"custom-cdf-dialog"
width=
"200"
height=
"100"
:destroy-on-close=
"false"
:before-close=
"isDetialDialogVisibleHandleClose"
style=
"margin: 0;padding: 0; background-color: rgba(0, 0, 0, 0);"
>
<childrenCdfCurve
ref=
"childrenCdfRef"
:propsDate=
"propsDate"
@
isDetialDialogVisibleHandleClose=
"isDetialDialogVisibleHandleClose"
/>
</el-dialog>
</div>
</
template
>
...
...
@@ -41,15 +38,11 @@ export default {
import
*
as
echarts
from
'echarts'
;
import
childrenCdfCurve
from
'./childrenCdfCurve.vue'
import
{
onMounted
,
onUnmounted
,
ref
}
from
'vue'
;
import
{
onMounted
,
onUnmounted
,
ref
,
nextTick
}
from
'vue'
;
const
idName
=
ref
(
Math
.
random
().
toString
(
30
).
slice
(
2
,
8
))
const
props
=
defineProps
({
idName
:
{
type
:
String
,
default
:
'main'
},
propsDate
:
{
type
:
Object
,
default
:
()
=>
({})
...
...
@@ -83,30 +76,32 @@ function showViewClick() {
// //console.log("时间");
isDetialDialogVisible
.
value
=
!
isDetialDialogVisible
.
value
;
showView
.
value
=
true
;
if
(
window
.
ue5
)
{
window
.
ue5
(
"callBackAllDialogFn"
,
String
(
JSON
.
stringify
({
type
:
"CDFCurveDetailDialog"
,
status
:
"open"
})));
}
if
(
window
.
ue5
)
{
window
.
ue5
(
"callBackAllDialogFn"
,
String
(
JSON
.
stringify
({
type
:
"CDFCurveDetailDialog"
,
status
:
"open"
})));
}
// //console.log("当前的值:",showView.value);
}
function
isDetialDialogVisibleHandleClose
()
{
isDetialDialogVisible
.
value
=
false
;
showView
.
value
=
false
;
if
(
window
.
ue5
)
{
window
.
ue5
(
"callBackAllDialogFn"
,
String
(
JSON
.
stringify
({
type
:
"CDFCurveDetailDialog"
,
status
:
"close"
})));
}
if
(
window
.
ue5
)
{
window
.
ue5
(
"callBackAllDialogFn"
,
String
(
JSON
.
stringify
({
type
:
"CDFCurveDetailDialog"
,
status
:
"close"
})));
}
}
onMounted
(()
=>
{
initChart
();
nextTick
(()
=>
{
initChart
();
})
//console.log("-------cdfCurve-------",props.idName);
document
.
getElementById
(
props
.
idName
).
style
.
height
=
'240px'
;
//
document.getElementById(props.idName).style.height = '240px';
});
onUnmounted
(()
=>
{
...
...
@@ -117,7 +112,7 @@ onUnmounted(() => {
});
function
initChart
()
{
const
chartDom
=
document
.
getElementById
(
props
.
idNam
e
);
const
chartDom
=
document
.
getElementById
(
idName
.
valu
e
);
chartDom
.
style
.
height
=
'180px'
;
chartDom
.
style
.
width
=
'170px'
;
myChart
=
echarts
.
init
(
chartDom
);
...
...
@@ -125,7 +120,7 @@ function initChart() {
const
option
=
{
legend
:
{
show
:
true
,
data
:
[
'
C
DF曲线图'
],
data
:
[
'
P
DF曲线图'
],
textStyle
:
{
color
:
'#fff'
,
fontSize
:
12
...
...
@@ -139,7 +134,7 @@ function initChart() {
icon
:
'rect'
,
// 使用矩形图标
itemWidth
:
15
,
// 图例宽度
itemHeight
:
5
,
// 图例高度,设为较小值形成线条效果
},
grid
:
{
top
:
'23%'
,
...
...
@@ -180,7 +175,7 @@ function initChart() {
},
series
:
[
{
name
:
'
C
DF曲线图'
,
name
:
'
P
DF曲线图'
,
data
:
[
12
,
13
,
5
,
103
,
19
,
3
,
18
],
type
:
'line'
,
smooth
:
0.6
,
...
...
@@ -214,24 +209,24 @@ function initChart() {
label
:
{
show
:
false
},
data
:
[
{
yAxis
:
45
,
lineStyle
:
{
color
:
'#ff0000'
,
width
:
2
,
type
:
'dashed'
},
},
{
yAxis
:
70
,
lineStyle
:
{
color
:
'#ff55f5'
,
width
:
2
,
type
:
'dashed'
},
}
]
//
data: [
//
{
//
yAxis: 45,
//
lineStyle: {
//
color: '#ff0000',
//
width: 2,
//
type: 'dashed'
//
},
//
},
//
{
//
yAxis: 70,
//
lineStyle: {
//
color: '#ff55f5',
//
width: 2,
//
type: 'dashed'
//
},
//
}
//
]
}
}
],
...
...
@@ -292,11 +287,13 @@ function resizeChart() {
position
:
relative
;
z-index
:
1
;
}
.cdfCurve
div
{
.cdfCurve
div
{
width
:
100%
;
height
:
100%
;
}
.showDetial
{
.showDetial
{
position
:
absolute
;
/* flex-direction: row; */
font
:
12px
"微软雅黑"
;
...
...
@@ -308,19 +305,23 @@ function resizeChart() {
/* justify-content: center;
align-items: center; */
}
.showDetial
.icon
{
.showDetial
.icon
{
margin
:
0
;
padding
:
0
;
top
:
2px
;
}
.showDetial
span
{
}
.showDetial
span
{
padding-left
:
5px
;
}
.showDetial
:hover
{
.showDetial
:hover
{
/* background-color: rgba(255, 255, 255, 0.91); */
color
:
#607FB0
;
}
/* .custom-cdf-dialog{
position: absolute;
left: 100px;
...
...
src/pages/all/components/cdf/childrenCdfCurve.vue
浏览文件 @
b548a9ad
...
...
@@ -7,7 +7,7 @@
</div>
<button
class=
"close-btn"
@
click=
"closePanel"
>
×
</button>
</div>
<!-- 设备列表内容区 -->
<div
class=
"content"
>
<div
class=
"content_header"
>
...
...
@@ -17,28 +17,12 @@
type=
"datetimerange"
/>
-->
<el-date-picker
popper-class=
"custom-date-popper"
v-model=
"dateRange"
type=
"daterange"
size=
"small"
unlink-panels
range-separator=
"->"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
format=
"YYYY-MM-DD HH:mm:ss"
date-format=
"YYYY/MM/DD ddd"
time-format=
"A hh:mm:ss"
:default-time=
"defaultDateTimeRange"
:disabled-date=
"disabledDate"
:disabled-hours=
"disabledHours"
:cell-class-name=
"(date) => 'date-picker-custom'"
/>
<el-button
@
click=
"handleDateRangeChange"
size=
"small"
>
查询
</el-button>
<el-date-picker
popper-class=
"custom-date-popper"
v-model=
"dateRange"
type=
"daterange"
size=
"small"
unlink-panels
range-separator=
"->"
start-placeholder=
"开始时间"
end-placeholder=
"结束时间"
format=
"YYYY-MM-DD HH:mm:ss"
date-format=
"YYYY/MM/DD ddd"
time-format=
"A hh:mm:ss"
:default-time=
"defaultDateTimeRange"
:disabled-date=
"disabledDate"
:disabled-hours=
"disabledHours"
:cell-class-name=
"(date) => 'date-picker-custom'"
/>
<el-button
@
click=
"handleDateRangeChange"
size=
"small"
>
查询
</el-button>
</div>
<div
id=
"ghCurve"
class=
"cdfCurve"
></div>
<div
id=
"sjCurve"
class=
"cdfCurve"
></div>
...
...
@@ -54,8 +38,8 @@ import * as echarts from 'echarts';
const
props
=
defineProps
([
'devices'
,
'isDetialDialogVisible'
])
const
emits
=
defineEmits
([
'errorDialoghandleClose'
,
'isDetialDialogVisibleHandleClose'
])
const
props
=
defineProps
([
'devices'
,
'isDetialDialogVisible'
])
const
emits
=
defineEmits
([
'errorDialoghandleClose'
,
'isDetialDialogVisibleHandleClose'
])
let
myCharts
=
[];
// 存储多个图表实例
const
lineColor
=
[
'#2e7dff'
,
'#6FFCBA'
,
'#7590bc'
,
'#ff95c7'
];
...
...
@@ -68,7 +52,7 @@ const chartConfigs = ref([
{
name
:
'空口链路丢包率'
,
data
:
[
12
,
13
,
85
,
53
,
19
,
23
,
18
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
colorIndex
:
0
}
]
...
...
@@ -79,7 +63,7 @@ const chartConfigs = ref([
{
name
:
'网络延迟'
,
data
:
[
25
,
35
,
65
,
45
,
30
,
40
,
28
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
colorIndex
:
1
}
]
...
...
@@ -104,7 +88,7 @@ const chartConfigs = ref([
]);
const
defaultDateTimeRange
=
ref
([
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
()
+
1
,
new
Date
().
getDate
(),
0
,
0
,
0
),
new
Date
(
new
Date
().
getFullYear
(),
new
Date
().
getMonth
()
+
1
,
new
Date
().
getDate
(),
0
,
0
,
0
),
...
...
@@ -121,74 +105,74 @@ function formatDate(date) {
return
`
${
year
}
-
${
month
}
-
${
day
}
${
hours
}
:
${
minutes
}
:
${
seconds
}
`
;
}
const
dateRange
=
ref
([]);
function
handleDateRangeChange
()
{
function
handleDateRangeChange
()
{
const
submitData
=
{
startTime
:
formatDate
(
dateRange
.
value
[
0
]),
endTime
:
formatDate
(
dateRange
.
value
[
1
])
}
//console.log("提交:",submitData);
if
(
submitData
.
startTime
&&
submitData
.
endTime
)
{
chartConfigs
.
value
=
[
{
id
:
'ghCurve'
,
series
:
[
if
(
submitData
.
startTime
&&
submitData
.
endTime
)
{
chartConfigs
.
value
=
[
{
name
:
'空口链路450Mbps-丢包率'
,
data
:
[
12
,
3
,
5
,
93
,
19
,
23
,
18
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
colorIndex
:
0
}
]
},
{
id
:
'sjCurve'
,
series
:
[
{
name
:
'网络cxcz延迟'
,
data
:
[
25
,
95
,
15
,
5
,
30
,
40
,
28
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
colorIndex
:
1
}
]
},
{
id
:
'dblCurve'
,
series
:
[
id
:
'ghCurve'
,
series
:
[
{
name
:
'空口链路450Mbps-丢包率'
,
data
:
[
12
,
3
,
5
,
93
,
19
,
23
,
18
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
colorIndex
:
0
}
]
},
{
name
:
'发送速率size'
,
data
:
[
20
,
70
,
60
,
25
,
90
,
22
,
60
,
18
,
12
,
28
,
12
,
56
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
],
colorIndex
:
2
id
:
'sjCurve'
,
series
:
[
{
name
:
'网络cxcz延迟'
,
data
:
[
25
,
95
,
15
,
5
,
30
,
40
,
28
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
],
colorIndex
:
1
}
]
},
{
name
:
'接收速率size'
,
data
:
[
110
,
18
,
60
,
18
,
12
,
28
,
12
,
56
,
89
,
21
,
7
,
25
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
],
colorIndex
:
3
id
:
'dblCurve'
,
series
:
[
{
name
:
'发送速率size'
,
data
:
[
20
,
70
,
60
,
25
,
90
,
22
,
60
,
18
,
12
,
28
,
12
,
56
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
],
colorIndex
:
2
},
{
name
:
'接收速率size'
,
data
:
[
110
,
18
,
60
,
18
,
12
,
28
,
12
,
56
,
89
,
21
,
7
,
25
],
Xdata
:
[
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
,
9
,
10
,
11
,
12
],
colorIndex
:
3
}
]
}
]
}
];
myCharts
.
forEach
(
chart
=>
{
if
(
chart
)
{
chart
.
dispose
();
}
});
chartConfigs
.
value
.
forEach
(
config
=>
{
const
chartDom
=
document
.
getElementById
(
config
.
id
);
if
(
chartDom
)
{
initChart
(
chartDom
,
config
);
// resizeChart()
}
});
}
else
{
];
myCharts
.
forEach
(
chart
=>
{
if
(
chart
)
{
chart
.
dispose
();
}
});
chartConfigs
.
value
.
forEach
(
config
=>
{
const
chartDom
=
document
.
getElementById
(
config
.
id
);
if
(
chartDom
)
{
initChart
(
chartDom
,
config
);
// resizeChart()
}
});
}
else
{
ElMessage
({
type
:
'warning'
,
message
:
'完善开始时间和结束时间的选择'
,
});
}
}
// 禁用未来日期
const
disabledDate
=
(
time
)
=>
{
...
...
@@ -197,6 +181,8 @@ const disabledDate = (time) => {
onMounted
(()
=>
{
// 初始化所有图表
chartConfigs
.
value
.
forEach
(
config
=>
{
alert
(
config
)
console
.
log
(
'初始化config'
,
config
)
const
chartDom
=
document
.
getElementById
(
config
.
id
);
if
(
chartDom
)
{
initChart
(
chartDom
,
config
);
...
...
@@ -217,10 +203,10 @@ onUnmounted(() => {
function
initChart
(
chartDom
,
config
)
{
const
myChart
=
echarts
.
init
(
chartDom
);
myCharts
.
push
(
myChart
);
// 存储图表实例
// 根据series配置动态构建legend数据
const
legendData
=
config
.
series
.
map
(
series
=>
series
.
name
);
// 动态构建series配置
const
seriesOptions
=
config
.
series
.
map
((
seriesItem
)
=>
{
const
color
=
lineColor
[
seriesItem
.
colorIndex
];
...
...
@@ -327,11 +313,11 @@ function initChart(chartDom, config) {
};
myChart
.
setOption
(
option
);
// 添加resize处理
const
handleResize
=
()
=>
myChart
.
resize
();
window
.
addEventListener
(
'resize'
,
handleResize
);
// 保存resize处理函数以便后续可能需要移除
myChart
.
_resizeHandler
=
handleResize
;
}
...
...
@@ -364,7 +350,7 @@ const closePanel = () => {
top
:
50%
;
left
:
50%
;
transform
:
translate
(
-50%
,
-50%
);
}
.header
{
...
...
@@ -407,7 +393,7 @@ const closePanel = () => {
.close-btn
{
width
:
15px
;
height
:
15px
;
background
:
#1E1E2D
;
background
:
#1E1E2D
;
border
:
none
;
color
:
#aaa
;
font-size
:
24px
;
...
...
@@ -433,10 +419,11 @@ const closePanel = () => {
background
:
#000000
;
}
.cdfCurve
{
.cdfCurve
{
width
:
900px
;
height
:
220px
;
}
.content_header
{
width
:
55%
;
display
:
flex
;
...
...
@@ -445,41 +432,50 @@ const closePanel = () => {
gap
:
10px
;
/* background-color: #2a2a3a; */
}
.content_header
span
{
width
:
60px
;
font-size
:
11px
;
color
:
#e0e0e0
;
}
:deep
(
.el-date-editor
)
{
background-color
:
#000000
;
box-shadow
:
0
0
2px
rgba
(
131
,
131
,
131
,
0.95
);
}
:deep
(
.el-button
)
{
background
:
#000000
;
background
:
#000000
;
border
:
none
;
color
:
#e0e0e0
;
width
:
70px
;
}
:deep
(
.el-range-input
)
{
:deep
(
.el-range-input
)
{
color
:
#ffffff
;
}
:deep
(
.el-range-separator
)
{
:deep
(
.el-range-separator
)
{
color
:
#ffffff
;
}
:deep
(
.el-button
:hover
)
{
background
:
linear-gradient
(
to
bottom
,
#2C76F1
,
#000000
);
border
:
none
;
border
:
none
;
box-shadow
:
none
;
}
:deep
(
.custom-date-popper
)
{
background-color
:
#1e1e2d
;
border
:
1px
solid
#383850
;
}
:deep
(
.date-picker-custom
)
{
background-color
:
#000000
;
box-shadow
:
none
;
}
/* .date-picker-custom :deep(.el-range-editor) {
width: 10%;
height: 100%;
...
...
src/pages/all/components/cdf/index.vue
浏览文件 @
b548a9ad
...
...
@@ -7,33 +7,27 @@
<div
class=
"divider-line"
></div>
</div>
<div
class=
"hot-title"
>
<div
class=
"hot-title-text"
>
巴西-最小值(CDF曲线图)
</div>
<div
class=
"hot-title-enlarge"
>
<svg
width=
"20"
height=
"20"
viewBox=
"0 0 32 32"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.5"
y=
"0.5"
width=
"31"
height=
"31"
rx=
"3.5"
stroke=
"white"
stroke-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M23.5002 8.5V13.5H21.8335V11.4043L18.0119 15.2259L16.8334 14.0474L20.7141 10.1667H18.5002V8.5H23.5002Z"
fill=
"white"
fill-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M8.5 23.5592V18.5592H10.1667V20.6549L13.9883 16.8333L15.1668 18.0118L11.2861 21.8925H13.5V23.5592H8.5Z"
fill=
"white"
fill-opacity=
"0.65"
/>
</svg>
</div>
<div
class=
"hot-title-text"
>
{{
props
.
title
}}
</div>
<div
class=
"hot-title-enlarge"
>
<svg
width=
"20"
height=
"20"
viewBox=
"0 0 32 32"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.5"
y=
"0.5"
width=
"31"
height=
"31"
rx=
"3.5"
stroke=
"white"
stroke-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M23.5002 8.5V13.5H21.8335V11.4043L18.0119 15.2259L16.8334 14.0474L20.7141 10.1667H18.5002V8.5H23.5002Z"
fill=
"white"
fill-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M8.5 23.5592V18.5592H10.1667V20.6549L13.9883 16.8333L15.1668 18.0118L11.2861 21.8925H13.5V23.5592H8.5Z"
fill=
"white"
fill-opacity=
"0.65"
/>
</svg>
</div>
</div>
<!-- 核心数据指标 -->
<div
class=
"container"
>
<div
class=
"flex-box flex-left"
>
<cdfCurve
:
idName=
"`$
{cdfCurveLeft}+${allIdName[0]}`" :
propsDate="componentProps">
</cdfCurve>
<div
class=
"flex-box flex-left"
>
<cdfCurve
:propsDate=
"componentProps"
></cdfCurve>
</div>
<div
class=
"flex-box flex-right"
>
<cdfCurve
:
idName=
"`$
{cdfCurveRight}+${allIdName[1]}`" :
propsDate="componentProps" :isShowDetial="true">
</cdfCurve>
</div>
<cdfCurve
:propsDate=
"componentProps"
:isShowDetial=
"true"
></cdfCurve>
</div>
</div>
</div>
</
template
>
...
...
@@ -41,23 +35,21 @@
<
script
setup
>
import
{
onBeforeUnmount
}
from
'vue'
;
import
cdfCurve
from
'./cdfCurve.vue'
const
cdfCurveRight
=
ref
(
'chart-right'
);
const
cdfCurveLeft
=
ref
(
'chart-left'
);
const
props
=
defineProps
({
allIdNam
e
:
{
type
:
Array
,
default
:
()
=>
[
'allIdName1'
,
'allIdName2'
],
}
,
titl
e
:
{
type
:
String
,
default
:
'位置默认'
}
});
onBeforeUnmount
(()
=>
{
onBeforeUnmount
(()
=>
{
//console.log("中,zhelixieza");
});
const
componentProps
=
ref
({});
</
script
>
<
style
scoped
>
/* 基础样式 */
.header-container
{
display
:
flex
;
...
...
@@ -91,14 +83,17 @@ const componentProps = ref({});
display
:
flex
;
align-items
:
center
;
}
.hot-title
{
.hot-title
{
display
:
flex
;
justify-content
:
space-between
;
}
.hot-title-text
{
font-weight
:
700
;
font-size
:
13px
;
.hot-title-text
{
font-weight
:
700
;
font-size
:
13px
;
}
.hot-title-enlarge
{
display
:
inline-flex
;
align-items
:
center
;
...
...
@@ -108,11 +103,12 @@ const componentProps = ref({});
transition
:
all
0.3s
ease
;
}
.hot-title-enlarge
:hover
.rect
{
/* transform: scale(1.51); */
.hot-title-enlarge
:hover
.rect
{
/* transform: scale(1.51); */
transform-origin
:
center
;
}
.hot-title-enlarge
:hover
.arrow-path
{
.hot-title-enlarge
:hover
.arrow-path
{
transform
:
scale
(
1.2
)
skew
(
-10deg
,
-10deg
);
transform-origin
:
center
;
transition
:
transform
0.3s
ease
;
...
...
@@ -132,12 +128,13 @@ const componentProps = ref({});
.flex-box
{
flex
:
1
;
/* display: flex;
align-items: center;
justify-content: center; */
}
.flex-left
{
.flex-left
{
/* background-color: rgb(180, 180, 180); */
}
}
</
style
>
\ No newline at end of file
src/pages/all/components/hotMapComponents/hotMap.vue
浏览文件 @
b548a9ad
<!-- <template>
<热力图
<div style="height: 100%;background-color: blueviolet;" >
<div style="width: 100%;height: 100%;">
<div class="main">
我是hotMap
</div>
</div>
</div>
</template>
<script>
export default {
name: "hotMap_chart"
}
</script>
<script setup>
// import { onMounted, onBeforeUnmount, computed, ref, reactive, nextTick, markRaw, watch } from "vue";
// import * as echarts from 'echarts';
// import { getLanguage, setLanguage } from '@/utils/auth'
// import visualApi from "../../../api/move/visual.js";
// const ChineseEnglishGlossary = ref({
// "前向分布": "Forward links availability",
// "反向分布": "Backward links availability",
// "Forward links availability": "Forward links availability",
// "Backward links availability": "Backward links availability"
// })
// const props = defineProps({
// componentProps: {
// type: Object,
// default: () => { }
// },
// time: {
// type: String,
// default: () => ''
// },
// eight: {
// type: Boolean,
// default: () => true
// },
// dataType: {
// type: Number,
// default: () => 0
// },
// tableObj: {
// type: Object,
// default: () => { }
// }
// })
// const timeIntal = ref(true)
// var watchList = []
// const watch1 = watch(() => props.time, (newVal) => {
// if (selectStatus.value) {
// // //console.log(objs.value[newVal], newVal);
// selectId.value = newVal
// if (timeIntal.value) {
// timeIntal.value = false
// setTimeout(() => {
// if (objs.value[newVal] && objs.value[newVal] != 'undefined') {
// planFn(objs.value[newVal], xName.value, yName.value, props.componentProps)
// }
// timeIntal.value = true
// }, 500);
// }
// }
// if (props.componentProps.dataType && props.componentProps.dataType == 1) {
// propsFn(props.componentProps)
// }
// })
// watchList.push(watch1)
// const watch2 = watch(() => props.tableObj.update, (newVal) => {
// if (newVal) {
// if (myChart) {
// propsFn(props.componentProps)
// myChart.resize()
// }
// }
// })
// watchList.push(watch2)
// var pieces1 = [
// { min: 0, max: 0, label: '0', color: '#ffffff' },
// { min: 1, max: 0, label: '1', color: '#72EFDD' },
// { min: 2, max: 2, label: '2', color: '#56CFE1' },
// { min: 3, max: 3, label: '3', color: '#4EA8DE' },
// // { min: 3, max: 10000000000, label: '≥3', color: '#BE5C37' }
// { min: 3, max: 10000000000, label: '≥4', color: '#5E60CE' }
// ]
// var pieces2 = [
// { min: 0, max: 0.6, label: '0.0 - 0.6', color: '#FFFFFF' },
// { min: 0.6, max: 0.8, label: '0.6 - 0.8', color: '#72EFDD' },
// { min: 0.8, max: 0.95, label: '0.8 - 0.95', color: '#56CFE1' },
// { min: 0.95, max: 0.99, label: '0.95 - 0.99', color: '#4EA8DE' },
// { min: 0.99, max: 0.997, label: '0.99 - 0.997', color: '#5E60CE' },
// { min: 0.997, max: 1, label: '0.997 - 1.0', color: '#7400B8' },
// ]
// var arr = []
// const planFn = (data, x, y, obj) => {
// var mappedData = data.map(function (item) {
// return { name: item[x], value: item[y[0].name] };
// });
// // 获取字段'value'的最大值
// const maxValue = mappedData.reduce((max, item) => Math.max(max, item.value), -Infinity);
// // 获取字段'value'的最小值
// const minValue = mappedData.reduce((min, item) => Math.min(min, item.value), Infinity);
// //console.log(mappedData, '热力图数据');
// chartDom = document.getElementById(obj.id);
// myChart = echarts.init(chartDom);
// option = {
// title: {
// text: props.eight ? obj.columnLabel : '',
// left: 'center',
// textStyle: {
// color: '#ccc', // 设置标题颜色为灰色
// fonSize: 1
// }
// },
// tooltip: {
// trigger: 'item',
// showDelay: 0,
// transitionDuration: 0.2,
// // textStyle: {
// // color: '#ff0000' // 这里设置鼠标悬浮时的文字颜色为红色
// // }
// },
// visualMap: {
// type: 'piecewise',
// left: 'right',
// top: 'bottom',
// calculable: true,
// realtime: false,
// // splitNumber: 6,
// formatter: function (a, b) {
// //console.log(a, b, '问题');
// // 将数值转换为整数并格式化输出
// return `${Number(a).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} - ${Number(b).toFixed(2).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`
// },
// label: '测试',
// pieces: obj.pieces == 1 ? pieces1 : pieces2,
// min: minValue - 1,
// max: maxValue,
// textStyle: {
// color: '#ffffff' // 这里设置颜色选择器文字的颜色
// },
// // range: [0, 1000],
// inRange: {
// color: [
// '#ffffbf',
// '#fee090',
// '#DBBF92',
// '#D78851',
// '#BE5C37',
// ]
// },
// // outOfRange: {
// // color: ['#fdae61',
// // '#f46d43',
// // '#d73027',
// // '#a50026'
// // ]
// // },
// // color: ['#d94e5d', '#eac736', '#50a3ba'],
// // calculable: true,
// // piecewise: true,
// },
// // visualMap: {
// // min: 0,
// // max: 1000,
// // orient: 'vertical',
// // left: 'left',
// // top: 'bottom',
// // color: ['#d94e5d', '#eac736', '#50a3ba'],
// // calculable: true,
// // piecewise: true
// // },
// series: [
// {
// name: obj.columnLabel,
// type: 'map',
// roam: true,
// map: obj.id,
// data: mappedData,
// emphasis: {
// label: {
// show: false
// },
// itemStyle: {
// // 鼠标悬浮时的样式
// // borderColor: 'red', // 鼠标悬停时边框颜色
// // borderWidth: 2,
// color: '#000000' // 鼠标悬停时内部填充颜色
// }
// },
// zoom: 1.3,
// itemStyle: {
// // borderWidth: 2, // 边框宽度
// // borderColor: '#000000', // 边框颜色
// // color: '#ffffff',
// // normal: { // 正常状态下的样式
// // color: function (params) {
// // // 定义颜色的逻辑
// // return '#ffffff';
// // }
// // },
// // emphasis: { // 高亮状态下的样式
// // color: function (params) {
// // // 鼠标悬停时的颜色逻辑
// // return 'red'; // 或者一个新的颜色值
// // }
// // }
// }
// // 使用encode来映射数据源的属性到热力图的x轴、y轴和值
// // encode: {
// // x: a, // 将x轴映射到city属性
// // y: 'hour', // 将y轴映射到hour属性
// // value: b // 将值映射到value属性
// // },
// // data: value.visualData,
// // // 维度标签
// // dimensionNames: dimension,
// // // 指标名称
// // metric: metrics
// }
// ]
// };
// //console.log(option, '------------------------65--');
// window.addEventListener("resize", function () {
// if (myChart) {
// var time = setInterval(() => {
// myChart.resize()
// }, 200);
// setTimeout(() => {
// clearInterval(time)
// }, 2000)
// }
// })
// if (getLanguage() == "english") {
// Object.entries(props.componentProps).forEach(([key, value]) => {
// //console.log(key, value, 'key, --------------------value', ChineseEnglishGlossary.value[value]);
// if (key === "columnLabel") {
// //console.log(key, value, 'key, -------123-------------value');
// props.componentProps[key] = ChineseEnglishGlossary.value[value]
// }
// })
// // //console.log(props.componentProps, '柱状图---asdaaaa-----784654------');
// }
// //console.log(option, '------------------------65--');
// option && myChart.setOption(option);
// }
// function groupBy(array, key) {
// return array.reduce((acc, item) => {
// // 使用对象的键来存储分组
// const groupKey = item[key];
// // 如果累加器中还没有这个键的分组,就初始化一个空数组
// if (!acc[groupKey]) {
// acc[groupKey] = [];
// }
// // 将当前项添加到对应分组的数组中
// acc[groupKey].push(item);
// return acc;
// }, {});
// }
// const propsFn = (value) => {
// if (value.visualData && value.visualData.length > 0) {
// // //console.log(props.componentProps.columnName, '热力图加载了几次?');
// echarts.registerMap(props.componentProps.id, props.componentProps.relitu);
// // planFn(props.componentProps)
// yName.value = []
// value.metrics.forEach(it => {
// yName.value.push({
// name: it.name,
// label: it.label
// })
// })
// if (value.dimensions.length > 1) {
// xName.value = value.dimensions[1].name
// objs.value = groupBy(value.visualData, value.dimensions[0].name)
// if (!selectId.value) {
// selectId.value = value.visualData[0][value.dimensions[0].name]//赋值初始化id
// }
// selectStatus.value = true
// planFn(objs.value[selectId.value], xName.value, yName.value, value)
// } else {
// xName.value = value.dimensions[0].name
// planFn(value.visualData, xName.value, yName.value, value)
// }
// }
// }
// const xName = ref('')
// const yName = ref([])
// const selectId = ref('')
// const objs = ref({})
// const selectStatus = ref(false)
// var option;
// var myChart
// var chartDom
// onMounted(() => {
// propsFn(props.componentProps)
// })
// onBeforeUnmount(() => {
// watchList.forEach(stop => stop())
// watchList.length = 0 // 清空数组
// if (myChart) {
// myChart.clear()
// }
// })
// </script>
// <style scoped>
// .main {
// width: 100%;
// height: 100%;
// overflow: hidden;
// border: 1px solid #3A4C5B;
// }
// </style> >-->
<
template
>
<!--热力图-->
<div
style=
"height: 100%; background-color: #000;"
>
...
...
@@ -346,7 +15,9 @@ export default {
<
script
setup
>
import
*
as
echarts
from
'echarts'
;
import
{
onMounted
,
onUnmounted
,
ref
}
from
'vue'
;
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
}
from
'vue'
;
import
{
getGridInfoList
}
from
'@/api/Zodiac'
;
import
{
cs
}
from
'element-plus/es/locales.mjs'
;
// 生成唯一的图表ID
const
chartId
=
ref
(
'hexagonHeatMap_'
+
Math
.
random
().
toString
(
36
).
substr
(
2
,
9
));
...
...
@@ -358,49 +29,49 @@ function generateHexagonData() {
const
data
=
[];
const
centerX
=
0
;
const
centerY
=
0
;
// 六边形排列参数
const
radius
=
15
;
const
startRadius
=
10
;
const
endRadius
=
40
;
const
angleStep
=
Math
.
PI
/
3
;
// 60度
// 生成类似巴西地图轮廓的六边形点
for
(
let
r
=
startRadius
;
r
<
endRadius
;
r
+=
radius
*
0.85
)
{
// 根据半径调整角度数量,形成不规则形状
const
angleCount
=
Math
.
round
(
8
-
r
/
10
)
+
Math
.
floor
(
Math
.
random
()
*
2
);
const
angleCount
=
Math
.
round
(
8
-
r
/
10
)
+
Math
.
floor
(
Math
.
random
()
*
2
);
for
(
let
i
=
0
;
i
<
angleCount
;
i
++
)
{
// 基础角度,添加偏移使形状更接近巴西地图
const
baseAngle
=
angleStep
*
i
;
let
angleOffset
=
0
;
// 根据位置添加偏移,形成不规则形状
if
(
r
<
startRadius
+
15
)
angleOffset
=
0.3
;
else
if
(
r
>
endRadius
-
15
)
angleOffset
=
-
0.2
;
else
if
(
i
>
angleCount
/
2
)
angleOffset
=
0.1
;
else
if
(
i
>
angleCount
/
2
)
angleOffset
=
0.1
;
const
angle
=
baseAngle
+
angleOffset
;
// 计算坐标
const
x
=
centerX
+
r
*
Math
.
cos
(
angle
);
const
y
=
centerY
+
r
*
Math
.
sin
(
angle
);
// 根据位置生成不同的值(模拟容量)
let
value
;
// 左侧区域值较低(蓝色)
if
(
x
<
-
10
)
{
value
=
Math
.
random
()
*
30
;
}
}
// 右侧区域值较高(红色)
else
if
(
x
>
20
)
{
value
=
70
+
Math
.
random
()
*
30
;
}
}
// 中间区域值中等(黄、绿)
else
{
value
=
30
+
Math
.
random
()
*
40
;
}
data
.
push
({
value
:
[
x
,
y
,
value
],
itemStyle
:
{
...
...
@@ -409,14 +80,14 @@ function generateHexagonData() {
});
}
}
// 添加东南部突出部分(类似巴西东南角)
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
angle
=
-
Math
.
PI
/
4
+
i
*
angleStep
/
2
;
const
angle
=
-
Math
.
PI
/
4
+
i
*
angleStep
/
2
;
const
r
=
endRadius
-
5
+
i
*
3
;
const
x
=
centerX
+
r
*
Math
.
cos
(
angle
);
const
y
=
centerY
+
r
*
Math
.
sin
(
angle
);
data
.
push
({
value
:
[
x
,
y
,
80
+
Math
.
random
()
*
20
],
itemStyle
:
{
...
...
@@ -424,7 +95,7 @@ function generateHexagonData() {
}
});
}
return
data
;
}
...
...
@@ -433,15 +104,15 @@ function initChart() {
const
chartDom
=
document
.
getElementById
(
chartId
.
value
);
chartDom
.
style
.
width
=
'100%'
;
chartDom
.
style
.
height
=
'150px'
;
if
(
!
chartDom
)
return
;
myChart
=
echarts
.
init
(
chartDom
);
// 生成热力图数据
const
data
=
generateHexagonData
();
const
option
=
{
backgroundColor
:
'#000'
,
title
:
{
...
...
@@ -511,27 +182,30 @@ function initChart() {
}
}
},
],
tooltip
:
{
trigger
:
'axis'
,
// 确保tooltip显示在最上层
extraCssText
:
'z-index: 999999 !important;'
,
backgroundColor
:
'rgba(50,50,50,0.8)'
,
borderColor
:
'#333'
,
borderWidth
:
1
,
padding
:
10
,
textStyle
:
{
color
:
'#fff'
,
fontSize
:
12
},
// 固定tooltip位置在顶部
position
:
function
(
pos
,
params
,
dom
,
rect
,
size
)
{
return
[
'5%'
,
pos
[
1
]];
}
}
],
tooltip
:
{
trigger
:
'axis'
,
// 确保tooltip显示在最上层
extraCssText
:
'z-index: 999999 !important;'
,
backgroundColor
:
'rgba(50,50,50,0.8)'
,
borderColor
:
'#333'
,
borderWidth
:
1
,
padding
:
10
,
textStyle
:
{
color
:
'#fff'
,
fontSize
:
12
},
// 固定tooltip位置在顶部
position
:
function
(
pos
,
params
,
dom
,
rect
,
size
)
{
return
[
'5%'
,
pos
[
1
]];
}
}
};
myChart
.
setOption
(
option
);
resizeChart
();
}
...
...
@@ -543,12 +217,19 @@ function resizeChart() {
}
}
onMounted
(()
=>
{
onMounted
(
async
()
=>
{
const
ret
=
await
getGridInfoList
()
console
.
log
(
'rethotMAP'
,
ret
)
// 确保DOM渲染完成后初始化图表
setTimeout
(()
=>
{
nextTick
(()
=>
{
initChart
();
window
.
addEventListener
(
'resize'
,
resizeChart
);
},
0
);
});
// setTimeout(() => {
// initChart();
// window.addEventListener('resize', resizeChart);
// }, 0);
});
onUnmounted
(()
=>
{
...
...
src/pages/all/components/hotMapComponents/index.vue
浏览文件 @
b548a9ad
...
...
@@ -7,28 +7,22 @@
<div
class=
"divider-line"
></div>
</div>
<div
class=
"hot-title"
>
<div
class=
"hot-title-text"
>
巴西-最小值(热力图)
</div>
<div
class=
"hot-title-enlarge"
>
<svg
class=
"rect"
width=
"20"
height=
"20"
viewBox=
"0 0 32 32"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.5"
y=
"0.5"
width=
"31"
height=
"31"
rx=
"3.5"
stroke=
"white"
stroke-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M23.5002 8.5V13.5H21.8335V11.4043L18.0119 15.2259L16.8334 14.0474L20.7141 10.1667H18.5002V8.5H23.5002Z"
fill=
"white"
fill-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M8.5 23.5592V18.5592H10.1667V20.6549L13.9883 16.8333L15.1668 18.0118L11.2861 21.8925H13.5V23.5592H8.5Z"
fill=
"white"
fill-opacity=
"0.65"
/>
</svg>
</div>
<div
class=
"hot-title-text"
>
{{
props
.
title
}}
</div>
<div
class=
"hot-title-enlarge"
>
<svg
class=
"rect"
width=
"20"
height=
"20"
viewBox=
"0 0 32 32"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.5"
y=
"0.5"
width=
"31"
height=
"31"
rx=
"3.5"
stroke=
"white"
stroke-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M23.5002 8.5V13.5H21.8335V11.4043L18.0119 15.2259L16.8334 14.0474L20.7141 10.1667H18.5002V8.5H23.5002Z"
fill=
"white"
fill-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M8.5 23.5592V18.5592H10.1667V20.6549L13.9883 16.8333L15.1668 18.0118L11.2861 21.8925H13.5V23.5592H8.5Z"
fill=
"white"
fill-opacity=
"0.65"
/>
</svg>
</div>
</div>
<!-- 核心数据指标 -->
<div
class=
"container"
>
<div
class=
"flex-box flex-left"
>
<div
class=
"flex-box flex-left"
>
<hotMap
:propsDate=
"componentProps"
></hotMap>
</div>
<div
class=
"flex-box flex-right"
>
...
...
@@ -44,11 +38,17 @@ import { ref } from 'vue';
import
hotMap
from
'./hotMap.vue'
import
testMap
from
'./testMap.vue'
const
props
=
defineProps
({
title
:
{
type
:
String
,
default
:
'默认未知'
}
})
const
componentProps
=
ref
({})
</
script
>
<
style
scoped
>
/* 基础样式 */
.header-container
{
display
:
flex
;
...
...
@@ -82,14 +82,17 @@ const componentProps = ref({})
display
:
flex
;
align-items
:
center
;
}
.hot-title
{
.hot-title
{
display
:
flex
;
justify-content
:
space-between
;
}
.hot-title-text
{
font-weight
:
700
;
font-size
:
13px
;
.hot-title-text
{
font-weight
:
700
;
font-size
:
13px
;
}
.hot-title-enlarge
{
display
:
inline-flex
;
align-items
:
center
;
...
...
@@ -99,11 +102,12 @@ const componentProps = ref({})
transition
:
all
0.3s
ease
;
}
.hot-title-enlarge
:hover
.rect
{
/* transform: scaleX(1.1); */
.hot-title-enlarge
:hover
.rect
{
/* transform: scaleX(1.1); */
transform-origin
:
center
;
}
.hot-title-enlarge
:hover
.arrow-path
{
.hot-title-enlarge
:hover
.arrow-path
{
transform
:
scale
(
1.2
)
skew
(
-10deg
,
-10deg
);
transform-origin
:
center
;
transition
:
transform
0.3s
ease
;
...
...
@@ -126,7 +130,8 @@ const componentProps = ref({})
align-items: center;
justify-content: center; */
}
.flex-left
{
.flex-left
{
background-color
:
rgb
(
180
,
180
,
180
);
}
}
</
style
>
\ No newline at end of file
src/pages/all/components/hotMapComponents/testMap.vue
浏览文件 @
b548a9ad
<
template
>
<!--热力图-->
<div
style=
"height: 100%; background-color: blueviolet;"
>
<div
style=
"width: 100%; height: 100%;"
>
<div
id=
"main"
class=
"main"
>
我是hotMap
</div>
<!--热力图-->
<div
style=
"height: 100%; background-color: #000;"
>
<div
style=
"width: 100%; height: 100%;"
>
<div
:id=
"chartId"
class=
"main"
></div>
</div>
</div>
</div>
</
template
>
<
script
>
export
default
{
name
:
"hotMap_chart"
}
</
script
>
<
script
setup
>
import
*
as
echarts
from
'echarts'
;
import
{
onMounted
}
from
'vue'
;
import
{
nextTick
,
onMounted
,
onUnmounted
,
ref
}
from
'vue'
;
import
{
getGridInfoList
}
from
'@/api/Zodiac'
;
import
{
cs
}
from
'element-plus/es/locales.mjs'
;
onMounted
(()
=>
{
initChart
(
);
})
;
// 生成唯一的图表ID
const
chartId
=
ref
(
'hexagonHeatMap_'
+
Math
.
random
().
toString
(
36
).
substr
(
2
,
9
)
);
let
myChart
=
null
;
function
initChart
()
{
var
ROOT_PATH
=
'https://echarts.apache.org/examples'
;
var
CDN_PATH
=
'https://echarts.apache.org/zh/js/vendors/'
;
// 生成六边形热力图数据
function
generateHexagonData
()
{
// 模拟巴西地图形状的六边形网格数据
const
data
=
[];
const
centerX
=
0
;
const
centerY
=
0
;
var
chartDom
=
document
.
getElementById
(
'main'
);
if
(
!
chartDom
)
return
;
// 六边形排列参数
const
radius
=
15
;
const
startRadius
=
10
;
const
endRadius
=
40
;
const
angleStep
=
Math
.
PI
/
3
;
// 60度
var
myChart
=
echarts
.
init
(
chartDom
);
// 生成类似巴西地图轮廓的六边形点
for
(
let
r
=
startRadius
;
r
<
endRadius
;
r
+=
radius
*
0.85
)
{
// 根据半径调整角度数量,形成不规则形状
const
angleCount
=
Math
.
round
(
8
-
r
/
10
)
+
Math
.
floor
(
Math
.
random
()
*
2
);
myChart
.
showLoading
();
for
(
let
i
=
0
;
i
<
angleCount
;
i
++
)
{
// 基础角度,添加偏移使形状更接近巴西地图
const
baseAngle
=
angleStep
*
i
;
let
angleOffset
=
0
;
Promise
.
all
([
fetch
(
ROOT_PATH
+
'/data/asset/geo/USA.json'
).
then
(
res
=>
res
.
json
()),
loadScript
(
CDN_PATH
+
'd3-array@2.8.0/dist/d3-array.js'
),
loadScript
(
CDN_PATH
+
'd3-geo@2.0.1/dist/d3-geo.js'
)
]).
then
(([
usaJson
])
=>
{
const
projection
=
d3
.
geoAlbersUsa
();
myChart
.
hideLoading
();
echarts
.
registerMap
(
'USA'
,
usaJson
);
//console.log("获得地图数据",usaJson);
const
option
=
{
title
:
{
text
:
'USA Population Estimates (2012)'
,
subtext
:
'Data from www.census.gov'
,
left
:
'right'
},
tooltip
:
{
trigger
:
'item'
,
showDelay
:
0
,
transitionDuration
:
0.2
},
visualMap
:
{
left
:
'right'
,
min
:
500000
,
max
:
38000000
,
inRange
:
{
color
:
[
'#313695'
,
'#4575b4'
,
'#74add1'
,
'#abd9e9'
,
'#e0f3f8'
,
'#ffffbf'
,
'#fee090'
,
'#fdae61'
,
'#f46d43'
,
'#d73027'
,
'#a50026'
]
},
text
:
[
'High'
,
'Low'
],
calculable
:
true
},
toolbox
:
{
show
:
true
,
left
:
'left'
,
top
:
'top'
,
feature
:
{
dataView
:
{
readOnly
:
false
},
restore
:
{},
saveAsImage
:
{}
}
},
series
:
[
{
name
:
'USA PopEstimates'
,
type
:
'map'
,
map
:
'USA'
,
projection
:
{
project
:
function
(
point
)
{
return
projection
(
point
);
},
unproject
:
function
(
point
)
{
return
projection
.
invert
(
point
);
// 根据位置添加偏移,形成不规则形状
if
(
r
<
startRadius
+
15
)
angleOffset
=
0.3
;
else
if
(
r
>
endRadius
-
15
)
angleOffset
=
-
0.2
;
else
if
(
i
>
angleCount
/
2
)
angleOffset
=
0.1
;
const
angle
=
baseAngle
+
angleOffset
;
// 计算坐标
const
x
=
centerX
+
r
*
Math
.
cos
(
angle
);
const
y
=
centerY
+
r
*
Math
.
sin
(
angle
);
// 根据位置生成不同的值(模拟容量)
let
value
;
// 左侧区域值较低(蓝色)
if
(
x
<
-
10
)
{
value
=
Math
.
random
()
*
30
;
}
},
emphasis
:
{
label
:
{
show
:
true
// 右侧区域值较高(红色)
else
if
(
x
>
20
)
{
value
=
70
+
Math
.
random
()
*
30
;
}
},
data
:
[
{
name
:
'Alabama'
,
value
:
4822023
},
{
name
:
'Alaska'
,
value
:
731449
},
{
name
:
'Arizona'
,
value
:
6553255
},
// ...其他数据保持不变...
]
// 中间区域值中等(黄、绿)
else
{
value
=
30
+
Math
.
random
()
*
40
;
}
data
.
push
({
value
:
[
x
,
y
,
value
],
itemStyle
:
{
opacity
:
0.9
}
});
}
]
};
}
// 添加东南部突出部分(类似巴西东南角)
for
(
let
i
=
0
;
i
<
5
;
i
++
)
{
const
angle
=
-
Math
.
PI
/
4
+
i
*
angleStep
/
2
;
const
r
=
endRadius
-
5
+
i
*
3
;
const
x
=
centerX
+
r
*
Math
.
cos
(
angle
);
const
y
=
centerY
+
r
*
Math
.
sin
(
angle
);
data
.
push
({
value
:
[
x
,
y
,
80
+
Math
.
random
()
*
20
],
itemStyle
:
{
opacity
:
0.9
}
});
}
return
data
;
}
// 初始化图表
function
initChart
()
{
const
chartDom
=
document
.
getElementById
(
chartId
.
value
);
chartDom
.
style
.
width
=
'100%'
;
chartDom
.
style
.
height
=
'150px'
;
if
(
!
chartDom
)
return
;
myChart
=
echarts
.
init
(
chartDom
);
// 生成热力图数据
const
data
=
generateHexagonData
();
// const option = {
// backgroundColor: '#000',
// title: {
// text: '链路层容量',
// left: 'center',
// // top: 10,
// left: 10,
// textStyle: {
// color: '#fff',
// fontSize: 10,
// fontWeight: 'normal'
// }
// },
// tooltip: {
// // formatter: function(params) {
// // return `容量: ${params.data[2].toFixed(1)}`;
// // },
// backgroundColor: 'rgba(0, 0, 0, 0.7)',
// borderColor: '#444',
// textStyle: {
// color: '#fff'
// }
// },
// visualMap: {
// min: 0,
// max: 100,
// calculable: true,
// orient: 'horizontal',
// left: 'center',
// // bottom: 30,
// inRange: {
// color: ['#0050b3', '#1890ff', '#7cb305', '#ffd500', '#ff4d4f']
// },
// textStyle: {
// color: '#fff'
// },
// // itemWidth: 40,
// // itemHeight: 10,
// borderWidth: 0
// },
// xAxis: {
// type: 'value',
// show: false,
// min: -50,
// max: 50
// },
// yAxis: {
// type: 'value',
// show: false,
// min: -50,
// max: 50
// },
// series: [{
// name: '链路容量',
// type: 'scatter',
// coordinateSystem: 'cartesian2d',
// symbol: 'path://M0,-10 L10,5 L10,15 L0,20 L-10,15 L-10,5 Z', // 六边形路径
// symbolSize: [15, 15], // 六边形大小
// data: data,
// label: {
// show: false
// },
// emphasis: {
// itemStyle: {
// shadowBlur: 10,
// shadowColor: 'rgba(0, 0, 0, 0.5)'
// }
// }
// },
// ],
// tooltip: {
// trigger: 'axis',
// // 确保tooltip显示在最上层
// extraCssText: 'z-index: 999999 !important;',
// backgroundColor: 'rgba(50,50,50,0.8)',
// borderColor: '#333',
// borderWidth: 1,
// padding: 10,
// textStyle: {
// color: '#fff',
// fontSize: 12
// },
// // 固定tooltip位置在顶部
// position: function (pos, params, dom, rect, size) {
// return ['5%', pos[1]];
// }
// }
// };
myChart
.
setOption
(
option
);
resizeChart
();
}
window
.
addEventListener
(
'resize'
,
function
()
{
myChart
.
resize
();
});
});
function
loadScript
(
src
)
{
return
new
Promise
((
resolve
,
reject
)
=>
{
const
script
=
document
.
createElement
(
'script'
);
script
.
src
=
src
;
script
.
onload
=
resolve
;
script
.
onerror
=
reject
;
document
.
head
.
appendChild
(
script
);
});
}
// 响应式调整图表大小
function
resizeChart
()
{
if
(
myChart
)
{
myChart
.
resize
();
}
}
onMounted
(
async
()
=>
{
const
ret
=
await
getGridInfoList
()
console
.
log
(
'ret'
,
ret
)
// 确保DOM渲染完成后初始化图表
nextTick
(()
=>
{
initChart
();
window
.
addEventListener
(
'resize'
,
resizeChart
);
});
// setTimeout(() => {
// initChart();
// window.addEventListener('resize', resizeChart);
// }, 0);
});
onUnmounted
(()
=>
{
if
(
myChart
)
{
window
.
removeEventListener
(
'resize'
,
resizeChart
);
myChart
.
dispose
();
myChart
=
null
;
}
});
</
script
>
<
style
scoped
>
.main
{
width
:
100%
;
height
:
100%
;
overflow
:
hidden
;
border
:
1px
solid
#3A4C5B
;
width
:
100%
;
height
:
100%
;
/* min-height: 400px; */
/* overflow: hidden; */
}
</
style
>
\ No newline at end of file
src/pages/all/components/instant/index.vue
浏览文件 @
b548a9ad
...
...
@@ -3,32 +3,26 @@
<!-- 标题栏 -->
<div
class=
"section-divider"
>
<div
class=
"divider-line"
></div>
<h3
class=
"section-title"
>
可用性
</h3>
<h3
class=
"section-title"
>
网络时延/丢包
</h3>
<div
class=
"divider-line"
></div>
</div>
<div
class=
"hot-title"
>
<div
class=
"hot-title-text"
>
巴西-最小值(CDF曲线图)
</div>
<div
class=
"hot-title-enlarge"
>
<svg
class=
"rect"
width=
"20"
height=
"20"
viewBox=
"0 0 32 32"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.5"
y=
"0.5"
width=
"31"
height=
"31"
rx=
"3.5"
stroke=
"white"
stroke-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M23.5002 8.5V13.5H21.8335V11.4043L18.0119 15.2259L16.8334 14.0474L20.7141 10.1667H18.5002V8.5H23.5002Z"
fill=
"white"
fill-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M8.5 23.5592V18.5592H10.1667V20.6549L13.9883 16.8333L15.1668 18.0118L11.2861 21.8925H13.5V23.5592H8.5Z"
fill=
"white"
fill-opacity=
"0.65"
/>
</svg>
</div>
<div
class=
"hot-title-text"
>
巴西-最小值(PDF曲线图)
</div>
<div
class=
"hot-title-enlarge"
>
<svg
class=
"rect"
width=
"20"
height=
"20"
viewBox=
"0 0 32 32"
fill=
"none"
xmlns=
"http://www.w3.org/2000/svg"
>
<rect
x=
"0.5"
y=
"0.5"
width=
"31"
height=
"31"
rx=
"3.5"
stroke=
"white"
stroke-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M23.5002 8.5V13.5H21.8335V11.4043L18.0119 15.2259L16.8334 14.0474L20.7141 10.1667H18.5002V8.5H23.5002Z"
fill=
"white"
fill-opacity=
"0.65"
/>
<path
class=
"arrow-path "
d=
"M8.5 23.5592V18.5592H10.1667V20.6549L13.9883 16.8333L15.1668 18.0118L11.2861 21.8925H13.5V23.5592H8.5Z"
fill=
"white"
fill-opacity=
"0.65"
/>
</svg>
</div>
</div>
<!-- 核心数据指标 -->
<div
class=
"container"
>
<div
class=
"flex-box flex-left"
>
<div
class=
"flex-box flex-left"
>
<instantCurve
:idName=
"`instant-left-$
{props.allIdName}`" :propsDate="componentProps">
</instantCurve>
</div>
<div
class=
"flex-box flex-right"
>
...
...
@@ -40,20 +34,25 @@
<
script
setup
>
import
instantCurve
from
'./instantCurve.vue'
const
instantCurveRight
=
ref
(
'instantCurve_chart-right'
);
const
instantCurveLeft
=
ref
(
'instantCurve_chart-left'
);
const
instantCurveRight
=
ref
(
'instantCurve_chart-right'
);
const
instantCurveLeft
=
ref
(
'instantCurve_chart-left'
);
const
props
=
defineProps
({
allIdName
:
{
type
:
String
,
default
:
'allIdName'
,
},
title
:
{
type
:
String
,
default
:
'巴西-最小值(PDF曲线图)'
}
});
console
.
log
(
'props.allIdName'
,
props
.
allIdName
)
const
componentProps
=
ref
({})
</
script
>
<
style
scoped
>
/* 基础样式 */
.header-container
{
display
:
flex
;
...
...
@@ -87,14 +86,17 @@ const componentProps = ref({})
display
:
flex
;
align-items
:
center
;
}
.hot-title
{
.hot-title
{
display
:
flex
;
justify-content
:
space-between
;
}
.hot-title-text
{
font-weight
:
700
;
font-size
:
13px
;
.hot-title-text
{
font-weight
:
700
;
font-size
:
13px
;
}
.hot-title-enlarge
{
display
:
inline-flex
;
align-items
:
center
;
...
...
@@ -105,8 +107,8 @@ const componentProps = ref({})
}
.hot-title-enlarge
:hover
.arrow-path
{
transform
:
scale
(
1.2
)
skew
(
-10deg
,
-10deg
);
.hot-title-enlarge
:hover
.arrow-path
{
transform
:
scale
(
1.2
)
skew
(
-10deg
,
-10deg
);
transform-origin
:
center
;
transition
:
transform
0.3s
ease
;
}
...
...
@@ -128,7 +130,8 @@ const componentProps = ref({})
align-items: center;
justify-content: center; */
}
.flex-left
{
.flex-left
{
/* background-color: rgb(180, 180, 180); */
}
}
</
style
>
\ No newline at end of file
src/pages/footer/component/timers.vue
浏览文件 @
b548a9ad
...
...
@@ -21,7 +21,7 @@
}" />
<div
class=
"right_block"
>
<!--限制 :disabled="!is_flag_confirmAndPauseAndSpeed" -->
<el-button
class=
"right_block_confirm_btn"
size=
"
mini
"
<el-button
class=
"right_block_confirm_btn"
size=
"
small
"
@
click=
"handleDateRangeChange(pick_select_date)"
>
确认
</el-button>
<div
class=
"right_block_center"
>
<!--
<el-button
circle
class=
"right_block_conter_btn"
@
click=
"playBackward"
>
...
...
src/pages/header/component/screenConfigCase.vue
浏览文件 @
b548a9ad
...
...
@@ -2,25 +2,25 @@
<div
class=
"templateCase_right_content"
>
<div
class=
"templateCase_right_content_header"
>
<div
class=
"templateCase_right_content_header_item"
>
<span>
应用
</span>
<img
src=
"@/assets/images/headers/case_header.png"
alt=
""
style=
"width: 20px; height: 20px;"
>
<!--
<span>
模板名称
</span>
-->
<input
ref=
"inputRef"
class=
"templateName"
v-model=
"templateName"
:disabled=
"!isEdit"
></input>
<img
src=
"@/assets/images/headers/case_header.png"
alt=
""
title=
"编辑"
style=
"width: 20px; height: 20px;cursor: pointer;"
@
click=
"handleEdit"
>
</div>
</div>
<div
class=
"templateCase_right_content_body"
>
<div
class=
"horizontal-sections"
>
<div
class=
"section-item"
v-for=
"(
item, index) in titles
"
:key=
"index"
>
<div
class=
"section-item"
v-for=
"(
el, index) in settingConfig
"
:key=
"index"
>
<div
class=
"section-item_title"
>
<span>
{{
item
.
title
}}
</span>
<span>
{{
el
.
title
}}
</span>
</div>
<div
class=
"section-item_content_up"
>
<!--
<div
v-for=
"(element,index) in [template1Selector,template2Selector]"
:key=
"index"
>
</div>
-->
<div
class=
"selector-item"
v-for=
"(item, key) in item.templateSelector"
:key=
"key"
>
<label
class=
"selector-label"
>
{{
item
.
label
}}
</label>
<div
class=
"selector-item"
v-for=
"(item, key) in el.templateSelector"
:key=
"key"
>
<label
class=
"selector-label"
>
{{
item
.
label
}}
</label>
<div
class=
"custom-select"
>
<!-- 粒度 -->
<el-select
v-model=
"item.default"
placeholder=
""
style=
"width: 100%;"
>
<el-select
v-model=
"item.default"
placeholder=
""
:disabled=
"!isEdit"
style=
"width: 100%;"
@
change=
"(val) => selectOnChange(val, index, key)"
>
<el-option
v-for=
"itemele in item.options"
:key=
"itemele.value"
:label=
"itemele.label"
:value=
"itemele.value"
/>
</el-select>
...
...
@@ -28,9 +28,10 @@
</div>
</div>
<div
class=
"section-item_content_down"
>
<hotMapComponent
v-if=
"index === 0"
></hotMapComponent>
<cdf
v-if=
"index === 1"
:allIdName=
"allIdName[0]"
></cdf>
<instant
v-if=
"index === 2"
:allIdName=
"allIdName[1]"
></instant>
<KeepAlive>
<component
:is=
"el.defaultComponent"
:title=
"titleFn(el)"
></component>
</KeepAlive>
</div>
</div>
...
...
@@ -43,25 +44,42 @@
import
hotMapComponent
from
'@/pages/all/components/hotMapComponents/index.vue'
;
import
cdf
from
'@/pages/all/components/cdf/index.vue'
;
import
instant
from
'@/pages/all/components/instant/index.vue'
;
import
{
markRaw
,
nextTick
,
watch
}
from
'vue'
const
isEdit
=
ref
(
false
)
const
inputRef
=
ref
()
const
templateName
=
ref
(
'默认模板名称'
)
const
props
=
defineProps
({
settingConfig
:
{
type
:
Object
,
default
:
()
=>
{
}
}
})
const
allIdName
=
ref
([[
'allIdName11'
,
'allIdName12'
],
[
'allIdName21'
,
'allIdName22'
]]);
// 组件逻辑可以在这里添加
const
titles
=
[
const
settingConfig
=
ref
(
[
{
title
:
'容量/流量'
,
defaultComponent
:
markRaw
(
hotMapComponent
),
templateSelector
:
[
{
label
:
'曲线类型'
,
default
:
'热力图'
,
type
:
'capacityCurveType'
,
options
:
[
{
value
:
'瞬时值曲线'
,
label
:
'瞬时值曲线'
,
},
{
value
:
'PDF曲线'
,
label
:
'PDF曲线'
,
},
{
value
:
'热力图'
,
...
...
@@ -72,6 +90,7 @@ const titles = [
{
label
:
'地理标准'
,
default
:
'最小值'
,
type
:
'capacityGeoStandard'
,
options
:
[
{
value
:
'最小值'
,
...
...
@@ -90,6 +109,7 @@ const titles = [
{
label
:
'时间标准'
,
default
:
'最小值'
,
type
:
'capacityTimeStandard'
,
options
:
[
{
value
:
'最小值'
,
...
...
@@ -109,10 +129,12 @@ const titles = [
},
{
title
:
'可用性'
,
templateSelector
:
[
defaultComponent
:
markRaw
(
cdf
),
templateSelector
:
[
{
label
:
'曲线类型'
,
default
:
'热力图'
,
default
:
'PDF曲线'
,
type
:
'availabilityCurveType'
,
options
:
[
{
value
:
'PDF曲线'
,
...
...
@@ -127,6 +149,7 @@ const titles = [
{
label
:
'地理标准'
,
default
:
'最小值'
,
type
:
'availabilityGeoStandard'
,
options
:
[
{
value
:
'最小值'
,
...
...
@@ -145,6 +168,7 @@ const titles = [
{
label
:
'时间标准'
,
default
:
'最小值'
,
type
:
'availabilityTimeStandard'
,
options
:
[
{
value
:
'最小值'
,
...
...
@@ -164,10 +188,12 @@ const titles = [
},
{
title
:
'网络时延/丢包'
,
templateSelector
:
[
defaultComponent
:
markRaw
(
instant
),
templateSelector
:
[
{
label
:
'
时延
曲线类型'
,
label
:
'曲线类型'
,
default
:
'瞬时值曲线'
,
type
:
'latencyCurveType'
,
options
:
[
{
value
:
'瞬时值曲线'
,
...
...
@@ -186,6 +212,7 @@ const titles = [
{
label
:
'地理标准'
,
default
:
'最小值'
,
type
:
'latencyGeoStandard'
,
options
:
[
{
value
:
'最小值'
,
...
...
@@ -204,6 +231,7 @@ const titles = [
{
label
:
'时间标准'
,
default
:
'最小值'
,
type
:
'latencyTimeStandard'
,
options
:
[
{
value
:
'最小值'
,
...
...
@@ -219,66 +247,140 @@ const titles = [
}
]
},
{
label
:
'丢包曲线类型'
,
default
:
'瞬时值曲线'
,
options
:
[
{
value
:
'最小值'
,
label
:
'最小值'
,
},
{
value
:
'最大值'
,
label
:
'最大值'
,
},
{
value
:
'平均值'
,
label
:
'平均值'
,
}
]
},
{
label
:
'地理标准'
,
default
:
'最小值'
,
options
:
[
{
value
:
'最小值'
,
label
:
'最小值'
,
},
{
value
:
'最大值'
,
label
:
'最大值'
,
},
{
value
:
'平均值'
,
label
:
'平均值'
,
}
]
},
{
label
:
'时间标准'
,
default
:
'最小值'
,
options
:
[
{
value
:
'最小值'
,
label
:
'最小值'
,
},
{
value
:
'最大值'
,
label
:
'最大值'
,
},
{
value
:
'平均值'
,
label
:
'平均值'
,
}
]
},
//
{
//
label: '丢包曲线类型',
//
default: '瞬时值曲线',
//
options: [
//
{
//
value: '最小值',
//
label: '最小值',
//
},
//
{
//
value: '最大值',
//
label: '最大值',
//
},
//
{
//
value: '平均值',
//
label: '平均值',
//
}
//
]
//
},
//
{
//
label: '地理标准',
//
default: '最小值',
//
options: [
//
{
//
value: '最小值',
//
label: '最小值',
//
},
//
{
//
value: '最大值',
//
label: '最大值',
//
},
//
{
//
value: '平均值',
//
label: '平均值',
//
}
//
]
//
},
//
{
//
label: '时间标准',
//
default: '最小值',
//
options: [
//
{
//
value: '最小值',
//
label: '最小值',
//
},
//
{
//
value: '最大值',
//
label: '最大值',
//
},
//
{
//
value: '平均值',
//
label: '平均值',
//
}
//
]
//
},
]
}
];
]);
watch
(()
=>
props
.
settingConfig
,
(
newVal
)
=>
{
// console.log('newVal', newVal)
if
(
!
newVal
)
return
templateName
.
value
=
newVal
.
templateName
for
(
let
attr
in
newVal
)
{
for
(
let
item
of
settingConfig
.
value
)
{
const
obj
=
item
.
templateSelector
.
find
(
el
=>
el
.
type
===
attr
)
if
(
!
obj
)
continue
obj
.
default
=
newVal
[
attr
]
switch
(
newVal
[
attr
])
{
case
'瞬时值曲线'
:
item
.
defaultComponent
=
markRaw
(
cdf
);
break
case
'热力图'
:
item
.
defaultComponent
=
markRaw
(
hotMapComponent
)
break
case
'PDF曲线'
:
item
.
defaultComponent
=
markRaw
(
cdf
)
break
default
:
break
}
}
}
isEdit
.
value
=
false
},
{
immediate
:
true
})
const
selectOnChange
=
(
val
,
index
,
key
)
=>
{
console
.
log
(
'row'
,
val
,
index
,
key
)
settingConfig
.
value
[
index
].
templateSelector
.
default
=
val
switch
(
val
)
{
case
'瞬时值曲线'
:
settingConfig
.
value
[
index
].
defaultComponent
=
markRaw
(
cdf
);
break
case
'热力图'
:
settingConfig
.
value
[
index
].
defaultComponent
=
markRaw
(
hotMapComponent
)
console
.
log
(
'热力图'
,
settingConfig
.
value
[
index
].
defaultComponent
)
break
case
'PDF曲线'
:
settingConfig
.
value
[
index
].
defaultComponent
=
markRaw
(
cdf
)
break
default
:
break
}
}
const
handleEdit
=
async
()
=>
{
isEdit
.
value
=
!
isEdit
.
value
if
(
isEdit
.
value
)
{
await
nextTick
()
inputRef
.
value
.
focus
()
}
}
const
titleFn
=
(
el
)
=>
{
const
templateSelector
=
el
.
templateSelector
return
`
${
templateSelector
[
0
].
default
}
-
${
templateSelector
[
1
].
default
}
-
${
templateSelector
[
2
].
default
}
`
}
defineExpose
({
configData
:
()
=>
{
const
obj
=
{
templateName
:
templateName
.
value
}
settingConfig
.
value
.
forEach
(
item
=>
{
item
.
templateSelector
.
forEach
(
el
=>
{
obj
[
el
.
type
]
=
el
.
default
})
})
return
obj
}
})
const
template2Selector
=
[]
</
script
>
<
style
scoped
>
...
...
@@ -337,6 +439,19 @@ const template2Selector = []
justify-content
:
space-between
;
}
.templateCase_right_content_header_item
.templateName
{
width
:
160px
;
background
:
transparent
;
outline
:
none
;
border
:
none
;
color
:
white
;
border-bottom
:
1px
solid
transparent
;
padding-bottom
:
6px
;
padding-right
:
12px
;
}
...
...
src/pages/header/component/screenConfigeDialog.vue
浏览文件 @
b548a9ad
...
...
@@ -69,20 +69,30 @@
<div
class=
"selector-item"
>
<label
class=
"selector-label"
>
{{
templateSelector
.
label
}}
</label>
<label
class=
"selector-label"
>
模板列表
</label>
<div
class=
"custom-select"
>
<!-- 粒度 -->
<el-select
v-model=
"templateSelector.value"
placeholder=
""
style=
"width: 100%;"
>
<el-option
v-for=
"item in templateSelector.options"
:key=
"item.value"
:label=
"item.label"
<el-select
v-model=
"templateSelector"
placeholder=
"请选择模板列表"
@
change=
"templateOnChange"
style=
"width: 100%;"
>
<el-option
v-for=
"item in templateSelectorOptions"
:key=
"item.value"
:label=
"item.label"
:value=
"item.value"
/>
</el-select>
</div>
</div>
</div>
<div
class=
"content-item"
>
<hotMapComponent></hotMapComponent>
<cdf
:allIdName=
"allIdName[0]"
></cdf>
<instant
:allIdName=
"allIdName[1]"
></instant>
<KeepAlive>
<component
:is=
"currentComponent1"
></component>
</KeepAlive>
<KeepAlive>
<component
:is=
"currentComponent2"
></component>
</KeepAlive>
<KeepAlive>
<component
:is=
"currentComponent3"
></component>
</KeepAlive>
</div>
<div>
<el-button
type=
"primary"
class=
"apply-btn apply-btn-right"
>
应用
</el-button>
...
...
@@ -97,28 +107,29 @@
<div
class=
"templateCase_left_header"
>
<div
class=
"templateCase_left_header_item_title"
>
模板列表
</div>
<div
class=
"templateCase_left_header_item_tool"
>
<el-icon
@
click=
"
templateCasedeleteHandFn
"
>
<el-icon
@
click=
"
handleDelete"
title=
"删除"
style=
"cursor: pointer
"
>
<Delete
/>
</el-icon>
<el-icon
@
click=
"
templateCaseAddHandFn
"
>
<el-icon
@
click=
"
handleAdd"
title=
"添加"
style=
"cursor: pointer
"
>
<Plus
/>
</el-icon>
</div>
</div>
<div
class=
"templateCase_left_content"
>
<div
class=
"templateCase_left_content_item"
v-for=
"(item, index) in templateCaseList"
:key=
"index"
@
click=
"templateCaseClickFn(index)"
:class=
"
{ 'CaseClickActive': activeTemplateIndex === index }">
{{
item
}}
<div
class=
"templateCase_left_content_item"
v-for=
"(item, index) in templateCaseList"
:key=
"item.templateId"
@
click=
"templateCaseClickFn(item, index)"
:class=
"
{ 'CaseClickActive': activeTemplateIndex === index }">
{{
item
.
templateName
}}
</div>
</div>
</div>
<div
class=
"templateCase_right templateCase"
>
<screenConfigCase></screenConfigCase>
<screenConfigCase
ref=
"screenConfigCaseRef"
:settingConfig=
"currentSettingConfig"
></screenConfigCase>
</div>
</div>
<el-button
type=
"primary"
class=
"apply-btn"
>
应用
</el-button>
<el-button
type=
"primary"
class=
"apply-btn"
@
click=
"handleApply"
>
应用
</el-button>
</div>
</div>
</main>
...
...
@@ -127,23 +138,32 @@
<
script
setup
>
import
{
ref
,
computed
,
onMounted
,
watch
}
from
'vue'
;
import
{
ref
,
computed
,
onMounted
,
watch
,
markRaw
}
from
'vue'
;
import
hotMapComponent
from
'@/pages/all/components/hotMapComponents/index.vue'
;
import
cdf
from
'@/pages/all/components/cdf/index.vue'
;
import
instant
from
'@/pages/all/components/instant/index.vue'
;
import
screenConfigCase
from
'./screenConfigCase.vue'
;
import
{
getCapacityAndTraffic
}
from
'@/api/Zodiac'
;
import
{
getCapacityAndTraffic
,
getAvailability
,
getTemplateList
,
templateAdd
,
templateDel
,
templateDetail
,
templateuUpdate
}
from
'@/api/Zodiac'
;
import
useAppStore
from
'@/store/module/app'
import
{
ElMessage
,
ElMessageBox
}
from
'element-plus'
let
currentComponent1
=
markRaw
(
hotMapComponent
)
//容量流量 热力图
let
currentComponent2
=
markRaw
(
cdf
)
//可用性 PDF曲线
let
currentComponent3
=
markRaw
(
instant
)
//let 瞬时值曲线组件 //前面那个人写的好乱更屎一样,我服了,在这里偷偷吐槽一下嘿嘿
const
screenConfigCaseRef
=
ref
()
const
currentSettingConfig
=
ref
()
const
templateCaseList
=
ref
([])
const
appStore
=
useAppStore
();
const
emits
=
defineEmits
([
'handleScreenConfigeClose'
]);
const
allIdName
=
ref
([[
'allIdName11'
,
'allIdName12'
],
[
'allIdName21'
,
'allIdName22'
]]);
// 标签页状态管理
const
activeTab
=
ref
(
'equipmentCount'
);
// 默认选中"地面站设备数量"
const
keliSelector
=
ref
(
{
label
:
'地面粒度'
,
...
...
@@ -179,43 +199,78 @@ const childrenSelector = ref(
const
isGlobal
=
computed
(()
=>
keliSelector
.
value
.
value
===
'global'
);
const
templateSelector
=
ref
(
{
label
:
'模板选择'
,
value
:
'模板1'
,
options
:
[
{
value
:
'模板1'
,
label
:
'模板1'
,
},
{
value
:
'模板2'
,
label
:
'模板2'
,
},
{
value
:
'模板3'
,
label
:
'模板3'
,
},
{
value
:
'模板4'
,
}
]
}
)
const
templateSelector
=
ref
()
const
templateSelectorOptions
=
ref
([])
watch
(()
=>
templateCaseList
.
value
,
()
=>
{
console
.
log
(
'templateCaseList'
,
templateCaseList
.
value
)
templateSelectorOptions
.
value
=
templateCaseList
.
value
.
map
(
item
=>
({
label
:
item
.
templateName
,
value
:
item
.
templateId
}))
})
const
templateCaseList
=
ref
([
'模板1'
,
'模板2'
])
// 下拉选择器状态
const
selectedValues
=
ref
([]);
const
dropdownVisible
=
ref
([
false
,
false
,
false
]);
const
templateCasedeleteHandFn
=
()
=>
{
//console.log('templateCasedeleteHandFn');
const
handleDelete
=
()
=>
{
if
(
!
currentSettingConfig
.
value
.
templateId
)
{
ElMessage
({
type
:
'error'
,
message
:
'请先选择一个模板'
,
})
return
}
ElMessageBox
.
confirm
(
`您确定删除 [
${
currentSettingConfig
.
value
.
templateName
}
] ?`
,
'Warning'
,
{
confirmButtonText
:
'确定'
,
cancelButtonText
:
'取消'
,
type
:
'warning'
,
}
)
.
then
(
async
()
=>
{
const
ret
=
await
templateDel
({
templateId
:
currentSettingConfig
.
value
.
templateId
// 模板id
})
if
(
ret
.
code
==
200
)
{
await
handleList
()
// 刷新列表获取最新数据
currentSettingConfig
.
value
=
templateCaseList
.
value
[
0
]
||
{}
// 删除后默认选中第一个模板
activeTemplateIndex
.
value
=
0
;
}
ElMessage
({
type
:
'success'
,
message
:
'删除成功'
,
})
})
};
const
templateCaseAddHandFn
=
()
=>
{
//console.log('templateCaseAddHandFn');
const
handleAdd
=
()
=>
{
// console.log('新增')
// const ret = await templateAdd({
// name: '模板1',
// settingConfig: {}
// })
const
templateId
=
Date
.
now
();
templateCaseList
.
value
.
push
({
//新增模板
templateName
:
'新增模板'
,
//模板名
templateId
,
// 模板id,后端生成的应该是uuid,这里先用时间戳模拟
})
currentSettingConfig
.
value
=
{
templateName
:
'新增模板'
,
templateAdd
:
true
,
templateId
,
}
activeTemplateIndex
.
value
=
templateCaseList
.
value
.
length
-
1
;
// 设置当前选中为新增的模板
};
// 初始化选中值
onMounted
(
async
()
=>
{
await
getCapacityAndTrafficData
()
await
handleList
();
// await getCapacityAndTrafficData()
// await getAvailabilityData();
});
// 切换下拉菜单显示
...
...
@@ -238,10 +293,23 @@ const getCapacityAndTrafficData = async () => {
console
.
log
(
res
)
}
const
getAvailabilityData
=
async
()
=>
{
const
res
=
await
getAvailability
({
granularity
:
keliSelector
.
value
.
value
,
startTime
:
'2025-11-03 00:00:00'
,
endTime
:
'2025-11-04 00:00:00'
,
regionName
:
''
,
signalSiteCode
:
''
,
gridCodes
:
''
})
console
.
log
(
'可用性'
,
res
)
}
const
activeTemplateIndex
=
ref
(
0
);
const
templateCaseClickFn
=
(
index
)
=>
{
const
templateCaseClickFn
=
(
i
tem
,
i
ndex
)
=>
{
//console.log('templateCaseClickFn', index);
activeTemplateIndex
.
value
=
index
;
currentSettingConfig
.
value
=
item
;
};
// 点击外部关闭下拉菜单
document
.
addEventListener
(
'click'
,
(
e
)
=>
{
...
...
@@ -271,8 +339,69 @@ const keliOnChange = () => {
break
;
}
}
watch
(()
=>
keliSelector
.
value
.
value
,
()
=>
keliOnChange
)
const
handleApply
=
async
()
=>
{
let
ret
=
null
if
(
currentSettingConfig
.
value
.
templateAdd
)
{
// 如果是新增的模板,先调用新增接口,再调用修改接口
ret
=
await
templateAdd
({
// templateName: currentSettingConfig.value.templateName, // 模板名
...
screenConfigCaseRef
.
value
.
configData
()
// 获取当前配置
})
}
else
{
ret
=
await
templateuUpdate
({
templateId
:
currentSettingConfig
.
value
.
templateId
,
// 模板id
...
screenConfigCaseRef
.
value
.
configData
()
// 获取当前配置
})
}
if
(
ret
.
code
==
200
)
{
await
handleList
()
// 刷新列表获取最新数据
ElMessage
({
message
:
'模板设置成功'
,
type
:
'success'
,
})
}
}
const
handleList
=
async
()
=>
{
const
ret
=
await
getTemplateList
()
if
(
ret
.
code
==
200
)
{
templateCaseList
.
value
=
ret
.
data
;
currentSettingConfig
.
value
=
ret
.
data
[
activeTemplateIndex
.
value
]
}
}
const
templateOnChange
=
(
val
)
=>
{
console
.
log
(
'val'
,
val
)
const
selectedTemplate
=
templateCaseList
.
value
.
find
(
item
=>
item
.
templateId
===
val
)
console
.
log
(
'selectedTemplate'
,
selectedTemplate
)
// availabilityCurveType
// capacityCurveType
// latencyCurveType
const
obj
=
{
'PDF曲线'
:
markRaw
(
cdf
),
'热力图'
:
markRaw
(
hotMapComponent
),
'瞬时值曲线'
:
markRaw
(
instant
)
}
currentComponent1
=
obj
[
selectedTemplate
.
capacityCurveType
]
currentComponent2
=
obj
[
selectedTemplate
.
availabilityCurveType
]
currentComponent3
=
obj
[
selectedTemplate
.
latencyCurveType
]
// if()
}
watch
(()
=>
keliSelector
.
value
.
value
,
keliOnChange
)
</
script
>
...
...
src/pages/header/index.vue
浏览文件 @
b548a9ad
...
...
@@ -57,7 +57,7 @@
</div>
</div>
<el-dialog
v-model=
"screenConfigeDialogVisible"
:destroy-on-close=
"
tru
e"
:modal=
"false"
width=
"100"
<el-dialog
v-model=
"screenConfigeDialogVisible"
:destroy-on-close=
"
fals
e"
:modal=
"false"
width=
"100"
:show-close=
"false"
:before-close=
"handleScreenConfigeClose"
style=
" background-color: rgba(0, 0, 0,0);padding: 0;margin: 0;"
>
<screenConfige
@
handleScreenConfigeClose=
"handleScreenConfigeClose"
></screenConfige>
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论