<template>
	<div class="temp-wrap">
		<div class="tools-row">
			<div class="tools-row-left">
				<el-select v-model="curBill" placeholder="请选择版本" @change="handleChangeBill"
					class="tools-row-control tools-row-control--primary tools-row-control--bill">
					<el-option v-for="item in billList" :key="item.value" :label="item.label" :value="item.value" />
				</el-select>
				<el-button class="tools-row-control tools-row-control--primary tools-row-compare-btn"
					@click="handleOpenVersionCompare">
					<img class="tools-row-compare-icon" src="./assets/icons/compare-icon.svg" alt="" />
					<span>版本对比</span>
				</el-button>
			</div>
			<div class="tools-row-right">
				<el-input v-model="searchValue" class="tools-row-control--search" placeholder="搜索条款" clearable
					@keyup.enter="handleSearchSubmit">
					<template #suffix>
						<el-icon class="tools-row-search-icon" @click="handleSearchSubmit">
							<Search />
						</el-icon>
					</template>
				</el-input>
				<div class="tools-row-right-actions">
					<el-checkbox class="tools-row-control" v-model="checkedValue" label="只看涉华条款" size="large"
						@change="handleChangeCheckbox" />
					<el-select v-model="selectedDomain" class="tools-row-control tools-row-control--domain"
						placeholder="全部领域">
						<el-option label="全部领域" value="" />
						<el-option v-for="item in domainOptions" :key="item.value" :label="item.label"
							:value="item.value" />
					</el-select>
					<el-select v-model="selectedLimit" class="tools-row-control tools-row-control--limit"
						placeholder="全部限制手段">
						<el-option label="全部限制手段" value="" />
						<el-option v-for="item in limitOptions" :key="item.value" :label="item.label"
							:value="item.value" />
					</el-select>
				</div>
			</div>
		</div>
		<div class="content-row">
			<div class="side">
				<div class="side-box side-box-domain">
					<AnalysisBox title="涉及领域" width="520px" height="415px" v-loading="domainLoading">
						<div class="chart-ai-wrap">
							<div :class="['right-box2-main', { 'right-box-main--full': !domainFooterText }]" id="chart2"></div>
							<div class="overview-tip-row">
								<TipTab class="overview-tip" :text="'涉华科技法案数量及通过率变化趋势，数据来源：美国国会官网'"/>
								<AiButton class="overview-tip-action" @mouseenter="handleShowAiPane('domain')" />
							</div>
							<div v-if="aiPaneVisible.domain" class="overview-ai-pane"
								@mouseleave="handleHideAiPane('domain')">
								<AiPane :aiContent="overviewAiContent.domain" />
							</div>
						</div>
						<div v-if="domainFooterText" class="right-box2-footer">
							<div class="right-box2-footer-left">
								<img src="./assets/icons/right-icon1.png" alt="" />
							</div>
							<div class="right-box2-footer-center">
								{{ domainFooterText }}
							</div>
							<div class="right-box2-footer-right">
								<img src="./assets/icons/arrow-right.png" alt="" />
							</div>
						</div>
					</AnalysisBox>
				</div>
				<div class="side-box side-box-limit">
					<AnalysisBox title="限制手段" width="520px" height="415px" v-loading="limitLoading">
						<div class="chart-ai-wrap">
							<div :class="['right-box1-main', { 'right-box-main--full': !limitFooterText }]" id="chart1"></div>
							<div class="overview-tip-row">
								<TipTab class="overview-tip" :text="'涉华科技法案数量及通过率变化趋势，数据来源：美国国会官网'"/>
								<AiButton class="overview-tip-action" @mouseenter="handleShowAiPane('limit')" />
							</div>
							<div v-if="aiPaneVisible.limit" class="overview-ai-pane"
								@mouseleave="handleHideAiPane('limit')">
								<AiPane :aiContent="overviewAiContent.limit" />
							</div>
						</div>
						<div v-if="limitFooterText" class="right-box1-footer">
							<div class="right-box1-footer-left">
								<img src="./assets/icons/right-icon1.png" alt="" />
							</div>
							<div class="right-box1-footer-center">
								{{ limitFooterText }}
							</div>
							<div class="right-box1-footer-right">
								<img src="./assets/icons/arrow-right.png" alt="" />
							</div>
						</div>
					</AnalysisBox>
				</div>
			</div>
			<div class="terms">
				<div class="terms-switch">
					<span class="terms-switch-label">高亮实体</span>
					<el-switch
						v-model="termsHighlight"
						inline-prompt
						active-text="开"
						inactive-text="关"
					/>
					<span class="terms-switch-divider"></span>
					<span class="terms-switch-label">显示原文</span>
					<el-switch
						v-model="termsShowOriginal"
						inline-prompt
						active-text="开"
						inactive-text="关"
					/>
				</div>
				<AnalysisBox title="主要条款" :showAllBtn="false" v-loading="termsLoading">
					<div class="left-main">
						<div class="left-main-item" v-for="(term, index) in displayTermsList" :key="getTermKey(term, index)">
							<div class="term-body">
								<div class="term-index">{{ getTermSerial(index) }}</div>
								<div class="term-main">
									<div class="term-row term-row-cn">
										<div class="term-no-cn">第{{ term.tkxh }}条.</div>
										<div class="term-content-cn" v-html="getTermContentHtml(term, 'cn')"></div>
									</div>
									<div class="term-row term-row-en" v-if="termsShowOriginal">
										<div class="term-no-en">Sec.{{ term.tkxh }}</div>
										<div class="term-content-en" v-html="getTermContentHtml(term, 'en')"></div>
									</div>
								</div>
							</div>
							<!-- <div class="open">
							<img src="./assets/icons/open-icon.png" alt="" />
						</div> -->
						</div>
					</div>
					<div class="left-footer">
						<div class="left-footer-text">
							{{ `共 ${total} 项` }}
						</div>
						<div class="left-footer-right">
							<el-pagination background layout="prev, pager, next" :total="total"
								v-model:current-page="currentPage" v-model:page-size="pageSize"
								@current-change="handleCurrentChange" />
						</div>
					</div>
				</AnalysisBox>
			</div>
		</div>
	</div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, computed, watch } from "vue";
import { useRoute, onBeforeRouteLeave } from "vue-router";
import * as echarts from "echarts";
import { Search } from "@element-plus/icons-vue";
import getPieChart from "./utils/piechart";
import { getBillContentId, getBillContentTk, getBillContentXzfs, getBillHyly } from "@/api/bill";
import { getChartAnalysis } from "@/api/aiAnalysis/index";
import TipTab from "@/components/base/TipTab/index.vue";
import AiButton from "@/components/base/Ai/AiButton/index.vue";
import AiPane from "@/components/base/Ai/AiPane/index.vue";
import { MUTICHARTCOLORS } from "@/common/constant";
import { extractTextEntity } from "@/api/intelligent/index";


const route = useRoute();
const pageAbortController = new AbortController();

const isRequestCanceled = error => {
	return (
		error?.code === "ERR_CANCELED" ||
		error?.name === "CanceledError" ||
		error?.name === "AbortError" ||
		(typeof error?.message === "string" && /canceled|aborted/i.test(error.message))
	);
};

const getPageSignal = () => pageAbortController.signal;

const stopCurrentPageRequests = () => {
	pageAbortController.abort();
	// 让旧请求回调全部失效，避免离开页面后回写状态
	tkRequestToken.value += 1;
	xzfsRequestToken.value += 1;
	hylyRequestToken.value += 1;
	entityRequestToken.value += 1;
	termsLoading.value = false;
	limitLoading.value = false;
	domainLoading.value = false;
	aiPaneLoading.value = { domain: false, limit: false };
};

const curBill = ref("");
const curBillId = ref(null);
const checkedValue = ref(false);
const searchValue = ref("");
const searchKeyword = ref("");
const selectedDomain = ref("");
const selectedLimit = ref("");
const domainOptions = ref([]);
const limitOptions = ref([]);
const billList = ref([]);
const currentPage = ref(1);
const pageSize = ref(10);
const total = ref(0);

const termsLoading = ref(false);
const limitLoading = ref(false);
const domainLoading = ref(false);

const termsHighlight = ref(true);
const termsShowOriginal = ref(true);

const entityRequestToken = ref(0);
const termEntityCache = ref(new Map());

const escapeHtml = value => {
	const str = String(value ?? "");
	return str
		.replace(/&/g, "&amp;")
		.replace(/</g, "&lt;")
		.replace(/>/g, "&gt;")
		.replace(/"/g, "&quot;")
		.replace(/'/g, "&#39;");
};

const normalizeEntities = entities => {
	const list = Array.isArray(entities) ? entities : [];
	return list
		.map(item => {
			return {
				text_span: String(item?.text_span ?? "").trim(),
				type: String(item?.type ?? "").trim()
			};
		})
		.filter(item => item.text_span);
};

const getEntityRanges = (text, entities) => {
	const ranges = [];
	const rawText = String(text ?? "");
	if (!rawText) return ranges;

	const list = normalizeEntities(entities).sort((a, b) => b.text_span.length - a.text_span.length);
	for (const ent of list) {
		let startIndex = 0;
		while (startIndex < rawText.length) {
			const idx = rawText.indexOf(ent.text_span, startIndex);
			if (idx === -1) break;
			ranges.push({ start: idx, end: idx + ent.text_span.length, ent });
			startIndex = idx + ent.text_span.length;
		}
	}
	ranges.sort((a, b) => a.start - b.start || b.end - a.end);

	const merged = [];
	let lastEnd = 0;
	for (const r of ranges) {
		if (r.start < lastEnd) continue;
		merged.push(r);
		lastEnd = r.end;
	}
	return merged;
};

const buildHighlightedHtml = (text, entities, enableHighlight) => {
	const rawText = String(text ?? "");
	if (!rawText) return "";

	const safeText = escapeHtml(rawText).replace(/\n/g, "<br />");
	if (!enableHighlight) return safeText;

	const ranges = getEntityRanges(rawText, entities);
	if (!ranges.length) return safeText;

	let html = "";
	let cursor = 0;
	for (const r of ranges) {
		if (cursor < r.start) {
			html += escapeHtml(rawText.slice(cursor, r.start));
		}
		const spanText = rawText.slice(r.start, r.end);
		const type = escapeHtml(r.ent?.type ?? "");
		html += `<span class="term-entity" data-entity-type="${type}">${escapeHtml(spanText)}</span>`;
		cursor = r.end;
	}
	if (cursor < rawText.length) {
		html += escapeHtml(rawText.slice(cursor));
	}
	return html.replace(/\n/g, "<br />");
};

const getTermEntityKey = (term, lang) => {
	const baseKey = getTermKey(term, -1);
	return `${baseKey}__${lang}`;
};

const ensureEntitiesForTerms = async terms => {
	if (!termsHighlight.value) return;
	const list = Array.isArray(terms) ? terms : [];
	if (!list.length) return;

	const currentToken = ++entityRequestToken.value;

	const tasks = [];
	for (const term of list) {
		const cnKey = getTermEntityKey(term, "cn");
		const enKey = getTermEntityKey(term, "en");
		if (!termEntityCache.value.has(cnKey) && String(term?.fynr ?? "").trim()) {
			tasks.push({ key: cnKey, text: term.fynr });
		}
		if (!termEntityCache.value.has(enKey) && String(term?.ywnr ?? "").trim()) {
			tasks.push({ key: enKey, text: term.ywnr });
		}
	}
	if (!tasks.length) return;

	try {
		const results = await Promise.all(
			tasks.map(async item => {
				const res = await extractTextEntity(item.text, { signal: getPageSignal() });
				const entities = normalizeEntities(res?.result ?? res?.data?.result ?? res?.data ?? res);
				return { key: item.key, entities };
			})
		);
		if (currentToken !== entityRequestToken.value) return;
		for (const r of results) {
			termEntityCache.value.set(r.key, r.entities);
		}
	} catch (error) {
		if (currentToken !== entityRequestToken.value) return;
	}
};

const getTermContentHtml = (term, lang) => {
	const raw = lang === "en" ? term?.ywnr : term?.fynr;
	const key = getTermEntityKey(term, lang);
	const entities = termEntityCache.value.get(key) || [];
	return buildHighlightedHtml(raw, entities, termsHighlight.value);
};

const tkRequestToken = ref(0);
const xzfsRequestToken = ref(0);
const hylyRequestToken = ref(0);

const mainTermsList = ref([]);
const domainFooterText = ref("");
const limitFooterText = ref("");
const btnActiveIndex = ref(1);
const handleSelectBtn = index => {
	btnActiveIndex.value = index;
};

const getTermKey = (term, index) => {
	return term?.ywid ?? term?.id ?? term?.tkxh ?? index;
};

const getTermSerial = index => {
	return (currentPage.value - 1) * pageSize.value + index + 1;
};

const chart1Data = ref([]);
const chart1ColorList = ref([...MUTICHARTCOLORS]);

const chart2ColorList = ref([...MUTICHARTCOLORS]);

const chart2Data = ref([]);

const aiPaneVisible = ref({
	domain: false,
	limit: false
});

const overviewAiContent = ref({
	domain: "智能总结生成中...",
	limit: "智能总结生成中..."
});

const aiPaneFetched = ref({
	domain: false,
	limit: false
});

const aiPaneLoading = ref({
	domain: false,
	limit: false
});

const displayTermsList = computed(() => {
	const keyword = (searchKeyword.value || "").trim().toLowerCase();
	const domain = selectedDomain.value;
	const limit = selectedLimit.value;
	return (mainTermsList.value || []).filter(term => {
		if (keyword) {
			const cn = String(term?.fynr ?? "").toLowerCase();
			const en = String(term?.ywnr ?? "").toLowerCase();
			const no = String(term?.tkxh ?? "").toLowerCase();
			if (!cn.includes(keyword) && !en.includes(keyword) && !no.includes(keyword)) return false;
		}
		if (domain) {
			const list = term?.hylyList || term?.hyly || [];
			const arr = Array.isArray(list) ? list : [];
			if (!arr.includes(domain)) return false;
		}
		if (limit) {
			const list = term?.xzfsList || term?.xzfs || [];
			const arr = Array.isArray(list) ? list : [];
			if (!arr.includes(limit)) return false;
		}
		return true;
	});
});

watch([selectedDomain, selectedLimit], () => {
	currentPage.value = 1;
	handleGetBillContentTk(checkedValue.value ? "Y" : "N");
});

watch(
	[termsHighlight, termsShowOriginal],
	() => {
		ensureEntitiesForTerms(displayTermsList.value);
	},
	{ immediate: true }
);

const buildAiChartPayload = key => {
	if (key === "domain") {
		return {
			type: "饼图",
			name: "涉及领域",
			data: (chart2Data.value || []).map(item => ({
				industry_name: item.name,
				count_bill: Number(item.value || 0)
			}))
		};
	}
	if (key === "limit") {
		return {
			type: "饼图",
			name: "限制手段",
			data: (chart1Data.value || []).map(item => ({
				industry_name: item.name,
				count_bill: Number(item.value || 0)
			}))
		};
	}
	return { type: "", name: "", data: [] };
};

const requestAiPaneContent = async key => {
	if (!key || aiPaneLoading.value[key] || aiPaneFetched.value[key]) return;
	aiPaneLoading.value = { ...aiPaneLoading.value, [key]: true };
	overviewAiContent.value = { ...overviewAiContent.value, [key]: "智能总结生成中..." };

	try {
		const payload = buildAiChartPayload(key);
		const res = await getChartAnalysis(
			{ text: JSON.stringify(payload) },
			{
				signal: getPageSignal(),
				onChunk: chunk => {
					const current = overviewAiContent.value[key];
					const base = current === "智能总结生成中..." ? "" : current;
					overviewAiContent.value = {
						...overviewAiContent.value,
						[key]: base + chunk
					};
				}
			}
		);
		const list = res?.data;
		const first = Array.isArray(list) ? list[0] : null;
		const interpretation = first?.解读 || first?.["解读"];
		if (interpretation) {
			overviewAiContent.value = {
				...overviewAiContent.value,
				[key]: interpretation
			};
		}
		aiPaneFetched.value = { ...aiPaneFetched.value, [key]: true };
	} catch (error) {
		if (isRequestCanceled(error)) return;
		console.error("获取图表解读失败", error);
		overviewAiContent.value = { ...overviewAiContent.value, [key]: "智能总结生成失败" };
	} finally {
		aiPaneLoading.value = { ...aiPaneLoading.value, [key]: false };
	}
};

const handleShowAiPane = key => {
	aiPaneVisible.value = {
		...aiPaneVisible.value,
		[key]: true
	};
	requestAiPaneContent(key);
};

const handleHideAiPane = key => {
	aiPaneVisible.value = {
		...aiPaneVisible.value,
		[key]: false
	};
};

const handleSearchSubmit = () => {
	searchKeyword.value = searchValue.value;
	currentPage.value = 1;
	handleGetBillContentTk(checkedValue.value ? "Y" : "N");
};

// 绘制echarts图表
const setChart = (option, chartId) => {
	let chartDom = document.getElementById(chartId);
	chartDom.removeAttribute("_echarts_instance_");
	let chart = echarts.init(chartDom);
	chart.setOption(option);
	return chart;
};

// 切换原文
const handleChangeBill = val => {
	curBill.value = val;
	const item = billList.value.find(item => item.value === val);
	if (item) {
		curBillId.value = item.value;
		selectedDomain.value = "";
		selectedLimit.value = "";
		currentPage.value = 1;
		handleGetBillContentTk(checkedValue.value ? "Y" : "N");
		handleGetBillContentXzfs();
		handleGetBillHyly();
	}
};

const handleOpenVersionCompare = () => {
	const targetUrl = `/billLayout/versionCompare?billId=${route.query.billId}`;
	window.open(targetUrl, "_blank");
};

// 获取法案id列表
const handleGetBillList = async () => {
	const params = {
		id: route.query.billId
	};
	try {
		const res = await getBillContentId(params, { signal: getPageSignal() });
		console.log("法案id列表", res);
		const rawList = Array.isArray(res?.data) ? res.data : [];
		const seen = new Set();
		billList.value = rawList
			.map(item => {
				return {
					label: item.contentZh,
					value: item.contentZh
				};
			})
			.filter(item => {
				const uniqKey = `${item.value ?? ""}`;
				if (seen.has(uniqKey)) return false;
				seen.add(uniqKey);
				return true;
			});
		if (billList.value.length > 0) {
			curBill.value = billList.value[0].value;
			curBillId.value = billList.value[0].value;
		}
	} catch (error) { }
};

const handleChangeCheckbox = val => {
	currentPage.value = 1;
	handleGetBillContentTk(val ? "Y" : "N");
	handleGetBillContentXzfs();
	handleGetBillHyly();
};

const handleCurrentChange = val => {
	currentPage.value = val;
	handleGetBillContentTk(checkedValue.value ? "Y" : "N");
};

// 根据原文ID获取条款列表
const handleGetBillContentTk = async cRelated => {
	const currentToken = ++tkRequestToken.value;
	termsLoading.value = true;

	const params = {
		billId: route.query.billId,
		id: curBill.value,
		cRelated: cRelated,
		pageSize: pageSize.value,
		currentPage: currentPage.value
	};

	if (selectedDomain.value) {
		params.domainNameList = selectedDomain.value;
	}

	if (selectedLimit.value) {
		params.measuresNameList = selectedLimit.value;
	}

	if (searchKeyword.value && searchKeyword.value.trim()) {
		params.content = searchKeyword.value.trim();
	}
	try {
		const res = await getBillContentTk(params, { signal: getPageSignal() });
		if (currentToken !== tkRequestToken.value) {
			return;
		}
		console.log("条款内容", res);
		if (res && res.data) {
			mainTermsList.value = (res.data.content || []).map(item => {
				// 处理 fynr
				if (item.fynr) {
					const matchComplex = item.fynr.match(
						/^(?:正文内容[:：]\s*)?[“"]?\s*第\s*([0-9a-zA-Z]+)\s*[条节][:：\.\。]?[”"]?\s*/
					);
					if (matchComplex) {
						// 匹配 "第xxx条"、"正文内容：第xxx条"、"“第xxx条" 等
						if (!item.tkxh) {
							item.tkxh = matchComplex[1];
						}
						item.fynr = item.fynr.replace(matchComplex[0], "");
					} else {
						// 匹配 "xxx."
						item.fynr = item.fynr.replace(/^\d+\.\s*/, "");
					}
				}
				// 处理 ywnr
				if (item.ywnr) {
					const matchSec = item.ywnr.match(/^(?:SEC\.|SECTION)\s*([0-9a-zA-Z]+)[\.:]?\s*/i);
					if (matchSec) {
						if (!item.tkxh) {
							item.tkxh = matchSec[1];
						}
						item.ywnr = item.ywnr.replace(matchSec[0], "");
					} else {
						item.ywnr = item.ywnr.replace(/^\d+\.\s*/, "");
					}
				}
				// 处理 tkxh 末尾的点
				if (item.tkxh) {
					item.tkxh = item.tkxh.replace(/\.$/, "");
				}
				return item;
			});
			total.value = res.data.totalElements || 0;
			ensureEntitiesForTerms(mainTermsList.value);
		} else {
			mainTermsList.value = [];
			total.value = 0;
		}
	} catch (error) {
		if (isRequestCanceled(error)) {
			return;
		}
		if (currentToken !== tkRequestToken.value) {
			return;
		}
		console.error("获取条款内容失败", error);
		mainTermsList.value = [];
		total.value = 0;
	} finally {
		if (currentToken === tkRequestToken.value) {
			termsLoading.value = false;
		}
	}
};

// 获取限制方式列表
const handleGetBillContentXzfs = async () => {
	const currentToken = ++xzfsRequestToken.value;
	limitLoading.value = true;

	const params = {
		billId: route.query.billId,
		versionId: curBill.value,
		cRelated: checkedValue.value ? "Y" : "N"
	};

	try {
		const res = await getBillContentXzfs(params, { signal: getPageSignal() });
		if (currentToken !== xzfsRequestToken.value) {
			return;
		}
		console.log("限制方式", res);
		const limitSeen = new Set();
		limitOptions.value = (res?.data || [])
			.map(item => item?.xzfsmc)
			.filter(Boolean)
			.filter(name => {
				if (limitSeen.has(name)) return false;
				limitSeen.add(name);
				return true;
			})
			.map(name => {
				return { label: name, value: name };
			});
		chart1Data.value = res.data.map(item => {
			return {
				name: item.xzfsmc,
				value: item.countTk
			};
		});
		aiPaneFetched.value = { ...aiPaneFetched.value, limit: false };
		let chart1 = getPieChart(chart1Data.value, chart1ColorList.value);
		setChart(chart1, "chart1");
	} catch (error) {
		if (isRequestCanceled(error)) {
			return;
		}
		if (currentToken !== xzfsRequestToken.value) {
			return;
		}
	} finally {
		if (currentToken === xzfsRequestToken.value) {
			limitLoading.value = false;
		}
	}
};

// 行业领域
const handleGetBillHyly = async () => {
	const currentToken = ++hylyRequestToken.value;
	domainLoading.value = true;

	const params = {
		billId: route.query.billId,
		versionId: curBill.value,
		cRelated: checkedValue.value ? "Y" : "N"
	};

	try {
		const res = await getBillHyly(params, { signal: getPageSignal() });
		if (currentToken !== hylyRequestToken.value) {
			return;
		}
		console.log("行业领域", res.data);
		const domainSeen = new Set();
		domainOptions.value = (res?.data || [])
			.map(item => item?.hylymc)
			.filter(Boolean)
			.filter(name => {
				if (domainSeen.has(name)) return false;
				domainSeen.add(name);
				return true;
			})
			.map(name => {
				return { label: name, value: name };
			});
		chart2Data.value = res.data.map(item => {
			return {
				name: item.hylymc,
				value: item.countTk
			};
		});
		aiPaneFetched.value = { ...aiPaneFetched.value, domain: false };

		let chart2 = getPieChart(chart2Data.value, chart2ColorList.value);
		setChart(chart2, "chart2");
	} catch (error) {
		if (isRequestCanceled(error)) {
			return;
		}
		if (currentToken !== hylyRequestToken.value) {
			return;
		}
	} finally {
		if (currentToken === hylyRequestToken.value) {
			domainLoading.value = false;
		}
	}
};

onMounted(async () => {
	await handleGetBillList();
	handleGetBillContentTk("N");
	await handleGetBillContentXzfs();
	await handleGetBillHyly();
});

onBeforeRouteLeave(() => {
	stopCurrentPageRequests();
});

onBeforeUnmount(() => {
	stopCurrentPageRequests();
});
</script>

<style lang="scss" scoped>
.temp-wrap {
	display: flex;
	flex-direction: column;

	.tools-row {
		margin-top: 16px;
		display: flex;
		align-items: center;

		.tools-row-left {
			width: 520px;
			display: flex;
			align-items: center;
			justify-content: space-between;
			column-gap: 16px;
		}

		.tools-row-right {
			width: 1064px;
			margin-left: 16px;
			display: flex;
			align-items: center;
			column-gap: 16px;
		}

		.tools-row-right-actions {
			margin-left: auto;
			display: flex;
			align-items: center;
			column-gap: 16px;
		}

		.tools-row-control {
			height: 32px;
			font-size: 16px;
			font-weight: 400;

			:deep(.el-select__wrapper) {
				height: 32px;
				font-size: 16px;
				font-weight: 400;
			}

			:deep(.el-checkbox__label) {
				font-size: 16px;
				font-weight: 400;
			}
		}

		.tools-row-control--primary {
			:deep(.el-select__wrapper) {
				background: rgb(246, 250, 255);
				border: 1px solid var(--color-primary-35);
				box-shadow: none;
				color: var(--color-primary-100);
			}

			:deep(.el-select__selected-item) {
				color: var(--color-primary-100);
				font-size: 16px;
				font-weight: 400;
			}

			:deep(.el-select__caret) {
				color: var(--color-primary-100);
			}
		}

		:deep(.el-button.tools-row-control--primary) {
			height: 32px;
			padding: 0 12px;
			border: 1px solid var(--color-primary-35);
			background: rgb(246, 250, 255);
			color: var(--color-primary-100);
			font-size: 16px;
			font-weight: 400;
			width: 111px;
		}

		.tools-row-compare-btn {
			display: inline-flex;
			align-items: center;
		}

		.tools-row-compare-icon {
			width: 14px;
			height: 14px;
			flex: 0 0 14px;
			margin-right: 6px;
		}

		.tools-row-control--bill {
			width: 392px;
		}

		.tools-row-control--search {
			width: 200px;
			margin-right: auto;

			:deep(.el-input__wrapper) {
				height: 32px;
				background: var(--el-fill-color-blank);
				border-radius: 4px;
				box-shadow: 0 0 0 1px var(--el-border-color) inset;
			}

			:deep(.el-input__wrapper.is-focus) {
				box-shadow: 0 0 0 1px var(--el-color-primary) inset !important;
				border-color: var(--el-color-primary) !important;
			}

			:deep(.el-input__wrapper:not(.is-focus):hover) {
				box-shadow: 0 0 0 1px var(--el-border-color) inset !important;
				border-color: var(--el-border-color) !important;
			}

			:deep(.el-input__inner) {
				font-size: 16px;
			}
		}

		.tools-row-search-icon {
			cursor: pointer;
		}

		.tools-row-control--domain,
		.tools-row-control--limit {
			width: 150px;
		}
	}

	.content-row {
		display: flex;
	}

	.box-header {
		display: flex;
		position: relative;
		height: 50px;

		.box-header-left {
			margin-top: 18px;
			width: 8px;
			height: 20px;
			border-radius: 0 4px 4px 0;
			background: var(--color-main-active);
		}

		.box-header-title {
			margin-left: 14px;
			margin-top: 14px;
			height: 26px;
			color: var(--color-main-active);
			font-family: Microsoft YaHei;
			font-size: 20px;
			font-weight: 700;
			line-height: 26px;
			letter-spacing: 0px;
			text-align: left;
		}

		.box-header-btn-box {
			position: absolute;
			top: 14px;
			right: 52px;
			display: flex;
			justify-content: flex-end;

			.btn {
				margin-left: 8px;
				padding: 0;
			}
		}

		.header-right {
			position: absolute;
			top: 14px;
			right: 12px;
			display: flex;
			justify-content: flex-end;
			gap: 4px;

			.icon {
				width: 28px;
				height: 28px;

				img {
					width: 100%;
					height: 100%;
				}
			}
		}
	}

	.terms {
		margin-top: 16px;
		margin-left: 16px;
		width: 1064px;
		height: 1232px;
		position: relative;

		.terms-switch {
			position: absolute;
			top: 13px;
			right: 85px;
			z-index: 5;
			display: flex;
			column-gap: 6px;
			align-items: center;

			.terms-switch-label {
				font-size: 16px;
				color: var(--text-primary-65-color);
			}

			.terms-switch-divider {
				display: inline-block;
				width: 1px;
				height: 14px;
				background: var(--el-border-color);
				margin: 0 2px;
			}

			:deep(.el-button--small) {
				height: 26px;
				padding: 0 10px;
				font-size: 12px;
			}
		}

		:deep(.wrapper-main) {
			display: flex;
			flex-direction: column;
			height: calc(100% - 45px);
			gap:16px;
		}

		.left-main {
			flex: 1;
			min-height: 0;
			overflow-y: auto;
			display: flex;
			flex-direction: column;
			gap: 12px;
			padding: 0 16px;

				.left-main-item {
				width: 1016px;
				box-sizing: border-box;
				border-radius: 2px;
				background: rgb(247, 248, 249);
				display: flex;
				align-items: flex-start;
				position: relative;
				padding: 16px;

				.term-body {
					display: flex;
					column-gap: 18px;
					flex: 1;
					min-width: 0;
					width: 100%;
				}

				.term-index {
					width: 24px;
					height: 24px;
					border-radius: 50%;
					background: var(--color-primary-10);
					color: var(--color-primary-100);
					font-size: 12px;
					font-weight: 400;
					line-height: 24px;
					text-align: center;
					flex: 0 0 24px;
				}

				.term-main {
					flex: 1;
					min-width: 0;
					display: flex;
					flex-direction: column;
					row-gap: 6px;
				}

				.term-row {
					display: flex;
					align-items: flex-start;
					column-gap: 18px;
				}

				.term-no-cn {
					font-size: 16px;
					font-weight: 700;
					line-height: 24px;
					color: var(--color-primary-100);
					white-space: nowrap;
					width: 90px;
					text-align: center;
					flex: 0 0 90px;
				}

				.term-no-en {
					font-size: 14px;
					font-weight: 400;
					line-height: 24px;
					color: var(--color-primary-100);
					white-space: nowrap;
					width: 90px;
					text-align: center;
					flex: 0 0 90px;
				}

				.term-content-cn {
					flex: 1;
					font-size: 16px;
					font-weight: 700;
					line-height: 24px;
					color: var(--text-primary-80-color);

					:deep(.term-entity) {
						display: inline;
						padding: 0 2px;
						border-radius: 4px;
						background: rgba(255, 213, 79, 0.35);
						box-shadow: inset 0 0 0 1px rgba(255, 193, 7, 0.25);
					}
				}

				.term-content-en {
					flex: 1;
					font-size: 14px;
					font-weight: 400;
					line-height: 24px;
					color: var(--text-primary-65-color);

					:deep(.term-entity) {
						display: inline;
						padding: 0 2px;
						border-radius: 4px;
						background: rgba(255, 213, 79, 0.28);
						box-shadow: inset 0 0 0 1px rgba(255, 193, 7, 0.2);
					}
				}

				.open {
					position: absolute;
					top: 22px;
					right: 23px;
					width: 20px;
					height: 20px;

					img {
						width: 100%;
						height: 100%;
					}
				}
			}

			.left-main-item:nth-child(2n-1) {
				background: rgba(249, 250, 252, 1);
			}
		}

		.left-footer {
			margin: 0 16px 16px;
			height: 40px;
			display: flex;
			justify-content: space-between;

			.left-footer-text {
				margin-top: 6px;
				height: 18px;
				color: rgba(132, 136, 142, 1);
				font-family: Microsoft YaHei;
				font-size: 14px;
				font-weight: 400;
				line-height: 18px;
				letter-spacing: 0px;
				text-align: left;
			}
		}
	}

	.side {
		width: 520px;
		margin-top: 16px;

		.side-box {
			width: 520px;
		}

		.chart-ai-wrap {
			position: relative;
			display: flex;
			flex-direction: column;
		}

		.overview-tip-row {
			margin-top: 10px;
			position: relative;
			display: flex;
			align-items: center;
			justify-content: center;
		}

		.overview-tip-action {
			position: absolute;
			right: 0px;
		}

		.overview-ai-pane {
			position: absolute;
			left: 0;
			bottom: -22px;
			width: 100%;
			z-index: 3;
			pointer-events: none;

			:deep(.ai-pane-wrapper) {
				pointer-events: auto;
			}
		}

		.side-box-limit {
			margin-top: 15px;
			width: 520px;
			height: 415px;

			.right-box1-main {
				width: 520px;
				height: 275px;
				padding: 16px;
			}

			.right-box-main--full {
				height: 315px;
			}

			.right-box1-footer {
				width: 493px;
				height: 40px;
				display: flex;
				border: 1px solid rgba(231, 241, 255, 1);
				border-radius: 4px;
				background: rgba(246, 251, 255, 1);
				margin-left: 13px;

				.right-box1-footer-left {
					margin-top: 10px;
					margin-left: 12px;
					width: 19px;
					height: 20px;

					img {
						width: 100%;
						height: 100%;
					}
				}

				.right-box1-footer-center {
					margin-left: 13px;
					margin-top: 8px;
					width: 400px;
					height: 24px;
					color: var(--color-main-active);
					font-family: Microsoft YaHei;
					font-size: 14px;
					font-weight: 400;
					line-height: 24px;
					overflow: hidden;
				}

				.right-box1-footer-right {
					margin-left: 13px;
					margin-top: 8px;
					width: 24px;
					height: 24px;
					background: rgba(231, 241, 255, 1);
					border-radius: 12px;
					background: #e7f1ff;
					box-sizing: border-box;
					padding: 3px;

					img {
						width: 100%;
						height: 100%;
					}
				}
			}
		}

		.side-box-domain {
			width: 520px;
			height: 415px;

			.right-box2-main {
				width: 520px;
				height: 275px;
				padding: 16px;
			}

			.right-box-main--full {
				height: 315px;
			}

			.right-box2-footer {
				width: 493px;
				height: 40px;
				display: flex;
				border: 1px solid rgba(231, 241, 255, 1);
				border-radius: 4px;
				background: rgba(246, 251, 255, 1);
				margin-left: 13px;

				.right-box2-footer-left {
					margin-top: 10px;
					margin-left: 12px;
					width: 19px;
					height: 20px;

					img {
						width: 100%;
						height: 100%;
					}
				}

				.right-box2-footer-center {
					margin-left: 13px;
					margin-top: 8px;
					width: 400px;
					height: 24px;
					color: var(--color-main-active);
					font-family: Microsoft YaHei;
					font-size: 14px;
					font-weight: 400;
					line-height: 24px;
				}

				.right-box2-footer-right {
					margin-left: 13px;
					margin-top: 8px;
					width: 24px;
					height: 24px;
					background: rgba(231, 241, 255, 1);
					border-radius: 12px;
					background: #e7f1ff;
					box-sizing: border-box;
					padding: 3px;

					img {
						width: 100%;
						height: 100%;
					}
				}
			}
		}
	}
}

:deep(.el-checkbox__label) {
	font-size: 16px !important;
}
</style>

<style>
.bill-template-popper.el-popper {
	padding: 8px 16px !important;
	border-radius: 10px !important;
	background-color: rgb(59, 65, 75) !important;
	font-size: 16px !important;
	font-weight: 400 !important;
	font-family: "Microsoft YaHei" !important;
	line-height: 30px !important;
	color: #fff !important;
	border: none !important;
	max-width: 600px;
}

.bill-template-popper.el-popper .el-popper__arrow::before {
	background-color: rgb(59, 65, 75) !important;
	border-color: rgb(59, 65, 75) !important;
}
</style>
