<template>
	<div class="character-relationships">
		<div class="headerBox">
			<span
				v-for="(item, index) in list"
				:key="index"
				class="headerItem"
				:class="{ active: item === activeIndex }"
				@click="activeIndex = item"
				>{{ item }}</span
			>
		</div>
		<div class="headerBtnBox"><img src="./assets/下载按钮.png" alt="" /><img src="./assets/收藏按钮.png" alt="" /></div>
		<!-- 主要内容，人物关系图 -->
		<div class="mainBox">
			<div class="graph" id="relGraph"></div>
		</div>
	</div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, watch } from "vue";
import * as echarts from "echarts";
import Center from "./assets/巴里·帕维尔.png";
import P1 from "./assets/卡罗尔·M·波滕格.png";
import P2 from "./assets/理查德·丹齐格.png";
import P3 from "./assets/吉姆·米特雷.png";
import P4 from "./assets/拉斐尔·S·科恩.png";
import P5 from "./assets/卡娅·卡拉斯.png";
import P6 from "./assets/伊万娜·柯.png";
import P7 from "./assets/丹尼尔·埃格尔.png";
import P8 from "./assets/马克·埃斯珀.png";
import P9 from "./assets/格雷戈里·史密斯.png";
import P10 from "./assets/斯特凡诺·斯特凡尼尼.png";
import P11 from "./assets/谢莉·卡尔伯森.png";
import PS from "./assets/菲利普·布里德洛夫.png";

const list = ref(["圆形布局", "力导向布局", "树形布局"]);
const activeIndex = ref("圆形布局");

const nodes = [
	{
		id: "c",
		name: "巴里·帕维尔",
		category: 0,
		symbolSize: 80,
		symbol: `image://${Center}`,
		label: {
			show: true,
			position: "bottom",
			formatter: "{n|巴里·帕维尔}",
			rich: {
				n: {
					color: "rgba(5,95,194,1)",
					fontSize: 24,
					fontWeight: 700,
					fontFamily: "Microsoft YaHei",
					lineHeight: 36
				}
			}
		}
	},
	// 从三点钟方向顺时针排序
	{ id: "n11", name: "谢莉·卡尔伯森", category: 1, symbolSize: 80, symbol: `image://${P11}` },
	{ id: "n7", name: "丹尼尔·埃格尔", category: 1, symbolSize: 80, symbol: `image://${P7}`, r: 80 },
	{ id: "n6", name: "伊万娜·柯", category: 1, symbolSize: 80, symbol: `image://${P6}` },
	{ id: "n9", name: "格雷戈里·史密斯", category: 1, symbolSize: 80, symbol: `image://${P9}` },
	{ id: "n12", name: "菲利普·布里德洛夫", category: 1, symbolSize: 80, symbol: `image://${PS}` },
	{ id: "n5", name: "卡娅·卡拉斯", category: 1, symbolSize: 80, symbol: `image://${P5}`, r: 80 },
	{ id: "n8", name: "马克·埃斯珀", category: 1, symbolSize: 80, symbol: `image://${P8}` },
	{ id: "n10", name: "斯特凡诺·斯特凡尼尼", category: 1, symbolSize: 80, symbol: `image://${P10}`, r: 80 },
	{ id: "n2", name: "理查德·丹齐格", category: 1, symbolSize: 80, symbol: `image://${P2}` },
	{ id: "n1", name: "卡罗尔·M·波滕格", category: 1, symbolSize: 80, symbol: `image://${P1}` },
	{ id: "n4", name: "拉斐尔·S·科恩", category: 1, symbolSize: 80, symbol: `image://${P4}` },
	{ id: "n3", name: "吉姆·米特雷", category: 1, symbolSize: 80, symbol: `image://${P3}`, r: 80 }
];

const links = [
	{ source: "n11", target: "c", label: { show: true, formatter: "兰德同事" } },
	{ source: "n7", target: "c", label: { show: true, formatter: "兰德共同作者" } },
	{ source: "n6", target: "c", label: { show: true, formatter: "兰德共同作者" } },
	{ source: "n9", target: "c", label: { show: true, formatter: "兰德共同作者" } },
	{ source: "n12", target: "c", label: { show: true, formatter: "共同作者" } },
	{ source: "n5", target: "c", label: { show: true, formatter: "爱沙尼亚总理" } },
	{ source: "n8", target: "c", label: { show: true, formatter: "国防部同事" } },
	{ source: "n10", target: "c", label: { show: true, formatter: "外交部同事" } },
	{ source: "n2", target: "c", label: { show: true, formatter: "讲座嘉宾" } },
	{ source: "n1", target: "c", label: { show: true, formatter: "议题搭档" } },
	{ source: "n4", target: "c", label: { show: true, formatter: "兰德同事" } },
	{ source: "n3", target: "c", label: { show: true, formatter: "兰德同事" } }
];

let chart;

onMounted(() => {
	const el = document.getElementById("relGraph");
	if (!el) return;
	chart = echarts.init(el);
	const setOption = () => {
		const rect = el.getBoundingClientRect();
		const cx = rect.width / 2;
		const cy = rect.height / 2;
		const radius = Math.min(cx, cy) - 140;

		const dataNodes = nodes.map((n, i) => {
			if (n.id === "c") {
				return { ...n, x: cx, y: cy, fixed: true };
			}
			// 均匀环形分布
			const idx = i - 1;
			const angle = (idx / (nodes.length - 1)) * Math.PI * 2;
			const rLocal = radius + (n.r || 0);
			const x = cx + rLocal * Math.cos(angle);
			const y = cy + rLocal * Math.sin(angle);
			return { ...n, x, y };
		});

		chart.setOption({
			tooltip: {},
			series: [
				{
					type: "graph",
					layout: activeIndex.value === "圆形布局" ? "none" : "force",
					circular: { rotateLabel: true },
					force: { repulsion: 800, edgeLength: [80, 160] },
					roam: true,
					data: activeIndex.value === "圆形布局" ? dataNodes : nodes,
					links: links,
					edgeSymbol: ["none", "arrow"],
					edgeSymbolSize: [4, 10],
					lineStyle: { color: "rgba(174,214,255,1)", width: 2, opacity: 0.8 },
					edgeLabel: {
						show: true,
						position: "middle",
						distance: -18,
						formatter: ({ data }) => data?.label?.formatter || "",
						color: "rgb(5, 95, 194)",
						fontSize: 12,
						fontWeight: 400,
						fontFamily: "Microsoft YaHei",
						lineHeight: 24,
						backgroundColor: "rgba(231, 243, 255, 1)",
						borderRadius: 24,
						padding: [0, 12]
					},
					label: { show: true, position: "bottom", color: "rgb(59,65,75)", fontSize: 16 },
					itemStyle: { color: "rgba(5,95,194,1)" },
					emphasis: { focus: "adjacency" }
				}
			]
		});
	};
	setOption();
	const onResize = () => chart && chart.resize();
	window.addEventListener("resize", onResize);
	watch(activeIndex, () => setOption());
	onBeforeUnmount(() => {
		window.removeEventListener("resize", onResize);
		chart && chart.dispose();
	});
});
</script>

<style lang="scss" scoped>
* {
	padding: 0;
	margin: 0;
}
.character-relationships {
	width: 1600px;
	height: 688px;
	background-color: #fff;
	margin: 0 auto;
	position: relative;
	border-radius: 4px;
	box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
	.headerBox {
		position: absolute;
		top: 14px;
		right: 96px;
		.headerItem {
			padding: 1px 8px;
			border-radius: 4px;
			font-size: 16px;
			font-weight: 400;
			line-height: 30px;
			cursor: pointer;
			color: rgb(59, 65, 75);
			font-family: "Microsoft YaHei";
			margin-right: 8px;
			border: 1px solid rgb(230, 231, 232);
		}
		.active {
			background-color: rgba(246, 250, 255, 1);
			border-color: rgb(5, 95, 194);
			color: rgb(5, 95, 194);
		}
	}
	.headerBtnBox {
		position: absolute;
		top: 14px;
		right: 12px;
		img {
			width: 28px;
			height: 28px;
			margin-right: 4px;
			cursor: pointer;
		}
	}
	.mainBox {
		width: 100%;
		height: 100%;
		padding-top: 42px;
		.graph {
			width: 100%;
			height: 100%;
		}
	}
}
</style>
