From 46df470bbba226da5224d9adc1c47ecfadf11e1d Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期四, 18 七月 2024 14:21:01 +0800
Subject: [PATCH] chart resize

---
 src/directive/customDirective.ts                                 |   34 ++++++++
 src/components/chat/Chat.vue                                     |   63 ++++++++-------
 src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue |   26 +++++-
 src/hooks/usePageDisplay.ts                                      |   23 +++++
 src/directive/index.ts                                           |    4 
 src/components/chat/chatComponents/summaryCom/SummaryCom.vue     |   40 ++++++++--
 6 files changed, 145 insertions(+), 45 deletions(-)

diff --git a/src/components/chat/Chat.vue b/src/components/chat/Chat.vue
index 8783ac6..7088f2e 100644
--- a/src/components/chat/Chat.vue
+++ b/src/components/chat/Chat.vue
@@ -9,48 +9,49 @@
 					:key="index"
 				>
 					<img
-						class="rounded-full size-12 mr-4"
+						class="rounded-full size-12 flex-0"
 						:class="{ 'mr-4': item.role === RoleEnum.assistant, 'ml-4': item.role === RoleEnum.user }"
 						:src="roleImageMap[item.role]"
 						alt=""
 						srcset=""
 					/>
-
-					<div class="inline-flex flex-col" :class="{ 'w-full': item.role === RoleEnum.assistant }">
-						<div class="relative w-full" v-if="item.content?.values">
-							<div
-								class="text-sm rounded-[6px] p-4 leading-relaxed"
-								:style="{ backgroundColor: item.role === RoleEnum.user ? 'rgb(197 224 255)' : 'white' }"
-							>
-								<div v-if="item.content.errCode === ErrorCode.Message" class="text-red-500 w-full">{{ item.content.msg }}</div>
-								<component v-else :is="answerTypeMapCom[item.content.type]" :data="item.content.values" />
-							</div>
-
-							<div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 mr-2 mt-2 space-x-2">
+					<div class="flex-auto flex" :class="{'justify-end':item.role===RoleEnum.user}">
+						<div class="inline-flex flex-col" :class="{ 'w-full': item.role === RoleEnum.assistant }">
+							<div class="relative w-full" v-if="item.content?.values">
 								<div
-									class="flex items-center justify-center size-[15px]"
-									v-if="item.content?.type === AnswerType.Text || item.content?.type === AnswerType.Knowledge"
+									class="text-sm rounded-[6px] p-4 leading-relaxed"
+									:style="{ backgroundColor: item.role === RoleEnum.user ? 'rgb(197 224 255)' : 'white' }"
 								>
-									<i class="p-2 ywicon icon-copy cursor-pointer hover:text-[#0284ff] hover:!text-[18px]" @click="copyClick(item)" />
+									<div v-if="item.content.errCode === ErrorCode.Message" class="text-red-500 w-full">{{ item.content.msg }}</div>
+									<component v-else :is="answerTypeMapCom[item.content.type]" :data="item.content.values" />
 								</div>
-								<div class="flex items-center justify-center size-[15px]">
-									<i
-										:class="{ 'text-[#0284ff]': item.state === AnswerState.Like }"
-										class="p-2 ywicon icon-dianzan cursor-pointer hover:text-[#0284ff] font-medium hover:!text-[18px]"
-										@click="likeClick(item)"
-									/>
-								</div>
-								<div class="flex items-center justify-center size-[15px]">
-									<i
-										:class="{ 'text-[#0284ff]': item.state === AnswerState.Unlike }"
-										class="p-2 ywicon icon-buzan cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
-										@click="unLikeClick(item)"
-									/>
+
+								<div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 mr-2 mt-2 space-x-2">
+									<div
+										class="flex items-center justify-center size-[15px]"
+										v-if="item.content?.type === AnswerType.Text || item.content?.type === AnswerType.Knowledge"
+									>
+										<i class="p-2 ywicon icon-copy cursor-pointer hover:text-[#0284ff] hover:!text-[18px]" @click="copyClick(item)" />
+									</div>
+									<div class="flex items-center justify-center size-[15px]">
+										<i
+											:class="{ 'text-[#0284ff]': item.state === AnswerState.Like }"
+											class="p-2 ywicon icon-dianzan cursor-pointer hover:text-[#0284ff] font-medium hover:!text-[18px]"
+											@click="likeClick(item)"
+										/>
+									</div>
+									<div class="flex items-center justify-center size-[15px]">
+										<i
+											:class="{ 'text-[#0284ff]': item.state === AnswerState.Unlike }"
+											class="p-2 ywicon icon-buzan cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
+											@click="unLikeClick(item)"
+										/>
+									</div>
 								</div>
 							</div>
-						</div>
 
-						<Loding v-else class="w-fit"  :process="process" />
+							<Loding v-else class="w-fit" :process="process" />
+						</div>
 					</div>
 				</div>
 				<div v-if="showAskMore" class="ml-4 mt-5 text-sm">
diff --git a/src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue b/src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue
index fc29950..a0f3c60 100644
--- a/src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue
+++ b/src/components/chat/chatComponents/recordSetCom/RecordSetCom.vue
@@ -33,12 +33,13 @@
 import type { RecordSetValues } from '/@/api/ai/chat';
 import { dateRegex } from '/@/utils/toolsValidate';
 import { PATH_ICON, SCATTER_SYMBOL_SIZE, chatComProps, timeDataOptionToContent } from '../common';
+import { usePageDisplay } from '/@/hooks/usePageDisplay';
+import { debounce } from '/@/utils/util';
 const activeName = ref('first');
 const chartRef = ref<HTMLDivElement>(null);
 const selectChartType = ref<ChartTypeEnum>(ChartTypeEnum.Line);
 
 const props = defineProps(chatComProps);
-
 
 const selectChartTypeChange = () => {
 	drawChart();
@@ -66,8 +67,8 @@
 	const xType = getXType(xData);
 	chartInstance.setOption({
 		grid: {
-			// bottom: 120,
-			right: '15%',
+			left: 35,
+			right: 45,
 			bottom: '5%',
 		},
 		tooltip: {
@@ -155,6 +156,15 @@
 	});
 };
 
+const showEvent = () => {
+	window.addEventListener('resize', resizeChart);
+};
+
+const hideEvent = () => {
+	window.removeEventListener('resize', resizeChart);
+};
+let resizeChart = null;
+const { haveExecutedMounted } = usePageDisplay(showEvent, hideEvent);
 onMounted(() => {
 	setTimeout(() => {
 		const parent = chartRef.value.parentElement;
@@ -165,7 +175,15 @@
 			width: parentBound.width,
 			height: parentBound.height,
 		});
-
+		resizeChart = debounce(() => {
+			const parentBound = parent.getBoundingClientRect();
+			chartInstance.resize({
+				width: parentBound.width,
+				height: parentBound.height,
+			});
+		});
+		showEvent();
+		haveExecutedMounted.value = true;
 		drawChart();
 	}, 300);
 });
diff --git a/src/components/chat/chatComponents/summaryCom/SummaryCom.vue b/src/components/chat/chatComponents/summaryCom/SummaryCom.vue
index ab0a51f..eaf963f 100644
--- a/src/components/chat/chatComponents/summaryCom/SummaryCom.vue
+++ b/src/components/chat/chatComponents/summaryCom/SummaryCom.vue
@@ -20,7 +20,7 @@
 				v-if="recordSetList && recordSetList.length > 0"
 			>
 				<div class="h-[20rem] flex-auto w-full">
-					<div ref="chartRefList" v-for="(item, index) in recordSetList" :key="index"></div>
+					<div ref="chartRef" v-for="(item, index) in recordSetList" :key="index"></div>
 				</div>
 			</div>
 			<div v-if="urlList && urlList.length > 0" class="w-full">
@@ -35,12 +35,15 @@
 import * as echarts from 'echarts';
 import type { TableInstance } from 'element-plus';
 import _ from 'lodash';
-import { computed, onMounted, ref } from 'vue';
+import type { ShallowRef } from 'vue';
+import { computed, onMounted, ref, shallowRef } from 'vue';
 import { AnswerType } from '../../model/types';
 import { PATH_ICON, SCATTER_SYMBOL_SIZE, chatComProps, timeDataOptionToContent } from '../common';
 import HTMLCom from '../htmlCom/HTMLCom.vue';
 import { ChartTypeEnum, chartTypeMapEchart } from '../types';
 import { axisLabelFormatter } from '/@/utils/chart';
+import { usePageDisplay } from '/@/hooks/usePageDisplay';
+import { debounce } from '/@/utils/util';
 const props = defineProps(chatComProps);
 
 const selectChartType = ref<ChartTypeEnum>(ChartTypeEnum.Line);
@@ -85,7 +88,7 @@
 const urlList = computed(() => props.data.filter((item) => item.type === AnswerType.Url));
 
 const drawAllChart = () => {
-	chartInstanceList.map((item, index) => {
+	chartInstanceList.value.map((item, index) => {
 		drawChart(item, recordSetList.value[index]);
 	});
 };
@@ -145,9 +148,9 @@
 		grid: {
 			// bottom: 120,
 			// right: '15%',
-			left: '5%',
-			right: '5%',
-			bottom: '8%',
+			left: 35,
+			right: 45,
+			bottom: 20,
 		},
 		toolbox: {
 			show: true,
@@ -240,7 +243,17 @@
 		item.doLayout();
 	});
 };
-let chartInstanceList: echarts.ECharts[] = null;
+let chartInstanceList: ShallowRef<echarts.ECharts[]> = shallowRef(null);
+
+const showEvent = () => {
+	window.addEventListener('resize', resizeChart);
+};
+
+const hideEvent = () => {
+	window.removeEventListener('resize', resizeChart);
+};
+let resizeChart = null;
+const { haveExecutedMounted } = usePageDisplay(showEvent, hideEvent);
 onMounted(() => {
 	setTimeout(() => {
 		const parent = chartRefList.value[0]?.parentElement;
@@ -257,12 +270,23 @@
 		let divideCount = 1;
 
 		const width = parentBound.width / divideCount;
-		chartInstanceList = chartRefList.value.map((item) => {
+		chartInstanceList.value = chartRefList.value.map((item) => {
 			return echarts.init(item, undefined, {
 				width: width,
 				height: parentBound.height,
 			});
 		});
+		resizeChart = debounce(() => {
+			const parentBound = parent.getBoundingClientRect();
+			chartInstanceList.value.map((item) =>
+				item.resize({
+					width: parentBound.width,
+					height: parentBound.height,
+				})
+			);
+		});
+		showEvent();
+		haveExecutedMounted.value = true;
 		drawAllChart();
 	}, 1000);
 });
diff --git a/src/directive/customDirective.ts b/src/directive/customDirective.ts
index b6eb85d..5a13bdd 100644
--- a/src/directive/customDirective.ts
+++ b/src/directive/customDirective.ts
@@ -184,3 +184,37 @@
 		},
 	});
 }
+
+//#region ====================== v-resize ======================
+const resizeMap = new WeakMap();
+const ob = new ResizeObserver((entries) => {
+	for (const entry of entries) {
+		// 鑾峰彇dom鍏冪礌鐨勫洖璋�
+		const handler = resizeMap.get(entry.target);
+		//瀛樺湪鍥炶皟鍑芥暟
+		if (handler) {
+			// 灏嗙洃鍚殑鍊肩粰鍥炶皟鍑芥暟
+			handler({
+				width: entry.borderBoxSize[0].inlineSize,
+				height: entry.borderBoxSize[0].blockSize,
+			});
+		}
+	}
+});
+
+export const elementResizeDirective = (app: App) => {
+	app.directive('resize', {
+		mounted(el: any, binding: any) {
+			//灏哾om涓庡洖璋冪殑鍏崇郴濉炲叆map
+			resizeMap.set(el, binding.value);
+			//鐩戝惉el鍏冪礌鐨勫彉鍖�
+			ob.observe(el);
+		},
+		unmounted(el: any) {
+			//鍙栨秷鐩戝惉
+			ob.unobserve(el);
+		},
+	});
+};
+
+//#endregion
diff --git a/src/directive/index.ts b/src/directive/index.ts
index 926f0be..d0ced37 100644
--- a/src/directive/index.ts
+++ b/src/directive/index.ts
@@ -1,6 +1,6 @@
 import type { App } from 'vue';
 import { authDirective } from '/@/directive/authDirective';
-import { wavesDirective, dragDirective,eleFocusDirective } from '/@/directive/customDirective';
+import { wavesDirective, dragDirective, eleFocusDirective, elementResizeDirective } from '/@/directive/customDirective';
 import { inputLimit } from '/@/directive/inputLimit';
 
 /**
@@ -19,5 +19,5 @@
 	// 杈撳叆闄愬埗鎸囦护
 	inputLimit(app);
 	eleFocusDirective(app);
-	
+	elementResizeDirective(app);
 }
diff --git a/src/hooks/usePageDisplay.ts b/src/hooks/usePageDisplay.ts
new file mode 100644
index 0000000..e9cb5f1
--- /dev/null
+++ b/src/hooks/usePageDisplay.ts
@@ -0,0 +1,23 @@
+import { onActivated, onDeactivated, ref } from 'vue';
+
+/**
+ * 寮�鍚矾鐢辩紦瀛橀〉闈紝绂诲紑鏃讹紝鍜岃繘鍏ユ椂鍙栨秷/寮�鍚闃呬簨浠�
+ * @returns
+ */
+export const usePageDisplay = (pageShow?: () => void, pageHide?: () => void) => {
+	const haveExecutedMounted = ref(false);
+	onActivated(() => {
+		if (!haveExecutedMounted.value) {
+			return;
+		}
+		pageShow?.();
+	});
+
+	onDeactivated(() => {
+		pageHide?.();
+	});
+
+	return {
+        haveExecutedMounted
+    };
+};

--
Gitblit v1.9.3