<template>
	<div class="datasub">
		<div class="datasub-left">
			<div class="left">
				<div class="left-title">
					<img src="./assets/icon01.png" alt="" />
					<div class="tit">资助领域分布情况</div>
					<div :class="radio1 === true ? 'btn-select' : 'btn'" style="		right:254px;" @click="setRadio1(true)">
						资助经费
					</div>
					<div :class="radio1 === false ? 'btn-select' : 'btn'" style="		right: 166px;" @click="setRadio1(false)">
						资助项目
					</div>

					<el-select v-model="value1" placeholder="Select" class="select" popper-class="datasub-select-popper"
						@change="handleLeft1YearChange">
						<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
				</div>
				<div class="left-main ">
					<div class="left-main-echarts" ref="leftChartRef" v-show="radio1 === true"></div>
					<div class="left-main-echarts" ref="leftChartRef1" v-show="radio1 === false"></div>
					<el-empty v-show="!hasLeft1ChartData && !isLeft1Loading" class="datasub-el-empty" description="暂无数据"
						:image-size="100" />
					<div class="source" v-show="hasLeft1ChartData">
						<TipTab :text="'资助领域分布情况，数据来源：美国国会官网'" />
					</div>
					<div class="chart-box" v-show="hasLeft1ChartData">
						<div class="btn-box" v-if="!isShowAiContentLeft1" @mouseenter="handleSwitchAiLeft1(true)">
							<AiButton />
						</div>
						<div class="content-box" v-else @mouseleave="handleSwitchAiLeft1(false)">
							<AiPane :aiContent="aiContentLeft1" />
						</div>
					</div>
				</div>
			</div>
			<div class="left">
				<div class="left-title">
					<img src="./assets/icon03.png" alt="" />
					<div class="tit">机构资助领域情况</div>
					<el-select v-model="value2" placeholder="Select" class="select" popper-class="datasub-select-popper"
						@change="handleGetOrgFundsArea">
						<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
				</div>
				<div class="left-main1">
					<div class="left-sankey-echarts" ref="leftSankeyRef"></div>
					<el-empty v-show="!hasLeft2ChartData" class="datasub-el-empty" description="暂无数据" :image-size="100" />
					<div class="source" v-show="hasLeft2ChartData">
						<TipTab :text="'机构资助领域情况，数据来源：美国国会官网'" />
					</div>
					<div class="chart-box" v-show="hasLeft2ChartData">
						<div class="btn-box" v-if="!isShowAiContentLeft2" @mouseenter="handleSwitchAiLeft2(true)">
							<AiButton />
						</div>
						<div class="content-box" v-else @mouseleave="handleSwitchAiLeft2(false)">
							<AiPane :aiContent="aiContentLeft2" />
						</div>
					</div>
				</div>
			</div>
		</div>
		<div class="datasub-right">
			<div class="right">
				<div class="right-title">
					<img src="./assets/icon02.png" alt="" />
					<div class="tit">资助经费变化情况</div>
					<div :class="radio2 === true ? 'btn-select' : 'btn'" style="		right:254px;" @click="setRadio2(true)">
						资助经费
					</div>
					<div :class="radio2 === false ? 'btn-select' : 'btn'" style="		right: 166px;" @click="setRadio2(false)">
						资助项目
					</div>
					<el-select v-model="value" placeholder="Select" class="select" popper-class="datasub-select-popper"
						@change="handleRight1RangeChange">
						<el-option v-for="item in options" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
				</div>
				<div class="right-main">
					<div class="right-main-echarts" ref="rightChartRef" v-show="radio2 === true"></div>
					<div class="right-main-echarts" ref="rightChartRef1" v-show="radio2 === false"></div>
					<div class="right-main-tit" v-show="hasRight1ChartData">亿美元</div>
					<el-empty v-show="!hasRight1ChartData && !isRight1Loading" class="datasub-el-empty" description="暂无数据"
						:image-size="100" />
					<div class="source" v-show="hasRight1ChartData">
						<TipTab :text="'资助经费变化情况，数据来源：美国国会官网'" />
					</div>
					<div class="chart-box" v-show="hasRight1ChartData">
						<div class="btn-box" v-if="!isShowAiContentRight1" @mouseenter="handleSwitchAiRight1(true)">
							<AiButton />
						</div>
						<div class="content-box" v-else @mouseleave="handleSwitchAiRight1(false)">
							<AiPane :aiContent="aiContentRight1" />
						</div>
					</div>
				</div>
			</div>
			<div class="right">
				<div class="right-title">
					<img src="./assets/icon04.png" alt="" />
					<div class="tit">项目资助强度分布</div>
					<el-select v-model="value3" placeholder="Select" class="select" popper-class="datasub-select-popper"
						@change="handleRight2YearChange">
						<el-option v-for="item in options1" :key="item.value" :label="item.label" :value="item.value" />
					</el-select>
				</div>
				<div class="right-main1">
					<div class="right-boxplot-echarts" ref="boxplotChartRef"></div>
					<div class="right-main1-tit" v-show="hasRight2ChartData">单位：亿美元</div>
					<el-empty v-show="!hasRight2ChartData" class="datasub-el-empty" description="暂无数据" :image-size="100" />
					<div class="source" v-show="hasRight2ChartData">
						<TipTab :text="'项目资助强度分布，数据来源：美国国会官网'" />
					</div>
					<div class="chart-box" v-show="hasRight2ChartData">
						<div class="btn-box" v-if="!isShowAiContentRight2" @mouseenter="handleSwitchAiRight2(true)">
							<AiButton />
						</div>
						<div class="content-box" v-else @mouseleave="handleSwitchAiRight2(false)">
							<AiPane :aiContent="aiContentRight2" />
						</div>
					</div>
				</div>
			</div>
		</div>
	</div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick, computed } from "vue";
import { getChartAnalysis } from "@/api/aiAnalysis";
import AiButton from "@/components/base/Ai/AiButton/index.vue";
import AiPane from "@/components/base/Ai/AiPane/index.vue";
import TipTab from "@/views/thinkTank/TipTab/index.vue";
import {
	findFundField, findCountryProjectAreaList, getCountryFundingChange, getCountryFundProjectChange, getOrgFundsArea, getOrgFundStrength
} from "@/api/scientificFunding/overview";

import * as echarts from "echarts";

const isNonEmptyArray = (v) => Array.isArray(v) && v.length > 0;

// 兼容后端多种返回结构：[] / {data:[]} / {content:[]} 等
const extractArrayData = (res) => {
	const d = res?.data;
	if (Array.isArray(d)) return d;
	if (Array.isArray(d?.data)) return d.data;
	if (Array.isArray(d?.content)) return d.content;
	if (Array.isArray(d?.list)) return d.list;
	return [];
};

const isSuccessCode = (res) => Number(res?.code) === 200;



const value = ref(10);




const options = [
	{
		value: 10,
		label: "近十年"
	},
	{
		value: 5,
		label: "近五年"
	}
];
/** value 须与 v-model 类型一致（数字），否则 el-select 无法匹配 label，会显示成「2025」而非「2025年」 */
const options1 = [
	{
		value: 2026,
		label: "2026年"
	},
	{
		value: 2025,
		label: "2025年"
	},
	{
		value: 2024,
		label: "2024年"
	}
];
const normalizeYearParam = (val) => {
	const y = Number(val);
	return Number.isFinite(y) ? y : val;
};

/** 资助经费变化情况：固定时间窗起点 */
const buildStartDateByRange = (rangeYears) => {
	const n = Number(rangeYears);
	if (n === 10) return "2015-01-01";
	if (n === 5) return "2020-01-01";
	// 兜底：保持原逻辑的“年初”
	const y = new Date().getFullYear() - (Number.isFinite(n) ? n : 0);
	return `${y}-01-01`;
};
const radio1 = ref(true)
const setRadio1 = (val) => {
	if (radio1.value === val) return;
	radio1.value = val;
	// 切换模式：先清空当前模式数据与图表，再按当前年份重新拉数
	if (val) {
		left1RawFund.value = [];
		if (leftChart) {
			leftChart.dispose();
			leftChart = null;
		}
	} else {
		left1RawProject.value = [];
		if (leftChart1) {
			leftChart1.dispose();
			leftChart1 = null;
		}
	}
	handleLeft1YearChange();
	// 切换显示后强制当前图表 resize，确保 canvas 尺寸稳定
	nextTick(() => {
		if (radio1.value) {
			if (leftChart) leftChart.resize();
		} else {
			if (leftChart1) leftChart1.resize();
		}
	});
};
const value1 = ref(2025);
const leftChartRef = ref(null);
const leftChartRef1 = ref(null);
const left1RawFund = ref([]);
const left1RawProject = ref([]);
const left1FundLoading = ref(false);
const left1ProjLoading = ref(false);
const hasLeft1ChartData = computed(() => {
	return radio1.value ? isNonEmptyArray(left1RawFund.value) : isNonEmptyArray(left1RawProject.value);
});
const isLeft1Loading = computed(() => (radio1.value ? left1FundLoading.value : left1ProjLoading.value));

let left1FundReqSeq = 0;
let left1ProjReqSeq = 0;
const handleLeft1YearChange = () => {
	// 根据当前“资助经费/资助项目”切换状态请求对应接口
	if (radio1.value) {
		handleGetFundField();
	} else {
		handleFindCountryProjectAreaList();
	}
};
// 资助体系v2.0:资助领域分布情况:资助经费
const handleGetFundField = async () => {
	invalidateAiContent(aiContentLeft1, isAiLoadingLeft1, left1AiSeq);
	const seq = ++left1FundReqSeq;
	left1FundLoading.value = true;
	try {
		let params = {
			year: normalizeYearParam(value1.value)
		}
		const res = await findFundField(params);
		if (seq !== left1FundReqSeq) return;
		console.log("资助领域分布情况", res);
		if (isSuccessCode(res)) {
			const list = extractArrayData(res);
			left1RawFund.value = list;
			if (list.length) {
				await nextTick();
				initLeftDonut(list, true)
			} else if (leftChart) {
				leftChart.dispose();
				leftChart = null;
			}
		} else {
			left1RawFund.value = [];
			if (leftChart) {
				leftChart.dispose();
				leftChart = null;
			}
		}
	} catch (error) {
		if (seq !== left1FundReqSeq) return;
		console.error("获取资助领域分布情况error", error);
		left1RawFund.value = [];
		if (leftChart) {
			leftChart.dispose();
			leftChart = null;
		}
	} finally {
		if (seq === left1FundReqSeq) {
			left1FundLoading.value = false;
		}
	}
};

//资助体系v2.0:资助领域分布情况:资助项目
const handleFindCountryProjectAreaList = async () => {
	invalidateAiContent(aiContentLeft1, isAiLoadingLeft1, left1AiSeq);
	const seq = ++left1ProjReqSeq;
	left1ProjLoading.value = true;
	try {
		let params = {
			year: normalizeYearParam(value1.value)
		}
		const res = await findCountryProjectAreaList(params);
		if (seq !== left1ProjReqSeq) return;
		console.log("资助领域分布情况", res);
		if (isSuccessCode(res)) {
			const list = extractArrayData(res);
			left1RawProject.value = list;
			if (list.length) {
				await nextTick();
				initLeftDonut(list, false)
			} else if (leftChart1) {
				leftChart1.dispose();
				leftChart1 = null;
			}
		} else {
			left1RawProject.value = [];
			if (leftChart1) {
				leftChart1.dispose();
				leftChart1 = null;
			}
		}
	} catch (error) {
		if (seq !== left1ProjReqSeq) return;
		console.error("获取资助领域分布情况error", error);
		left1RawProject.value = [];
		if (leftChart1) {
			leftChart1.dispose();
			leftChart1 = null;
		}
	} finally {
		if (seq === left1ProjReqSeq) {
			left1ProjLoading.value = false;
		}
	}
};
// 资助领域分布情况
const initLeftDonut = (rawData, show) => {

	const color = [
		'rgba(206, 79, 81, 1)',
		'rgba(145, 202, 255, 1)',
		'rgba(255, 169, 64, 1)',
		'rgba(146, 84, 222, 1)',
		'rgba(92, 219, 211, 1)',
		'rgba(5, 95, 194, 1)'
	];

	const option = {
		tooltip: {
			trigger: 'axis',
			axisPointer: {
				type: 'shadow'
			}
		},
		grid: {
			left: 5,
			right: 0,
			top: 0,
			bottom: 10,
			containLabel: true
		},
		xAxis: {
			type: 'value',
			boundaryGap: [0, 0.01],
			axisLabel: {
				show: false // 不展示X轴文字
			}
		},
		yAxis: {
			type: 'category',
			data: rawData.map(item => item.countryName)
		},
		series: rawData.flatMap(country => {
			return country.fundAreaList.map((area, index) => ({
				name: area.areaName,
				type: 'bar',
				stack: country.countryName,
				itemStyle: {
					color: color[index % color.length]
				},
				data: country.fundAreaList.map(a => a.amount)
			}));
		}).map((seriesItem, index) => ({
			...seriesItem,
			data: seriesItem.data.map((amount, i) => ({
				value: amount,
				name: rawData[i].countryName
			}))
		}))
	};
	if (show == true) {

		if (leftChart) leftChart.dispose();
		leftChart = echarts.init(leftChartRef.value);
		leftChart.setOption(option);
		nextTick(() => leftChart && leftChart.resize());
	} else {

		if (leftChart1) leftChart1.dispose();
		leftChart1 = echarts.init(leftChartRef1.value);
		leftChart1.setOption(option);
		nextTick(() => leftChart1 && leftChart1.resize());
	}

};
const rightChartRef = ref(null);
const rightChartRef1 = ref(null);
const right1RawFund = ref([]);
const right1RawProject = ref([]);
const right1FundLoading = ref(false);
const right1ProjLoading = ref(false);
const hasRight1ChartData = computed(() => {
	return radio2.value ? isNonEmptyArray(right1RawFund.value) : isNonEmptyArray(right1RawProject.value);
});
const isRight1Loading = computed(() => (radio2.value ? right1FundLoading.value : right1ProjLoading.value));
const radio2 = ref(true)
const handleRight1RangeChange = () => {
	// 根据当前“资助经费/资助项目”切换状态请求对应接口
	if (radio2.value) {
		handlegetCountryFundingChange();
	} else {
		handlegetCountryFundProjectChange();
	}
};
const setRadio2 = (val) => {
	if (radio2.value === val) return;
	radio2.value = val;
	// 切换模式：先清空当前模式数据与图表，再按当前时间窗重新拉数
	if (val) {
		right1RawFund.value = [];
		if (rightChart) {
			rightChart.dispose();
			rightChart = null;
		}
	} else {
		right1RawProject.value = [];
		if (rightChart1) {
			rightChart1.dispose();
			rightChart1 = null;
		}
	}
	handleRight1RangeChange();
	// 切换显示后强制当前图表 resize，确保 canvas 尺寸稳定
	nextTick(() => {
		if (radio2.value) {
			if (rightChart) rightChart.resize();
		} else {
			if (rightChart1) rightChart1.resize();
		}
	});
};
// 资助体系v2.0:资助经费变化情况:资助经费 
const handlegetCountryFundingChange = async () => {
	invalidateAiContent(aiContentRight1, isAiLoadingRight1, right1AiSeq);
	try {
		right1FundLoading.value = true;
		let params = {
			startDate: buildStartDateByRange(value.value)
		}
		const res = await getCountryFundingChange(params);
		console.log("资助经费变化情况", res);
		if (isSuccessCode(res)) {
			const list = extractArrayData(res);
			right1RawFund.value = list;
			if (list.length) {
				await nextTick();
				initRightLine(list, true)
			} else if (rightChart) {
				rightChart.dispose();
				rightChart = null;
			}
		} else {
			right1RawFund.value = [];
			if (rightChart) {
				rightChart.dispose();
				rightChart = null;
			}
		}
	} catch (error) {
		console.error("获取资助经费变化情况error", error);
		right1RawFund.value = [];
		if (rightChart) {
			rightChart.dispose();
			rightChart = null;
		}
	} finally {
		right1FundLoading.value = false;
	}
};
//资助体系v2.0:资助经费变化情况:资助项目
const handlegetCountryFundProjectChange = async () => {
	invalidateAiContent(aiContentRight1, isAiLoadingRight1, right1AiSeq);
	try {
		right1ProjLoading.value = true;
		let params = {
			startDate: buildStartDateByRange(value.value)
		}
		const res = await getCountryFundProjectChange(params);
		console.log("资助项目变化情况", res);
		if (isSuccessCode(res)) {
			const list = extractArrayData(res);
			right1RawProject.value = list;
			if (list.length) {
				await nextTick();
				initRightLine(list)
			} else if (rightChart1) {
				rightChart1.dispose();
				rightChart1 = null;
			}
		} else {
			right1RawProject.value = [];
			if (rightChart1) {
				rightChart1.dispose();
				rightChart1 = null;
			}
		}
	} catch (error) {
		console.error("获取资助项目变化情况error", error);
		right1RawProject.value = [];
		if (rightChart1) {
			rightChart1.dispose();
			rightChart1 = null;
		}
	} finally {
		right1ProjLoading.value = false;
	}
};

//项目资助强度分布
const value3 = ref(2025);
const boxplotChartRef = ref(null);
const right2RawStrength = ref([]);
const hasRight2ChartData = computed(() => isNonEmptyArray(right2RawStrength.value));
const handleRight2YearChange = () => {
	handlegetOrgFundStrength();
};
const handlegetOrgFundStrength = async () => {
	invalidateAiContent(aiContentRight2, isAiLoadingRight2, right2AiSeq);
	try {
		let params = {
			year: normalizeYearParam(value3.value)
		}
		const res = await getOrgFundStrength(params);
		console.log("项目资助强度分布", res);
		if (isSuccessCode(res)) {
			const list = extractArrayData(res);
			right2RawStrength.value = list;
			if (list.length) {
				await nextTick();
				initBoxPlot(list)
			} else if (boxplotChart) {
				boxplotChart.dispose();
				boxplotChart = null;
			}
		} else {
			right2RawStrength.value = [];
			if (boxplotChart) {
				boxplotChart.dispose();
				boxplotChart = null;
			}
		}
	} catch (error) {
		console.error("获取项目资助强度分布error", error);
		right2RawStrength.value = [];
		if (boxplotChart) {
			boxplotChart.dispose();
			boxplotChart = null;
		}
	}
};
//项目资助强度分布
const initBoxPlot = (data) => {
	if (!boxplotChartRef.value) {
		console.warn("boxplotChartRef is null");
		return;
	}
	if (boxplotChart) boxplotChart.dispose();
	boxplotChart = echarts.init(boxplotChartRef.value);

	// 提取所有行业名称
	const categories = data.map(item => item.industryName);

	// 初始化数据数组
	const dataUS = [];
	const dataCN = [];

	// 遍历数据，填充每个行业的数据
	data.forEach(item => {
		const { industryName, orgDonationSourceVOList } = item;
		const usData = orgDonationSourceVOList.find(org => org.orgName === "美国")?.amount || 0;
		const cnData = orgDonationSourceVOList.find(org => org.orgName === "中国")?.amount || 0;

		// 生成箱线图所需的五数概括（最小值、Q1、中位数、Q3、最大值）
		dataUS.push([usData, usData, usData, usData, usData]); // 示例数据，实际应根据数据计算
		dataCN.push([cnData, cnData, cnData, cnData, cnData]); // 示例数据，实际应根据数据计算
	});

	// 构建 ECharts 配置
	const option = {
		legend: {
			data: ["美国", "中国"],
			left: 20,
			top: 0,
			itemWidth: 12,
			itemHeight: 12,
			icon: 'circle',
			textStyle: {
				color: "#5F656C",
				fontSize: 14
			}
		},
		tooltip: {
			trigger: "item",
			axisPointer: {
				type: "shadow"
			}
		},
		grid: {
			left: 50,
			right: 20,
			top: 60,
			bottom: 40
		},
		xAxis: {
			type: "category",
			data: categories,
			boundaryGap: true,
			nameGap: 30,
			splitArea: {
				show: false
			},
			axisLine: {
				show: true,
				lineStyle: {
					color: "#E6E6E6"
				}
			},
			axisTick: {
				show: false
			},
			axisLabel: {
				color: "#5F656C",
				fontSize: 14,
				margin: 15
			},
			splitLine: {
				show: false
			}
		},
		yAxis: {
			type: "value",
			splitLine: {
				show: true,
				lineStyle: {
					color: "#F0F2F5",
					type: "solid"
				}
			},
			axisLine: {
				show: false
			},
			axisTick: {
				show: false
			},
			axisLabel: {
				color: "#5F656C",
				fontSize: 14
			}
		},
		series: [
			{
				name: "美国",
				type: "boxplot",
				data: dataUS,
				boxWidth: 30,
				itemStyle: {
					color: "#fff",
					borderColor: "#1890FF",
					borderWidth: 1
				},
				emphasis: {
					itemStyle: {
						borderWidth: 2,
						shadowBlur: 5,
						shadowOffsetX: 1,
						shadowColor: "rgba(0,0,0,0.2)"
					}
				}
			},
			{
				name: "中国",
				type: "boxplot",
				data: dataCN,
				boxWidth: 30,
				itemStyle: {
					color: "#fff",
					borderColor: "#D15054",
					borderWidth: 1
				},
				emphasis: {
					itemStyle: {
						borderWidth: 2,
						shadowBlur: 5,
						shadowOffsetX: 1,
						shadowColor: "rgba(0,0,0,0.2)"
					}
				}
			}
		]
	};

	boxplotChart.setOption(option);
};



let leftChart;
let leftChart1;
let rightChart;
let rightChart1;
let leftSankey;
let boxplotChart;

// ------- AI 解读（默认仅展示 AiButton，悬停后再请求 AI） -------
const isShowAiContentLeft1 = ref(false);
const isShowAiContentLeft2 = ref(false);
const isShowAiContentRight1 = ref(false);
const isShowAiContentRight2 = ref(false);

const aiContentLeft1 = ref("");
const aiContentLeft2 = ref("");
const aiContentRight1 = ref("");
const aiContentRight2 = ref("");

const isAiLoadingLeft1 = ref(false);
const isAiLoadingLeft2 = ref(false);
const isAiLoadingRight1 = ref(false);
const isAiLoadingRight2 = ref(false);

const left1AiAbortController = ref(null);
const left2AiAbortController = ref(null);
const right1AiAbortController = ref(null);
const right2AiAbortController = ref(null);

const AI_LOADING_TEXT = "解读生成中…";
// 用于保证“切换筛选后只写入最新一次解读结果”
const left1AiSeq = ref(0);
const left2AiSeq = ref(0);
const right1AiSeq = ref(0);
const right2AiSeq = ref(0);

const invalidateAiContent = (targetRef, loadingRef, aiSeqRef) => {
	aiSeqRef.value += 1;
	loadingRef.value = false;
	targetRef.value = AI_LOADING_TEXT;
};

const appendAiInterpretationChunk = (targetRef, chunk, loadingText = "解读生成中…") => {
	if (!chunk) return;
	const current = String(targetRef.value || "");
	const base = current === loadingText ? "" : current;
	targetRef.value = base + String(chunk);
};

const getInterpretationTextFromChartResponse = (res) => {
	const list = res?.data;
	const first = Array.isArray(list) ? list[0] : null;
	return (
		first?.["解读"] ||
		first?.["interpretation"] ||
		first?.["analysis"] ||
		first?.["content"] ||
		""
	);
};

const fetchChartInterpretationOnce = async (
	payload,
	targetRef,
	loadingRef,
	aiSeqRef,
	abortControllerRef
) => {
	if (loadingRef.value) return;

	const hasValidContent =
		targetRef.value &&
		targetRef.value !== AI_LOADING_TEXT &&
		targetRef.value !== "解读加载失败" &&
		targetRef.value !== "暂无图表数据";
	if (hasValidContent) return;

	const localSeq = aiSeqRef.value;
	if (abortControllerRef?.value) {
		abortControllerRef.value.abort();
	}
	if (abortControllerRef) {
		abortControllerRef.value = new AbortController();
	}
	loadingRef.value = true;
	targetRef.value = AI_LOADING_TEXT;
	try {
		const res = await getChartAnalysis(
			{ text: JSON.stringify(payload) },
			{
				...(abortControllerRef?.value?.signal ? { signal: abortControllerRef.value.signal } : {}),
				onChunk: (chunk) => {
					if (aiSeqRef.value !== localSeq) return;
					appendAiInterpretationChunk(targetRef, chunk, AI_LOADING_TEXT);
				}
			}
		);
		if (aiSeqRef.value !== localSeq) return;

		const text = getInterpretationTextFromChartResponse(res);
		targetRef.value = text || targetRef.value || "未返回有效解读内容";
	} catch (e) {
		if (aiSeqRef.value !== localSeq) return;
		if (e?.name !== "AbortError") {
			console.error("图表解读请求失败", e);
			targetRef.value = "解读加载失败";
		}
	} finally {
		if (aiSeqRef.value === localSeq) loadingRef.value = false;
		if (abortControllerRef) abortControllerRef.value = null;
	}
};

const buildPayloadLeft1 = () => {
	const raw = radio1.value ? left1RawFund.value : left1RawProject.value;
	if (!Array.isArray(raw) || raw.length === 0) return null;
	return {
		type: "分布图",
		name: radio1.value ? "资助领域分布情况-资助经费" : "资助领域分布情况-资助项目",
		data: raw
	};
};
const buildPayloadLeft2 = () => {
	const raw = left2RawSankey.value;
	if (!Array.isArray(raw) || raw.length === 0) return null;
	return {
		type: "桑基图",
		name: "机构资助领域情况",
		data: raw
	};
};
const buildPayloadRight1 = () => {
	const raw = radio2.value ? right1RawFund.value : right1RawProject.value;
	if (!Array.isArray(raw) || raw.length === 0) return null;
	return {
		type: "折线图",
		name: radio2.value ? "资助经费变化情况-资助经费" : "资助经费变化情况-资助项目",
		data: raw
	};
};
const buildPayloadRight2 = () => {
	const raw = right2RawStrength.value;
	if (!Array.isArray(raw) || raw.length === 0) return null;
	return {
		type: "箱线图",
		name: "项目资助强度分布",
		data: raw
	};
};

const handleSwitchAiLeft1 = async (val) => {
	isShowAiContentLeft1.value = val;
	if (!val) {
		if (left1AiAbortController.value) {
			left1AiAbortController.value.abort();
			left1AiAbortController.value = null;
		}
		isAiLoadingLeft1.value = false;
		return;
	}
	const payload = buildPayloadLeft1();
	if (!payload) {
		aiContentLeft1.value = "暂无图表数据";
		return;
	}
	await fetchChartInterpretationOnce(payload, aiContentLeft1, isAiLoadingLeft1, left1AiSeq, left1AiAbortController);
};
const handleSwitchAiLeft2 = async (val) => {
	isShowAiContentLeft2.value = val;
	if (!val) {
		if (left2AiAbortController.value) {
			left2AiAbortController.value.abort();
			left2AiAbortController.value = null;
		}
		isAiLoadingLeft2.value = false;
		return;
	}
	const payload = buildPayloadLeft2();
	if (!payload) {
		aiContentLeft2.value = "暂无图表数据";
		return;
	}
	await fetchChartInterpretationOnce(payload, aiContentLeft2, isAiLoadingLeft2, left2AiSeq, left2AiAbortController);
};
const handleSwitchAiRight1 = async (val) => {
	isShowAiContentRight1.value = val;
	if (!val) {
		if (right1AiAbortController.value) {
			right1AiAbortController.value.abort();
			right1AiAbortController.value = null;
		}
		isAiLoadingRight1.value = false;
		return;
	}
	const payload = buildPayloadRight1();
	if (!payload) {
		aiContentRight1.value = "暂无图表数据";
		return;
	}
	await fetchChartInterpretationOnce(payload, aiContentRight1, isAiLoadingRight1, right1AiSeq, right1AiAbortController);
};
const handleSwitchAiRight2 = async (val) => {
	isShowAiContentRight2.value = val;
	if (!val) {
		if (right2AiAbortController.value) {
			right2AiAbortController.value.abort();
			right2AiAbortController.value = null;
		}
		isAiLoadingRight2.value = false;
		return;
	}
	const payload = buildPayloadRight2();
	if (!payload) {
		aiContentRight2.value = "暂无图表数据";
		return;
	}
	await fetchChartInterpretationOnce(payload, aiContentRight2, isAiLoadingRight2, right2AiSeq, right2AiAbortController);
};



//资助经费变化情况
const initRightLine = (data, show) => {

	const colorMap = [
		"rgba(20, 89, 187, 1)",
		"rgba(206, 79, 81, 1)",
		"rgba(255, 172, 77, 1)",
		"rgba(19, 168, 168, 1)",
		"rgba(114, 46, 209, 1)"
	];
	// 提取所有年份
	const years = data.map(item => item.year);

	// 提取所有组织名称
	const orgNames = data.flatMap(item => item.fundsOrgList.map(org => org.orgName));
	const uniqueOrgNames = [...new Set(orgNames)];

	// 构建 series 数据
	const series = uniqueOrgNames.map((orgName, index) => {
		const values = years.map(year => {
			const yearData = data.find(d => d.year === year);
			if (yearData) {
				const orgData = yearData.fundsOrgList.find(o => o.orgName === orgName);
				return orgData ? orgData.amount : 0;
			}
			return 0;
		});

		// 提取颜色并设置透明度为 0.2
		const color = colorMap[index % colorMap.length];
		const areaColor = color.replace("1)", "0.2)");

		return {
			name: orgName,
			type: "line",
			data: values,
			smooth: true,
			symbol: "emptyCircle",
			showSymbol: true,
			symbolSize: 6,
			endLabel: {
				show: true,
				formatter: orgName, // 只显示 orgName
				rich: {
					[orgName]: {
						fontSize: 14,
						fontFamily: "Microsoft YaHei",
						fontWeight: 400,
						lineHeight: 22,
						color: color
					}
				}
			},
			areaStyle: { color: areaColor }
		};

	});

	// 构建 ECharts 配置
	const option = {
		color: colorMap,
		grid: { left: 40, right: 80, top: 20, bottom: 40 },
		tooltip: { trigger: "axis" },
		legend: { show: false },
		xAxis: {
			type: "category",
			data: years,
			boundaryGap: false,
			axisLine: { show: false },
			axisTick: { show: false },
			axisLabel: {
				color: "rgba(132, 136, 142, 1)",
				fontSize: 14,
				fontFamily: "Microsoft YaHei",
				fontWeight: 400,
				lineHeight: 22
			}
		},
		yAxis: {
			type: "value",
			min: 0,
			max: 100,
			splitLine: { show: true, lineStyle: { color: "#e6e6e6", type: "dashed" } },
			axisLine: { show: false },
			axisTick: { show: false },
			axisLabel: {
				color: "rgba(132, 136, 142, 1)",
				fontSize: 14,
				fontFamily: "Microsoft YaHei",
				fontWeight: 400,
				lineHeight: 22
			}
		},
		series: series
	};
	if (show == true) {

		if (rightChart) rightChart.dispose();
		rightChart = echarts.init(rightChartRef.value);
		rightChart.setOption(option);
		nextTick(() => rightChart && rightChart.resize());
	} else {

		if (rightChart1) rightChart1.dispose();
		rightChart1 = echarts.init(rightChartRef1.value);
		rightChart1.setOption(option);
		nextTick(() => rightChart1 && rightChart1.resize());
	}
};

const leftSankeyRef = ref(null);
const value2 = ref(2025);
const left2RawSankey = ref([]);
const hasLeft2ChartData = computed(() => isNonEmptyArray(left2RawSankey.value));
// 机构资助领域情况
const handleGetOrgFundsArea = async () => {
	invalidateAiContent(aiContentLeft2, isAiLoadingLeft2, left2AiSeq);
	try {
		let params = {
			year: normalizeYearParam(value2.value)
		}
		const res = await getOrgFundsArea(params);
		console.log("机构资助领域情况", res);
		if (isSuccessCode(res)) {
			const list = extractArrayData(res);
			left2RawSankey.value = list;
			if (list.length) {
				await nextTick();
				initLeftSankey(list)
			} else if (leftSankey) {
				leftSankey.dispose();
				leftSankey = null;
			}
		} else {
			left2RawSankey.value = [];
			if (leftSankey) {
				leftSankey.dispose();
				leftSankey = null;
			}
		}
	} catch (error) {
		console.error("获取机构资助领域情况error", error);
		left2RawSankey.value = [];
		if (leftSankey) {
			leftSankey.dispose();
			leftSankey = null;
		}
	}
};
//机构资助领域情况
const initLeftSankey = (data) => {
	if (!leftSankeyRef.value) return;
	if (leftSankey) leftSankey.dispose();
	leftSankey = echarts.init(leftSankeyRef.value);

	// 提取所有组织名称和行业名称
	const orgNames = new Set();
	const industryNames = new Set();
	const links = [];

	data.forEach(item => {
		const { industryName, usadonationSourceVOList, chinaDonationSourceVOList } = item;
		industryNames.add(industryName);

		// 处理美国捐赠数据
		usadonationSourceVOList.forEach(org => {
			orgNames.add(org.orgName);
			links.push({
				source: org.orgName,
				target: industryName,
				value: org.amount
			});
		});

		// 处理中国捐赠数据
		chinaDonationSourceVOList.forEach(org => {
			orgNames.add(org.orgName);
			links.push({
				source: org.orgName,
				target: industryName,
				value: org.amount
			});
		});
	});

	// 构建节点数组
	const nodes = [
		...Array.from(orgNames).map(name => ({ name })),
		...Array.from(industryNames).map(name => ({ name }))
	];

	// 定义颜色映射
	const colorMap = {
		"国家地理空间情报局": "#722ED1",
		"国际商业机器公司": "#0A57A6",
		"成都海威华芯科技有限公司": "#2266FF",
		"新一代通信技术": "#B05FA0",
		"人工智能": "#5070DD"
	};

	// 构建 ECharts 配置
	const option = {
		tooltip: { trigger: "item" },
		series: [{
			type: "sankey",
			data: nodes.map(node => ({
				name: node.name,
				itemStyle: { color: colorMap[node.name] || "#bbb" }
			})),
			links: links,
			sort: 'none',
			layoutIterations: 0,
			draggable: false,
			nodeAlign: "justify",
			orient: "horizontal",
			/* 整体左移约 20px，并略增右侧留白，避免右侧行业名（如新一代通信网络）被裁切 */
			left: 10,
			right: 130,
			top: 0,
			bottom: 0,
			nodeWidth: 40,
			nodeGap: 10,
			lineStyle: { color: "#E7E7E8", opacity: 0.8, curveness: 0.5 },
			emphasis: { focus: "adjacency" },
			label: {
				show: true,
				color: "rgb(59, 65, 75)",
				fontSize: 14,
				fontFamily: "Microsoft YaHei",
				fontWeight: 400,
				lineHeight: 16,
				formatter: (params) => {
					return params.name;
				},
				position: 'right'
			}
		}]
	};

	leftSankey.setOption(option);
	nextTick(() => leftSankey && leftSankey.resize());
};


// const handleResize = () => {
// 	if (leftChart) leftChart.resize();
// 	if (leftChart1) leftChart1.resize();
// 	if (rightChart) rightChart.resize();
// 	if (leftSankey) leftSankey.resize();
// 	if (boxplotChart) boxplotChart.resize();
// };

onMounted(() => {
	// 仅拉取图表数据；AI 解读仅在用户悬停打开面板时触发
	void handleGetFundField();
	void handleFindCountryProjectAreaList();

	void handlegetCountryFundingChange();
	void handlegetCountryFundProjectChange();

	void handleGetOrgFundsArea();
	void handlegetOrgFundStrength();
});
// onBeforeUnmount(() => {
// 	window.removeEventListener("resize", handleResize);
// 	if (leftChart) {
// 		leftChart.dispose();
// 		leftChart = null;
// 	}
// 	if (leftChart1) {
// 		leftChart1.dispose();
// 		leftChart1 = null;
// 	}
// 	if (rightChart) {
// 		rightChart.dispose();
// 		rightChart = null;
// 	}
// 	if (leftSankey) {
// 		leftSankey.dispose();
// 		leftSankey = null;
// 	}
// 	if (boxplotChart) {
// 		boxplotChart.dispose();
// 		boxplotChart = null;
// 	}
// });
</script>

<style lang="scss" scoped>
* {
	margin: 0;
	padding: 0;
}

.datasub {
	width: 1600px;
	height: 936px;
	display: flex;
	justify-content: space-between;

	.datasub-left {
		width: 792px;
		height: 936px;

		.left {
			width: 792px;
			height: 460px;
			margin-right: 16px;
			margin-bottom: 16px;
			border-radius: 10px;
			box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
			background-color: #fff;

			.left-title {
				width: 792px;
				height: 48px;
				border-bottom: 1px solid rgb(234, 236, 238);
				position: relative;

				img {
					width: 19px;
					height: 19px;
					position: absolute;
					top: 16px;
					left: 21px;
				}

				.tit {
					margin-left: 60px;
					height: 48px;
					padding: 11px 0;
					font-size: 20px;
					font-weight: 700;
					font-family: "Microsoft YaHei";
					line-height: 26px;
					color: rgb(5, 95, 194);
				}

				.select {
					width: 120px;
					height: 28px;
					/* 统一四个下拉框：总宽 120px（含内边距），不影响 right/left 定位与按钮间距 */
					box-sizing: border-box;
					/* padding 放到 el-select__wrapper，避免内部触发器被压缩到 96px */
					padding: 0;
					position: absolute;
					top: 11px;
					right: 38px;
				}

				.select :deep(.el-select__wrapper) {

					min-height: 28px;
					box-sizing: border-box;
					padding: 0 12px;
				}
			}

			.left-main {
				width: 792px;
				height: 412px;
				box-sizing: border-box;
				/* 对齐智库概览-数据总览内边距 */
				padding: 24px 24px 65px 24px;
				position: relative;

				.left-main-echarts {
					width: 100%;
					height: 100%;
				}
			}

			.left-main1 {
				width: 792px;
				height: 412px;
				box-sizing: border-box;
				/* 对齐智库概览-数据总览内边距 */
				padding: 24px 24px 65px 24px;
				position: relative;

				.left-sankey-echarts {
					width: 100%;
					height: 100%;
				}
			}
		}
	}

	.datasub-right {
		width: 792px;
		height: 936px;

		.right {
			width: 792px;
			height: 460px;
			border-radius: 10px;
			margin-bottom: 16px;
			box-shadow: 0px 0px 20px 0px rgba(25, 69, 130, 0.1);
			background-color: #fff;

			.right-title {
				width: 792px;
				height: 48px;
				border-bottom: 1px solid rgb(234, 236, 238);
				position: relative;

				img {
					width: 19px;
					height: 19px;
					position: absolute;
					top: 16px;
					left: 21px;
				}

				.tit {
					margin-left: 60px;
					height: 48px;
					padding: 11px 0;
					font-size: 20px;
					font-weight: 700;
					font-family: "Microsoft YaHei";
					line-height: 26px;
					color: rgb(5, 95, 194);
				}

				.select1 {
					width: 155px;
					height: 28px;
					padding: 0px 12px;
					position: absolute;
					top: 11px;

				}

				.select {
					width: 120px;
					height: 28px;
					/* 统一四个下拉框：总宽 120px（含内边距），不影响 right/left 定位与按钮间距 */
					box-sizing: border-box;
					/* padding 放到 el-select__wrapper，避免内部触发器被压缩到 96px */
					padding: 0;
					position: absolute;
					top: 11px;
					right: 38px;
				}

				.select :deep(.el-select__wrapper) {

					min-height: 28px;
					box-sizing: border-box;
					padding: 0 12px;

				}
			}

			.right-main {
				width: 792px;
				height: 412px;
				box-sizing: border-box;
				/* 对齐智库概览-数据总览内边距 */
				padding: 24px 24px 65px 24px;
				position: relative;

				.right-main-echarts {
					/* 矢量 476 */
					width: 100%;
					height: 100%;
				}

				.right-main-tit {
					position: absolute;
					top: 18px;
					right: 83px;
					font-size: 14px;
					font-weight: 400;
					font-family: "Microsoft YaHei";
					line-height: 22px;
					color: rgb(132, 136, 142);
				}
			}

			.right-main1 {
				width: 792px;
				height: 412px;
				/* 对齐智库概览-数据总览内边距 */
				padding: 24px 24px 65px 24px;
				position: relative;
				box-sizing: border-box;

				.right-boxplot-echarts {
					width: 100%;
					height: 323px;

				}

				.right-main1-tit {
					position: absolute;
					top: 18px;
					right: 31px;
					font-size: 14px;
					font-weight: 400;
					font-family: "Microsoft YaHei";
					line-height: 22px;
					color: rgb(132, 136, 142);
					z-index: 10;
				}
			}
		}
	}
}

/* 数据总览内：TipTab 与 AI 解读（尽量复用智库概览的定位） */
.source {
	position: absolute;
	left: 24px;
	bottom: 21px;
	z-index: 2;
}

.chart-box {
	position: absolute;
	right: 0px;
	bottom: 18px;
	width: 74px;
	height: 28px;
	z-index: 3;

	.btn-box {
		width: 74px;
		height: 28px;
	}

	.content-box {
		width: 792px;
		position: absolute;
		right: 0;
		bottom: -18px;
	}
}

.datasub-el-empty {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0;
	margin: 0;
	z-index: 5;

	:deep(.el-empty__description) {
		margin-top: 8px;
	}
}


/* 参考智库概览页下拉框：不改默认 hover/selected 底色，只给选项文字做左缩进 */
:global(.datasub-select-popper .el-select-dropdown__item) {
	padding-left: 20px;
}

.btn {
	position: absolute;
	top: 11px;

	/* 切换按钮 */

	height: 28px;
	/* 自动布局 */
	display: flex;
	flex-direction: row;
	justify-content: center;
	align-items: center;
	gap: 8;
	padding: 1px 8px 1px 8px;

	color: rgba(59, 65, 75, 1);
	box-sizing: border-box;
	border: 1px solid rgba(230, 231, 232, 1);
	border-radius: 4px;
	background: rgba(255, 255, 255, 1);
	font-family: "Source Han Sans CN";
	font-style: Regular;
	font-size: 16px;
	font-weight: 400;
	line-height: 24px;
	letter-spacing: 0px;
	text-align: left;
}

.btn-select {
	position: absolute;
	top: 11px;
	/* 切换按钮 */

	height: 28px;
	/* 自动布局 */
	display: flex;
	flex-direction: row;
	justify-content: center;
	align-items: center;
	gap: 8;
	padding: 1px 8px 1px 8px;
	color: rgba(5, 95, 194, 1);
	box-sizing: border-box;
	border: 1px solid rgba(5, 95, 194, 1);
	border-radius: 4px;
	background: rgba(231, 243, 255, 1);
	font-family: "Source Han Sans CN";
	font-style: Regular;
	font-size: 16px;
	font-weight: 400;
	line-height: 24px;
	letter-spacing: 0px;
	text-align: left;
}
</style>
