updata
@ -18,6 +18,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@form-create/element-ui": "^2.5.30",
|
||||
"@jiaminghi/data-view": "^2.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"amfe-flexible": "^2.2.1",
|
||||
"axios": "0.18.1",
|
||||
@ -29,7 +30,8 @@
|
||||
"decimal.js": "^10.4.3",
|
||||
"driver.js": "0.9.5",
|
||||
"dropzone": "5.5.1",
|
||||
"echarts": "4.2.1",
|
||||
"echarts": "^4.9.0",
|
||||
"echarts-gl": "^1.1.2",
|
||||
"element-ui": "^2.15.14",
|
||||
"file-saver": "^2.0.1",
|
||||
"fuse.js": "3.4.4",
|
||||
@ -75,7 +77,7 @@
|
||||
"autoprefixer": "9.5.1",
|
||||
"babel-eslint": "10.1.0",
|
||||
"babel-jest": "23.6.0",
|
||||
"babel-loader": "^9.1.3",
|
||||
"babel-loader": "^8.2.5",
|
||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||
"bpmn-js": "^13.2.2",
|
||||
"chalk": "2.4.2",
|
||||
|
||||
@ -509,7 +509,7 @@ export default {
|
||||
this.searchDialogVisible = true
|
||||
},
|
||||
goScreen() {
|
||||
window.open('https://www.kaiyuancloud.cn/dev/#/screen/k8sRescource', '_blank');
|
||||
window.open('https://www.opencomputing.cn/#/screen/k8sRescource', '_blank');
|
||||
},
|
||||
channelFirstBtn() {
|
||||
reqApplyChannel({ user_id: this.userId }).then(res => {
|
||||
|
||||
@ -64,9 +64,14 @@ sessionStorage.setItem('client_uuid', uuidv4())
|
||||
|
||||
// 引入form-create 表单生成器
|
||||
import formCreate from "@form-create/element-ui"
|
||||
|
||||
Vue.use(formCreate);
|
||||
|
||||
// ============ 引入 DataV 数据可视化库 (Vue 2.x 版本) ============
|
||||
import dataV from '@jiaminghi/data-view'
|
||||
// 使用 DataV
|
||||
Vue.use(dataV)
|
||||
// ============ DataV 引入完成 ============
|
||||
|
||||
import * as filters from './filters' // global filters
|
||||
|
||||
import HappyScroll from 'vue-happy-scroll'
|
||||
|
||||
@ -181,7 +181,7 @@ export const constantRoutes = [
|
||||
{
|
||||
hidden: true, path: '/screen', name: 'screen', title: '可视化大屏', meta: {
|
||||
title: "可视化大屏", fullPath: "/operation/analyze/screen",
|
||||
}, component: () => import('@/views/product/bigScreen/index.vue'), children: [{
|
||||
}, component: () => import('@/views/product/bigScreen/Newscreen/index.vue'), children: [{
|
||||
path: "index",
|
||||
title: '可视化首页',
|
||||
component: () => import('@/views/product/bigScreen/mainPage/index.vue'),
|
||||
|
||||
@ -264,7 +264,7 @@ const actions = {
|
||||
// 如果权限列表包含空路径,认为用户有所有权限
|
||||
accessedRoutes = asyncRoutes || [];
|
||||
} else {
|
||||
// 使用修复后的过滤函数,传入用户角色和设备类型
|
||||
// 传入用户角色和设备类型
|
||||
accessedRoutes = filterAsyncRoutes(asyncRoutes, auths, userRoles, deviceType);
|
||||
}
|
||||
} else {
|
||||
@ -272,7 +272,7 @@ const actions = {
|
||||
accessedRoutes = [];
|
||||
}
|
||||
|
||||
// 新增:为普通用户添加订单管理和资源管理路由以及新的五个客户菜单
|
||||
// 为普通用户添加订单管理和资源管理路由以及新的五个客户菜单
|
||||
console.log("为用户添加特定路由");
|
||||
const userSpecificRoutes = addUserRoutes(asyncRoutes, userType, orgType, userRoles, deviceType);
|
||||
|
||||
|
||||
15
f/web-kboss/src/views/customer/historyOrder/index.vue
Normal file
@ -0,0 +1,15 @@
|
||||
<template>
|
||||
<div>
|
||||
历史订单
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
</style>
|
||||
@ -7,7 +7,6 @@
|
||||
|
||||
<!-- 页面顶部的横幅图片 -->
|
||||
<!-- <img src="" alt=""> -->
|
||||
|
||||
<div class="conter">
|
||||
<div class="left">
|
||||
<p class="title">
|
||||
@ -104,8 +103,8 @@
|
||||
</div>
|
||||
</el-form-item>
|
||||
<!-- 获取验证码按钮 - 添加防抖功能 -->
|
||||
<span :disabled="isDisabled || isGettingCode" class="getCodeStyleNew" style="height:40px;margin-left:10px"
|
||||
@click="debouncedGetCode">
|
||||
<span :disabled="isDisabled || isGettingCode" class="getCodeStyleNew"
|
||||
style="height:40px;margin-left:10px" @click="debouncedGetCode">
|
||||
{{ SendCode_text }}
|
||||
</span>
|
||||
</div>
|
||||
@ -373,7 +372,7 @@ export default {
|
||||
methods: {
|
||||
// 防抖函数
|
||||
debounce(func, wait) {
|
||||
return function() {
|
||||
return function () {
|
||||
const context = this;
|
||||
const args = arguments;
|
||||
clearTimeout(this.debounceTimer);
|
||||
@ -384,7 +383,7 @@ export default {
|
||||
},
|
||||
|
||||
// 防抖后的获取验证码方法
|
||||
debouncedGetCode: function() {
|
||||
debouncedGetCode: function () {
|
||||
if (this.isDisabled || this.isGettingCode) return;
|
||||
|
||||
this.isGettingCode = true;
|
||||
@ -400,7 +399,7 @@ export default {
|
||||
},
|
||||
|
||||
// 防抖后的获取重置密码验证码方法
|
||||
debouncedGetCode1: function() {
|
||||
debouncedGetCode1: function () {
|
||||
if (this.isDisabled1 || this.isGettingCode1) return;
|
||||
|
||||
this.isGettingCode1 = true;
|
||||
@ -459,8 +458,7 @@ export default {
|
||||
// 轮询获取微信登录授权码
|
||||
pollWxCode() {
|
||||
this.getCodeTimer = setInterval(async () => {
|
||||
try {
|
||||
// 请求微信授权码
|
||||
try {x // 请求微信授权码x
|
||||
const res = await reqGetCodeAPI({ state: this.wxState });
|
||||
if (!res.status) return;
|
||||
|
||||
@ -915,7 +913,7 @@ export default {
|
||||
}
|
||||
} else {
|
||||
this.$router.push(getHomePath());
|
||||
}``
|
||||
} ``
|
||||
} else if (res.roles.includes('运营')) {
|
||||
this.$router.push('/operation/supplierManagement');
|
||||
} else if (res.roles.includes('销售')) {
|
||||
|
||||
@ -0,0 +1,472 @@
|
||||
<template>
|
||||
<div id="vmcentercontainer">
|
||||
<div class="bg1"></div>
|
||||
<div class="bg2"></div>
|
||||
<div class="bg3"></div>
|
||||
<div class="echart-map-container">
|
||||
<div class="worldmap">
|
||||
<div class="wrapper">
|
||||
<div class="map-container" ref="myEchart"></div>
|
||||
<div
|
||||
v-for="(cluster, index) in clusterConfigs"
|
||||
:key="index"
|
||||
class="cluster-item-container"
|
||||
:style="getClusterStyle(cluster.position)"
|
||||
>
|
||||
<div class="item" v-if="['北京集群', '长三角集群', '珠三角集群'].includes(cluster.name)">
|
||||
<div class="right">{{ cluster.name }}</div>
|
||||
<div class="left">
|
||||
<span class="title">
|
||||
点击下方进入地图
|
||||
<br>
|
||||
查看集群详细信息
|
||||
</span>
|
||||
<div class="btn">进入地图</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item" v-else>
|
||||
<div class="left">
|
||||
<span class="title">
|
||||
点击下方进入地图
|
||||
<br>
|
||||
查看集群详细信息
|
||||
</span>
|
||||
<div class="btn">进入地图</div>
|
||||
</div>
|
||||
<div class="right">{{ cluster.name }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from "echarts";
|
||||
import "echarts/map/js/china.js";
|
||||
import { areaTwo } from "@/views/product/bigScreen/asset/cityData";
|
||||
|
||||
const CHART_CONSTANTS = {
|
||||
MAP_ZOOM: 1.23,
|
||||
MAP_CENTER: [105, 36],
|
||||
LINE_COLOR: "#ffcc00",
|
||||
BORDER_COLOR: "#389dff",
|
||||
RIPPLE_PERIOD: 5,
|
||||
RESIZE_DEBOUNCE_TIME: 300,
|
||||
HORIZONTAL_LENGTH: 4, // 横线长度调至4(更短,满足需求)
|
||||
BG_IMAGE_PATHS: {
|
||||
map: require("../../../../../assets/image/map.png"),
|
||||
lbx: require("../../../../../assets/image/lbx.png"),
|
||||
jt: require("../../../../../assets/image/jt.png")
|
||||
}
|
||||
};
|
||||
|
||||
export default {
|
||||
name: 'EchartMap',
|
||||
props: {
|
||||
routePath: { type: String, default: '/' },
|
||||
clickableCities: { type: Array, default: () => [] },
|
||||
showMap: { type: Boolean, default: true }
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
myChart: null,
|
||||
resizeTimer: null,
|
||||
// 调整labelPosition与城市坐标的间距,强化斜向延伸的视觉效果
|
||||
clusterConfigs: [
|
||||
{
|
||||
name: '北京集群',
|
||||
cityName: '北京',
|
||||
direction: 'right-top',
|
||||
labelPosition: [121.40, 50.90], // 远离城市坐标,斜向更明显
|
||||
position: { top: '18%', left: '73%' }
|
||||
},
|
||||
{
|
||||
name: '内蒙集群',
|
||||
cityName: '内蒙古',
|
||||
direction: 'left',
|
||||
labelPosition: [105.73, 50.83], // 远离城市坐标
|
||||
position: { top: '19%', left: '35%' }
|
||||
},
|
||||
{
|
||||
name: '新疆集群',
|
||||
cityName: '新疆',
|
||||
direction: 'left',
|
||||
labelPosition: [88.68, 52.77], // 远离城市坐标
|
||||
position: { top: '15.4%', left: '8%' }
|
||||
},
|
||||
{
|
||||
name: '长三角集群',
|
||||
cityName: '上海',
|
||||
direction: 'right',
|
||||
labelPosition: [128, 38.23], // 远离城市坐标
|
||||
position: { top: '40%', left: '80.5%' }
|
||||
},
|
||||
{
|
||||
name: '珠三角集群',
|
||||
cityName: '广东',
|
||||
direction: 'right',
|
||||
labelPosition: [125.5, 28.12], // 远离城市坐标
|
||||
position: { top: '57.3%', left: '80.9%' }
|
||||
},
|
||||
{
|
||||
name: '川渝集群',
|
||||
cityName: '四川',
|
||||
direction: 'left',
|
||||
labelPosition: [99.06, 21.8], // 远离城市坐标
|
||||
position: { top: '69.2%', left: '26%' }
|
||||
}
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
geoCoordMap() {
|
||||
return {
|
||||
"新疆": [87.68, 43.77],
|
||||
"内蒙古": [111.73, 40.83],
|
||||
"北京": [116.40, 39.90],
|
||||
"天津": [117.20, 39.12],
|
||||
"宁夏": [106.27, 38.47],
|
||||
"河北": [114.48, 38.03],
|
||||
"甘肃": [103.82, 36.06],
|
||||
"江苏": [118.78, 32.04],
|
||||
"上海": [121.47, 31.23],
|
||||
"四川": [104.06, 30.67],
|
||||
"重庆": [106.50, 29.53],
|
||||
// "浙江": [120.15, 30.28],
|
||||
"贵州": [106.63, 26.65],
|
||||
"广东": [113.26, 23.12],
|
||||
"香港": [114.16, 22.28],
|
||||
"济南": [117.00, 36.65],
|
||||
// "无锡": [120.30, 31.57],
|
||||
"广州": [113.23, 23.16],
|
||||
"青岛": [120.33, 36.07],
|
||||
"长沙": [113.00, 28.21],
|
||||
};
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
showMap(newVal) {
|
||||
newVal && this.$nextTick(() => this.initChart());
|
||||
},
|
||||
routePath: "refreshChart",
|
||||
clickableCities: { deep: true, handler: "refreshChart" }
|
||||
},
|
||||
mounted() {
|
||||
this.initChart();
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.myChart?.dispose();
|
||||
clearTimeout(this.resizeTimer);
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
},
|
||||
methods: {
|
||||
handleResize() {
|
||||
clearTimeout(this.resizeTimer);
|
||||
this.resizeTimer = setTimeout(() => this.myChart?.resize(), CHART_CONSTANTS.RESIZE_DEBOUNCE_TIME);
|
||||
},
|
||||
getClusterStyle(position) {
|
||||
return position ? { position: 'absolute', ...position, zIndex: 10 } : {};
|
||||
},
|
||||
initChart() {
|
||||
const chartDom = this.$refs.myEchart;
|
||||
if (!chartDom) return;
|
||||
this.myChart?.dispose();
|
||||
this.myChart = echarts.init(chartDom);
|
||||
this.myChart.setOption(this.buildChartOption(), true);
|
||||
this.myChart.on('click', this.handleAreaClick);
|
||||
},
|
||||
refreshChart() {
|
||||
this.$nextTick(() => this.initChart());
|
||||
},
|
||||
buildChartOption() {
|
||||
return {
|
||||
tooltip: { show: false },
|
||||
geo: this.buildGeoConfig(),
|
||||
series: [this.buildLineSeries(), this.buildEffectScatterSeries(), this.buildLabelScatterSeries()]
|
||||
};
|
||||
},
|
||||
buildGeoConfig() {
|
||||
return {
|
||||
map: "china",
|
||||
roam: false,
|
||||
zoom: CHART_CONSTANTS.MAP_ZOOM,
|
||||
center: CHART_CONSTANTS.MAP_CENTER,
|
||||
label: { normal: { show: false }, emphasis: { show: false } },
|
||||
itemStyle: {
|
||||
normal: { areaColor: "rgba(0,0,255,0)", borderColor: CHART_CONSTANTS.BORDER_COLOR, borderWidth: 1 },
|
||||
emphasis: { areaColor: "#0033cc", borderWidth: 0 }
|
||||
}
|
||||
};
|
||||
},
|
||||
buildLineSeries() {
|
||||
return {
|
||||
type: 'lines',
|
||||
coordinateSystem: 'geo',
|
||||
data: this.buildLineData(),
|
||||
lineStyle: { type: 'solid', width: 2, color: CHART_CONSTANTS.LINE_COLOR },
|
||||
symbol: ['none', 'none'],
|
||||
polyline: true,
|
||||
effect: { show: true, trailLength: 0, symbol: 'circle', symbolSize: 3, color: CHART_CONSTANTS.LINE_COLOR }
|
||||
};
|
||||
},
|
||||
buildEffectScatterSeries() {
|
||||
return {
|
||||
type: "effectScatter",
|
||||
coordinateSystem: "geo",
|
||||
data: this.buildScatterData(),
|
||||
symbol: "circle",
|
||||
symbolSize: (_, p) => p.name === '北京' ? 18 : 12,
|
||||
hoverSymbolSize: 15,
|
||||
tooltip: {
|
||||
show: true,
|
||||
formatter: ({name}) => name,
|
||||
backgroundColor: '#f4f6f8',
|
||||
textStyle: { color: "#333", fontSize: 12 },
|
||||
borderColor: '#333',
|
||||
padding: 7
|
||||
},
|
||||
label: { formatter: "{b}", position: "right", show: true, fontWeight: 'bolder' },
|
||||
itemStyle: { color: "#fdfdfd" },
|
||||
emphasis: { label: { show: false } },
|
||||
effectType: 'ripple',
|
||||
rippleEffect: { brushType: 'stroke', scale: 2.5, period: CHART_CONSTANTS.RIPPLE_PERIOD },
|
||||
effect: { show: true, scaleSize: 3, period: 4, color: CHART_CONSTANTS.LINE_COLOR, shadowBlur: 10 }
|
||||
};
|
||||
},
|
||||
buildLabelScatterSeries() {
|
||||
return {
|
||||
type: 'scatter',
|
||||
coordinateSystem: 'geo',
|
||||
data: this.clusterConfigs.map(c => ({
|
||||
value: c.labelPosition,
|
||||
label: { show: true, formatter: c.name, backgroundColor: '#000', color: '#fff', fontSize: 14, fontWeight: 'bold', padding: [8,12], borderRadius: 2 }
|
||||
})),
|
||||
symbol: 'none'
|
||||
};
|
||||
},
|
||||
// 核心修改:强制实现 城市斜向→更短横线→标签 的折线形态
|
||||
buildLineData() {
|
||||
const shortLen = CHART_CONSTANTS.HORIZONTAL_LENGTH;
|
||||
return this.clusterConfigs
|
||||
.map(cluster => {
|
||||
const cityCoord = this.geoCoordMap[cluster.cityName];
|
||||
const [labelLon, labelLat] = cluster.labelPosition;
|
||||
if (!cityCoord) return null;
|
||||
|
||||
const [cityLon, cityLat] = cityCoord;
|
||||
let lineStart, lineEnd;
|
||||
|
||||
// 1. 计算极短水平横线的两端点(长度固定为shortLen)
|
||||
switch (cluster.direction) {
|
||||
case 'left':
|
||||
// 横线在标签左侧,极短
|
||||
lineEnd = [labelLon, labelLat]; // 横线终点 = 标签位置
|
||||
lineStart = [labelLon + shortLen, labelLat]; // 横线起点 = 标签右移shortLen
|
||||
break;
|
||||
case 'right':
|
||||
default:
|
||||
// 横线在标签左侧,极短
|
||||
lineStart = [labelLon - shortLen, labelLat]; // 横线起点 = 标签左移shortLen
|
||||
lineEnd = [labelLon, labelLat]; // 横线终点 = 标签位置
|
||||
break;
|
||||
}
|
||||
|
||||
// 2. 折线顺序:城市(斜向) → 横线起点 → 横线终点(极短横线) → 标签
|
||||
// 城市到横线起点的距离足够远,斜向效果明显
|
||||
return {
|
||||
coords: [
|
||||
[cityLon, cityLat], // 起点:城市
|
||||
lineStart, // 中点1:横线起点(城市到这一步是明显斜向)
|
||||
lineEnd, // 中点2:横线终点(极短水平横线)
|
||||
[labelLon, labelLat]// 终点:标签
|
||||
]
|
||||
};
|
||||
})
|
||||
.filter(item => item !== null);
|
||||
},
|
||||
buildScatterData() {
|
||||
return Object.keys(this.geoCoordMap).map(key => ({
|
||||
name: key,
|
||||
value: this.geoCoordMap[key],
|
||||
symbolSize: key === '北京' ? 18 : 12
|
||||
}));
|
||||
},
|
||||
handleAreaClick(params) {
|
||||
if (!this.clickableCities?.includes(params?.name)) return;
|
||||
this.currentArea = areaTwo[params.name] || [];
|
||||
this.$emit('update:showMap', false);
|
||||
this.$emit('area-click', params);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
#vmcentercontainer {
|
||||
position: relative;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bg1, .bg2, .bg3 {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
background-size: 100% 100%;
|
||||
}
|
||||
|
||||
.bg1 {
|
||||
height: 518px;
|
||||
width: 518px;
|
||||
background: url(~@/assets/image/map.png);
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.bg2 {
|
||||
height: 643px;
|
||||
width: 643px;
|
||||
background: url(~@/assets/image/lbx.png);
|
||||
opacity: 0.6;
|
||||
animation: rotate1 15s linear infinite;
|
||||
}
|
||||
|
||||
.bg3 {
|
||||
height: 566px;
|
||||
width: 566px;
|
||||
background: url(~@/assets/image/jt.png);
|
||||
opacity: 0.8;
|
||||
animation: rotate2 15s linear infinite;
|
||||
}
|
||||
|
||||
.echart-map-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.worldmap {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 5;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.wrapper {
|
||||
padding: 15px;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: flex-start;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.map-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.cluster-item-container {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.item {
|
||||
display: flex;
|
||||
width: 200px;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.item .left {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
padding: 0 8px;
|
||||
background-color: rgba(147, 112, 219, 0.3);
|
||||
}
|
||||
|
||||
.left .title {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.item .btn {
|
||||
color: #FDBD00;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.item .right {
|
||||
text-align: center;
|
||||
width: 20px;
|
||||
font-size: 12px;
|
||||
background-color: #000;
|
||||
}
|
||||
|
||||
.sortBox {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
color: #bbd6f1;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.sortBox ul {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 15px;
|
||||
margin-top: 20px;
|
||||
padding: 0;
|
||||
margin: 20px 0 0 0;
|
||||
}
|
||||
|
||||
.sortBox li {
|
||||
list-style: none;
|
||||
border: 1px solid #2086ee;
|
||||
border-radius: 5px;
|
||||
width: 250px;
|
||||
height: 35px;
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
color: #d3d5ea;
|
||||
padding-left: 10px;
|
||||
font-weight: 700;
|
||||
background-color: rgba(32, 134, 238, 0.1);
|
||||
}
|
||||
|
||||
.go-back {
|
||||
font-weight: bold;
|
||||
border: 1px solid white;
|
||||
border-radius: 5px;
|
||||
padding: 8px 16px;
|
||||
margin-bottom: 30px;
|
||||
cursor: pointer;
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.go-back:hover {
|
||||
background-color: rgba(255, 255, 255, 0.2);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
@keyframes rotate1 {
|
||||
from { transform: translate(-50%, -50%) rotate(0deg); }
|
||||
to { transform: translate(-50%, -50%) rotate(360deg); }
|
||||
}
|
||||
|
||||
@keyframes rotate2 {
|
||||
from { transform: translate(-50%, -50%) rotate(0deg); }
|
||||
to { transform: translate(-50%, -50%) rotate(-360deg); }
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,424 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="center">
|
||||
<div class="top">
|
||||
<!-- 需求算力 -->
|
||||
<div class="top-tit">
|
||||
<div class="top-text">
|
||||
1500P
|
||||
</div>
|
||||
<div class="btm-text">
|
||||
需求算力
|
||||
</div>
|
||||
</div>
|
||||
<!-- 供给算力 -->
|
||||
<div class="top-tit">
|
||||
<div class="top-text">
|
||||
35320P
|
||||
</div>
|
||||
<div class="btm-text">
|
||||
供给算力
|
||||
</div>
|
||||
</div>
|
||||
<!-- 集群数 -->
|
||||
<div class="top-tit">
|
||||
<div class="top-text">
|
||||
7
|
||||
</div>
|
||||
<div class="btm-text">
|
||||
集群数量
|
||||
</div>
|
||||
</div>
|
||||
<!-- 客户数量 -->
|
||||
<div class="top-tit">
|
||||
<div class="top-text">
|
||||
352
|
||||
</div>
|
||||
<div class="btm-text">
|
||||
客户数量
|
||||
</div>
|
||||
</div>
|
||||
<!-- 芯片数量 -->
|
||||
<div class="top-tit">
|
||||
<div class="top-text">
|
||||
75368
|
||||
</div>
|
||||
<div class="btm-text">
|
||||
芯片数量
|
||||
</div>
|
||||
</div>
|
||||
<!-- 模型数量 -->
|
||||
<div class="top-tit">
|
||||
<div class="top-text">
|
||||
75
|
||||
</div>
|
||||
<div class="btm-text">
|
||||
模型数量
|
||||
</div>
|
||||
</div>
|
||||
<dv-decoration-5 style="width:660px;height:40px;" :color="['#379BE8', '#2765B4']" :dur="8" />
|
||||
</div>
|
||||
|
||||
<!-- 添加地图组件 -->
|
||||
<div class="map-container">
|
||||
<!-- 传递必需的props -->
|
||||
<Map :route-path="currentRoutePath" :clickable-cities="clickableCities" :show-map.sync="showMap"
|
||||
@area-click="handleAreaClick" />
|
||||
</div>
|
||||
<!-- 底部 -->
|
||||
<div class="bottom">
|
||||
<!-- 切换栏 -->
|
||||
<div class="btm-tab">
|
||||
<!-- 标签项 - 绑定点击事件和激活状态 -->
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 0 }"
|
||||
@click="switchTab(0)"
|
||||
>
|
||||
供给概览
|
||||
</div>
|
||||
<!-- 标签项 - 绑定点击事件和激活状态 -->
|
||||
<div
|
||||
class="tab-item"
|
||||
:class="{ active: activeTab === 1 }"
|
||||
@click="switchTab(1)"
|
||||
>
|
||||
需求概览
|
||||
</div>
|
||||
</div>
|
||||
<!-- 概览 -->
|
||||
<div class="overview" v-show="activeTab === 0">
|
||||
<!-- 概览项(原有内容不变) -->
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>2350</span>
|
||||
<span>CPU</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>5500</span>
|
||||
<span>GPU</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>进程数量</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>资源统计</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>30%</span>
|
||||
<span>运行中</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>70%</span>
|
||||
<span>关机中</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>故障数量</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>在线数量</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 概览two - 根据激活标签显示,不修改原有布局样式 -->
|
||||
<div class="overview-two" v-show="activeTab === 1">
|
||||
<!-- 概览项(原有内容不变) -->
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>CPU</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>GPU</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>进程数量</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>资源统计</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>运行中</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>关机中</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>故障数量</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="overview-item">
|
||||
<div class="overview-title">
|
||||
<span>0</span>
|
||||
<span>在线数量</span>
|
||||
</div>
|
||||
<div class="overview-img">
|
||||
<img src="../images/btm.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
// 引入地图组件
|
||||
import Map from './Map.vue';
|
||||
|
||||
export default {
|
||||
name: 'VmCenter',
|
||||
components: {
|
||||
Map
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
// 获取当前路由路径
|
||||
currentRoutePath: this.$route ? this.$route.path : '/',
|
||||
// 定义可点击的城市列表 - 根据实际需求修改
|
||||
clickableCities: ['北京', '上海', '广州', '深圳', '济南', '无锡', '青岛', '长沙', '天津', '南京', '杭州', '成都', '重庆', '武汉'],
|
||||
// 控制地图显示
|
||||
showMap: true,
|
||||
// 新增:标签切换标识,0=供给概览(对应overview),1=需求概览(对应overview-two)
|
||||
activeTab: 0
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
// 监听路由变化,更新routePath
|
||||
'$route.path'(newPath) {
|
||||
this.currentRoutePath = newPath;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// 如果当前没有路由对象,可以设置一个默认值
|
||||
if (!this.$route) {
|
||||
this.currentRoutePath = window.location.pathname;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleAreaClick(params) {
|
||||
console.log('区域被点击:', params);
|
||||
// 这里可以处理区域点击事件,比如跳转到详情页面等
|
||||
},
|
||||
// 新增:标签切换方法
|
||||
switchTab(tabIndex) {
|
||||
console.log('切换到标签:', tabIndex);
|
||||
|
||||
this.activeTab = tabIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.center {
|
||||
width: 100%;
|
||||
height: calc(100vh - 160px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.top {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-wrap: wrap;
|
||||
padding: 10px 0;
|
||||
padding-top: 40px;
|
||||
flex-shrink: 0;
|
||||
/* 防止被压缩 */
|
||||
|
||||
.top-tit {
|
||||
padding-left: 4%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-family: "Microsoft Yahei", "PingFang SC", sans-serif;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
transform: skew(-8deg);
|
||||
-webkit-transform: skew(-8deg);
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4);
|
||||
letter-spacing: 1px;
|
||||
|
||||
.top-text {
|
||||
font-size: 26px;
|
||||
}
|
||||
|
||||
.btm-text {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 地图容器样式 */
|
||||
.map-container {
|
||||
flex: 1;
|
||||
/* 占据剩余空间 */
|
||||
width: 100%;
|
||||
min-height: 0;
|
||||
/* 防止flex item溢出 */
|
||||
margin-top: -50px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.bottom {
|
||||
z-index: 99;
|
||||
width: 100%;
|
||||
position: fixed;
|
||||
bottom: 140px;
|
||||
left:0;
|
||||
width: 100%;
|
||||
height: 40px !important;
|
||||
|
||||
.btm-tab {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
color: #fff;
|
||||
font-size: 16px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.tab-item {
|
||||
margin-right: 40px;
|
||||
width: 140px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
background: url(../images/btmTab.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
cursor: pointer; /* 新增:添加鼠标手型,提升交互体验 */
|
||||
transition: all 0.3s ease; /* 新增:过渡动画,切换更平滑 */
|
||||
}
|
||||
|
||||
/* 新增:标签激活状态样式 */
|
||||
.tab-item.active {
|
||||
/* 可根据需求调整激活样式,示例:加深背景/改变文字颜色 */
|
||||
filter: brightness(1.2); /* 背景提亮,不修改原有背景图 */
|
||||
color: #409eff; /* 激活态文字高亮 */
|
||||
font-weight: 600;
|
||||
width: 150px;
|
||||
height: 50px;
|
||||
}
|
||||
|
||||
.overview,.overview-two{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
margin-top: 50px;
|
||||
.overview-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
margin-left: 50px;
|
||||
.overview-title{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
position: absolute;
|
||||
top: 0%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -60%);
|
||||
}
|
||||
.overview-img{
|
||||
width: 70px;
|
||||
height: 50px;
|
||||
img{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,642 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="left">
|
||||
<!-- 第1行:2个横向模块 -->
|
||||
<div class="row row-1">
|
||||
<div class="cluster">
|
||||
<div class="title">异构芯片规模</div>
|
||||
<div class="conter">
|
||||
<div class="conter-top">
|
||||
<div class="top-tit">33000 /<span>个</span></div>
|
||||
<div class="top-tit">5000 /<span>个</span></div>
|
||||
<div class="top-tit">8000 /<span>个</span></div>
|
||||
</div>
|
||||
<div class="conter-center">
|
||||
<img src="../images/3D.png" alt="">
|
||||
</div>
|
||||
<div class="conter-bottom">
|
||||
<div class="bottom-tit">NVIDIA</div>
|
||||
<div class="bottom-tit">晟腾</div>
|
||||
<div class="bottom-tit">传统超算</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="heterogeneous">
|
||||
<div class="title">集群规模</div>
|
||||
<div class="content">
|
||||
<dv-decoration-9 style="width:200px;height:200px;color: #fff;font-size: 20px; font-weight: 600;">
|
||||
5100P
|
||||
</dv-decoration-9>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 第2行:通栏模块(运行中芯片数量) -->
|
||||
<div class="row row-2">
|
||||
<div class="running">
|
||||
<div class="title">运行中芯片数量</div>
|
||||
<div ref="runningChart" class="chart-container "></div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 第3行:2个横向模块 -->
|
||||
<div class="row row-3">
|
||||
<div class="model">
|
||||
<div class="title">模型调用量</div>
|
||||
<div ref="modelChart" class="chart-container model-chart"></div>
|
||||
</div>
|
||||
<div class="token">
|
||||
<div class="title">token调用量</div>
|
||||
<div ref="tokenChart" class="chart-container token-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
runningChartInstance: null,
|
||||
modelChartInstance: null,
|
||||
tokenChartInstance: null,
|
||||
resizeTimer: null
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initRunningChart();
|
||||
this.initModelChart();
|
||||
this.initTokenChart();
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
},
|
||||
methods: {
|
||||
// 运行中芯片数量
|
||||
initRunningChart() {
|
||||
const chartDom = this.$refs.runningChart;
|
||||
if (!chartDom) return;
|
||||
|
||||
this.runningChartInstance = echarts.init(chartDom);
|
||||
|
||||
const xData = ['12/01', '12/02', '12/03', '12/04', '12/05', '12/06', '12/07'];
|
||||
const yData = [16909, 15050, 16240, 21470, 18940, 18950, 17450];
|
||||
|
||||
// 动态计算y轴范围
|
||||
const maxValue = Math.max(...yData);
|
||||
const minValue = Math.min(...yData);
|
||||
|
||||
// 计算合适的y轴最大最小值(留出一些空间)
|
||||
const yMax = Math.ceil(maxValue / 1000) * 1000 + 1000;
|
||||
const yMin = Math.floor(minValue / 1000) * 1000 - 1000;
|
||||
|
||||
// 找出最大值及其索引(用于标记点)
|
||||
const maxIndex = yData.indexOf(maxValue);
|
||||
|
||||
const markPointData = yData.map((value, index) => {
|
||||
if (index === maxIndex) {
|
||||
return {
|
||||
name: '最高',
|
||||
value: value,
|
||||
xAxis: index,
|
||||
yAxis: value,
|
||||
symbol: 'circle',
|
||||
symbolSize: 10,
|
||||
itemStyle: {
|
||||
color: '#fff',
|
||||
// borderColor: '#ff4d4f',
|
||||
// borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: function (params) {
|
||||
return (params.value / 10000).toFixed(1) + '万'; // 转换为"万"单位
|
||||
},
|
||||
color: '#fff',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 12
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}).filter(item => item !== null);
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(0,0,0,0.85)',
|
||||
borderColor: '#1890ff',
|
||||
textStyle: { color: '#fff' },
|
||||
formatter: function (params) {
|
||||
const value = params[0].value;
|
||||
return params[0].name + '<br/>' +
|
||||
params[0].marker + params[0].seriesName + ': ' +
|
||||
value.toLocaleString() + '个'; // 添加千分位分隔符
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
top: '12%',
|
||||
bottom: '15%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 12,
|
||||
interval: 0
|
||||
},
|
||||
axisLine: { lineStyle: { color: 'rgba(255,255,255,0.3)' } },
|
||||
axisTick: { show: false }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: yMin, // 使用动态计算的最小值
|
||||
max: yMax, // 使用动态计算的最大值
|
||||
splitNumber: 6,
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,0.1)',
|
||||
type: 'dashed'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 12,
|
||||
formatter: function (value) {
|
||||
// 将数值转换为"万"单位显示,保留1位小数
|
||||
return (value / 10000).toFixed(1) + '万';
|
||||
}
|
||||
},
|
||||
axisLine: { lineStyle: { color: 'rgba(255,255,255,0.3)' } },
|
||||
axisTick: { show: false }
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '芯片数',
|
||||
type: 'line',
|
||||
data: yData,
|
||||
symbol: 'none',
|
||||
symbolSize: 8,
|
||||
itemStyle: {
|
||||
color: '#1890ff',
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#1890ff',
|
||||
width: 3
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(24,144,255,0.4)' },
|
||||
{ offset: 1, color: 'rgba(24,144,255,0.05)' }
|
||||
])
|
||||
},
|
||||
markPoint: {
|
||||
symbol: 'circle',
|
||||
symbolSize: 10,
|
||||
data: markPointData
|
||||
}
|
||||
}
|
||||
],
|
||||
backgroundColor: 'transparent'
|
||||
};
|
||||
|
||||
this.runningChartInstance.setOption(option);
|
||||
},
|
||||
// 模型调用量
|
||||
initModelChart() {
|
||||
const chartDom = this.$refs.modelChart;
|
||||
if (!chartDom) return;
|
||||
|
||||
this.modelChartInstance = echarts.init(chartDom);
|
||||
|
||||
// 使用提供的表格数据
|
||||
const yData = ['deepseek', '通义千问', 'kimi', '豆包', '文心一言', '元宝'];
|
||||
const xData = [105, 78, 70, 120, 60, 85];
|
||||
|
||||
// 计算合适的X轴最大值
|
||||
const maxValue = Math.max(...xData);
|
||||
const xMax = Math.ceil(maxValue / 50) * 50 + 10;
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(0,0,0,0.85)',
|
||||
borderColor: '#50e3c2',
|
||||
formatter: function (params) {
|
||||
return params[0].name + ': ' + params[0].value;
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '2%',
|
||||
right: '5%',
|
||||
top: '10%',
|
||||
bottom: '10%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: xMax,
|
||||
splitNumber: 6,
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 10
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: 'rgba(255,255,255,0.3)' }
|
||||
},
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,0.1)',
|
||||
type: 'dashed'
|
||||
}
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'category',
|
||||
data: yData,
|
||||
axisLabel: {
|
||||
color: '#fff',
|
||||
fontSize: 10
|
||||
},
|
||||
axisLine: { show: false },
|
||||
axisTick: { show: false }
|
||||
},
|
||||
series: [
|
||||
// 底层:立体背景层(调宽barWidth,从10改为20)
|
||||
{
|
||||
name: '调用量',
|
||||
type: 'bar',
|
||||
data: xData,
|
||||
barWidth: 20,
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: [0, 8, 8, 0],
|
||||
color: '#1a9678',
|
||||
opacity: 0.6
|
||||
}
|
||||
},
|
||||
z: 1
|
||||
},
|
||||
// 上层:主体渐变层(调宽barWidth,从14改为24;关闭右侧数据展示)
|
||||
{
|
||||
name: '调用量',
|
||||
type: 'bar',
|
||||
data: xData,
|
||||
barWidth: 14,
|
||||
label: {
|
||||
show: false, // 关闭右侧数据标签展示
|
||||
position: 'right',
|
||||
color: '#50e3c2',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 12,
|
||||
formatter: '{c}'
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: [0, 8, 8, 0],
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
|
||||
{ offset: 0, color: '#76f7d8' },
|
||||
{ offset: 0.5, color: '#50e3c2' },
|
||||
{ offset: 1, color: '#27c8a7' }
|
||||
]),
|
||||
shadowColor: 'rgba(80, 227, 194, 0.5)',
|
||||
shadowBlur: 8,
|
||||
shadowOffsetX: 2,
|
||||
shadowOffsetY: 2
|
||||
}
|
||||
},
|
||||
z: 2
|
||||
}
|
||||
],
|
||||
backgroundColor: 'transparent'
|
||||
};
|
||||
this.modelChartInstance.setOption(option);
|
||||
},
|
||||
|
||||
// Token调用量
|
||||
initTokenChart() {
|
||||
const chartDom = this.$refs.tokenChart;
|
||||
if (!chartDom) return;
|
||||
|
||||
this.tokenChartInstance = echarts.init(chartDom);
|
||||
|
||||
// 使用提供的表格数据(单位是M,即百万)
|
||||
const xData = ['千问3-max', 'kimi', '豆包', 'deepseek', '千帆'];
|
||||
const yData = [5000, 4300, 3500, 3200, 2800]; // 单位:百万
|
||||
|
||||
// 计算合适的Y轴最大值
|
||||
const maxValue = Math.max(...yData);
|
||||
const yMax = Math.ceil(maxValue / 1000) * 1000 + 500;
|
||||
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(0,0,0,0.85)',
|
||||
borderColor: '#1890ff',
|
||||
formatter: function (params) {
|
||||
return params[0].name + '<br/>' + params[0].marker + params[0].seriesName + ': ' + params[0].value + 'M';
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '0', // 增大左侧间距,预留标签空间
|
||||
right: '10%', // 平衡右侧间距
|
||||
top: '15%',
|
||||
bottom: '25%', // 增大底部间距,防止标签截断
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 11, // 减小字体,避免重叠
|
||||
rotate: 0, // 保持水平显示,如需防重叠可改为15
|
||||
interval: 0, // 强制显示所有标签,不隐藏任何一个
|
||||
margin: 10, // 增大与轴线的间距
|
||||
// 长标签兜底处理
|
||||
formatter: function (value) {
|
||||
if (value.length > 8) {
|
||||
return value.substring(0, 8) + '...';
|
||||
}
|
||||
return value;
|
||||
}
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: 'rgba(255,255,255,0.3)' }
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
alignWithLabel: true // 刻度与标签对齐,优化布局
|
||||
}
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: 0,
|
||||
max: yMax,
|
||||
splitNumber: 6,
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,0.1)',
|
||||
type: 'dashed'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 12
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: { color: 'rgba(255,255,255,0.3)' }
|
||||
}
|
||||
},
|
||||
series: [
|
||||
// 底层
|
||||
{
|
||||
name: 'Token',
|
||||
type: 'bar',
|
||||
data: yData,
|
||||
barWidth: 10, // 减小柱状图宽度,避免挤压标签
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: [6, 6, 0, 0],
|
||||
color: '#0a4a86',
|
||||
opacity: 0.6
|
||||
}
|
||||
},
|
||||
z: 1
|
||||
},
|
||||
// 上层
|
||||
{
|
||||
name: 'Token',
|
||||
type: 'bar',
|
||||
data: yData,
|
||||
barWidth: 12,
|
||||
label: {
|
||||
show: false,
|
||||
position: 'top',
|
||||
color: '#1890ff',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 12,
|
||||
formatter: '{c}M'
|
||||
},
|
||||
itemStyle: {
|
||||
normal: {
|
||||
barBorderRadius: [6, 6, 0, 0],
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: '#40a9ff' },
|
||||
{ offset: 0.5, color: '#1890ff' },
|
||||
{ offset: 1, color: '#0f58a8' }
|
||||
]),
|
||||
shadowColor: 'rgba(24, 144, 255, 0.5)',
|
||||
shadowBlur: 8,
|
||||
shadowOffsetX: 2,
|
||||
shadowOffsetY: 2
|
||||
}
|
||||
},
|
||||
z: 2
|
||||
}
|
||||
],
|
||||
backgroundColor: 'transparent'
|
||||
};
|
||||
this.tokenChartInstance.setOption(option);
|
||||
},
|
||||
handleResize() {
|
||||
clearTimeout(this.resizeTimer);
|
||||
this.resizeTimer = setTimeout(() => {
|
||||
this.runningChartInstance?.resize();
|
||||
this.modelChartInstance?.resize();
|
||||
this.tokenChartInstance?.resize();
|
||||
}, 200);
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.runningChartInstance?.dispose();
|
||||
this.modelChartInstance?.dispose();
|
||||
this.tokenChartInstance?.dispose();
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.left {
|
||||
width: 100%;
|
||||
height: calc(100vh - 160px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.conter {
|
||||
color: #fff;
|
||||
position: relative;
|
||||
|
||||
.conter-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: 10px;
|
||||
|
||||
.top-tit {
|
||||
padding-left: 6px;
|
||||
|
||||
span {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.conter-center {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
img {
|
||||
width: 80%;
|
||||
height: 80%;
|
||||
}
|
||||
}
|
||||
|
||||
.conter-bottom {
|
||||
margin-top: -16px;
|
||||
display: flex;
|
||||
padding-left:10px;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
// padding-left: 20px;
|
||||
|
||||
.bottom-tit {
|
||||
padding-right: 4px;
|
||||
|
||||
span {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.row {
|
||||
width: 100%;
|
||||
height: calc(100% / 3);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
/* 模块宽度适配 */
|
||||
.cluster,
|
||||
.heterogeneous,
|
||||
.model,
|
||||
.token {
|
||||
width: 46%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cluster,
|
||||
.heterogeneous {
|
||||
.title {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
.running {
|
||||
width: 95%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.title {
|
||||
padding-left: 12%;
|
||||
height: 36px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 标题样式 */
|
||||
.title {
|
||||
background: url(../images/titleBg.png) no-repeat;
|
||||
background-size: cover;
|
||||
height: 36px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 20%;
|
||||
font-family: "Microsoft Yahei", "PingFang SC", sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
transform: skew(-12deg);
|
||||
text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.4);
|
||||
letter-spacing: 1px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* 图表容器 */
|
||||
.chart-container {
|
||||
width: 100%;
|
||||
height: calc(100% - 46px);
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
// 模型调用
|
||||
.model-chart {
|
||||
// height: 100%;
|
||||
height: calc(100% - 46px);
|
||||
width: 240px;
|
||||
}
|
||||
|
||||
.token-chart {
|
||||
width: 420px;
|
||||
}
|
||||
|
||||
.content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
/* 调整第3行的高度比例 */
|
||||
.row-3 {
|
||||
|
||||
.model,
|
||||
.token {
|
||||
.chart-container {
|
||||
height: calc(100% - 46px);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 响应式适配 */
|
||||
@media (min-width: 1920px) {
|
||||
.title {
|
||||
font-size: 18px;
|
||||
height: 45px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: calc(100% - 55px);
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1366px) {
|
||||
.title {
|
||||
font-size: 14px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
height: calc(100% - 48px);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,640 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="right">
|
||||
<!-- 第 1 行 -->
|
||||
<div class="row row-1">
|
||||
<!-- 应用类型 -->
|
||||
<div class="app-class">
|
||||
<div class="title">应用类型</div>
|
||||
<div class="content">
|
||||
<!-- 中心TOP1 -->
|
||||
<div class="circle-center">
|
||||
<div class="rank">TOP1</div>
|
||||
<div class="name">智能推理</div>
|
||||
</div>
|
||||
<!-- 周围TOP项 -->
|
||||
<div class="circle-item item-top2">
|
||||
<div class="rank">TOP2</div>
|
||||
<div class="name">智能训练</div>
|
||||
</div>
|
||||
<div class="circle-item item-top3">
|
||||
<div class="rank">TOP3</div>
|
||||
<div class="name">图形渲染</div>
|
||||
</div>
|
||||
<div class="circle-item item-top4">
|
||||
<div class="rank">TOP4</div>
|
||||
<div class="name">蛋白质分析</div>
|
||||
</div>
|
||||
<div class="circle-item item-top5">
|
||||
<div class="rank">TOP5</div>
|
||||
<div class="name">其他</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 用户种类 -->
|
||||
<div class="user-class">
|
||||
<div class="title">用户种类</div>
|
||||
<div class="content">
|
||||
<img src="../images/userClass.png" alt="用户种类示意图">
|
||||
<div class="user">
|
||||
<span class="finance">金融</span>
|
||||
<span class="medical">医疗</span>
|
||||
<span class="creative">文创</span>
|
||||
<span class="education">教育</span>
|
||||
<span class="intelligence">智能制造</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第 2 行 -->
|
||||
<div class="row row-2">
|
||||
<!-- 用户数量(无背景色) -->
|
||||
<div class="user-num">
|
||||
<div class="title">用户数量</div>
|
||||
<div class="content">
|
||||
<img src="../images/use-num.png" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<!-- 用户消费排行 -->
|
||||
<div class="user-consume">
|
||||
<div class="title">用户消费排行</div>
|
||||
<div class="content">
|
||||
<dv-scroll-board :config="scrollBoardConfig" style="width:95%;height:95%" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 第 3 行 -->
|
||||
<div class="row row-3">
|
||||
<!-- 算力使用情况(双折线图,无背景色) -->
|
||||
<div class="power-use">
|
||||
<div class="title">算力使用情况</div>
|
||||
<div ref="powerUseChart" class="power-use-chart"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as echarts from 'echarts';
|
||||
import img1 from '../images/1.png'
|
||||
import img2 from '../images/2.png'
|
||||
import img3 from '../images/3.png'
|
||||
import img4 from '../images/4.png'
|
||||
import img5 from '../images/5.png'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
scrollBoardConfig: {
|
||||
data: [
|
||||
[`<div class="rank-img"><img src="${img1}" /></div>`, '用户A', '¥520000'],
|
||||
[`<div class="rank-img"><img src="${img2}" /></div>`, '用户B', '¥450000'],
|
||||
[`<div class="rank-img"><img src="${img3}" /></div>`, '用户B', '¥186000'],
|
||||
[`<div class="rank-img"><img src="${img4}" /></div>`, '用户D', '¥120000'],
|
||||
[`<div class="rank-img"><img src="${img5}" /></div>`, '用户E', '¥56000'],
|
||||
[`<div class="rank-img"><img src="${img5}" /></div>`, '用户F', '¥43000'],
|
||||
[`<div class="rank-img"><img src="${img5}" /></div>`, '用户G', '¥35000'],
|
||||
[`<div class="rank-img"><img src="${img5}" /></div>`, '用户H', '¥28000'],
|
||||
],
|
||||
index: false,
|
||||
columnWidth: [50, 100, 90],
|
||||
rowHeight: 28,
|
||||
align: ['center', 'center', 'center'],
|
||||
rowNum: 5,
|
||||
oddRowBGC: '#040c45',
|
||||
evenRowBGC: '#17264f',
|
||||
waitTime: 2000,
|
||||
carousel: 'single',
|
||||
hoverPause: true
|
||||
},
|
||||
resizeTimer: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initPowerUseChart();
|
||||
window.addEventListener('resize', this.handleResize);
|
||||
},
|
||||
methods: {
|
||||
initPowerUseChart() {
|
||||
const chartDom = this.$refs.powerUseChart;
|
||||
if (!chartDom) return;
|
||||
const myChart = echarts.init(chartDom);
|
||||
|
||||
// 从图片中提取的数据,保持不变
|
||||
const dates = ['12/01', '12/02', '12/03', '12/04', '12/05', '12/06', '12/07'];
|
||||
const powerUsage = [12300, 11500, 11500, 13400, 12900, 13500, 13200];
|
||||
|
||||
// 动态计算y轴范围
|
||||
const maxValue = Math.max(...powerUsage);
|
||||
const minValue = Math.min(...powerUsage);
|
||||
|
||||
// 计算合适的y轴最大最小值(留出一些空间)
|
||||
const yMax = Math.ceil(maxValue / 1000) * 1000 + 1000;
|
||||
const yMin = Math.floor(minValue / 1000) * 1000 - 1000;
|
||||
|
||||
// 找出最大值及其索引(用于标记点)
|
||||
const maxIndex = powerUsage.indexOf(maxValue);
|
||||
|
||||
const markPointData = powerUsage.map((value, index) => {
|
||||
if (index === maxIndex) {
|
||||
return {
|
||||
name: '最高',
|
||||
value: value,
|
||||
xAxis: index,
|
||||
yAxis: value,
|
||||
symbol: 'circle',
|
||||
symbolSize: 10,
|
||||
itemStyle: {
|
||||
color: '#fff',
|
||||
// borderColor: '#ff4d4f',
|
||||
// borderWidth: 2
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
position: 'top',
|
||||
formatter: function(params) {
|
||||
return (params.value / 10000).toFixed(1) + '万'; // 转换为"万"单位
|
||||
},
|
||||
color: '#fff',
|
||||
fontWeight: 'bold',
|
||||
fontSize: 12
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}).filter(item => item !== null);
|
||||
|
||||
const option = {
|
||||
backgroundColor: 'transparent',
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
backgroundColor: 'rgba(0,0,0,0.85)',
|
||||
borderColor: '#1890ff',
|
||||
textStyle: { color: '#fff' },
|
||||
formatter: function(params) {
|
||||
const value = params[0].value;
|
||||
return params[0].name + '<br/>' +
|
||||
params[0].marker + params[0].seriesName + ': ' +
|
||||
value.toLocaleString() + '算力单位'; // 添加千分位分隔符
|
||||
}
|
||||
},
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
top: '12%',
|
||||
bottom: '15%',
|
||||
containLabel: true
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: dates,
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 12,
|
||||
interval: 0
|
||||
},
|
||||
axisLine: { lineStyle: { color: 'rgba(255,255,255,0.3)' } },
|
||||
axisTick: { show: false }
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
min: yMin, // 使用动态计算的最小值
|
||||
max: yMax, // 使用动态计算的最大值
|
||||
splitNumber: 6,
|
||||
splitLine: {
|
||||
lineStyle: {
|
||||
color: 'rgba(255,255,255,0.1)',
|
||||
type: 'dashed'
|
||||
}
|
||||
},
|
||||
axisLabel: {
|
||||
color: 'rgba(255,255,255,0.7)',
|
||||
fontSize: 12,
|
||||
formatter: function(value) {
|
||||
// 将数值转换为"万"单位显示,保留1位小数
|
||||
return (value / 10000).toFixed(1) + '万';
|
||||
}
|
||||
},
|
||||
axisLine: { lineStyle: { color: 'rgba(255,255,255,0.3)' } },
|
||||
axisTick: { show: false }
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: '算力使用',
|
||||
type: 'line',
|
||||
data: powerUsage,
|
||||
symbol: 'none',
|
||||
symbolSize: 8,
|
||||
itemStyle: {
|
||||
color: '#1890ff',
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2
|
||||
},
|
||||
lineStyle: {
|
||||
color: '#1890ff',
|
||||
width: 3
|
||||
},
|
||||
areaStyle: {
|
||||
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
|
||||
{ offset: 0, color: 'rgba(24,144,255,0.4)' },
|
||||
{ offset: 1, color: 'rgba(24,144,255,0.05)' }
|
||||
])
|
||||
},
|
||||
markPoint: {
|
||||
symbol: 'circle',
|
||||
symbolSize: 10,
|
||||
data: markPointData
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
myChart.setOption(option);
|
||||
},
|
||||
|
||||
handleResize() {
|
||||
clearTimeout(this.resizeTimer);
|
||||
this.resizeTimer = setTimeout(() => {
|
||||
if (this.$refs.powerUseChart) {
|
||||
const chart = echarts.getInstanceByDom(this.$refs.powerUseChart);
|
||||
if (chart) chart.resize();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.$refs.powerUseChart) {
|
||||
const chart = echarts.getInstanceByDom(this.$refs.powerUseChart);
|
||||
if (chart) chart.dispose();
|
||||
}
|
||||
window.removeEventListener('resize', this.handleResize);
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.user-consume {
|
||||
/deep/ .rank-img {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
|
||||
img {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 整体容器:纵向排列 3 行,每行高度平分 */
|
||||
.right {
|
||||
width: 100%;
|
||||
height: calc(100vh - 160px);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 15px;
|
||||
padding: 10px 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.row {
|
||||
width: 100%;
|
||||
height: calc(100% / 3);
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: stretch;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.app-class, .user-class, .user-num, .user-consume {
|
||||
width: 46%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.user-class img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
/* 用户数量模块样式调整 */
|
||||
.user-num .content {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center; /* 垂直居中 */
|
||||
overflow: hidden;
|
||||
padding: 5px; /* 添加内边距 */
|
||||
margin-top: -40px;
|
||||
}
|
||||
|
||||
.user-num .content img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: contain; /* 保持图片比例 */
|
||||
object-position: center center; /* 图片中心对齐 */
|
||||
}
|
||||
|
||||
.power-use {
|
||||
width: 95%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.title {
|
||||
background: url(../images/titleBg.png) no-repeat;
|
||||
background-size: 100% 100%;
|
||||
height: 40px;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding-left: 12%;
|
||||
font-family: "Microsoft Yahei", "PingFang SC", sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
transform: skew(-12deg);
|
||||
-webkit-transform: skew(-12deg);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.user-class .content {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
color: #fff;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
|
||||
.user {
|
||||
position: absolute;
|
||||
top: 56%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.finance, .medical, .creative, .education, .intelligence {
|
||||
padding-top: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.user-consume .content {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.power-use-chart {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
}
|
||||
|
||||
.power-use .title {
|
||||
padding-left: 12%;
|
||||
}
|
||||
|
||||
/* 应用类型模块内容容器 */
|
||||
.app-class .content {
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
position: relative;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
/* 中心TOP1样式 */
|
||||
.circle-center {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 92, 207, 0.3);
|
||||
border: 2px solid rgba(72, 176, 255, 0.8);
|
||||
box-shadow: 0 0 15px rgba(72, 176, 255, 0.6);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
|
||||
.rank {
|
||||
font-weight: bold;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 周围TOP项基础样式 */
|
||||
.circle-item {
|
||||
width: 74px;
|
||||
height: 74px;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 92, 207, 0.2);
|
||||
border: 1px solid rgba(72, 176, 255, 0.6);
|
||||
box-shadow: 0 0 10px rgba(72, 176, 255, 0.4);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
transform-origin: center center;
|
||||
|
||||
.rank {
|
||||
font-weight: bold;
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
|
||||
.name {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
/* 各TOP项定位 */
|
||||
.item-top2 {
|
||||
width: 70px;
|
||||
height: 70px;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
}
|
||||
.item-top3 {
|
||||
bottom: 2px;
|
||||
left: 2px;
|
||||
}
|
||||
.item-top4 {
|
||||
top: 4px;
|
||||
left: -4px;
|
||||
}
|
||||
.item-top5 {
|
||||
bottom: 2px;
|
||||
right: -2px;
|
||||
}
|
||||
|
||||
/* 增强动画效果 - 增加旋转速度 */
|
||||
@keyframes rotate2 {
|
||||
0%, 100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-5px, -5px) rotate(15deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(5px, 5px) rotate(-15deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate3 {
|
||||
0%, 100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(5px, 5px) rotate(-15deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(-5px, -5px) rotate(15deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate4 {
|
||||
0%, 100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(5px, -5px) rotate(15deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(-5px, 5px) rotate(-15deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes rotate5 {
|
||||
0%, 100% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: translate(-5px, 5px) rotate(-15deg);
|
||||
}
|
||||
50% {
|
||||
transform: translate(0, 0) rotate(0deg);
|
||||
}
|
||||
75% {
|
||||
transform: translate(5px, -5px) rotate(15deg);
|
||||
}
|
||||
}
|
||||
|
||||
/* 为每个小圆添加明显的轨道运动 */
|
||||
.item-top2 {
|
||||
animation: rotate2 4s ease-in-out infinite;
|
||||
box-shadow: 0 0 12px rgba(72, 176, 255, 0.6);
|
||||
border: 2px solid rgba(72, 176, 255, 0.8);
|
||||
}
|
||||
.item-top3 {
|
||||
animation: rotate3 5s ease-in-out infinite;
|
||||
animation-delay: 0.5s;
|
||||
box-shadow: 0 0 12px rgba(72, 176, 255, 0.6);
|
||||
border: 2px solid rgba(72, 176, 255, 0.8);
|
||||
}
|
||||
.item-top4 {
|
||||
animation: rotate4 6s ease-in-out infinite;
|
||||
animation-delay: 1s;
|
||||
box-shadow: 0 0 12px rgba(72, 176, 255, 0.6);
|
||||
border: 2px solid rgba(72, 176, 255, 0.8);
|
||||
}
|
||||
.item-top5 {
|
||||
animation: rotate5 7s ease-in-out infinite;
|
||||
animation-delay: 1.5s;
|
||||
box-shadow: 0 0 12px rgba(72, 176, 255, 0.6);
|
||||
border: 2px solid rgba(72, 176, 255, 0.8);
|
||||
}
|
||||
|
||||
/* 增强中心圆的光效 */
|
||||
@keyframes centerGlow {
|
||||
0%, 100% {
|
||||
box-shadow:
|
||||
0 0 20px rgba(72, 176, 255, 0.8),
|
||||
inset 0 0 25px rgba(72, 176, 255, 0.3);
|
||||
transform: scale(1);
|
||||
}
|
||||
50% {
|
||||
box-shadow:
|
||||
0 0 30px rgba(72, 176, 255, 1),
|
||||
inset 0 0 30px rgba(72, 176, 255, 0.5);
|
||||
transform: scale(1.02);
|
||||
}
|
||||
}
|
||||
|
||||
.circle-center {
|
||||
animation: centerGlow 3s ease-in-out infinite;
|
||||
}
|
||||
|
||||
/* 增强小圆的发光效果 */
|
||||
.circle-item {
|
||||
background: rgba(0, 92, 207, 0.25);
|
||||
border: 2px solid rgba(72, 176, 255, 0.7);
|
||||
|
||||
.rank {
|
||||
color: #66c2ff;
|
||||
text-shadow: 0 0 3px rgba(102, 194, 255, 0.8);
|
||||
}
|
||||
}
|
||||
|
||||
/* 增强悬停效果 */
|
||||
.circle-item:hover {
|
||||
animation-play-state: paused;
|
||||
transform: scale(1.15) !important;
|
||||
z-index: 10;
|
||||
box-shadow: 0 0 20px rgba(72, 176, 255, 1);
|
||||
border: 2px solid rgba(72, 176, 255, 1);
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
/* 为整个内容区域添加一个微妙的背景光晕(无脉动效果) */
|
||||
.app-class .content::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
background: radial-gradient(
|
||||
circle at center,
|
||||
rgba(72, 176, 255, 0.12) 0%,
|
||||
rgba(0, 92, 207, 0.06) 40%,
|
||||
rgba(0, 92, 207, 0.02) 70%,
|
||||
transparent 90%
|
||||
);
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 0;
|
||||
}
|
||||
</style>
|
||||
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/1.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/2.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/3.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/3D.png
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/4.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/5.png
Normal file
|
After Width: | Height: | Size: 1.1 KiB |
BIN
f/web-kboss/src/views/product/bigScreen/Newscreen/images/btm.png
Normal file
|
After Width: | Height: | Size: 150 KiB |
|
After Width: | Height: | Size: 3.1 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 8.7 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 21 KiB |
92
f/web-kboss/src/views/product/bigScreen/Newscreen/index.vue
Normal file
@ -0,0 +1,92 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<div class="top">
|
||||
<ScreenHeader></ScreenHeader>
|
||||
</div>
|
||||
<div class="center">
|
||||
<!-- 左边 -->
|
||||
<div class="left">
|
||||
<ScreenLeft></ScreenLeft>
|
||||
</div>
|
||||
<!-- 中间 -->
|
||||
<div class="content">
|
||||
<ScreenCenter></ScreenCenter>
|
||||
</div>
|
||||
<!-- 右边 -->
|
||||
<div class="right">
|
||||
<ScreenRight></ScreenRight>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div class="bottom">
|
||||
<ScreenFooter></ScreenFooter>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ScreenHeader from './screenHeader/index.vue';
|
||||
import ScreenLeft from './ScreenLeft/index.vue';
|
||||
import ScreenCenter from './ScreenCenter/index.vue';
|
||||
import ScreenRight from './ScreenRight/index.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
ScreenHeader,
|
||||
ScreenLeft,
|
||||
ScreenCenter,
|
||||
ScreenRight
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#app {
|
||||
box-sizing: border-box;
|
||||
height: 100vh;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: url("../../../../assets/image/bg.jpg") no-repeat center ;
|
||||
background-size: cover; // 添加背景大小控制
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.top {
|
||||
width: 100%;
|
||||
height: 85px;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 300px;
|
||||
width: 300px;
|
||||
position: absolute;
|
||||
right: 20px;
|
||||
}
|
||||
.center {
|
||||
display: flex;
|
||||
.left{
|
||||
width: 30%;
|
||||
}
|
||||
.content{
|
||||
width: 40%;
|
||||
}
|
||||
.right{
|
||||
width: 30%;
|
||||
}
|
||||
}
|
||||
.center {
|
||||
height: calc(100% - 80px);
|
||||
}
|
||||
</style>
|
||||
@ -0,0 +1,69 @@
|
||||
<template>
|
||||
<div id="vmheader">
|
||||
|
||||
<h1 style="cursor: pointer" @click="fullScreen">NCmatch算力供需对接平台</h1>
|
||||
<ZpTime class="time"></ZpTime>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZpTime from '../../components/common/ZpTime.vue'
|
||||
|
||||
export default {
|
||||
name: 'vmheader',
|
||||
components: {
|
||||
ZpTime,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async fullScreen() {
|
||||
// 判断是否全屏
|
||||
let full = document.fullscreenElement
|
||||
//进入全屏
|
||||
if (!full) {
|
||||
await document.documentElement.requestFullscreen()
|
||||
// this.$store.commit('setShowScreen', false)
|
||||
// this.$store.commit('setShowScreen', true)
|
||||
} else {
|
||||
//退出全屏
|
||||
await document.exitFullscreen()
|
||||
|
||||
}
|
||||
},
|
||||
goPage(item, index) {
|
||||
this.currentIndex = index
|
||||
this.$router.push(item.path)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped>
|
||||
#vmheader {
|
||||
height: 80px;
|
||||
position: relative;
|
||||
background: url("../../../../../assets/image/head_bg.png") no-repeat top center;
|
||||
background-size: 100% 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
/* 制定背景图像大小 */
|
||||
}
|
||||
|
||||
#vmheader h1 {
|
||||
color: #cfd1ee;
|
||||
font-size: 32px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.time {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 30px
|
||||
}
|
||||
</style>
|
||||
@ -96,7 +96,7 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>1
|
||||
<script>
|
||||
import countTo from 'vue-count-to';
|
||||
import VmCenterTop from './common/VmCenterTop.vue'
|
||||
import VmCenterContainer from './common/VmCenterContainer.vue'
|
||||
@ -483,9 +483,9 @@ export default {
|
||||
background-color: rgba(101, 132, 226, 0.1);
|
||||
padding: 15px;
|
||||
height: 85px;
|
||||
//display: flex;
|
||||
/* //display: flex;
|
||||
//justify-content: center;
|
||||
//align-items: center;
|
||||
//align-items: center; */
|
||||
}
|
||||
|
||||
.tophd {
|
||||
|
||||
@ -362,3 +362,4 @@ export default {
|
||||
height: calc(100vh - 180px);
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -23,9 +23,9 @@ export default {
|
||||
background-color: rgba(101, 132, 226, 0.1);
|
||||
padding: 15px;
|
||||
height: 85px;
|
||||
//display: flex;
|
||||
//justify-content: center;
|
||||
//align-items: center;
|
||||
/* //display: flex; */
|
||||
/* //justify-content: center; */
|
||||
/* //align-items: center; */
|
||||
}
|
||||
|
||||
.tophd {
|
||||
|
||||
@ -61,7 +61,7 @@ li {
|
||||
width: 100vw;
|
||||
background: url("../../../assets/image/bg.jpg") top center;
|
||||
height: 100vh;
|
||||
//overflow-y: auto;
|
||||
/* overflow-y: auto; */
|
||||
}
|
||||
|
||||
#content {
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
<div class="section">
|
||||
<div class="bigTitle">快捷导航</div>
|
||||
<ul class="recUl">
|
||||
<li v-for="(item,index) in navList" :key="index" @click="goBaidu(item)">
|
||||
<li v-for="(item, index) in navList" :key="index" @click="goBaidu(item)">
|
||||
<img :src="getNavIcon(index)" class="nav-icon" alt="icon" />
|
||||
{{ item.name }}
|
||||
</li>
|
||||
@ -25,12 +25,7 @@
|
||||
<div class="section">
|
||||
<div class="bigTitle">到期预警</div>
|
||||
<div class="table-container">
|
||||
<el-table
|
||||
height="250px"
|
||||
border
|
||||
:data="tableData"
|
||||
style="width: 100%"
|
||||
header-cell-class-name="table-header"
|
||||
<el-table height="250px" border :data="tableData" style="width: 100%" header-cell-class-name="table-header"
|
||||
cell-class-name="table-cell">
|
||||
<el-table-column prop="name" label="名称" min-width="120"></el-table-column>
|
||||
<el-table-column prop="instanceid" label="资源id" min-width="120"></el-table-column>
|
||||
@ -91,12 +86,7 @@
|
||||
<div class="todos card">
|
||||
<div class="title">待办事项</div>
|
||||
<ul class="todo-list">
|
||||
<li
|
||||
v-for="(item, index) in todoList"
|
||||
:key="index"
|
||||
class="todo-item"
|
||||
@click="handleTodoClick(item.name)"
|
||||
>
|
||||
<li v-for="(item, index) in todoList" :key="index" class="todo-item" @click="handleTodoClick(item.name)">
|
||||
<span class="todo-name">{{ item.name }}</span>
|
||||
<span class="todo-count">{{ item.count }}</span>
|
||||
</li>
|
||||
@ -104,11 +94,8 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<MessageCenter
|
||||
ref="messageCenter"
|
||||
:visible.sync="messageCenterVisible"
|
||||
@unread-count-update="handleUnreadCountUpdate"
|
||||
/>
|
||||
<MessageCenter ref="messageCenter" :visible.sync="messageCenterVisible"
|
||||
@unread-count-update="handleUnreadCountUpdate" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -146,6 +133,7 @@ export default Vue.extend({
|
||||
{ name: '处理中', count: 0 },
|
||||
{ name: '站内信', count: 0 }
|
||||
],
|
||||
mybalance: 0,
|
||||
messageCenterVisible: false,
|
||||
navIcons: [icon1, icon2, icon3, icon4]
|
||||
}
|
||||
@ -205,9 +193,9 @@ export default Vue.extend({
|
||||
|
||||
async initMybalance() {
|
||||
const res = await editReachargelogAPI()
|
||||
if (res.status==true) {
|
||||
if (res.status == true) {
|
||||
this.mybalance = res.data
|
||||
}else{
|
||||
} else {
|
||||
this.mybalance = res.data
|
||||
}
|
||||
},
|
||||
@ -232,7 +220,7 @@ export default Vue.extend({
|
||||
const res = await todoCount();
|
||||
if (res.status && res.data) {
|
||||
this.todoList = this.todoList.map(item => {
|
||||
switch(item.name) {
|
||||
switch (item.name) {
|
||||
case '待支付':
|
||||
return { ...item, count: res.data.pending_payment_orders || 0 };
|
||||
case '待续费':
|
||||
@ -256,7 +244,7 @@ export default Vue.extend({
|
||||
this.openMessageCenter();
|
||||
} else {
|
||||
let query = {};
|
||||
switch(todoName) {
|
||||
switch (todoName) {
|
||||
case '待支付':
|
||||
query = { filterType: 'processing' };
|
||||
break;
|
||||
@ -389,6 +377,7 @@ export default Vue.extend({
|
||||
|
||||
li {
|
||||
cursor: default;
|
||||
|
||||
&:hover {
|
||||
transform: none;
|
||||
box-shadow: none;
|
||||
@ -501,6 +490,7 @@ export default Vue.extend({
|
||||
.title {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.todo-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
@ -567,7 +557,8 @@ export default Vue.extend({
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.leftBox, .rightBox {
|
||||
.leftBox,
|
||||
.rightBox {
|
||||
width: 100%;
|
||||
flex: none;
|
||||
}
|
||||
|
||||
@ -31,7 +31,7 @@
|
||||
prop="address"
|
||||
min-width="180"
|
||||
label="基础网络">
|
||||
<template scope="scope">
|
||||
<template slot-scope="scope">
|
||||
(内){{ scope.row.IPSet[0].IP }}<br/>
|
||||
(外){{ scope.row.IPSet[1].IP }}
|
||||
</template>
|
||||
|
||||
@ -33,7 +33,6 @@ module.exports = {
|
||||
// lintOnSave: process.env.NODE_ENV === 'development',
|
||||
productionSourceMap: false,
|
||||
devServer: {
|
||||
// public:'www.kaiyuancloud.cn',
|
||||
port: port,
|
||||
open: true,
|
||||
overlay: {
|
||||
@ -41,32 +40,8 @@ module.exports = {
|
||||
errors: true
|
||||
},
|
||||
proxy: {
|
||||
// '/api': {
|
||||
// // 需要访问的地址
|
||||
// target: 'http://47.93.12.75:8891', //true
|
||||
// // target: 'hhttps://www.kaiyuancloud.cn/dev', //false
|
||||
//
|
||||
// // target: 'socks5://127.0.0.1:1086',
|
||||
// // target: 'http://192.168.0.227:8891',
|
||||
//
|
||||
// // target: 'http://59.110.20.133:8891',
|
||||
// // target: 'http://123.56.76.139:8891',
|
||||
// // target: 'https://dev.kaiyuancloud.cn',
|
||||
// // 开启websocket 代理
|
||||
// ws: true,
|
||||
// // 开启代理
|
||||
// changeOrigin: true,
|
||||
// // 路径重写
|
||||
// // 也可以根据实际开发场景,改成其他值 '^/api' : '/其他值' 进行接口请求
|
||||
// pathRewrite: {
|
||||
// '^/api': ''
|
||||
// }
|
||||
// },
|
||||
'/api': {
|
||||
// target: 'http://47.93.12.75:8891',
|
||||
target: 'https://dev.opencomputing.cn',
|
||||
|
||||
// target: 'https://www.kaiyuancloud.cn',
|
||||
ws: true,
|
||||
changeOrigin: true,
|
||||
pathRewrite: {
|
||||
@ -93,7 +68,11 @@ module.exports = {
|
||||
name: name,
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve('src')
|
||||
'@': resolve('src'),
|
||||
// 解决 echarts 地图路径问题 - 添加这3个别名
|
||||
'echarts/map/js/china.js': resolve('node_modules/echarts/map/json/china.json'),
|
||||
'echarts/china.json': resolve('node_modules/echarts/map/json/china.json'),
|
||||
'echarts/map/json/china.json': resolve('node_modules/echarts/map/json/china.json')
|
||||
}
|
||||
},
|
||||
// 生产环境去除console和debugger
|
||||
@ -124,7 +103,6 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
chainWebpack(config) {
|
||||
// it can improve the speed of the first screen, it is recommended to turn on preload
|
||||
// it can improve the speed of the first screen, it is recommended to turn on preload
|
||||
config.plugin('preload').tap(() => [
|
||||
{
|
||||
@ -156,6 +134,11 @@ module.exports = {
|
||||
})
|
||||
.end()
|
||||
|
||||
// 添加别名配置
|
||||
config.resolve.alias
|
||||
.set('echarts/map/js/china.js', resolve('node_modules/echarts/map/json/china.json'))
|
||||
.set('echarts/china.json', resolve('node_modules/echarts/map/json/china.json'))
|
||||
|
||||
// 生产环境配置
|
||||
config
|
||||
.when(process.env.NODE_ENV !== 'development',
|
||||
|
||||