528 lines
14 KiB
Vue
528 lines
14 KiB
Vue
<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">
|
||
<div
|
||
class="chart"
|
||
ref="chart"
|
||
id="pieChartMap"
|
||
@click="handleClick"
|
||
></div>
|
||
<!-- 底座背景 -->
|
||
<div class="bg"></div>
|
||
</div>
|
||
</div>
|
||
<materialAnalysisDialog
|
||
ref="materialAnalysisDialog"
|
||
></materialAnalysisDialog>
|
||
</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);
|
||
import * as echarts from 'echarts'
|
||
import 'echarts-gl' // 3d图表库
|
||
import { getPickingAnalysisByMonthApi } from '../../api/screen'
|
||
import materialAnalysisDialog from './materialAnalysisDialog'
|
||
|
||
export default {
|
||
components: {
|
||
materialAnalysisDialog,
|
||
},
|
||
data() {
|
||
return {
|
||
data: [],
|
||
maType: '',
|
||
}
|
||
},
|
||
mounted() {
|
||
this.$eventBus.$on('maType', (maType) => {
|
||
this.maType = maType
|
||
this.getPickingAnalysisByMonthApiPage()
|
||
})
|
||
setInterval(() => {
|
||
this.getPickingAnalysisByMonthApiPage()
|
||
}, 60 * 1000)
|
||
},
|
||
destroyed() {
|
||
this.$eventBus.$off('maType')
|
||
},
|
||
methods: {
|
||
getPickingAnalysisByMonthApiPage() {
|
||
this.data = []
|
||
let params = {
|
||
maType: this.maType,
|
||
}
|
||
getPickingAnalysisByMonthApi(params).then((res) => {
|
||
if (res.code == 200) {
|
||
this.data.push(
|
||
{
|
||
name: '数量领料',
|
||
value: res.data.num,
|
||
rate: res.data.rate,
|
||
itemStyle: {
|
||
color: '#01F4F5',
|
||
},
|
||
},
|
||
{
|
||
name: '编码领料',
|
||
value: res.data.num2,
|
||
rate: res.data.rate2,
|
||
itemStyle: {
|
||
color: '#077E98',
|
||
},
|
||
}
|
||
)
|
||
this.mastery(this.data)
|
||
}
|
||
})
|
||
},
|
||
// 生成扇形的曲面参数方程,用于 series-surface.parametricEquation
|
||
getParametricEquation(
|
||
startRatio,
|
||
endRatio,
|
||
isSelected,
|
||
isHovered,
|
||
k,
|
||
height
|
||
) {
|
||
// 计算
|
||
let midRatio = (startRatio + endRatio) / 2
|
||
|
||
let startRadian = startRatio * Math.PI * 2
|
||
let endRadian = endRatio * Math.PI * 2
|
||
let midRadian = midRatio * Math.PI * 2
|
||
|
||
// 如果只有一个扇形,则不实现选中效果。
|
||
if (startRatio === 0 && endRatio === 1) {
|
||
isSelected = false
|
||
}
|
||
|
||
// 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
|
||
k = typeof k !== 'undefined' ? k : 1 / 3
|
||
|
||
// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
|
||
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0
|
||
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0
|
||
|
||
// 计算高亮效果的放大比例(未高亮,则比例为 1)
|
||
let hoverRate = isHovered ? 1.05 : 1
|
||
|
||
// 返回曲面参数方程
|
||
return {
|
||
u: {
|
||
min: -Math.PI,
|
||
max: Math.PI * 3,
|
||
step: Math.PI / 32,
|
||
},
|
||
|
||
v: {
|
||
min: 0,
|
||
max: Math.PI * 2,
|
||
step: Math.PI / 20,
|
||
},
|
||
|
||
x: function (u, v) {
|
||
if (u < startRadian) {
|
||
return (
|
||
offsetX +
|
||
Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate
|
||
)
|
||
}
|
||
if (u > endRadian) {
|
||
return (
|
||
offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate
|
||
)
|
||
}
|
||
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate
|
||
},
|
||
|
||
y: function (u, v) {
|
||
if (u < startRadian) {
|
||
return (
|
||
offsetY +
|
||
Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate
|
||
)
|
||
}
|
||
if (u > endRadian) {
|
||
return (
|
||
offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate
|
||
)
|
||
}
|
||
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate
|
||
},
|
||
|
||
z: function (u, v) {
|
||
if (u < -Math.PI * 0.5) {
|
||
return Math.sin(u)
|
||
}
|
||
if (u > Math.PI * 2.5) {
|
||
return Math.sin(u)
|
||
}
|
||
return Math.sin(v) > 0 ? 1 * height : -1
|
||
},
|
||
}
|
||
},
|
||
// 生成模拟 3D 饼图的配置项
|
||
getPie3D(pieData, internalDiameterRatio) {
|
||
let series = []
|
||
let sumValue = 0
|
||
let startValue = 0
|
||
let endValue = 0
|
||
let legendData = []
|
||
let k =
|
||
typeof internalDiameterRatio !== 'undefined'
|
||
? (1 - internalDiameterRatio) / (1 + internalDiameterRatio)
|
||
: 1 / 3
|
||
// 为每一个饼图数据,生成一个 series-surface 配置
|
||
for (let i = 0; i < pieData.length; i++) {
|
||
sumValue += pieData[i].value
|
||
let seriesItem = {
|
||
name:
|
||
typeof pieData[i].name === 'undefined'
|
||
? `series${i}`
|
||
: pieData[i].name,
|
||
type: 'surface',
|
||
parametric: true,
|
||
wireframe: {
|
||
show: false,
|
||
},
|
||
pieData: pieData[i],
|
||
pieStatus: {
|
||
selected: false,
|
||
hovered: false,
|
||
k: k,
|
||
},
|
||
}
|
||
|
||
if (typeof pieData[i].itemStyle != 'undefined') {
|
||
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
|
||
|
||
seriesItem.itemStyle = itemStyle
|
||
}
|
||
series.push(seriesItem)
|
||
}
|
||
for (let i = 0; i < series.length; i++) {
|
||
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)
|
||
}
|
||
// // 补充一个透明的圆环,用于支撑高亮功能的近似实现。
|
||
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) {
|
||
return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2
|
||
},
|
||
y: function (u, v) {
|
||
return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2
|
||
},
|
||
z: function (u, v) {
|
||
return Math.cos(v) > 0 ? -0.5 : -5
|
||
},
|
||
},
|
||
})
|
||
|
||
// // 补充一个透明的圆环,用于支撑高亮功能的近似实现。
|
||
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) {
|
||
return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2
|
||
},
|
||
y: function (u, v) {
|
||
return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2
|
||
},
|
||
z: function (u, v) {
|
||
return Math.cos(v) > 0 ? -5 : -7
|
||
},
|
||
},
|
||
})
|
||
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) {
|
||
return ((Math.sin(v) * Math.sin(u) + Math.sin(u)) / Math.PI) * 2.2
|
||
},
|
||
y: function (u, v) {
|
||
return ((Math.sin(v) * Math.cos(u) + Math.cos(u)) / Math.PI) * 2.2
|
||
},
|
||
z: function (u, v) {
|
||
return Math.cos(v) > 0 ? -7 : -7
|
||
},
|
||
},
|
||
})
|
||
return series
|
||
},
|
||
mastery(data) {
|
||
var myChart = echarts.init(document.querySelector('#pieChartMap'))
|
||
// const optionsData = [
|
||
// {
|
||
// name: '数量领料',
|
||
// value: 76,
|
||
// itemStyle: {
|
||
// color: '#01F4F5',
|
||
// },
|
||
// },
|
||
// {
|
||
// name: '编码领料',
|
||
// value: 24,
|
||
// itemStyle: {
|
||
// color: '#077E98',
|
||
// },
|
||
// },
|
||
// ];
|
||
const series = this.getPie3D(this.data, 0.8, 360, 18, 56, 1)
|
||
|
||
series.push({
|
||
type: 'pie',
|
||
label: {
|
||
opacity: 1,
|
||
fontSize: 14,
|
||
lineHeight: 15,
|
||
textStyle: {
|
||
fontSize: 14,
|
||
},
|
||
},
|
||
labelLine: {
|
||
length: 10,
|
||
length2: 30,
|
||
},
|
||
startAngle: 40, //起始角度,支持范围[0, 360]。
|
||
clockwise: false, //饼图的扇区是否是顺时针排布。上述这两项配置主要是为了对齐3d的样式
|
||
radius: ['12%', '62%'],
|
||
center: ['50%', '50%'],
|
||
data: this.data,
|
||
itemStyle: {
|
||
opacity: 0,
|
||
},
|
||
})
|
||
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',
|
||
formatter: (params) => {
|
||
return `${params.percent}%\n${params.name}`
|
||
},
|
||
borderWidth: 0,
|
||
padding: [0, -50],
|
||
height: 70,
|
||
fontSize: 14,
|
||
align: 'center',
|
||
color: '#ffffff',
|
||
rich: {
|
||
hr: {
|
||
backgroundColor: '#fff',
|
||
borderRadius: 3,
|
||
width: 3,
|
||
height: 3,
|
||
padding: [3, 3, 0, -12],
|
||
},
|
||
},
|
||
// 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,
|
||
}
|
||
if (option && typeof option === 'object') {
|
||
myChart.setOption(option)
|
||
}
|
||
},
|
||
handleClick() {
|
||
this.$refs.materialAnalysisDialog.setOpen({
|
||
open: true,
|
||
maType: this.maType,
|
||
})
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.access-rate-page {
|
||
margin-bottom: 31px;
|
||
z-index: 2001;
|
||
.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>
|