提交 e6ae360b authored 作者: 汪雄's avatar 汪雄

完成基本的曲线配置

上级 243c186e
{
"Afghanistan": "阿富汗",
"Albania": "阿尔巴尼亚",
"Algeria": "阿尔及利亚",
"Angola": "安哥拉",
"Argentina": "阿根廷",
"Armenia": "亚美尼亚",
"Australia": "澳大利亚",
"Austria": "奥地利",
"Azerbaijan": "阿塞拜疆",
"Bahamas": "巴哈马",
"Bahrain": "巴林",
"Bangladesh": "孟加拉国",
"Belarus": "白俄罗斯",
"Belgium": "比利时",
"Belize": "伯利兹",
"Benin": "贝宁",
"Bhutan": "不丹",
"Bolivia": "玻利维亚",
"Bosnia and Herz.": "波斯尼亚和黑塞哥维那",
"Botswana": "博茨瓦纳",
"Brazil": "巴西",
"British Virgin Islands": "英属维京群岛",
"Brunei": "文莱",
"Bulgaria": "保加利亚",
"Burkina Faso": "布基纳法索",
"Burundi": "布隆迪",
"Cambodia": "柬埔寨",
"Cameroon": "喀麦隆",
"Canada": "加拿大",
"Cape Verde": "佛得角",
"Cayman Islands": "开曼群岛",
"Central African Rep.": "中非共和国",
"Chad": "乍得",
"Chile": "智利",
"China": "中国",
"Colombia": "哥伦比亚",
"Comoros": "科摩罗",
"Congo": "刚果",
"Costa Rica": "哥斯达黎加",
"Croatia": "克罗地亚",
"Cuba": "古巴",
"Cyprus": "塞浦路斯",
"Czech Rep.": "捷克共和国",
"Côte d'Ivoire": "科特迪瓦",
"Dem. Rep. Congo": "刚果民主共和国",
"Dem. Rep. Korea": "朝鲜",
"Denmark": "丹麦",
"Djibouti": "吉布提",
"Dominican Rep.": "多米尼加共和国",
"Ecuador": "厄瓜多尔",
"Egypt": "埃及",
"El Salvador": "萨尔瓦多",
"Equatorial Guinea": "赤道几内亚",
"Eritrea": "厄立特里亚",
"Estonia": "爱沙尼亚",
"Ethiopia": "埃塞俄比亚",
"Falkland Is.": "福克兰群岛",
"Fiji": "斐济",
"Finland": "芬兰",
"Fr. S. Antarctic Lands": "所罗门群岛",
"France": "法国",
"Gabon": "加蓬",
"Gambia": "冈比亚",
"Georgia": "格鲁吉亚",
"Germany": "德国",
"Ghana": "加纳",
"Greece": "希腊",
"Greenland": "格陵兰",
"Guatemala": "危地马拉",
"Guinea": "几内亚",
"Guinea-Bissau": "几内亚比绍",
"Guyana": "圭亚那",
"Haiti": "海地",
"Honduras": "洪都拉斯",
"Hungary": "匈牙利",
"Iceland": "冰岛",
"India": "印度",
"Indonesia": "印度尼西亚",
"Iran": "伊朗",
"Iraq": "伊拉克",
"Ireland": "爱尔兰",
"Isle of Man": "马恩岛",
"Israel": "以色列",
"Italy": "意大利",
"Jamaica": "牙买加",
"Japan": "日本",
"Jordan": "约旦",
"Kazakhstan": "哈萨克斯坦",
"Kenya": "肯尼亚",
"Korea": "韩国",
"Kuwait": "科威特",
"Kyrgyzstan": "吉尔吉斯斯坦",
"Lao PDR": "老挝",
"Latvia": "拉脱维亚",
"Lebanon": "黎巴嫩",
"Lesotho": "莱索托",
"Liberia": "利比里亚",
"Libya": "利比亚",
"Lithuania": "立陶宛",
"Luxembourg": "卢森堡",
"Macedonia": "马其顿",
"Madagascar": "马达加斯加",
"Malawi": "马拉维",
"Malaysia": "马来西亚",
"Maldives": "马尔代夫",
"Mali": "马里",
"Malta": "马耳他",
"Mauritania": "毛利塔尼亚",
"Mauritius": "毛里求斯",
"Mexico": "墨西哥",
"Moldova": "摩尔多瓦",
"Monaco": "摩纳哥",
"Mongolia": "蒙古",
"Montenegro": "黑山共和国",
"Morocco": "摩洛哥",
"Mozambique": "莫桑比克",
"Myanmar": "缅甸",
"Namibia": "纳米比亚",
"Nepal": "尼泊尔",
"Netherlands": "荷兰",
"New Caledonia": "新喀里多尼亚",
"New Zealand": "新西兰",
"Nicaragua": "尼加拉瓜",
"Niger": "尼日尔",
"Nigeria": "尼日利亚",
"Norway": "挪威",
"Oman": "阿曼",
"Pakistan": "巴基斯坦",
"Panama": "巴拿马",
"Papua New Guinea": "巴布亚新几内亚",
"Paraguay": "巴拉圭",
"Peru": "秘鲁",
"Philippines": "菲律宾",
"Poland": "波兰",
"Portugal": "葡萄牙",
"Puerto Rico": "波多黎各",
"Qatar": "卡塔尔",
"Reunion": "留尼旺",
"Romania": "罗马尼亚",
"Russia": "俄罗斯",
"Rwanda": "卢旺达",
"S. Geo. and S. Sandw. Is.": "南乔治亚和南桑威奇群岛",
"S. Sudan": "南苏丹",
"San Marino": "圣马力诺",
"Saudi Arabia": "沙特阿拉伯",
"Senegal": "塞内加尔",
"Serbia": "塞尔维亚",
"Sierra Leone": "塞拉利昂",
"Singapore": "新加坡",
"Slovakia": "斯洛伐克",
"Slovenia": "斯洛文尼亚",
"Solomon Is.": "所罗门群岛",
"Somalia": "索马里",
"South Africa": "南非",
"Spain": "西班牙",
"Sri Lanka": "斯里兰卡",
"Sudan": "苏丹",
"Suriname": "苏里南",
"Swaziland": "斯威士兰",
"Sweden": "瑞典",
"Switzerland": "瑞士",
"Syria": "叙利亚",
"Tajikistan": "塔吉克斯坦",
"Tanzania": "坦桑尼亚",
"Thailand": "泰国",
"Togo": "多哥",
"Tonga": "汤加",
"Trinidad and Tobago": "特立尼达和多巴哥",
"Tunisia": "突尼斯",
"Turkey": "土耳其",
"Turkmenistan": "土库曼斯坦",
"U.S. Virgin Islands": "美属维尔京群岛",
"Uganda": "乌干达",
"Ukraine": "乌克兰",
"United Arab Emirates": "阿拉伯联合酋长国",
"United Kingdom": "英国",
"United States": "美国",
"Uruguay": "乌拉圭",
"Uzbekistan": "乌兹别克斯坦",
"Vanuatu": "瓦努阿图",
"Vatican City": "梵蒂冈城",
"Venezuela": "委内瑞拉",
"Vietnam": "越南",
"W. Sahara": "西撒哈拉",
"Yemen": "也门",
"Yugoslavia": "南斯拉夫",
"Zaire": "扎伊尔",
"Zambia": "赞比亚",
"Zimbabwe": "津巴布韦"
}
\ No newline at end of file
......@@ -36,7 +36,7 @@ function getStaticPath() {
}
const staticPath = getStaticPath();
//console.log(`Serving static files from: ${staticPath}`);
console.log(`Serving static files from: ${staticPath}`);
// 1. CORS 中间件 - 放在最前面
app.use((req, res, next) => {
......@@ -65,9 +65,13 @@ app.use((req, res, next) => {
}
});
// 3. API代理 - 简化版本
app.use('/api', createProxyMiddleware({
target: 'http://121.229.107.155:2251',
target: 'http://127.0.0.1:19020', // 后端API地址
// target: 'http://121.229.107.155:2251',
changeOrigin: true,
pathRewrite: { '^/api': '/api' },
logLevel: 'debug',
......@@ -79,7 +83,8 @@ app.use('/api', createProxyMiddleware({
onError: (err, req, res) => {
console.error('Proxy Error:', err);
res.status(500).json({ error: 'Proxy error' });
}
},
// ws: true, // ws 转发
}));
// 4. 静态文件服务
......
......@@ -8,6 +8,7 @@
*/
import request from "@/utils/request";
import { pa } from "element-plus/es/locales.mjs";
// 左侧菜单-星座构型信息
export function stellationInfoApi() {
return request({
......@@ -108,19 +109,21 @@ export function getGridPanel() {
});
}
// 容量/流量数据
export function getCapacityAndTraffic(data) {
// 容量数据
export function getCapacity(data) {
return request({
url: "/commPanel/getCapacityAndTraffic",
url: "/commPanel/getCapacity",
method: "get",
params: {
gridCodes: data.gridCodes || null,
granularity: data.granularity,
startTime: data.startTime,
endTime: data.endTime,
regionName: data.regionName || null,
signalSiteCode: data.signalSiteCode || null,
},
params: data,
});
}
//流量
export function getTraffic(data) {
return request({
url: "/commPanel/getTraffic",
method: "get",
params: data,
});
}
......@@ -129,14 +132,7 @@ 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,
},
params: data,
});
}
......@@ -145,14 +141,7 @@ 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,
},
params: data,
});
}
......@@ -161,14 +150,7 @@ 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,
},
params: data,
});
}
......@@ -226,3 +208,26 @@ export function templateuUpdate(data) {
data,
});
}
export function templateConfigAdd(data) {
return request({
url: "/objectApi/add",
method: "POST",
data,
});
}
export function templateConfigQuery() {
return request({
url: "/objectApi/queryByIp",
method: "POST",
});
}
//获取所有曲线数据
export function getPanelCurve(data) {
return request({
url: "/commPanel/getPanelCurve",
method: "get",
params: data,
});
}
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -3,7 +3,7 @@
<div class="container">
<div class="main">
<div :id="idName" class="cdfCurve"></div>
<div class="showDetial" @click="showViewClick" v-if="isShowDetial">
<!-- <div class="showDetial" @click="showViewClick" v-if="isShowDetial">
<el-icon v-if="showView" class="icon">
<View />
</el-icon>
......@@ -11,13 +11,13 @@
<Hide />
</el-icon>
<span>详情</span>
</div>
<div class="showValue">
</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 }}
</div>
</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="false" :before-close="isDetialDialogVisibleHandleClose"
......@@ -38,7 +38,7 @@ export default {
import * as echarts from 'echarts';
import childrenCdfCurve from './childrenCdfCurve.vue'
import { onMounted, onUnmounted, ref, nextTick } from 'vue';
import { onMounted, onUnmounted, ref, nextTick, computed, watch } from 'vue';
const idName = ref(Math.random().toString(30).slice(2, 8))
......@@ -58,7 +58,40 @@ const props = defineProps({
legendName: {
type: String,
default: 'PDF曲线图'
},
data: {
type: Array,
default: () => []
},
zoomHeight: {
type: String,
default: null
}
})
const dataX = computed(() => {
if (props.data.length > 0 && props.data[0]?.x == 'PDF分布') {
let arr = []
props.data.forEach(item => {
arr = item.y.dropRate.map(el => el.x)
})
return arr
}
return props.data.length > 0 ? props.data.map(item => item.x) : ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
})
const dataY = computed(() => {
if (props.data.length > 0 && props.data[0]?.x == 'PDF分布') {
let arr = []
props.data.forEach(item => {
arr = item.y.dropRate.map(el => el.y)
})
return arr
}
return props.data.length > 0 ? props.data.map(item => item.y) : [12, 13, 5, 103, 19, 3, 18]
})
watch(() => props.data, (newVal) => {
initChart();
})
const showView = ref(false);
......@@ -123,8 +156,9 @@ function initChart() {
const chartDom = document.getElementById(idName.value);
chartDom.style.height = '100%';
chartDom.style.width = '100%';
if (!myChart) {
myChart = echarts.init(chartDom);
//console.log("初始化图表propsDate:",chartDom,myChart);
};
const option = {
legend: {
show: true,
......@@ -148,22 +182,112 @@ function initChart() {
top: '23%',
right: '8%',
bottom: '16%',
left: '18%'
left: '18%',
containLabel: true //自动计算x轴label
},
xAxis: {
type: 'category',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: dataX.value,
// axisLabel: {
// interval: 0,
// rotate: 0,
// fontSize: 10,
// color: '#fff',
// }
axisLabel: {
interval: 0,
rotate: 0,
fontSize: 10,
color: '#fff',
rotate: 45,
margin: 20,
fontSize: 10,
// interval: 'auto', // 或直接不写
// interval: function (index) {
// return index % 10 === 0 // 每10个显示一个
// },
hideOverlap: true, // 防重叠(很关键)
formatter: function (value) {
// console.log('x - value', value)
if (value.toString().includes('-')) {
// console.log('嘿嘿', value)
let str = []
const arr = value.split('-') // 只保留日期部分
for (let val of arr) {
if (Number(val) >= 1e8 && val.includes('.')) {
// console.log(val)
val = (Number(val) / 1e8).toFixed(0) + '亿'
}
str.push(val)
}
return str.join('-') // 用换行符连接
}
// console.log('value', value)
return value
}
},
axisLine: {
show: true, //去除轴线
lineStyle: {
color: "#DCE2E8",//设置x轴轴线颜色
}
},
},
dataZoom: dataX.value.length <= 7 ? [] : [
// {
// type: 'slider',
// xAxisIndex: 0,
// startValue: 0,
// endValue: 5, // 一屏只看20个点 ⭐
// height: 5,
// showDetail: false,
// top: 40
// },
// {
// type: 'inside',
// start: 0,
// end: 10,
// left: '18%',
// right: '8%',
// minSpan: 1,
// handleLabel: {
// show: false
// },
// labelFormatter: function (value) {
// console.log('xxx', dataX[value])
// return dataX[value]
// },
// textStyle: {
// color: 'rgba(255, 255, 255, 0.92)',
// fontSize: 8
// }
// },
{
start: 0,
end: 100,
minSpan: 1,
bottom: 8,
left: '14%',
right: '22%',
height: Number(props?.zoomHeight) || 20,
handleLabel: {
show: false
},
labelFormatter: function (value) {
return dataX[value]
},
textStyle: {
color: 'rgba(255, 255, 255, 0.92)',
fontSize: 8
}
}
],
yAxis: {
type: 'value',
max: 120,
// max: 120,
minInterval: 1,
splitLine: {
show: true,
lineStyle: {
......@@ -185,7 +309,7 @@ function initChart() {
{
name: props.legendName,
color: props.color,
data: [12, 13, 5, 103, 19, 3, 18],
data: dataY.value,
type: 'line',
smooth: 0.6,
symbol: 'none',
......
......@@ -23,10 +23,11 @@
<!-- 核心数据指标 -->
<div class="container">
<div class="flex-box flex-left">
<cdfCurve :legendName="props.legendName[0]"></cdfCurve>
<cdfCurve :legendName="props.legendName[0]" :data="props.data[0]"></cdfCurve>
</div>
<div class="flex-box flex-right">
<cdfCurve :legendName="props.legendName[1]" color="#6ffcba" :isShowDetial="true"></cdfCurve>
<cdfCurve :legendName="props.legendName[1]" :data="props.data[1]" color="#6ffcba" :isShowDetial="true">
</cdfCurve>
</div>
</div>
</div>
......@@ -39,7 +40,7 @@ import cdfCurve from './cdfCurve.vue'
const props = defineProps({
title: {
type: String,
default: '位置默认'
default: '默认曲线图'
},
slogan: {
type: String,
......@@ -49,6 +50,14 @@ const props = defineProps({
type: Array,
default: () => ['默认曲线图1', '默认曲线图2']
},
data: {
type: Array,
default: () => []
},
zoomHeight: {
type: String,
default: null
}
});
onBeforeUnmount(() => {
//console.log("中,zhelixieza");
......@@ -63,6 +72,7 @@ const componentProps = ref({});
display: flex;
flex-direction: column;
gap: 15px;
height: 100%;
}
/* 标题栏 */
......
......@@ -13,21 +13,44 @@ export default {
<script setup>
import * as echarts from 'echarts';
import { nextTick, onMounted, onUnmounted, ref } from 'vue';
import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
import worldJson from '@/assets/json/world.json';
import chineseWorldName from '@/assets/json/chineseWorldName.json';
import testJson from '@/assets/json/test.json'
let data = null
// let data = null
const props = defineProps({
title: {
type: String,
default: '默认未知'
},
data: {
type: Array,
default: () => []
}
})
const transformData = () => {
data = testJson.data.map((item) => ({
watch(() => props.data, (newVal) => {
updateChart();
})
const data = computed(() => {
const result = []
// console.log('y--props.data', props.data)
props.data.forEach(el => {
let y = el.y
// console.log('el.y', el.y)
if (Object.prototype.toString.call(y) == '[object Object]' && y.hasOwnProperty('dropRate')) {
y = y.dropRate
}
// console.log('y', y)
y.forEach(y => {
const { longitude: item, value } = y
if (item.vertex1Lat !== null) {
result.push({
name: item.gridName,
value: [
item.vertex1Lon,
......@@ -42,13 +65,38 @@ const transformData = () => {
item.vertex5Lat,
item.vertex6Lon,
item.vertex6Lat,
Math.random() * 100,
value,
],
}));
console.log('data', data)
}
})
}
// console.log('item', item)
})
})
return result
})
// const transformData = () => {
// data = testJson.data.map((item) => ({
// name: item.gridName,
// value: [
// item.vertex1Lon,
// item.vertex1Lat,
// item.vertex2Lon,
// item.vertex2Lat,
// item.vertex3Lon,
// item.vertex3Lat,
// item.vertex4Lon,
// item.vertex4Lat,
// item.vertex5Lon,
// item.vertex5Lat,
// item.vertex6Lon,
// item.vertex6Lat,
// Math.random() * 100,
// ],
// }));
// console.log('data', data)
// }
transformData()
// transformData()
// 生成唯一的图表ID
const chartId = ref('hexagonHeatMap_' + Math.random().toString(36).substr(2, 9));
......@@ -60,10 +108,10 @@ function initChart() {
chartDom.style.width = '100%';
chartDom.style.height = '100%';
if (!chartDom) return;
echarts.registerMap("world", worldJson);
if (!myChart) {
myChart = echarts.init(chartDom);
};
const option = {
backgroundColor: '#000',
......@@ -85,6 +133,16 @@ function initChart() {
// itemHeight: 5, // 图例高度,设为较小值形成线条效果
// },
tooltip: {
trigger: 'item',
formatter: function (params) {
const val = params.value
const color = params.color
// console.log('params', params)
return `<span style="display:inline-block;margin-right:4px;border-radius:10px;width:10px;height:10px;background-color:${color};"></span> ${params.name} ${val[12]}`
}
},
title: {
text: props.title,
......@@ -153,17 +211,14 @@ function initChart() {
type: "custom",
// name:'moren',
coordinateSystem: "geo",
// emphasis: {
// style: {
// fill: "#ffcc00", // 高亮颜色
// opacity: 1,
// },
// },
emphasis: {
focus: "self",
},
renderItem(params, api) {
// console.log("params", api.value(0));
if (!api.value(0) == null) {
return null
}
const point1 = api.coord([api.value(0), api.value(1)]);
const point2 = api.coord([api.value(2), api.value(3)]);
const point3 = api.coord([api.value(4), api.value(5)]);
......@@ -183,7 +238,7 @@ function initChart() {
},
};
},
data: data,
data: data.value,
}
]
}
......@@ -192,6 +247,20 @@ function initChart() {
resizeChart();
}
function updateChart() {
if (!myChart) return;
myChart.setOption({
series: [
{
type: 'custom',
data: data.value
}
]
});
}
// 响应式调整图表大小
function resizeChart() {
if (myChart) {
......
......@@ -23,10 +23,10 @@
<!-- 核心数据指标 -->
<div class="container">
<div class="flex-box flex-left">
<hotMap :title="props.legendName[0]"></hotMap>
<hotMap :title="props.legendName[0]" :data="props.data[0]"></hotMap>
</div>
<div class="flex-box flex-right">
<hotMap :title="props.legendName[1]"></hotMap>
<hotMap :title="props.legendName[1]" :data="props.data[1]"></hotMap>
</div>
</div>
</div>
......@@ -35,7 +35,6 @@
<script setup>
import { ref } from 'vue';
import hotMap from './hotMap.vue'
import testMap from './testMap.vue'
const props = defineProps({
slogan: {
......@@ -49,8 +48,13 @@ const props = defineProps({
title: {
type: String,
default: '默认热力图'
},
data: {
type: Array,
default: () => []
}
})
console.log(props.legendName[0], 'props.legendName')
......
......@@ -3,11 +3,11 @@
<!-- 标题栏 -->
<div class="section-divider">
<div class="divider-line"></div>
<h3 class="section-title">{{props.slogan}}</h3>
<h3 class="section-title">{{ props.slogan }}</h3>
<div class="divider-line"></div>
</div>
<div class="hot-title">
<div class="hot-title-text">{{props.title}}</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" />
......@@ -23,10 +23,12 @@
<!-- 核心数据指标 -->
<div class="container">
<div class="flex-box flex-left">
<instantCurve :idName="`instant-left-${props.allIdName}`" :legendName="props.legendName[0]" :propsDate="componentProps"></instantCurve>
<instantCurve :idName="`instant-left-${props.allIdName}`" :data="props.data[0]"
:legendName="props.legendName[0]" :propsDate="componentProps"></instantCurve>
</div>
<div class="flex-box flex-right">
<instantCurve :idName="`instant-right-${props.allIdName}`" color="#6ffcba" :legendName="props.legendName[1]" :isShowDetail="true"></instantCurve>
<instantCurve :idName="`instant-right-${props.allIdName}`" :data="props.data[1]" color="#6ffcba"
:legendName="props.legendName[1]" :isShowDetail="true"></instantCurve>
</div>
</div>
</div>
......@@ -39,19 +41,28 @@ const instantCurveLeft = ref('instantCurve_chart-left');
const props = defineProps({
legendName: {
type: Array,
default: ()=>['默认曲线图1', '默认曲线图2']
default: () => ['默认曲线图1', '默认曲线图2']
},
title: {
type: String,
default: '巴西-最小值(PDF曲线图)'
default: '默认曲线图'
},
slogan: {
type: String,
default: '网络延时/丢包'
},
data: {
type: Array,
default: () => []
},
zoomHeight: {
type: String,
default: null
}
});
console.log('props.allIdName', props.allIdName)
console.log('瞬时值曲线', props.data)
const componentProps = ref({})
</script>
......@@ -62,6 +73,7 @@ const componentProps = ref({})
display: flex;
flex-direction: column;
gap: 15px;
height: 100%;
}
/* 标题栏 */
......
......@@ -3,7 +3,7 @@
<div class="container">
<div class="main">
<div :id="idName" class="cdfCurve"></div>
<div class="showDetial" @click="showViewClick" v-if="isShowDetail">
<!-- <div class="showDetial" @click="showViewClick" v-if="isShowDetail">
<el-icon v-if="showView" class="icon">
<View />
</el-icon>
......@@ -11,13 +11,13 @@
<Hide />
</el-icon>
<span>详情</span>
</div>
<div class="showValue">
</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 }}
</div>
</div>
</div> -->
</div>
......@@ -39,7 +39,7 @@ export default {
<script setup>
import * as echarts from 'echarts';
import childrenInstantCurveDetail from './childrenInstantCurve.vue'
import { onMounted, onUnmounted, ref, nextTick } from 'vue';
import { onMounted, onUnmounted, ref, nextTick, watch } from 'vue';
const idName = ref(Math.random().toString(30).slice(2, 8))
......@@ -60,9 +60,32 @@ const props = defineProps({
color: {
type: String,
default: '#5470C6'
},
data: {
type: Array,
default: () => []
},
zoomHeight: {
type: String,
default: null
}
})
watch(() => props.data, (newVal) => {
initChart();
})
const dataX = computed(() => {
return props.data.length > 0 ? props.data.map(item => item.x.split(' ')[1].slice(0, 8)) : ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
})
const dataY = computed(() => {
if (props.data[0]?.y && Object.prototype.toString(props.data[0]?.y) === '[object Object]' && props.data[0].y?.errorRate !== undefined) {
props.data.forEach(item => {
item.y = item.y.dropRate
})
}
return props.data.length > 0 ? props.data.map(item => item.y) : [12, 13, 5, 103, 19, 3, 18]
})
......@@ -127,7 +150,9 @@ onUnmounted(() => {
function initChart() {
const chartDom = document.getElementById(idName.value);
if (!myChart) {
myChart = echarts.init(chartDom);
};
chartDom.style.height = '100%';
chartDom.style.width = '100%';
const option = {
......@@ -153,22 +178,40 @@ function initChart() {
top: '23%',
right: '8%',
bottom: '16%',
left: '18%'
left: '18%',
containLabel: true //自动计算x轴label
},
xAxis: {
type: 'category',
// type: 'time',
boundaryGap: false,
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
data: dataX.value,
// data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
axisLabel: {
interval: 0,
rotate: 0,
fontSize: 10,
color: '#fff',
rotate: 45,
fontSize: 10,
margin: 20,
interval: 'auto', // 或直接不写
// interval: function (index) {
// return index % 10 === 0 // 每10个显示一个
// },
hideOverlap: true, // 防重叠(很关键)
},
axisLine: {
show: true, //去除轴线
lineStyle: {
color: "#DCE2E8",//设置x轴轴线颜色
}
},
},
yAxis: {
type: 'value',
max: 120,
// max: 120,
minInterval: 1,
splitLine: {
show: true,
lineStyle: {
......@@ -180,17 +223,72 @@ function initChart() {
splitNumber: 5,
axisLabel: {
color: '#fff',
// rotate: 45,
fontSize: 10,
formatter: function (value) {
return value.toFixed(0);
if (Number(value) >= 1e8) {
return (Number(value) / 1e8).toFixed(0) + '亿'
}
return value
}
}
},
dataZoom: dataX.value.length <= 5 ? [] : [
// {
// type: 'slider',
// xAxisIndex: 0,
// startValue: 0,
// endValue: 20, // 一屏只看20个点 ⭐
// height: 5,
// showDetail: false,
// top: 40
// },
// {
// type: 'inside',
// start: 0,
// end: 10,
// left: '18%',
// right: '8%',
// minSpan: 1,
// handleLabel: {
// show: false
// },
// labelFormatter: function (value) {
// console.log('xxx', dataX[value])
// return dataX[value]
// },
// textStyle: {
// color: 'rgba(255, 255, 255, 0.92)',
// fontSize: 8
// }
// },
{
start: 0,
end: 100,
minSpan: 1,
type: 'slider',
left: '10%',
right: '10%',
height: Number(props.zoomHeight) || 20,
bottom: 8,
handleLabel: {
show: false
},
labelFormatter: function (value) {
return dataX[value]
},
textStyle: {
color: 'rgba(255, 255, 255, 0.92)',
fontSize: 8
}
}
],
series: [
{
color: props.color,
name: props.legendName,
data: [12, 13, 85, 53, 19, 23, 18],
data: dataY.value,
type: 'line',
smooth: 0.6,
symbol: 'none',
......@@ -223,24 +321,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'
// },
// }
// ]
}
}
],
......
......@@ -29,7 +29,8 @@
</div>
<div class="section-item_content_down">
<KeepAlive>
<component :is="el.defaultComponent" :title="titleFn(el)" :slogan="el.title" :legendName="el.legendName"></component>
<component :is="el.defaultComponent" :title="titleFn(el)" :slogan="el.title" :legendName="el.legendName">
</component>
</KeepAlive>
</div>
......@@ -64,64 +65,64 @@ const props = defineProps({
const settingConfig = ref([
{
title: '容量/流量',
legendName:['链路层容量','用户实际流量'],
legendName: ['链路层容量', '用户实际流量'],
defaultComponent: markRaw(hotMapComponent),
templateSelector: [
{
label: '曲线类型',
default: '热力图',
default: '3',
type: 'capacityCurveType',
options: [
{
value: '瞬时值曲线',
value: '1',
label: '瞬时值曲线',
},
{
value: 'PDF曲线',
value: '2',
label: 'PDF曲线',
},
{
value: '热力图',
value: '3',
label: '热力图',
},
]
},
{
label: '地理标准',
default: '最小值',
default: '1',
type: 'capacityGeoStandard',
options: [
{
value: '最小值',
value: '1',
label: '最小值',
},
{
value: '最大值',
value: '3',
label: '最大值',
},
{
value: '平均值',
value: '2',
label: '平均值',
}
]
},
{
label: '时间标准',
default: '最小值',
default: '1',
type: 'capacityTimeStandard',
options: [
{
value: '最小值',
value: '1',
label: '最小值',
},
{
value: '最大值',
value: '3',
label: '最大值',
},
{
value: '平均值',
value: '2',
label: '平均值',
}
]
......@@ -130,58 +131,58 @@ const settingConfig = ref([
},
{
title: '可用性',
legendName:['规划可用性','实际可用性'],
legendName: ['规划可用性', '实际可用性'],
defaultComponent: markRaw(cdf),
templateSelector: [
{
label: '曲线类型',
default: 'PDF曲线',
default: '2',
type: 'availabilityCurveType',
options: [
{
value: 'PDF曲线',
value: '2',
label: 'PDF曲线',
},
{
value: '热力图',
value: '3',
label: '热力图',
},
]
},
{
label: '地理标准',
default: '最小值',
default: '1',
type: 'availabilityGeoStandard',
options: [
{
value: '最小值',
value: '1',
label: '最小值',
},
{
value: '最大值',
value: '3',
label: '最大值',
},
{
value: '平均值',
value: '2',
label: '平均值',
}
]
},
{
label: '时间标准',
default: '最小值',
default: '1',
type: 'availabilityTimeStandard',
options: [
{
value: '最小值',
value: '1',
label: '最小值',
},
{
value: '最大值',
value: '3',
label: '最大值',
},
{
value: '平均值',
value: '2',
label: '平均值',
}
]
......@@ -190,62 +191,62 @@ const settingConfig = ref([
},
{
title: '网络时延/丢包',
legendName:['搜星时延','丢包率'],
legendName: ['搜星时延', '丢包率'],
defaultComponent: markRaw(instant),
templateSelector: [
{
label: '曲线类型',
default: '瞬时值曲线',
default: '1',
type: 'latencyCurveType',
options: [
{
value: '瞬时值曲线',
value: '1',
label: '瞬时值曲线',
},
{
value: 'PDF曲线',
value: '2',
label: 'PDF曲线',
},
{
value: '热力图',
value: '3',
label: '热力图',
},
]
},
{
label: '地理标准',
default: '最小值',
default: '1',
type: 'latencyGeoStandard',
options: [
{
value: '最小值',
value: '1',
label: '最小值',
},
{
value: '最大值',
value: '3',
label: '最大值',
},
{
value: '平均值',
value: '2',
label: '平均值',
}
]
},
{
label: '时间标准',
default: '最小值',
default: '1',
type: 'latencyTimeStandard',
options: [
{
value: '最小值',
value: '1',
label: '最小值',
},
{
value: '最大值',
value: '3',
label: '最大值',
},
{
value: '平均值',
value: '2',
label: '平均值',
}
]
......@@ -309,45 +310,53 @@ const settingConfig = ref([
]);
watch(() => props.settingConfig, (newVal) => {
// console.log('newVal', newVal)
console.log('newVal', newVal)
if (!newVal) return
templateName.value = newVal.templateName
// debugger
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]
if (attr.includes('CurveType')) {
switch (newVal[attr]) {
case '瞬时值曲线':
case '1':
item.defaultComponent = markRaw(cdf);
break
case '热力图':
item.defaultComponent = markRaw(hotMapComponent)
break
case 'PDF曲线':
case '2':
item.defaultComponent = markRaw(cdf)
break
case '3':
item.defaultComponent = markRaw(hotMapComponent)
break
default:
break
}
}
}
}
isEdit.value = false
}, { immediate: true })
const selectOnChange = (val, index, key) => {
console.log('row', val, index, key)
if (key !== 0) return
settingConfig.value[index].templateSelector.default = val
switch (val) {
case '瞬时值曲线':
case '1':
settingConfig.value[index].defaultComponent = markRaw(cdf);
break
case '热力图':
case '3':
settingConfig.value[index].defaultComponent = markRaw(hotMapComponent)
console.log('热力图', settingConfig.value[index].defaultComponent)
break
case 'PDF曲线':
case '2':
settingConfig.value[index].defaultComponent = markRaw(cdf)
break
default:
......@@ -365,7 +374,46 @@ const handleEdit = async () => {
const titleFn = (el) => {
const templateSelector = el.templateSelector
return `${templateSelector[0].default} - ${templateSelector[1].default} - ${templateSelector[2].default}`
const curveType = {
'1': '瞬时值曲线',
'2': 'PDF曲线',
'3': '热力图'
}
const geoTimeStandard = {
'1': '最小值',
'2': '平均值',
'3': '最大值',
}
return `${curveType[templateSelector[0].default]} - ${geoTimeStandard[templateSelector[1].default]} - ${geoTimeStandard[templateSelector[2].default]}`
}
const resetConfig = () => {
settingConfig.value.forEach((item, index) => {
if (index == 0) {
item.defaultComponent = markRaw(hotMapComponent)
}
if (index == 1) {
item.defaultComponent = markRaw(cdf)
}
if (index == 2) {
item.defaultComponent = markRaw(instant)
}
item.templateSelector.forEach(el => {
if (index == 0) {
el.default = '3'
}
if (index == 1) {
el.default = '2'
}
if (index == 2) {
el.default = '1'
}
})
})
// console.log('重置配置项', settingConfig.value)
isEdit.value = false
}
defineExpose({
......@@ -380,7 +428,8 @@ defineExpose({
})
})
return obj
}
},
resetConfig
})
......@@ -519,7 +568,7 @@ defineExpose({
.section-item_content_down {
width: 100%;
/* height: 100%; */
height: 340px;
height: 440px;
/* background-color: #9520a0; */
padding: 10px 0;
}
......
<template>
<div class="dashboard-container">
<div class="dashboard-container" v-loading="loading" element-loading-text="加载中..."
element-loading-background="rgba(0, 0, 0, 0.4)">
<!-- 顶部导航栏 -->
<header class="dashboard-header">
<div class="logo">
......@@ -80,27 +81,30 @@
</div>
</div>
</div>
<div class="content-item">
<div class="content-item" style="height: 480px;">
<KeepAlive>
<component :is="currentComponent1" :title="titles[0]" slogan="容量/流量" :legendName="['链路层容量', '用户实际流量']">
<!-- <KeepAlive> -->
<component :is="currentComponent1" :data="[capacityData, trafficData]" :title="titles[0]" slogan="容量/流量"
:legendName="['链路层容量', '用户实际流量']">
</component>
</KeepAlive>
<!-- </KeepAlive> -->
<KeepAlive>
<component :is="currentComponent2" :title="titles[1]" slogan="可用性" :legendName="['规划可用性', '实际可用性']">
<!-- <KeepAlive> -->
<component :is="currentComponent2" :data="[availabilityData]" :title="titles[1]" slogan="可用性"
:legendName="['规划可用性', '实际可用性']">
</component>
</KeepAlive>
<!-- </KeepAlive> -->
<KeepAlive>
<component :is="currentComponent3" :title="titles[2]" slogan="网络时延/丢包" :legendName="['搜星时延', '丢包率']">
<!-- <KeepAlive> -->
<component :is="currentComponent3" :data="[delayData, lossRateData]" :title="titles[2]" slogan="网络时延/丢包"
:legendName="['搜星时延', '丢包率']">
</component>
</KeepAlive>
<!-- </KeepAlive> -->
</div>
<div>
<el-button type="primary" class="apply-btn apply-btn-right">应用</el-button>
<el-button type="primary" @click="handleConfigApplay" class="apply-btn apply-btn-right">应用</el-button>
</div>
</div>
</div>
......@@ -143,23 +147,46 @@
<script setup>
import { ref, computed, onMounted, watch, markRaw } from 'vue';
import { ref, computed, onMounted, watch, markRaw, nextTick } 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, getAvailability, getTemplateList, templateAdd, templateDel, templateDetail, templateuUpdate } from '@/api/Zodiac';
import {
getAvailability, getTemplateList, templateAdd, templateDel,
templateDetail, templateuUpdate, templateConfigAdd, templateConfigQuery, getCapacity, getTraffic,
getDelay, getLossRate, getPanelCurve
} from '@/api/Zodiac';
import useAppStore from '@/store/module/app'
import { ElMessage, ElMessageBox } from 'element-plus'
import { component } from 'vxe-pc-ui';
let currentComponent1 = ref(markRaw(hotMapComponent)) //容量流量 热力图
let currentComponent2 = ref(markRaw(cdf)) //可用性 PDF曲线
let currentComponent3 = ref(markRaw(instant)) //let 瞬时值曲线组件 //前面那个人写的好乱更屎一样,我服了,在这里偷偷吐槽一下嘿嘿
let capacityData = ref([])
let trafficData = ref([])
let delayData = ref([])
let lossRateData = ref([])
let availabilityData = ref([])
const resetData = () => {
capacityData.value = []
trafficData.value = []
delayData.value = []
lossRateData.value = []
availabilityData.value = []
}
let currentComponent1 = markRaw(hotMapComponent) //容量流量 热力图
let currentComponent2 = markRaw(cdf) //可用性 PDF曲线
let currentComponent3 = markRaw(instant) //let 瞬时值曲线组件 //前面那个人写的好乱更屎一样,我服了,在这里偷偷吐槽一下嘿嘿
const screenConfigCaseRef = ref()
const currentSettingConfig = ref()
const templateCaseList = ref([])
const loading = ref(true)
const appStore = useAppStore();
......@@ -167,7 +194,10 @@ const emits = defineEmits(['handleScreenConfigeClose']);
// 标签页状态管理
const activeTab = ref('equipmentCount'); // 默认选中"地面站设备数量"
const titles = ref([]);
watch(activeTab, (newVal) => {
templateSelector.value = '' // 切换标签页时重置模板选择
});
const titles = ref(['', '', '']);
const keliSelector = ref(
{
......@@ -250,6 +280,8 @@ const handleDelete = () => {
})
};
const handleAdd = () => {
screenConfigCaseRef.value.resetConfig() // 重置配置项
currentSettingConfig.value = null // 新增时清空当前配置,避免影响新增模板的添加
const templateId = Date.now();
templateCaseList.value.push({
//新增模板
......@@ -268,7 +300,11 @@ const handleAdd = () => {
};
// 初始化选中值
onMounted(async () => {
await handleConfigData()
await handleList();
await getPanelCurveData()
// await handleConfigData()
// await getCapacityAndTrafficData()
// await getAvailabilityData();
});
......@@ -279,35 +315,85 @@ const toggleDropdown = (index) => {
dropdownVisible.value = dropdownVisible.value.map((val, i) => i === index ? !val : false);
};
const transformHotMapData = (data) => {
return data.map(item => ({
name: item.name,
x_value: item.x,
y_value: item.y
}))
}
const getCapacityAndTrafficData = async () => {
const res = await getCapacityAndTraffic({
granularity: keliSelector.value.value,
startTime: '2025-11-03 00:00:00',
endTime: '2025-11-06 00:00:00',
regionName: '',
signalSiteCode: '',
gridCodes: ''
// 容量
const getCapacityData = async (data) => {
const obj = {
startTime: '2025-11-03 23:59:59',
endTime: '2025-11-04 23:59:59',
})
console.log(res)
}
const res = await getCapacity({ ...data, ...obj })
if (res.code == 200) {
CapacityAndTrafficData.value.push(res.data)
}
}
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: ''
})
// //流量
const getTrafficData = async (data) => {
data.startTime = '2026-01-03 23:59:59'
data.endTime = '2026-01-04 23:59:59'
const res = await getTraffic(data)
if (res.code == 200) {
CapacityAndTrafficData.value.push(res.data)
}
}
const getDelayData = async (data) => {
data.startTime = '2025-01-03 23:59:59'
data.endTime = '2025-01-04 23:59:59'
data = {
...data,
curveType: currentSettingConfig.value.latencyCurveType,
standard: currentSettingConfig.value.latencyGeoStandard,
timeStandard: currentSettingConfig.value.latencyTimeStandard
}
const res = await getDelay(data)
if (res.code == 200) {
delayAndLossData.value.push(res.data)
}
}
const getLossRateData = async (data) => {
data.startTime = '2026-01-03 23:59:59'
data.endTime = '2026-01-04 23:59:59'
const res = await getLossRate(data)
if (res.code == 200) {
delayAndLossData.value.push(res.data)
}
}
const getAvailabilityData = async (data) => {
const res = await getAvailability(data)
if (res.code == 200) {
// AvailabilityData.value.push(res.data)
}
console.log('可用性', res)
}
const getPanelCurveData = async (data) => {
const res = await getPanelCurve(data)
if (res.code == 200) {
console.log('所有曲线数据', res.data)
capacityData.value = res.data.capacity
trafficData.value = res.data.traffic
delayData.value = res.data.delay
lossRateData.value = res.data.lossRate
availabilityData.value = res.data.availability
}
}
const activeTemplateIndex = ref(0);
const templateCaseClickFn = (item, index) => {
//console.log('templateCaseClickFn', index);
activeTemplateIndex.value = index;
currentSettingConfig.value = item;
};
......@@ -339,17 +425,17 @@ const keliOnChange = () => {
break;
}
}
watch(() => keliSelector.value.value, () => keliOnChange)
watch(() => keliSelector.value.value, keliOnChange)
const handleApply = async () => {
let ret = null
loading.value = true
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() // 获取当前配置
......@@ -358,13 +444,103 @@ const handleApply = async () => {
if (ret.code == 200) {
await handleList() // 刷新列表获取最新数据
loading.value = false
ElMessage({
message: '模板设置成功',
type: 'success',
})
}
}
const handleConfigApplay = async () => {
if (templateSelector.value == null || templateSelector.value == '') {
ElMessage({
message: '请先选择一个模板',
type: 'error',
})
return
}
loading.value = true
const ret = await templateConfigAdd({
granularity: keliSelector.value.value,
granularityValue: childrenSelector.value.value,
selectedTemplate: templateSelector.value
})
if (ret.code == 200) {
const data = {
granularity: keliSelector.value.value,
// startTime: '2026-01-03 23:59:59',
// endTime: '2026-01-04 23:59:59',
regionName: keliSelector.value.value == 'region' ? childrenSelector.value.value : null,
signalSiteCode: keliSelector.value.value == 'station' ? childrenSelector.value.value : null,
gridCodes: keliSelector.value.value == 'grid' ? childrenSelector.value.value : null,
}
await getPanelCurveData(data);
loading.value = false
appStore.chartConfig = {
_capacityData: capacityData.value,
_trafficData: trafficData.value,
_delayData: delayData.value,
_availabilityData: availabilityData.value,
_lossRateData: lossRateData.value,
component1: currentComponent1.value,
component2: currentComponent2.value,
component3: currentComponent3.value,
_titles: titles.value
}
console.log('appStore.chartConfig 传递的时候', appStore.chartConfig)
// Promise.all([
// // getCapacityData(data),
// // getTrafficData(data),
// // getAvailabilityData(data),
// getDelayData(data),
// // getLossRateData(data)
// ]).then(() => {
// ElMessage({
// message: '曲线数据获取成功',
// type: 'success',
// })
// }).catch(() => {
// ElMessage({
// message: '曲线数据获取失败',
// type: 'error',
// })
// })
// const ret = await getCapacityData(data)
// await getTrafficData(data)
}
}
const handleConfigData = async () => {
console.log('handleConfigData')
const ret = await templateConfigQuery()
if (ret.code == 200 && ret.data.templateConfigResponse !== null) {
keliSelector.value.value = ret.data.granularity
setTimeout(() => {
childrenSelector.value.value = ret.data.granularityValue
templateSelector.value = ret.data.templateConfigResponse.templateId
}, 0);
currentSettingConfig.value = ret.data.templateConfigResponse
calculateConfig(ret.data.templateConfigResponse)
// getPanelCurveData({
// granularity: ret.data.granularity,
// regionName: ret.data.granularity == 'region' ? ret.data.granularityValue : null,
// signalSiteCode: ret.data.granularity == 'station' ? ret.data.granularityValue : null,
// gridCodes: ret.data.granularity == 'grid' ? ret.data.granularityValue : null,
// })
// nextTick(() => {
// childrenSelector.value.value = ret.data.granularityValue
// templateSelector.value = ret.data.templateConfigResponse.templateId
// })
// calculateTitle(ret.data.templateConfigResponse)
}
console.log('ret', ret)
}
const handleList = async () => {
......@@ -372,34 +548,54 @@ const handleList = async () => {
if (ret.code == 200) {
templateCaseList.value = ret.data;
currentSettingConfig.value = ret.data[activeTemplateIndex.value]
loading.value = false
}
}
const templateOnChange = (val) => {
console.log('val', val)
const selectedTemplate = templateCaseList.value.find(item => item.templateId === val)
currentSettingConfig.value = selectedTemplate
resetData() // 切换模板时重置数据,避免数据混乱
console.log('selectedTemplate', selectedTemplate)
// availabilityCurveType
// capacityCurveType
// latencyCurveType
calculateConfig();
}
const calculateConfig = (selectedTemplate = currentSettingConfig.value) => {
const obj = {
'PDF曲线': markRaw(cdf),
'热力图': markRaw(hotMapComponent),
'瞬时值曲线': markRaw(instant)
'2': cdf,
'3': hotMapComponent,
'1': instant
}
currentComponent1 = obj[selectedTemplate.capacityCurveType]
currentComponent2 = obj[selectedTemplate.availabilityCurveType]
currentComponent3 = obj[selectedTemplate.latencyCurveType]
currentComponent1.value = obj[selectedTemplate.capacityCurveType]
currentComponent2.value = obj[selectedTemplate.availabilityCurveType]
currentComponent3.value = obj[selectedTemplate.latencyCurveType]
titles.value[0] = selectedTemplate.capacityCurveType + '-' + selectedTemplate.capacityGeoStandard + '-' + selectedTemplate.capacityTimeStandard
titles.value[1] = selectedTemplate.availabilityCurveType + '-' + selectedTemplate.availabilityGeoStandard + '-' + selectedTemplate.availabilityTimeStandard
titles.value[2] = selectedTemplate.latencyCurveType + '-' + selectedTemplate.latencyGeoStandard + '-' + selectedTemplate.latencyTimeStandard
const curveType = {
'1': '瞬时值曲线',
'2': 'PDF曲线',
'3': '热力图'
}
const geoTimeStandard = {
'1': '最小值',
'2': '平均值',
'3': '最大值',
}
// if()
titles.value[0] = curveType[selectedTemplate.capacityCurveType] + '-' + geoTimeStandard[selectedTemplate.capacityGeoStandard] + '-' + geoTimeStandard[selectedTemplate.capacityTimeStandard]
titles.value[1] = curveType[selectedTemplate.availabilityCurveType] + '-' + geoTimeStandard[selectedTemplate.availabilityGeoStandard] + '-' + geoTimeStandard[selectedTemplate.availabilityTimeStandard]
titles.value[2] = curveType[selectedTemplate.latencyCurveType] + '-' + geoTimeStandard[selectedTemplate.latencyGeoStandard] + '-' + geoTimeStandard[selectedTemplate.latencyTimeStandard]
}
const initChartData = () => {
}
......@@ -851,7 +1047,7 @@ const templateOnChange = (val) => {
.content-item {
display: flex;
flex-direction: row;
height: 340px;
height: 440px;
gap: 20px;
padding: 10px 5px;
/* background-color: #1c5abe; */
......
<template>
<div class="constellation-panel">
<div class="constellation-panel" v-loading="loading">
<!-- 顶部区域:标题与核心指标 -->
<div class="header-container">
<allHotMap></allHotMap>
<!-- <allHotMap></allHotMap> -->
<component :is="component1" :key="component1" :data="[capacityData, trafficData]" zoomHeight="2"
:title="titles[0]" slogan="容量/流量" :legendName="['链路层容量', '用户实际流量']"></component>
</div>
<!-- 卫星列表 -->
<div class="satellite-section">
<cdf></cdf>
<!-- <cdf></cdf> -->
<component :is="component2" :key="component2" :data="[availabilityData]" zoomHeight="14" :title="titles[1]"
slogan="可用性" :legendName="['规划可用性', '实际可用性']"></component>
</div>
<!-- 地面系统 -->
<div class="ground-system-section">
<instant></instant>
<!-- <instant></instant> -->
<component :is="component3" :key="component3" :data="[delayData, lossRateData]" zoomHeight="14" :title="titles[2]"
slogan="网络时延/丢包" :legendName="['搜星时延', '丢包率']"></component>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue';
import { markRaw, onMounted, ref, watch } from 'vue';
import allHotMap from '@/pages/all/components/hotMapComponents/index.vue'
import errorDialog from '@/pages/lefts/component/errorDialog.vue'
import cdf from '@/pages/all/components/cdf/index.vue'
import instant from '@/pages/all/components/instant/index.vue'
import useAppStore from '@/store/module/app'
import { getPanelCurve, templateConfigQuery } from '@/api/Zodiac'
const component1 = ref(markRaw(allHotMap))
const component2 = ref(markRaw(cdf))
const component3 = ref(markRaw(instant))
let capacityData = ref([])
let trafficData = ref([])
let delayData = ref([])
let lossRateData = ref([])
let availabilityData = ref([])
const titles = ref(['', '', '']);
const appStore = useAppStore();
const loading = ref(false)
let granularity = null
let granularityValue = null
watch(() => appStore.chartConfig, (newVal) => {
console.log('appStore.chartConfig', appStore.chartConfig)
console.log('newVal', newVal)
if (appStore.chartConfig) {
const { _capacityData, _trafficData, _delayData, _availabilityData, _lossRateData, _titles } = appStore.chartConfig
component1.value = markRaw(appStore.chartConfig.component1)
component2.value = markRaw(appStore.chartConfig.component2)
component3.value = markRaw(appStore.chartConfig.component3)
capacityData.value = _capacityData
trafficData.value = _trafficData
delayData.value = _delayData
availabilityData.value = _availabilityData
lossRateData.value = _lossRateData
console.log('1', capacityData.value)
console.log('2', trafficData.value)
console.log('3', delayData.value)
console.log('4', availabilityData.value)
console.log('5', lossRateData.value)
titles.value = _titles
// console.log('component1.value', component1.value)
// console.log('component2.value', component2.value)
// console.log('component3.value', component3.value)
}
}, { deep: true })
const getPanelCurveData = async (data) => {
const res = await getPanelCurve({
granularity: granularity,
regionName: granularity == 'region' ? granularityValue : null,
signalSiteCode: granularity == 'station' ? granularityValue : null,
gridCodes: granularity == 'grid' ? granularityValue : null,
})
if (res.code == 200 && res.data !== null) {
// console.log('所有曲线数据', res.data)
capacityData.value = res.data.capacity
trafficData.value = res.data.traffic
delayData.value = res.data.delay
lossRateData.value = res.data.lossRate
availabilityData.value = res.data.availability
}
}
const hanleTemplateConfigQuery = async () => {
const ret = await templateConfigQuery()
if (ret.code == 200 && ret.data.templateConfigResponse !== null) {
granularity = ret.data.granularity
granularityValue = ret.data.granularityValue
calculateConfig(ret.data.templateConfigResponse)
}
console.log('templateConfigQuery', ret)
}
onMounted(async () => {
await hanleTemplateConfigQuery()
await getPanelCurveData()
loading.value = false
})
const calculateConfig = (selectedTemplate) => {
const obj = {
'2': cdf,
'3': allHotMap,
'1': instant
}
component1.value = obj[selectedTemplate.capacityCurveType]
component2.value = obj[selectedTemplate.availabilityCurveType]
component3.value = obj[selectedTemplate.latencyCurveType]
const curveType = {
'1': '瞬时值曲线',
'2': 'PDF曲线',
'3': '热力图'
}
const geoTimeStandard = {
'1': '最小值',
'2': '平均值',
'3': '最大值',
}
titles.value[0] = curveType[selectedTemplate.capacityCurveType] + '-' + geoTimeStandard[selectedTemplate.capacityGeoStandard] + '-' + geoTimeStandard[selectedTemplate.capacityTimeStandard]
titles.value[1] = curveType[selectedTemplate.availabilityCurveType] + '-' + geoTimeStandard[selectedTemplate.availabilityGeoStandard] + '-' + geoTimeStandard[selectedTemplate.availabilityTimeStandard]
titles.value[2] = curveType[selectedTemplate.latencyCurveType] + '-' + geoTimeStandard[selectedTemplate.latencyGeoStandard] + '-' + geoTimeStandard[selectedTemplate.latencyTimeStandard]
}
// 激活的标签页
const activeTab = ref('equipment');
......@@ -42,10 +164,10 @@ const groundMetrics = ref([
]);
const orbitMetrics = ref([
{ label: '在轨卫星数', value: '108' ,statusClass: 'top-left'},
{ label: '组网卫星数', value: '1,296' ,statusClass: 'top-right'},
{ label: '地面站数', value: '33' ,statusClass: 'bottom-left'},
{ label: '开通格网数', value: '3,600' ,statusClass: 'bottom-right'},
{ label: '在轨卫星数', value: '108', statusClass: 'top-left' },
{ label: '组网卫星数', value: '1,296', statusClass: 'top-right' },
{ label: '地面站数', value: '33', statusClass: 'bottom-left' },
{ label: '开通格网数', value: '3,600', statusClass: 'bottom-right' },
]);
function tableHandleRowClickFn(row, column, event) {
......@@ -75,17 +197,17 @@ function errorDialoghandleClose() {
display: flex;
flex-direction: column;
gap: 15px;
height: 280px;
min-height: 300px;
}
.satellite-section{
min-height: 325px;
.satellite-section {
min-height: 300px;
/* background-color: #2E7DFF; */
/* overflow-y: hidden; */
}
.ground-system-section{
min-height: 350px;
.ground-system-section {
min-height: 300px;
/* background-color: #2E7DFF; */
/* overflow-y: hidden; */
}
......
......@@ -13,7 +13,8 @@
<div class="orbit-visualization">
<div class="orbit-visualization-container" style="min-height: 41vh;">
<div class="table-header">
<el-input placeholder="搜索" size="small" class="search-input" @input="searchSegmentList_up" v-model="searchSegmentValue">
<el-input placeholder="搜索" size="small" class="search-input" @input="searchSegmentList_up"
v-model="searchSegmentValue">
<template #prefix>
<el-icon class="search-icon">
<Search />
......@@ -28,12 +29,16 @@
<el-table-column prop="entryTime" label="入境时刻(北京时间)" width="150" align="center"></el-table-column>
<el-table-column prop="exitTime" label="出境时刻(北京时间)" width="150" align="center">
<template #default="scope">
{{scope.row.exitTime === "-"?scope.row.exitTime:compareTime(useAppStoreInstance.subSystemTimeLineEndSelectTime, scope.row.exitTime)?scope.row.exitTime:"-" }}
{{ scope.row.exitTime ===
"-" ? scope.row.exitTime : compareTime(useAppStoreInstance.subSystemTimeLineEndSelectTime,
scope.row.exitTime)?scope.row.exitTime:"-" }}
</template>
</el-table-column>
<el-table-column prop="duration" label="时长(sec)" width="80" align="center">
<template #default="scope">
{{scope.row.duration === "-"?scope.row.duration:compareTime(useAppStoreInstance.subSystemTimeLineEndSelectTime, scope.row.exitTime)?scope.row.duration:"-" }}
{{ scope.row.duration ===
"-" ? scope.row.duration : compareTime(useAppStoreInstance.subSystemTimeLineEndSelectTime,
scope.row.exitTime)?scope.row.duration:"-" }}
</template>
</el-table-column>
<el-table-column prop="groundStation" label="地面站" width="90" align="center"></el-table-column>
......@@ -61,7 +66,8 @@
<div class="equipment-panel">
<div class="orbit-visualization-container">
<div class="table-header">
<el-input placeholder="搜索" size="small" class="search-input" @input="searchAlterList" v-model="searchAlterValue">
<el-input placeholder="搜索" size="small" class="search-input" @input="searchAlterList"
v-model="searchAlterValue">
<template #prefix>
<el-icon class="search-icon">
<Search />
......@@ -70,7 +76,8 @@
</el-input>
</div>
<el-table :data="alertData" size="small" height="380px" class="custom-table" @row-click="handleAlertDataRowClick">
<el-table :data="alertData" size="small" height="380px" class="custom-table"
@row-click="handleAlertDataRowClick">
<el-table-column prop="alertCode" label="告警码" width="80" align="center"></el-table-column>
<el-table-column prop="alertName" label="告警名称" width="80" align="center"></el-table-column>
<el-table-column prop="alertObject" label="告警对象" width="120" align="center"></el-table-column>
......@@ -84,7 +91,7 @@
</el-table-column>
<!-- <el-table-column prop="faultServiceLeve" label="服务故障等级" width="150" align="center"></el-table-column> -->
<el-table-column prop="alterCreateTime" label="告警产生时间" width="120" align="center"></el-table-column>
<el-table-column label="告警状态" width="70" align="center" fixed="right" >
<el-table-column label="告警状态" width="70" align="center" fixed="right">
<template #default="scope">
<el-tag :class="`alert-status_${OpposeAlertDataStatusMap[scope.row.alertStatus]}`">
<!-- {{ scope.row.alertStatus === '0' ? '未处理' : '已处理' }} -->
......@@ -98,18 +105,11 @@
</div>
</div>
<el-dialog v-model="errorDataShowDialogVisible"
:show-close="false"
:modal="false"
modal-penetrable
:before-close="handleIsErrorDataCloseFn"
:destroy-on-close=""
style="background: rgba(0, 0, 0, 0);padding: 0;margin: 0;"
>
<errorDataShowComponent @handleIsErrorDataCloseFn="handleIsErrorDataCloseFn" :errorDetailItems="errorDetailItems"></errorDataShowComponent>
<el-dialog v-model="errorDataShowDialogVisible" :show-close="false" :modal="false" modal-penetrable
:before-close="handleIsErrorDataCloseFn" :destroy-on-close="true"
style="background: rgba(0, 0, 0, 0);padding: 0;margin: 0;">
<errorDataShowComponent @handleIsErrorDataCloseFn="handleIsErrorDataCloseFn" :errorDetailItems="errorDetailItems">
</errorDataShowComponent>
</el-dialog>
</div>
</template>
......@@ -190,17 +190,17 @@ onMounted(() => {
// }
},{ deep: true, immediate: true });
}, { deep: true, immediate: true });
})
// useAppStoreInstance.subsystemSocket.onmessage = (event) => {
// const Jsondata = JSON.parse(event.data);
// primitive_rawData_up.value = arcInfoTransform(Jsondata.arcSegmentInfoArray)
// rawData_up.value = primitive_rawData_up.value
// primitiveAlertData.value = alertInfoTransformFn(Jsondata.satelliteAlertInfoArray)
// alertData.value = primitiveAlertData.value
// //console.log("222222222right2---------",rawData_up.value,Jsondata.arcSegmentInfoArray);
// // useAppStoreInstance.setSubsystemSocketContent(Jsondata)
// }
// useAppStoreInstance.subsystemSocket.onmessage = (event) => {
// const Jsondata = JSON.parse(event.data);
// primitive_rawData_up.value = arcInfoTransform(Jsondata.arcSegmentInfoArray)
// rawData_up.value = primitive_rawData_up.value
// primitiveAlertData.value = alertInfoTransformFn(Jsondata.satelliteAlertInfoArray)
// alertData.value = primitiveAlertData.value
// //console.log("222222222right2---------",rawData_up.value,Jsondata.arcSegmentInfoArray);
// // useAppStoreInstance.setSubsystemSocketContent(Jsondata)
// }
})
const alertLevelMap = {
'1': 'Ⅰ级',
......@@ -209,16 +209,16 @@ const alertLevelMap = {
'4': 'Ⅳ级'
}
const OpposeAlertLevelMap = {
'Ⅰ级':'1',
'Ⅱ级':'2',
'Ⅲ级':'3',
'Ⅳ级':'4',
'Ⅰ级': '1',
'Ⅱ级': '2',
'Ⅲ级': '3',
'Ⅳ级': '4',
}
const OpposeAlertDataStatusMap = ref({
"手工清除":'2',
"活动":'1',
"自动清除":'0',
"手工清除": '2',
"活动": '1',
"自动清除": '0',
})
// 卫星告警信息数据(随机生成)
const primitiveAlertData = [
......@@ -258,7 +258,7 @@ const compareTime = (time1, time2) => {
// 比较时间戳
if (date1 >= date2) {
return true;
}else {
} else {
return false;
}
};
......@@ -268,14 +268,14 @@ const compareTime = (time1, time2) => {
const alertData = ref(primitiveAlertData)
const AlertDataLevelMap = ref({
'一级告警':1,
'二级告警':2,
'三级告警':3,
'四级告警':4,
'一级告警': 1,
'二级告警': 2,
'三级告警': 3,
'四级告警': 4,
})
const AlertDataStatusMap = ref({
"1":'手工清除',
"0":'活动',
"1": '手工清除',
"0": '活动',
})
const alertInfoTransformFn = (data) => {
//console.log("wodsad--------alertInfoTransformFn",data,typeof data);
......@@ -294,7 +294,7 @@ const alertInfoTransformFn = (data) => {
alertLevel: alertLevelMap[AlertDataLevelMap.value[data[0].alarmLevel]] ? alertLevelMap[AlertDataLevelMap.value[data[0].alarmLevel]] : '-',
// faultServiceLeve: "F4(灾难性)",
alterCreateTime: data[0].alarmOccurrenceTime ? data[0].alarmOccurrenceTime : '-',
alertStatus: data[0].clearStatus ? data[0].clearStatus: '-',
alertStatus: data[0].clearStatus ? data[0].clearStatus : '-',
}));
}
......@@ -335,7 +335,7 @@ const handleAlertDataRowClick = (row) => {
{ label: '告警状态', value: row.alertStatus || '-' },
{ label: '告警名称', value: row.alertName || '-' },
{ label: '告警对象', value: row.alertObject || '-' },
{ label: '告警级别',value: row.alertLevel },
{ label: '告警级别', value: row.alertLevel },
{ label: '告警类型', value: row.elementType || '-' },
{ label: '告警产生时间', value: row.alterCreateTime || '-' },
......@@ -344,12 +344,12 @@ const handleAlertDataRowClick = (row) => {
{ label: '告警定位信息', value: row?.orginData[0]?.locationInfo || '-' },
{ label: '告警原因', value: row?.orginData[0]?.manufacturerAlarmCause || '-' },
]
]
errorDataShowDialogVisible.value = true;
if (window.ue5) {
window.ue5("callBackAllDialogFn", String(JSON.stringify({
type:"SatelliteAlarmInfoDialog",
status:"open"
type: "SatelliteAlarmInfoDialog",
status: "open"
})));
}
}
......@@ -359,8 +359,8 @@ const handleIsErrorDataCloseFn = () => {
errorDataShowDialogVisible.value = false;
if (window.ue5) {
window.ue5("callBackAllDialogFn", String(JSON.stringify({
type:"SatelliteAlarmInfoDialog",
status:"close"
type: "SatelliteAlarmInfoDialog",
status: "close"
})));
}
}
......@@ -472,7 +472,7 @@ const handleIsErrorDataCloseFn = () => {
background: #000000;
border: 1px solid rgba(59, 130, 246, 0.3);
border-radius: 6px;
height:100%;
height: 100%;
margin-top: 5px;
overflow-y: auto;
font-size: 12px;
......@@ -575,27 +575,32 @@ const handleIsErrorDataCloseFn = () => {
color: #ffffff;
}
[class*="alert-level_"]{
[class*="alert-level_"] {
color: #ffffff;
}
.alert-level_1{
.alert-level_1 {
background-color: #ed323e;
}
.alert-level_2 {
background-color: #eea929;
}
.alert-level_3 {
background-color: #3270ed;
}
.alert-level_4 {
background-color: #17a0e0;
}
.alertStatusClassName{
.alertStatusClassName {
background-color: #000000;
background: #000000;
}
[class*="alert-status_"]{
[class*="alert-status_"] {
font-size: 12px;
/* height:'100px'; */
background-color: #000000;
......@@ -604,22 +609,25 @@ const handleIsErrorDataCloseFn = () => {
.alert-status_2 {
color: #28D86E !important;
background:black;
background: black;
}
.alert-status_1 {
color: red !important;
background:black;
background: black;
}
.alert-status_0 {
color: green !important;
background:black;
background: black;
}
:deep(.el-table tr){
:deep(.el-table tr) {
background: black;
}
:deep(.custom-table .el-table__body tr:hover) {
background: linear-gradient(to right, #2c4f89 0%, rgb(0, 0, 0)) 100% !important;
}
......@@ -682,23 +690,8 @@ const handleIsErrorDataCloseFn = () => {
:deep(.el-table--fit .el-table__inner-wrapper:before){
width: calc(100% );
:deep(.el-table--fit .el-table__inner-wrapper:before) {
width: calc(100%);
background: black;
}
</style>
\ No newline at end of file
<template>
<div style="width: 100vh;height: 20px;background-color: red;"></div>
<h1>hello</h1>
</template>
<script setup>
import { onMounted } from 'vue'
import { getGridInfoList } from '@/api/Zodiac';
const ret = await getGridInfoList()
console.log('显示显示ret', ret)
onMounted(() => {
initCanvas()
})
const initCanvas = () => {
const canvas = document.getElementById("map")
const ctx = canvas.getContext("2d")
console.log('ctx', ctx)
const width = canvas.width
const height = canvas.height
}
// 示例经纬度数据
const points = [
{ name: "北京", lng: 116.4, lat: 39.9 },
{ name: "上海", lng: 121.47, lat: 31.23 },
{ name: "东京", lng: 139.69, lat: 35.68 },
{ name: "纽约", lng: -74.00, lat: 40.71 },
{ name: "伦敦", lng: -0.12, lat: 51.50 }
]
// Mercator 投影
function project(lng, lat) {
const x = (lng + 180) * (width / 360)
const latRad = lat * Math.PI / 180
const mercN = Math.log(Math.tan((Math.PI / 4) + (latRad / 2)))
const y = (height / 2) - (width * mercN / (2 * Math.PI))
return [x, y]
}
</script>
<style scoped>
</style>
\ No newline at end of file
......@@ -14,7 +14,7 @@ axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
//console.log("import.meta.env.VITE_API_URL",import.meta.env.VITE_API_URL);
// console.log("import.meta.env.VITE_API_URL",import.meta.env.VITE_API_URL);
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
......
......@@ -28,6 +28,7 @@ export default defineConfig({
sourcemap: 'true', // 按需开启
minify: 'esbuild', // 压缩方式
cssCodeSplit: true, // CSS代码分割
drop: ['console', 'debugger'],
// Rollup配置
rollupOptions: {
......@@ -69,15 +70,15 @@ export default defineConfig({
},
},
server: {
port: 80,//指定开发服务器的端口
port: 8081,//指定开发服务器的端口
// host: true,//指定开发度武器的主机名
host: '0.0.0.0',//开发服务器将监听所有可用的网络地址(包括局域网和本地网络)
open: true,//自动在默认浏览器上打开
proxy: {
'/api': {
target: 'http://121.229.107.155:19020',
ws: false,//代理websocked
// target: 'http://192.168.1.242:19020',
// ws: true,//代理websocked
changeOrigin: true, //是否跨域
secure: false, //是否https接口
rewrite: (path) => path.replace(/^\/api/, ""),//重写请求路径,使用正则表达式将请求路径中的 /dev-api 前缀替换为空字符串。例如,/dev-api/users 将被重写为 /users,然后代理到目标服务器。
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论