<template>
	<div class="leftBorder">
		<div class="title">
			<div class="text">工程数</div>
		</div>
		<div class="projectNum">
			<div v-for="(item, index) in projectNumList" :key="index">
				<div class="numItem">{{ item }}</div>
			</div>
		</div>
		<div class="title">
			<div class="text">在建工程分类</div>
		</div>
		<div class="" id="mainCenter"></div>
		<div v-for="(item, index) in percentList" :key="index" class="allPercent">
			<div :class="item.css">{{ item.number }}</div>
		</div>
		<div class="title">
			<div class="text">扬尘今日预警</div>
		</div>
		<div class="pieBg">
			<div class="imgbg">
				<img src="@/assets/images/screenImg/blueCircleBig.gif" alt="" />
			</div>
			<div class="" id="mainBottom"></div>
		</div>
	</div>
</template>

<script lang="ts" setup>
import { nextTick, ref } from "vue";
import * as echarts from "echarts";
import "echarts-gl";
//工程数
const projectNum = ref("513498");
const projectNumList = projectNum.value.split("");
console.log(projectNumList);
//在建工程分类
const percentList = ref([
	{ number: "40.84%", css: "greenPercent" },
	{ number: "48.29%", css: "bluePercent" },
	{ number: "10.87%", css: "yellowPercent" }
]);
const threeDOption = () => {
	const chartDom = document.getElementById("mainCenter") as HTMLElement;
	const myChart = echarts.init(chartDom);

	const allNumber = 1814;
	const data = [
		{
			name: "房屋建筑",
			value: 48.29,
			itemStyle: {
				color: "#3c6fb6"
			}
		},
		{
			name: "市政公用",
			value: 40.84,
			itemStyle: {
				color: "#53d5a3"
			}
		},
		{
			name: "其他",
			value: 10.87,
			itemStyle: {
				color: "#f6bc05"
			}
		}
	];
	function array2obj(array: [], key: string) {
		let resObj = {};
		for (let i = 0; i < array.length; i++) {
			resObj[array[i][key]] = array[i];
		}
		return resObj;
	}
	const objData = array2obj(data, "name");
	// 生成扇形的曲面参数方程，用于 series-surface.parametricEquation
	function getParametricEquation(
		startRatio: number,
		endRatio: number,
		isSelected: boolean,
		isHovered: boolean,
		k: number,
		h: number
	) {
		// 计算
		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: number, v: number) {
				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: number, v: number) {
				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: number, v: number) {
				if (u < -Math.PI * 0.5) {
					return Math.sin(u);
				}
				if (u > Math.PI * 2.5) {
					return Math.sin(u) * h * 0.1;
				}
				return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
			}
		};
	}

	// 生成模拟 3D 饼图的配置项
	function getPie3D(pieData: string | any[], internalDiameterRatio: number) {
		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);
		}

		// 使用上一次遍历时，计算出的数据和 sumValue，调用 getParametricEquation 函数，
		// 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation，也就是实现每一个扇形。
		for (let i = 0; i < series.length; i++) {
			endValue = startValue + series[i].pieData.value;

			series[i].pieData.startRatio = startValue / sumValue;
			series[i].pieData.endRatio = endValue / sumValue;
			series[i].parametricEquation = 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
			},
			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: number, v: number) {
					return Math.sin(v) * Math.sin(u) + Math.sin(u);
				},
				y: function (u: number, v: number) {
					return Math.sin(v) * Math.cos(u) + Math.cos(u);
				},
				z: function (u: any, v: number) {
					return Math.cos(v) > 0 ? 0.1 : -0.1;
				}
			}
		});

		// 准备待返回的配置项，把准备好的 legendData、series 传入。
		let option = {
			//animation: false,
			legend: {
				// orient 设置布局方式，默认水平布局，可选值：'horizontal'（水平） | 'vertical'（垂直）
				orient: "horizontal",
				x: "center",
				y: "left",
				itemWidth: 18,
				itemHeight: 18,
				// itemGap设置各个item之间的间隔，单位px，默认为10，横向布局时为水平间隔，纵向布局时为纵向间隔
				itemGap: 30,
				formatter: function (name: string) {
					return "{title|" + name + "}{value| " + `${((objData[name].value / 100) * allNumber).toFixed(0)}` + "}";
				},
				textStyle: {
					rich: {
						title: {
							fontSize: 13,
							lineHeight: 15,
							color: "white",
							fontFamily: "DigitalRegular"
						},
						value: {
							fontSize: 19,
							lineHeight: 20,
							color: "white",
							fontFamily: "YouSheBiaoTiHei"
						}
					}
				}
			},
			tooltip: {
				formatter: (params: { seriesName: string; color: any; seriesIndex: string | number }) => {
					if (params.seriesName !== "mouseoutSeries") {
						return `${
							params.seriesName
						}<br/><span style="display:inline-block;margin-right:5px;border-radius:10px;width:10px;height:10px;background-color:${
							params.color
						};"></span>${option.series[params.seriesIndex].pieData.value}%`;
					}
				}
			},
			xAxis3D: {
				min: -1,
				max: 1
			},
			yAxis3D: {
				min: -1,
				max: 1
			},
			zAxis3D: {
				min: -1,
				max: 1
			},
			grid3D: {
				show: false,
				boxHeight: 10,
				viewControl: {
					//3d效果可以放大、旋转等，请自己去查看官方配置
					alpha: 40,
					// beta: 40,
					rotateSensitivity: 0,
					zoomSensitivity: 0,
					panSensitivity: 0,
					autoRotate: false
				},
				//后处理特效可以为画面添加高光、景深、环境光遮蔽（SSAO）、调色等效果。可以让整个画面更富有质感。
				postEffect: {
					//配置这项会出现锯齿，请自己去查看官方配置有办法解决
					enable: true,
					bloom: {
						enable: true,
						bloomIntensity: 0.1
					},
					SSAO: {
						enable: true,
						quality: "medium",
						radius: 2
					}
				}
			},
			series: series
		};
		return option;
	}

	// 传入数据生成 option

	let option = getPie3D(data, 0.65);
	option && myChart.setOption(option);
};

nextTick(() => {
	threeDOption();
});
//扬尘今日预警
const pieOption = () => {
	const chartDomPie = document.getElementById("mainBottom") as HTMLElement;
	const myChartPie = echarts.init(chartDomPie);

	let scale = 1;
	let echartData = [
		{
			value: 25,
			name: "PM10",
			itemStyle: {
				normal: {
					//颜色渐变
					color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
						{ offset: 0, color: "#1d2f31" },
						{ offset: 1, color: "#30ab7b" }
					])
				}
			},
			labelLine: {
				lineStyle: {
					color: "#2fa678"
				}
			},
			label: {
				normal: {
					rich: {
						b: {
							height: 5,
							width: 5,
							lineHeight: 15,
							marginBottom: 10,
							padding: [0, -2.5],
							borderRadius: 5,
							backgroundColor: "#2fa678" // 圆点颜色
						}
					}
				}
			}
		},
		{
			value: 25,
			name: "  噪音",
			itemStyle: {
				normal: {
					//颜色渐变
					color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
						{ offset: 0, color: "#2c2e29" },
						{ offset: 1, color: "#f9bd02" }
					])
				}
			},
			labelLine: {
				lineStyle: {
					color: "#e2ad06"
				}
			},
			label: {
				normal: {
					rich: {
						b: {
							height: 5,
							width: 5,
							lineHeight: 15,
							marginBottom: 10,
							padding: [0, -2.5],
							borderRadius: 5,
							backgroundColor: "#e2ad06" // 圆点颜色
						}
					}
				}
			}
		},
		{
			value: 25,
			name: "TSP  ",
			itemStyle: {
				normal: {
					//颜色渐变
					color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
						{ offset: 0, color: "#f04b17" },
						{ offset: 1, color: "#2b242b" }
					])
				}
			},
			labelLine: {
				lineStyle: {
					color: "#e94a18"
				}
			},
			label: {
				normal: {
					rich: {
						b: {
							height: 5,
							width: 5,
							lineHeight: 15,
							marginBottom: 10,
							padding: [0, -2.5],
							borderRadius: 5,
							backgroundColor: "#e94a18" // 圆点颜色
						}
					}
				}
			}
		},
		{
			value: 25,
			name: "PM2.5",
			itemStyle: {
				normal: {
					//颜色渐变
					color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
						{ offset: 0, color: "#5488d8" },
						{ offset: 1, color: "#222c3a" }
					])
				}
			},
			labelLine: {
				lineStyle: {
					color: "#5183cf"
				}
			},
			label: {
				normal: {
					rich: {
						b: {
							height: 5,
							width: 5,
							lineHeight: 15,
							marginBottom: 10,
							padding: [0, -2.5],
							borderRadius: 5,
							backgroundColor: "#5183cf" // 圆点颜色
						}
					}
				}
			}
		}
	];
	let total_datas = 88;
	let rich = {
			top: {
				color: "white",
				fontSize: 15,
				left: 20,
				padding: [-20, -80, -20, -80],
				fontFamily: "SourceHanSansCNH"
			},
			total: {
				color: "#ffc72b",
				fontSize: 40 * scale,
				align: "center"
			},

			bottom: {
				color: "white",
				fontSize: 16,
				height: 5,
				width: 5,
				lineHeight: 5,
				marginBottom: 10,
				padding: [0, -100, -15, -105],
				borderRadius: 5,
				fontFamily: "OPPOSansB"
			},
			hr: {
				borderColor: "#0b5263",
				width: "100%",
				borderWidth: 1,
				height: 0
			}
		},
		optionPie = {
			title: {
				text: total_datas,
				subtext: "今日报警次数",
				itemGap: 5,
				top: "top",
				padding: [108, 100],
				textStyle: {
					color: "#f2f2f2",
					fontSize: 48,
					fontFamily: "DigitalRegular"
				},
				subtextStyle: {
					fontSize: 14,
					color: ["#f2f2f2"],
					fontFamily: "SourceHanSansCNR"
				},
				x: "center",
				y: "center"
			},
			series: [
				{
					name: "违纪总次数",
					type: "pie",
					radius: ["38%", "50%"],
					hoverAnimation: false,
					label: {
						normal: {
							formatter: function (params: { value: number; name: string }) {
								let total = 0; //考生总数量
								echartData.forEach(function (value) {
									total += value.value;
								});
								let percent = ((params.value / total) * 100).toFixed(0);
								return "{top|" + params.name + "}\n{b| }\n{bottom|" + params.value + "次  /  " + percent + "%}";
							},
							rich: rich
						}
					},
					labelLine: {
						normal: {
							length: 20,
							length2: 135,
							align: "right",
							lineStyle: {
								width: 1
							},
							emphasis: {
								show: true
							}
						}
					},
					data: echartData
				}
			]
		};
	optionPie && myChartPie.setOption(optionPie);
};
nextTick(() => {
	pieOption();
});
</script>

<style lang="scss" scoped>
.leftBorder {
	position: fixed;
	top: 15%;
	right: 0;
	width: 27%;
	height: 100%;
	background: url("@/assets/images/screenImg/rightBorder.png") no-repeat right center;
	.title {
		width: 100%;
		height: 50px;
		font-family: YouSheBiaoTiHei;
		color: white;
		background: url("@/assets/images/screenImg/littleTitle.png") no-repeat left center;
		background-size: 75%;
		.text {
			padding: 0 0 0 50px;
			font-size: 18px;
		}
	}
	.projectNum {
		display: flex;
		width: 90%;
		height: 100px;
		margin-left: 22px;
		.numItem {
			width: 56px;
			height: 62px;
			margin-right: 10px;
			font-family: DigitalRegular;
			font-size: 48px;
			line-height: 62px;
			color: white;
			text-align: center;
			background: url("@/assets/images/screenImg/frame.png") no-repeat;
			background-size: 100%;
		}
	}
}
/* stylelint-disable-next-line selector-id-pattern */
#mainCenter {
	width: 100%;
	height: 290px;
	margin-right: 80px;
}
.pieBg {
	position: relative;
	width: 90%;
	height: 250px;
	.imgbg {
		width: 245px;
		height: 245px;
		margin: 0 auto;
		background: url("@/assets/images/screenImg/blueCircleBigbg.png") no-repeat center center;
		background-size: 100%;
		img {
			position: absolute;
			top: 14.5%;
			left: 31.5%;
			width: 174px;
			height: 174px;
		}
	}
	/* stylelint-disable-next-line selector-id-pattern */
	#mainBottom {
		position: absolute;
		top: -8.5%;
		left: 0;
		width: 100%;
		height: 290px;
	}
}
.allPercent {
	// position: relative;
	.greenPercent {
		position: absolute;
		top: 22%;
		left: 19%;
		width: 76px;
		height: 30px;
		font-family: OPPOSansH;
		color: rgb(48 172 124);
		text-align: center;
		border-bottom: 5px solid #dddddd;
		border-image: linear-gradient(to right, rgb(48 172 124 / 0%), rgb(48 172 124 / 100%)) 30 30;
	}
	.bluePercent {
		position: absolute;
		top: 26%;
		left: 73%;
		width: 76px;
		height: 30px;
		font-family: OPPOSansH;
		color: rgb(49 123 196);
		text-align: center;
		border-bottom: 5px solid #dddddd;
		border-image: linear-gradient(to right, rgb(49 123 196 / 20%), rgb(49 123 196 / 80%)) 30 30;
	}
	.yellowPercent {
		position: absolute;
		top: 38%;
		left: 64%;
		width: 76px;
		height: 30px;
		font-family: OPPOSansH;
		color: rgb(252 191 2);
		text-align: center;
		border-bottom: 5px solid #dddddd;
		border-image: linear-gradient(to right, rgb(252 191 2 / 0%), rgb(252 191 2 / 100%)) 30 30;
	}
}
</style>
