devicesmgt/sgzb-screen/src/components/home/rightOne.vue

528 lines
14 KiB
Vue
Raw Normal View History

2023-12-16 18:10:04 +08:00
<template>
<div class="access-rate-page">
<div class="access-rate-box">
<div class="access-rate-box-title-bg">
<h5 class="access-rate-box-title">当月领料分析</h5>
</div>
<div class="chart-container">
2024-08-26 20:53:34 +08:00
<div
class="chart"
ref="chart"
id="pieChartMap"
@click="handleClick"
></div>
2023-12-16 18:10:04 +08:00
<!-- 底座背景 -->
<div class="bg"></div>
</div>
</div>
2024-08-26 20:53:34 +08:00
<materialAnalysisDialog
ref="materialAnalysisDialog"
></materialAnalysisDialog>
2023-12-16 18:10:04 +08:00
</div>
</template>
<script>
// import Highcharts from "highcharts/highstock";
// import HighchartsMore from "highcharts/highcharts-more";
// import HighchartsDrilldown from "highcharts/modules/drilldown";
// import Highcharts3D from "highcharts/highcharts-3d";
// HighchartsMore(Highcharts);
// HighchartsDrilldown(Highcharts);
// Highcharts3D(Highcharts);
2024-08-26 20:53:34 +08:00
import * as echarts from 'echarts'
2023-12-16 18:10:04 +08:00
import 'echarts-gl' // 3d图表库
2024-08-26 20:53:34 +08:00
import { getPickingAnalysisByMonthApi } from '../../api/screen'
import materialAnalysisDialog from './materialAnalysisDialog'
2024-04-25 09:26:22 +08:00
2023-12-16 18:10:04 +08:00
export default {
2024-04-25 09:26:22 +08:00
components: {
2024-08-26 20:53:34 +08:00
materialAnalysisDialog,
2024-04-25 09:26:22 +08:00
},
2023-12-16 18:10:04 +08:00
data() {
return {
data: [],
2024-08-26 20:53:34 +08:00
maType: '',
}
2023-12-16 18:10:04 +08:00
},
mounted() {
this.$eventBus.$on('maType', (maType) => {
this.maType = maType
this.getPickingAnalysisByMonthApiPage()
2024-08-26 20:53:34 +08:00
})
2023-12-16 18:10:04 +08:00
setInterval(() => {
this.getPickingAnalysisByMonthApiPage()
2024-08-26 20:53:34 +08:00
}, 60 * 1000)
2023-12-16 18:10:04 +08:00
},
destroyed() {
2024-08-26 20:53:34 +08:00
this.$eventBus.$off('maType')
2023-12-16 18:10:04 +08:00
},
methods: {
getPickingAnalysisByMonthApiPage() {
this.data = []
let params = {
2024-08-26 20:53:34 +08:00
maType: this.maType,
2023-12-16 18:10:04 +08:00
}
2024-08-26 20:53:34 +08:00
getPickingAnalysisByMonthApi(params).then((res) => {
2023-12-16 18:10:04 +08:00
if (res.code == 200) {
2024-08-26 20:53:34 +08:00
this.data.push(
{
name: '数量领料',
value: res.data.num,
rate: res.data.rate,
itemStyle: {
color: '#01F4F5',
},
2023-12-16 18:10:04 +08:00
},
{
2024-08-26 20:53:34 +08:00
name: '编码领料',
value: res.data.num2,
2023-12-16 18:10:04 +08:00
rate: res.data.rate2,
itemStyle: {
color: '#077E98',
},
2024-08-26 20:53:34 +08:00
}
)
this.mastery(this.data)
2023-12-16 18:10:04 +08:00
}
})
},
// 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
2024-08-26 20:53:34 +08:00
getParametricEquation(
startRatio,
endRatio,
isSelected,
isHovered,
k,
height
) {
2023-12-16 18:10:04 +08:00
// 计算
2024-08-26 20:53:34 +08:00
let midRatio = (startRatio + endRatio) / 2
2023-12-16 18:10:04 +08:00
2024-08-26 20:53:34 +08:00
let startRadian = startRatio * Math.PI * 2
let endRadian = endRatio * Math.PI * 2
let midRadian = midRatio * Math.PI * 2
2023-12-16 18:10:04 +08:00
// 如果只有一个扇形,则不实现选中效果。
if (startRatio === 0 && endRatio === 1) {
2024-08-26 20:53:34 +08:00
isSelected = false
2023-12-16 18:10:04 +08:00
}
// 通过扇形内径/外径的值,换算出辅助参数 k默认值 1/3
2024-08-26 20:53:34 +08:00
k = typeof k !== 'undefined' ? k : 1 / 3
2023-12-16 18:10:04 +08:00
// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0
2024-08-26 20:53:34 +08:00
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0
2023-12-16 18:10:04 +08:00
// 计算高亮效果的放大比例(未高亮,则比例为 1
2024-08-26 20:53:34 +08:00
let hoverRate = isHovered ? 1.05 : 1
2023-12-16 18:10:04 +08:00
// 返回曲面参数方程
return {
u: {
min: -Math.PI,
max: Math.PI * 3,
2024-08-26 20:53:34 +08:00
step: Math.PI / 32,
2023-12-16 18:10:04 +08:00
},
v: {
min: 0,
max: Math.PI * 2,
2024-08-26 20:53:34 +08:00
step: Math.PI / 20,
2023-12-16 18:10:04 +08:00
},
x: function (u, v) {
if (u < startRadian) {
2024-08-26 20:53:34 +08:00
return (
offsetX +
Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
)
2023-12-16 18:10:04 +08:00
}
if (u > endRadian) {
2024-08-26 20:53:34 +08:00
return (
offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
)
2023-12-16 18:10:04 +08:00
}
2024-08-26 20:53:34 +08:00
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
2023-12-16 18:10:04 +08:00
},
y: function (u, v) {
if (u < startRadian) {
2024-08-26 20:53:34 +08:00
return (
offsetY +
Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
)
2023-12-16 18:10:04 +08:00
}
if (u > endRadian) {
2024-08-26 20:53:34 +08:00
return (
offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
)
2023-12-16 18:10:04 +08:00
}
2024-08-26 20:53:34 +08:00
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
2023-12-16 18:10:04 +08:00
},
z: function (u, v) {
2024-08-26 20:53:34 +08:00
if (u < -Math.PI * 0.5) {
return Math.sin(u)
2023-12-16 18:10:04 +08:00
}
if (u > Math.PI * 2.5) {
2024-08-26 20:53:34 +08:00
return Math.sin(u)
2023-12-16 18:10:04 +08:00
}
2024-08-26 20:53:34 +08:00
return Math.sin(v) > 0 ? 1 * height : -1
},
}
2023-12-16 18:10:04 +08:00
},
// 生成模拟 3D 饼图的配置项
getPie3D(pieData, internalDiameterRatio) {
2024-08-26 20:53:34 +08:00
let series = []
let sumValue = 0
let startValue = 0
let endValue = 0
let legendData = []
let k =
typeof internalDiameterRatio !== 'undefined'
? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
: 1 / 3
2023-12-16 18:10:04 +08:00
// 为每一个饼图数据,生成一个 series-surface 配置
for (let i = 0; i < pieData.length; i++) {
2024-08-26 20:53:34 +08:00
sumValue += pieData[i].value
2023-12-16 18:10:04 +08:00
let seriesItem = {
2024-08-26 20:53:34 +08:00
name:
typeof pieData[i].name === 'undefined'
? `series${i}`
: pieData[i].name,
2023-12-16 18:10:04 +08:00
type: 'surface',
parametric: true,
wireframe: {
2024-08-26 20:53:34 +08:00
show: false,
2023-12-16 18:10:04 +08:00
},
pieData: pieData[i],
pieStatus: {
selected: false,
hovered: false,
2024-08-26 20:53:34 +08:00
k: k,
},
}
2023-12-16 18:10:04 +08:00
if (typeof pieData[i].itemStyle != 'undefined') {
2024-08-26 20:53:34 +08:00
let itemStyle = {}
typeof pieData[i].itemStyle.color != 'undefined'
? (itemStyle.color = pieData[i].itemStyle.color)
: null
typeof pieData[i].itemStyle.opacity != 'undefined'
? (itemStyle.opacity = pieData[i].itemStyle.opacity)
: null
2023-12-16 18:10:04 +08:00
2024-08-26 20:53:34 +08:00
seriesItem.itemStyle = itemStyle
2023-12-16 18:10:04 +08:00
}
2024-08-26 20:53:34 +08:00
series.push(seriesItem)
2023-12-16 18:10:04 +08:00
}
for (let i = 0; i < series.length; i++) {
2024-08-26 20:53:34 +08:00
endValue = startValue + series[i].pieData.value
console.log(series[i])
series[i].pieData.startRatio = startValue / sumValue
series[i].pieData.endRatio = endValue / sumValue
series[i].parametricEquation = this.getParametricEquation(
series[i].pieData.startRatio,
series[i].pieData.endRatio,
false,
false,
k,
series[i].pieData.value
)
startValue = endValue
legendData.push(series[i].name)
2023-12-16 18:10:04 +08:00
}
// // 补充一个透明的圆环,用于支撑高亮功能的近似实现。
series.push({
name: 'mouseoutSeries',
type: 'surface',
parametric: true,
wireframe: {
show: false,
},
itemStyle: {
opacity: 0.1,
color: '#E1E8EC',
},
parametricEquation: {
u: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
v: {
min: 0,
max: Math.PI,
step: Math.PI / 20,
},
x: function (u, v) {
2024-08-26 20:53:34 +08:00
return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2
2023-12-16 18:10:04 +08:00
},
y: function (u, v) {
2024-08-26 20:53:34 +08:00
return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2
2023-12-16 18:10:04 +08:00
},
z: function (u, v) {
2024-08-26 20:53:34 +08:00
return Math.cos(v) > 0 ? -0.5 : -5
2023-12-16 18:10:04 +08:00
},
},
2024-08-26 20:53:34 +08:00
})
2023-12-16 18:10:04 +08:00
// // 补充一个透明的圆环,用于支撑高亮功能的近似实现。
series.push({
name: 'mouseoutSeries',
type: 'surface',
parametric: true,
wireframe: {
show: false,
},
itemStyle: {
opacity: 0.1,
color: '#E1E8EC',
},
parametricEquation: {
u: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
v: {
min: 0,
max: Math.PI,
step: Math.PI / 20,
},
x: function (u, v) {
2024-08-26 20:53:34 +08:00
return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2
2023-12-16 18:10:04 +08:00
},
y: function (u, v) {
2024-08-26 20:53:34 +08:00
return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2
2023-12-16 18:10:04 +08:00
},
z: function (u, v) {
2024-08-26 20:53:34 +08:00
return Math.cos(v) > 0 ? -5 : -7
2023-12-16 18:10:04 +08:00
},
},
2024-08-26 20:53:34 +08:00
})
2023-12-16 18:10:04 +08:00
series.push({
name: 'mouseoutSeries',
type: 'surface',
parametric: true,
wireframe: {
show: false,
},
itemStyle: {
opacity: 0.1,
color: '#E1E8EC',
},
parametricEquation: {
u: {
min: 0,
max: Math.PI * 2,
step: Math.PI / 20,
},
v: {
min: 0,
max: Math.PI,
step: Math.PI / 20,
},
x: function (u, v) {
2024-08-26 20:53:34 +08:00
return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2.2
2023-12-16 18:10:04 +08:00
},
y: function (u, v) {
2024-08-26 20:53:34 +08:00
return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2.2
2023-12-16 18:10:04 +08:00
},
z: function (u, v) {
2024-08-26 20:53:34 +08:00
return Math.cos(v) > 0 ? -7 : -7
2023-12-16 18:10:04 +08:00
},
},
2024-08-26 20:53:34 +08:00
})
return series
2023-12-16 18:10:04 +08:00
},
mastery(data) {
2024-08-26 20:53:34 +08:00
var myChart = echarts.init(document.querySelector('#pieChartMap'))
2023-12-16 18:10:04 +08:00
// const optionsData = [
// {
// name: '数量领料',
// value: 76,
// itemStyle: {
// color: '#01F4F5',
// },
// },
// {
// name: '编码领料',
// value: 24,
// itemStyle: {
// color: '#077E98',
// },
// },
// ];
2024-08-26 20:53:34 +08:00
const series = this.getPie3D(this.data, 0.8, 360, 18, 56, 1)
2023-12-16 18:10:04 +08:00
series.push({
type: 'pie',
label: {
opacity: 1,
fontSize: 14,
lineHeight: 15,
textStyle: {
fontSize: 14,
},
},
labelLine: {
2023-12-25 13:25:16 +08:00
length: 10,
length2: 30,
2023-12-16 18:10:04 +08:00
},
startAngle: 40, //起始角度,支持范围[0, 360]。
clockwise: false, //饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
2023-12-25 13:25:16 +08:00
radius: ['12%', '62%'],
2023-12-16 18:10:04 +08:00
center: ['50%', '50%'],
data: this.data,
itemStyle: {
opacity: 0,
},
2024-08-26 20:53:34 +08:00
})
2023-12-16 18:10:04 +08:00
let option = {
legend: {
show: false,
tooltip: {
show: true,
},
},
animation: true,
title: {
x: 'center',
top: '20',
textStyle: {
color: '#fff',
fontSize: 14,
},
},
backgroundColor: '#333',
labelLine: {
show: true,
lineStyle: {
color: '#7BC0CB',
},
},
label: {
show: true,
position: 'inside',
2024-08-26 20:53:34 +08:00
formatter: (params) => {
2023-12-16 18:10:04 +08:00
return `${params.percent}%\n${params.name}`
},
borderWidth: 0,
padding: [0, -50],
height: 70,
fontSize: 14,
2024-08-26 20:53:34 +08:00
align: 'center',
color: '#ffffff',
2023-12-16 18:10:04 +08:00
rich: {
hr: {
backgroundColor: '#fff',
borderRadius: 3,
width: 3,
height: 3,
2024-08-26 20:53:34 +08:00
padding: [3, 3, 0, -12],
2023-12-16 18:10:04 +08:00
},
2024-08-26 20:53:34 +08:00
},
2023-12-16 18:10:04 +08:00
// rich: {
// b: {
// fontSize: 14,
// lineHeight: 20,
// color: "#ffffff",
// },
// c: {
// fontSize: 14,
// lineHeight: 25,
// color: "#ffffff",
// },
// },
},
xAxis3D: {
min: -1,
max: 1,
},
yAxis3D: {
min: -1,
max: 1,
},
zAxis3D: {
min: -1,
max: 1,
},
grid3D: {
show: false,
boxHeight: 0.2,
top: '-15%',
environment: '#010B3F',
viewControl: {
distance: 150,
alpha: 20,
beta: 0,
autoRotate: false, // 自动旋转
},
},
series: series,
2024-08-26 20:53:34 +08:00
}
if (option && typeof option === 'object') {
myChart.setOption(option)
2023-12-16 18:10:04 +08:00
}
},
2024-04-26 10:25:38 +08:00
handleClick() {
2024-08-26 20:53:34 +08:00
this.$refs.materialAnalysisDialog.setOpen({
open: true,
maType: this.maType,
})
},
2023-12-16 18:10:04 +08:00
},
2024-08-26 20:53:34 +08:00
}
2023-12-16 18:10:04 +08:00
</script>
<style lang="scss" scoped>
.access-rate-page {
margin-bottom: 31px;
2024-04-25 09:26:22 +08:00
z-index: 2001;
2023-12-16 18:10:04 +08:00
.access-rate-box {
.access-rate-box-title-bg {
width: 433px;
height: 50px;
background: url(../../assets/img/myImage/title_right.png) no-repeat center;
background-size: 100% 100%;
position: relative;
.access-rate-box-title {
position: absolute;
left: 6%;
top: 28%;
font-size: 20px;
font-family: Alibaba PuHuiTi, AlibabaPuHuiTi;
font-weight: 500;
color: #ffffff;
line-height: 23px;
letter-spacing: 2px;
}
}
.chart-container {
margin: 12px 0;
width: 433px;
height: 113px;
.chart {
width: 100%;
height: 200px;
}
// .bg {
// width: 337px;
// height: 144px;
// background: center top url(../../assets/img/myImage/bg.png)
// no-repeat;
// background-size: cover;
// margin-top: -120px;
// margin-left: 18%;
// }
}
}
}
</style>