updata
@ -18,6 +18,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@form-create/element-ui": "^2.5.30",
|
"@form-create/element-ui": "^2.5.30",
|
||||||
|
"@jiaminghi/data-view": "^2.10.0",
|
||||||
"@xterm/xterm": "^5.5.0",
|
"@xterm/xterm": "^5.5.0",
|
||||||
"amfe-flexible": "^2.2.1",
|
"amfe-flexible": "^2.2.1",
|
||||||
"axios": "0.18.1",
|
"axios": "0.18.1",
|
||||||
@ -29,7 +30,8 @@
|
|||||||
"decimal.js": "^10.4.3",
|
"decimal.js": "^10.4.3",
|
||||||
"driver.js": "0.9.5",
|
"driver.js": "0.9.5",
|
||||||
"dropzone": "5.5.1",
|
"dropzone": "5.5.1",
|
||||||
"echarts": "4.2.1",
|
"echarts": "^4.9.0",
|
||||||
|
"echarts-gl": "^1.1.2",
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"file-saver": "^2.0.1",
|
"file-saver": "^2.0.1",
|
||||||
"fuse.js": "3.4.4",
|
"fuse.js": "3.4.4",
|
||||||
@ -75,7 +77,7 @@
|
|||||||
"autoprefixer": "9.5.1",
|
"autoprefixer": "9.5.1",
|
||||||
"babel-eslint": "10.1.0",
|
"babel-eslint": "10.1.0",
|
||||||
"babel-jest": "23.6.0",
|
"babel-jest": "23.6.0",
|
||||||
"babel-loader": "^9.1.3",
|
"babel-loader": "^8.2.5",
|
||||||
"babel-plugin-dynamic-import-node": "2.3.3",
|
"babel-plugin-dynamic-import-node": "2.3.3",
|
||||||
"bpmn-js": "^13.2.2",
|
"bpmn-js": "^13.2.2",
|
||||||
"chalk": "2.4.2",
|
"chalk": "2.4.2",
|
||||||
|
|||||||
@ -509,7 +509,7 @@ export default {
|
|||||||
this.searchDialogVisible = true
|
this.searchDialogVisible = true
|
||||||
},
|
},
|
||||||
goScreen() {
|
goScreen() {
|
||||||
window.open('https://www.kaiyuancloud.cn/dev/#/screen/k8sRescource', '_blank');
|
window.open('https://www.opencomputing.cn/#/screen/k8sRescource', '_blank');
|
||||||
},
|
},
|
||||||
channelFirstBtn() {
|
channelFirstBtn() {
|
||||||
reqApplyChannel({ user_id: this.userId }).then(res => {
|
reqApplyChannel({ user_id: this.userId }).then(res => {
|
||||||
|
|||||||
@ -64,9 +64,14 @@ sessionStorage.setItem('client_uuid', uuidv4())
|
|||||||
|
|
||||||
// 引入form-create 表单生成器
|
// 引入form-create 表单生成器
|
||||||
import formCreate from "@form-create/element-ui"
|
import formCreate from "@form-create/element-ui"
|
||||||
|
|
||||||
Vue.use(formCreate);
|
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 * as filters from './filters' // global filters
|
||||||
|
|
||||||
import HappyScroll from 'vue-happy-scroll'
|
import HappyScroll from 'vue-happy-scroll'
|
||||||
|
|||||||
@ -181,7 +181,7 @@ export const constantRoutes = [
|
|||||||
{
|
{
|
||||||
hidden: true, path: '/screen', name: 'screen', title: '可视化大屏', meta: {
|
hidden: true, path: '/screen', name: 'screen', title: '可视化大屏', meta: {
|
||||||
title: "可视化大屏", fullPath: "/operation/analyze/screen",
|
title: "可视化大屏", fullPath: "/operation/analyze/screen",
|
||||||
}, component: () => import('@/views/product/bigScreen/index.vue'), children: [{
|
}, component: () => import('@/views/product/bigScreen/Newscreen/index.vue'), children: [{
|
||||||
path: "index",
|
path: "index",
|
||||||
title: '可视化首页',
|
title: '可视化首页',
|
||||||
component: () => import('@/views/product/bigScreen/mainPage/index.vue'),
|
component: () => import('@/views/product/bigScreen/mainPage/index.vue'),
|
||||||
|
|||||||
@ -264,7 +264,7 @@ const actions = {
|
|||||||
// 如果权限列表包含空路径,认为用户有所有权限
|
// 如果权限列表包含空路径,认为用户有所有权限
|
||||||
accessedRoutes = asyncRoutes || [];
|
accessedRoutes = asyncRoutes || [];
|
||||||
} else {
|
} else {
|
||||||
// 使用修复后的过滤函数,传入用户角色和设备类型
|
// 传入用户角色和设备类型
|
||||||
accessedRoutes = filterAsyncRoutes(asyncRoutes, auths, userRoles, deviceType);
|
accessedRoutes = filterAsyncRoutes(asyncRoutes, auths, userRoles, deviceType);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -272,7 +272,7 @@ const actions = {
|
|||||||
accessedRoutes = [];
|
accessedRoutes = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新增:为普通用户添加订单管理和资源管理路由以及新的五个客户菜单
|
// 为普通用户添加订单管理和资源管理路由以及新的五个客户菜单
|
||||||
console.log("为用户添加特定路由");
|
console.log("为用户添加特定路由");
|
||||||
const userSpecificRoutes = addUserRoutes(asyncRoutes, userType, orgType, userRoles, deviceType);
|
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>
|
||||||
@ -77,7 +77,7 @@
|
|||||||
</span>
|
</span>
|
||||||
<svg @click="copyBtn" class="copy-btn" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"
|
<svg @click="copyBtn" class="copy-btn" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"
|
||||||
width="12" height="12" style="fill: #1019ab;">
|
width="12" height="12" style="fill: #1019ab;">
|
||||||
<path
|
<path
|
||||||
d="M394.666667 106.666667h448a74.666667 74.666667 0 0 1 74.666666 74.666666v448a74.666667 74.666667 0 0 1-74.666666 74.666667H394.666667a74.666667 74.666667 0 0 1-74.666667-74.666667V181.333333a74.666667 74.666667 0 0 1 74.666667-74.666666z m0 64a10.666667 10.666667 0 0 0-10.666667 10.666666v448a10.666667 10.666667 0 0 0 10.666667 10.666667h448a10.666667 10.666667 0 0 0 10.666666-10.666667V181.333333a10.666667 10.666667 0 0 0-10.666666-10.666666H394.666667z m245.333333 597.333333a32 32 0 0 1 64 0v74.666667a74.666667 74.666667 0 0 1-74.666667 74.666666H181.333333a74.666667 74.666667 0 0 1-74.666666-74.666666V394.666667a74.666667 74.666667 0 0 1 74.666666-74.666667h74.666667a32 32 0 0 1 0 64h-74.666667a10.666667 10.666667 0 0 0-10.666666 10.666667v448a10.666667 10.666667 0 0 0 10.666666 10.666666h448a10.666667 10.666667 0 0 0 10.666667-10.666666v-74.666667z"
|
d="M394.666667 106.666667h448a74.666667 74.666667 0 0 1 74.666666 74.666666v448a74.666667 74.666667 0 0 1-74.666666 74.666667H394.666667a74.666667 74.666667 0 0 1-74.666667-74.666667V181.333333a74.666667 74.666667 0 0 1 74.666667-74.666666z m0 64a10.666667 10.666667 0 0 0-10.666667 10.666666v448a10.666667 10.666667 0 0 0 10.666667 10.666667h448a10.666667 10.666667 0 0 0 10.666666-10.666667V181.333333a10.666667 10.666667 0 0 0-10.666666-10.666666H394.666667z m245.333333 597.333333a32 32 0 0 1 64 0v74.666667a74.666667 74.666667 0 0 1-74.666667 74.666666H181.333333a74.666667 74.666667 0 0 1-74.666666-74.666666V394.666667a74.666667 74.666667 0 0 1 74.666666-74.666667h74.666667a32 32 0 0 1 0 64h-74.666667a10.666667 10.666667 0 0 0-10.666666 10.666667v448a10.666667 10.666667 0 0 0 10.666666 10.666666h448a10.666667 10.666667 0 0 0 10.666667-10.666666v-74.666667z"
|
||||||
p-id="1521"></path>
|
p-id="1521"></path>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
@ -7,7 +7,6 @@
|
|||||||
|
|
||||||
<!-- 页面顶部的横幅图片 -->
|
<!-- 页面顶部的横幅图片 -->
|
||||||
<!-- <img src="" alt=""> -->
|
<!-- <img src="" alt=""> -->
|
||||||
|
|
||||||
<div class="conter">
|
<div class="conter">
|
||||||
<div class="left">
|
<div class="left">
|
||||||
<p class="title">
|
<p class="title">
|
||||||
@ -104,8 +103,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 获取验证码按钮 - 添加防抖功能 -->
|
<!-- 获取验证码按钮 - 添加防抖功能 -->
|
||||||
<span :disabled="isDisabled || isGettingCode" class="getCodeStyleNew" style="height:40px;margin-left:10px"
|
<span :disabled="isDisabled || isGettingCode" class="getCodeStyleNew"
|
||||||
@click="debouncedGetCode">
|
style="height:40px;margin-left:10px" @click="debouncedGetCode">
|
||||||
{{ SendCode_text }}
|
{{ SendCode_text }}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@ -373,7 +372,7 @@ export default {
|
|||||||
methods: {
|
methods: {
|
||||||
// 防抖函数
|
// 防抖函数
|
||||||
debounce(func, wait) {
|
debounce(func, wait) {
|
||||||
return function() {
|
return function () {
|
||||||
const context = this;
|
const context = this;
|
||||||
const args = arguments;
|
const args = arguments;
|
||||||
clearTimeout(this.debounceTimer);
|
clearTimeout(this.debounceTimer);
|
||||||
@ -384,7 +383,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 防抖后的获取验证码方法
|
// 防抖后的获取验证码方法
|
||||||
debouncedGetCode: function() {
|
debouncedGetCode: function () {
|
||||||
if (this.isDisabled || this.isGettingCode) return;
|
if (this.isDisabled || this.isGettingCode) return;
|
||||||
|
|
||||||
this.isGettingCode = true;
|
this.isGettingCode = true;
|
||||||
@ -400,7 +399,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
// 防抖后的获取重置密码验证码方法
|
// 防抖后的获取重置密码验证码方法
|
||||||
debouncedGetCode1: function() {
|
debouncedGetCode1: function () {
|
||||||
if (this.isDisabled1 || this.isGettingCode1) return;
|
if (this.isDisabled1 || this.isGettingCode1) return;
|
||||||
|
|
||||||
this.isGettingCode1 = true;
|
this.isGettingCode1 = true;
|
||||||
@ -459,8 +458,7 @@ export default {
|
|||||||
// 轮询获取微信登录授权码
|
// 轮询获取微信登录授权码
|
||||||
pollWxCode() {
|
pollWxCode() {
|
||||||
this.getCodeTimer = setInterval(async () => {
|
this.getCodeTimer = setInterval(async () => {
|
||||||
try {
|
try {x // 请求微信授权码x
|
||||||
// 请求微信授权码
|
|
||||||
const res = await reqGetCodeAPI({ state: this.wxState });
|
const res = await reqGetCodeAPI({ state: this.wxState });
|
||||||
if (!res.status) return;
|
if (!res.status) return;
|
||||||
|
|
||||||
@ -915,7 +913,7 @@ export default {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.$router.push(getHomePath());
|
this.$router.push(getHomePath());
|
||||||
}``
|
} ``
|
||||||
} else if (res.roles.includes('运营')) {
|
} else if (res.roles.includes('运营')) {
|
||||||
this.$router.push('/operation/supplierManagement');
|
this.$router.push('/operation/supplierManagement');
|
||||||
} else if (res.roles.includes('销售')) {
|
} 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>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>1
|
<script>
|
||||||
import countTo from 'vue-count-to';
|
import countTo from 'vue-count-to';
|
||||||
import VmCenterTop from './common/VmCenterTop.vue'
|
import VmCenterTop from './common/VmCenterTop.vue'
|
||||||
import VmCenterContainer from './common/VmCenterContainer.vue'
|
import VmCenterContainer from './common/VmCenterContainer.vue'
|
||||||
@ -483,9 +483,9 @@ export default {
|
|||||||
background-color: rgba(101, 132, 226, 0.1);
|
background-color: rgba(101, 132, 226, 0.1);
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 85px;
|
height: 85px;
|
||||||
//display: flex;
|
/* //display: flex;
|
||||||
//justify-content: center;
|
//justify-content: center;
|
||||||
//align-items: center;
|
//align-items: center; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.tophd {
|
.tophd {
|
||||||
|
|||||||
@ -362,3 +362,4 @@ export default {
|
|||||||
height: calc(100vh - 180px);
|
height: calc(100vh - 180px);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
@ -23,9 +23,9 @@ export default {
|
|||||||
background-color: rgba(101, 132, 226, 0.1);
|
background-color: rgba(101, 132, 226, 0.1);
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
height: 85px;
|
height: 85px;
|
||||||
//display: flex;
|
/* //display: flex; */
|
||||||
//justify-content: center;
|
/* //justify-content: center; */
|
||||||
//align-items: center;
|
/* //align-items: center; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.tophd {
|
.tophd {
|
||||||
|
|||||||
@ -61,7 +61,7 @@ li {
|
|||||||
width: 100vw;
|
width: 100vw;
|
||||||
background: url("../../../assets/image/bg.jpg") top center;
|
background: url("../../../assets/image/bg.jpg") top center;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
//overflow-y: auto;
|
/* overflow-y: auto; */
|
||||||
}
|
}
|
||||||
|
|
||||||
#content {
|
#content {
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="bigTitle">快捷导航</div>
|
<div class="bigTitle">快捷导航</div>
|
||||||
<ul class="recUl">
|
<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" />
|
<img :src="getNavIcon(index)" class="nav-icon" alt="icon" />
|
||||||
{{ item.name }}
|
{{ item.name }}
|
||||||
</li>
|
</li>
|
||||||
@ -25,12 +25,7 @@
|
|||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="bigTitle">到期预警</div>
|
<div class="bigTitle">到期预警</div>
|
||||||
<div class="table-container">
|
<div class="table-container">
|
||||||
<el-table
|
<el-table height="250px" border :data="tableData" style="width: 100%" header-cell-class-name="table-header"
|
||||||
height="250px"
|
|
||||||
border
|
|
||||||
:data="tableData"
|
|
||||||
style="width: 100%"
|
|
||||||
header-cell-class-name="table-header"
|
|
||||||
cell-class-name="table-cell">
|
cell-class-name="table-cell">
|
||||||
<el-table-column prop="name" label="名称" min-width="120"></el-table-column>
|
<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>
|
<el-table-column prop="instanceid" label="资源id" min-width="120"></el-table-column>
|
||||||
@ -91,12 +86,7 @@
|
|||||||
<div class="todos card">
|
<div class="todos card">
|
||||||
<div class="title">待办事项</div>
|
<div class="title">待办事项</div>
|
||||||
<ul class="todo-list">
|
<ul class="todo-list">
|
||||||
<li
|
<li v-for="(item, index) in todoList" :key="index" class="todo-item" @click="handleTodoClick(item.name)">
|
||||||
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-name">{{ item.name }}</span>
|
||||||
<span class="todo-count">{{ item.count }}</span>
|
<span class="todo-count">{{ item.count }}</span>
|
||||||
</li>
|
</li>
|
||||||
@ -104,11 +94,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<MessageCenter
|
<MessageCenter ref="messageCenter" :visible.sync="messageCenterVisible"
|
||||||
ref="messageCenter"
|
@unread-count-update="handleUnreadCountUpdate" />
|
||||||
:visible.sync="messageCenterVisible"
|
|
||||||
@unread-count-update="handleUnreadCountUpdate"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -146,6 +133,7 @@ export default Vue.extend({
|
|||||||
{ name: '处理中', count: 0 },
|
{ name: '处理中', count: 0 },
|
||||||
{ name: '站内信', count: 0 }
|
{ name: '站内信', count: 0 }
|
||||||
],
|
],
|
||||||
|
mybalance: 0,
|
||||||
messageCenterVisible: false,
|
messageCenterVisible: false,
|
||||||
navIcons: [icon1, icon2, icon3, icon4]
|
navIcons: [icon1, icon2, icon3, icon4]
|
||||||
}
|
}
|
||||||
@ -205,9 +193,9 @@ export default Vue.extend({
|
|||||||
|
|
||||||
async initMybalance() {
|
async initMybalance() {
|
||||||
const res = await editReachargelogAPI()
|
const res = await editReachargelogAPI()
|
||||||
if (res.status==true) {
|
if (res.status == true) {
|
||||||
this.mybalance = res.data
|
this.mybalance = res.data
|
||||||
}else{
|
} else {
|
||||||
this.mybalance = res.data
|
this.mybalance = res.data
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -232,7 +220,7 @@ export default Vue.extend({
|
|||||||
const res = await todoCount();
|
const res = await todoCount();
|
||||||
if (res.status && res.data) {
|
if (res.status && res.data) {
|
||||||
this.todoList = this.todoList.map(item => {
|
this.todoList = this.todoList.map(item => {
|
||||||
switch(item.name) {
|
switch (item.name) {
|
||||||
case '待支付':
|
case '待支付':
|
||||||
return { ...item, count: res.data.pending_payment_orders || 0 };
|
return { ...item, count: res.data.pending_payment_orders || 0 };
|
||||||
case '待续费':
|
case '待续费':
|
||||||
@ -256,7 +244,7 @@ export default Vue.extend({
|
|||||||
this.openMessageCenter();
|
this.openMessageCenter();
|
||||||
} else {
|
} else {
|
||||||
let query = {};
|
let query = {};
|
||||||
switch(todoName) {
|
switch (todoName) {
|
||||||
case '待支付':
|
case '待支付':
|
||||||
query = { filterType: 'processing' };
|
query = { filterType: 'processing' };
|
||||||
break;
|
break;
|
||||||
@ -389,6 +377,7 @@ export default Vue.extend({
|
|||||||
|
|
||||||
li {
|
li {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: none;
|
transform: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
@ -501,6 +490,7 @@ export default Vue.extend({
|
|||||||
.title {
|
.title {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.todo-list {
|
.todo-list {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
@ -567,7 +557,8 @@ export default Vue.extend({
|
|||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.leftBox, .rightBox {
|
.leftBox,
|
||||||
|
.rightBox {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
flex: none;
|
flex: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
prop="address"
|
prop="address"
|
||||||
min-width="180"
|
min-width="180"
|
||||||
label="基础网络">
|
label="基础网络">
|
||||||
<template scope="scope">
|
<template slot-scope="scope">
|
||||||
(内){{ scope.row.IPSet[0].IP }}<br/>
|
(内){{ scope.row.IPSet[0].IP }}<br/>
|
||||||
(外){{ scope.row.IPSet[1].IP }}
|
(外){{ scope.row.IPSet[1].IP }}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -33,7 +33,6 @@ module.exports = {
|
|||||||
// lintOnSave: process.env.NODE_ENV === 'development',
|
// lintOnSave: process.env.NODE_ENV === 'development',
|
||||||
productionSourceMap: false,
|
productionSourceMap: false,
|
||||||
devServer: {
|
devServer: {
|
||||||
// public:'www.kaiyuancloud.cn',
|
|
||||||
port: port,
|
port: port,
|
||||||
open: true,
|
open: true,
|
||||||
overlay: {
|
overlay: {
|
||||||
@ -41,32 +40,8 @@ module.exports = {
|
|||||||
errors: true
|
errors: true
|
||||||
},
|
},
|
||||||
proxy: {
|
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': {
|
'/api': {
|
||||||
// target: 'http://47.93.12.75:8891',
|
|
||||||
target: 'https://dev.opencomputing.cn',
|
target: 'https://dev.opencomputing.cn',
|
||||||
|
|
||||||
// target: 'https://www.kaiyuancloud.cn',
|
|
||||||
ws: true,
|
ws: true,
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
pathRewrite: {
|
pathRewrite: {
|
||||||
@ -93,7 +68,11 @@ module.exports = {
|
|||||||
name: name,
|
name: name,
|
||||||
resolve: {
|
resolve: {
|
||||||
alias: {
|
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
|
// 生产环境去除console和debugger
|
||||||
@ -124,7 +103,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
chainWebpack(config) {
|
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
|
// it can improve the speed of the first screen, it is recommended to turn on preload
|
||||||
config.plugin('preload').tap(() => [
|
config.plugin('preload').tap(() => [
|
||||||
{
|
{
|
||||||
@ -156,6 +134,11 @@ module.exports = {
|
|||||||
})
|
})
|
||||||
.end()
|
.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
|
config
|
||||||
.when(process.env.NODE_ENV !== 'development',
|
.when(process.env.NODE_ENV !== 'development',
|
||||||
|
|||||||