From 82210fced4310307d5a2b03470d16a8ec98331ab Mon Sep 17 00:00:00 2001
From: wujingjing <gersonwu@qq.com>
Date: 星期五, 19 七月 2024 11:16:41 +0800
Subject: [PATCH] iconfont更新及聊天组件反馈功能实现

---
 src/api/ai/chat.ts                                           |   12 +
 customer_list/ch/static/fonts/iconfont/iconfont.css          |  513 ++++++++++++++++--------------------------
 customer_list/ch/static/fonts/iconfont/iconfont.ttf          |    0 
 src/components/chat/Chat.vue                                 |   64 +++++
 src/hooks/usePageDisplay.ts                                  |   41 ++-
 src/hooks/useClickOther.ts                                   |   29 ++
 src/components/chat/components/FeedbackPanel.vue             |   52 ++++
 customer_list/ch/static/fonts/iconfont/iconfont.woff2        |    0 
 customer_list/ch/static/fonts/iconfont/iconfont.woff         |    0 
 src/components/chat/chatComponents/summaryCom/SummaryCom.vue |    4 
 10 files changed, 376 insertions(+), 339 deletions(-)

diff --git a/customer_list/ch/static/fonts/iconfont/iconfont.css b/customer_list/ch/static/fonts/iconfont/iconfont.css
index 4971d6f..902543c 100644
--- a/customer_list/ch/static/fonts/iconfont/iconfont.css
+++ b/customer_list/ch/static/fonts/iconfont/iconfont.css
@@ -1,416 +1,291 @@
 @font-face {
-	font-family: 'iconfont'; /* Project id 2298093 */
-	src: url('./iconfont.woff2') format('woff2'), url('./iconfont.woff') format('woff'), url('./iconfont.ttf') format('truetype');
+  font-family: "ywicon"; /* Project id 4499025 */
+  src: url('iconfont.woff2?t=1721295446708') format('woff2'),
+       url('iconfont.woff?t=1721295446708') format('woff'),
+       url('iconfont.ttf?t=1721295446708') format('truetype');
 }
 
-.iconfont {
-	font-family: 'iconfont' !important;
-	font-size: 16px;
-	font-style: normal;
-	-webkit-font-smoothing: antialiased;
-	-moz-osx-font-smoothing: grayscale;
+.ywicon {
+  font-family: "ywicon" !important;
+  font-size: 16px;
+  font-style: normal;
+  -webkit-font-smoothing: antialiased;
+  -moz-osx-font-smoothing: grayscale;
 }
 
-.icon-quanjushezhi_o:before {
-	content: '\eb80';
+.icon-wentifankui:before {
+  content: "\e614";
 }
 
-.icon-yunshangchuan_o:before {
-	content: '\ebb3';
+.icon-zuoyoujiantou:before {
+  content: "\e673";
 }
 
-.icon-yunxiazai_o:before {
-	content: '\ebb4';
+.icon-zuoyoujiantou1:before {
+  content: "\e602";
 }
 
-.icon-shuaxin:before {
-	content: '\e63e';
+.icon-cedian:before {
+  content: "\e65a";
 }
 
-.icon-diannao1:before {
-	content: '\e622';
+.icon-shuzhuangtu:before {
+  content: "\e600";
 }
 
-.icon-barcode-qr:before {
-	content: '\e61e';
+.icon-tubiao-zhexiantu:before {
+  content: "\eb96";
 }
 
-.icon-zhongduancanshuchaxun:before {
-	content: '\e638';
+.icon-sandiantu:before {
+  content: "\e927";
 }
 
-.icon-shouye_dongtaihui:before {
-	content: '\e606';
+.icon-gongzuozongjie:before {
+  content: "\e63e";
 }
 
-.icon-putong:before {
-	content: '\e603';
+.icon-dizhi:before {
+  content: "\e610";
 }
 
-.icon-dongtai:before {
-	content: '\e659';
-}
-
-.icon-wenducanshu-05:before {
-	content: '\e634';
-}
-
-.icon-zhongduancanshu:before {
-	content: '\e63b';
-}
-
-.icon-tongzhi1:before {
-	content: '\e63a';
-}
-
-.icon-tongzhi2:before {
-	content: '\e649';
-}
-
-.icon-tongzhi3:before {
-	content: '\e648';
-}
-
-.icon-tongzhi4:before {
-	content: '\e60c';
+.icon-youxiang:before {
+  content: "\e639";
 }
 
 .icon-dianhua:before {
-	content: '\e615';
+  content: "\e65b";
 }
 
-.icon-xianshimima:before {
-	content: '\e63c';
+.icon-shoucangxuanzhong:before {
+  content: "\e6c0";
 }
 
-.icon-yincangmima:before {
-	content: '\e63d';
+.icon-shoucang2:before {
+  content: "\e6c1";
 }
 
-.icon-shuxing:before {
-	content: '\e67a';
+.icon-fold:before {
+  content: "\e6af";
 }
 
-.icon-juxingkaobei:before {
-	content: '\e7a5';
+.icon-bengzhan:before {
+  content: "\e609";
 }
 
-.icon-shuxingtu:before {
-	content: '\e685';
+.icon-biyan:before {
+  content: "\e819";
 }
 
-.icon-bolangneng:before {
-	content: '\e745';
+.icon-unfold:before {
+  content: "\e6b0";
 }
 
-.icon-bolangnengshiyanchang:before {
-	content: '\e746';
+.icon-bengzhan1:before {
+  content: "\e60b";
 }
 
-.icon--chaifenhang:before {
-	content: '\e6d1';
+.icon-bianji:before {
+  content: "\e646";
 }
 
-.icon--chaifenlie:before {
-	content: '\e6d0';
+.icon-tianjia:before {
+  content: "\e606";
 }
 
-.icon-tupianyulan:before {
-	content: '\e67e';
+.icon-jiaose:before {
+  content: "\e830";
 }
 
-.icon-15tupianyulan:before {
-	content: '\e624';
+.icon-shanchu:before {
+  content: "\e61a";
 }
 
-.icon-728bianjiqi_zitidaxiao:before {
-	content: '\e660';
+.icon-shanchu3:before {
+  content: "\e637";
 }
 
-.icon-ziti:before {
-	content: '\e7b1';
+.icon-el-icon-download:before {
+  content: "\e6b1";
 }
 
-.icon-font-size:before {
-	content: '\eaef';
+.icon-el-icon-magic-stick:before {
+  content: "\e6b2";
 }
 
-.icon-tuodong:before {
-	content: '\e6a8';
+.icon-download2:before {
+  content: "\e6b3";
 }
 
-.icon-zhongyingwen1:before {
-	content: '\e7a3';
+.icon-folder-opened:before {
+  content: "\e6b4";
 }
 
-.icon-fuhao-yingwen:before {
-	content: '\e714';
+.icon-el-icon-scissors:before {
+  content: "\e74d";
 }
 
-.icon-fuhao-zhongwen:before {
-	content: '\e712';
+.icon-a-zaizhiqingkuang1:before {
+  content: "\e6c8";
 }
 
-.icon-diqiu:before {
-	content: '\e689';
+.icon-zhiwei1:before {
+  content: "\e6c9";
 }
 
-.icon-xingqiu:before {
-	content: '\e65c';
+.icon-xiaoxi:before {
+  content: "\e65c";
 }
 
-.icon-diqiu1:before {
-	content: '\e631';
+.icon-changyonglogo37:before {
+  content: "\e71e";
 }
 
-.icon-huanjingxingqiu:before {
-	content: '\e617';
+.icon-windows:before {
+  content: "\e880";
 }
 
-.icon-zidingyibuju:before {
-	content: '\e637';
+.icon-pointer:before {
+  content: "\e7bb";
 }
 
-.icon-dayin:before {
-	content: '\e612';
+.icon-weixin:before {
+  content: "\e695";
 }
 
-.icon-step:before {
-	content: '\e601';
+.icon-weibiaoti517:before {
+  content: "\e61d";
 }
 
-.icon-30xuanzhongyuanxingfill:before {
-	content: '\e677';
+.icon-ai23:before {
+  content: "\e68a";
 }
 
-.icon-shibai:before {
-	content: '\e60b';
+.icon-tishi:before {
+  content: "\e622";
 }
 
-.icon-7_round_solid:before {
-	content: '\e64d';
+.icon-zanting:before {
+  content: "\e67d";
 }
 
-.icon-6_round_solid:before {
-	content: '\e64e';
+.icon-yingyongzhongxin:before {
+  content: "\e67f";
 }
 
-.icon-9_round_solid:before {
-	content: '\e64f';
+.icon-tuichu:before {
+  content: "\e689";
 }
 
-.icon-1_round_solid:before {
-	content: '\e650';
+.icon-compare:before {
+  content: "\e68e";
 }
 
-.icon-5_round_solid:before {
-	content: '\e651';
-}
-
-.icon-2_round_solid:before {
-	content: '\e654';
-}
-
-.icon-0_round_solid:before {
-	content: '\e655';
-}
-
-.icon-3_round_solid:before {
-	content: '\e656';
-}
-
-.icon-4_round_solid:before {
-	content: '\e657';
-}
-
-.icon-8_round_solid:before {
-	content: '\e658';
-}
-
-.icon-radio-off-full:before {
-	content: '\ea6b';
-}
-
-.icon-tongzhi:before {
-	content: '\e600';
-}
-
-.icon-ditu:before {
-	content: '\e8bc';
-}
-
-.icon-ico:before {
-	content: '\e646';
-}
-
-.icon-chazhaobiaodanliebiao:before {
-	content: '\e76a';
-}
-
-.icon-biaodan:before {
-	content: '\e61d';
-}
-
-.icon-siweidaotu:before {
-	content: '\e614';
-}
-
-.icon-jiliandongxuanzeqi:before {
-	content: '\e616';
-}
-
-.icon-caijian:before {
-	content: '\e611';
-}
-
-.icon-fuwenben:before {
-	content: '\e7e4';
-}
-
-.icon-fuwenbenkuang:before {
-	content: '\e66f';
-}
-
-.icon-shangchuan:before {
-	content: '\e663';
-}
-
-.icon-xuanzeqi:before {
-	content: '\e635';
-}
-
-.icon-fangkuang:before {
-	content: '\e642';
-}
-
-.icon-gouxuan-weixuanzhong-xianxingfangkuang:before {
-	content: '\e77b';
-}
-
-.icon-shidu:before {
-	content: '\e60a';
-}
-
-.icon-yangan:before {
-	content: '\e67d';
-}
-
-.icon-wendu:before {
-	content: '\e686';
-}
-
-.icon-zaosheng:before {
-	content: '\e61c';
-}
-
-.icon-jinridaiban:before {
-	content: '\e60f';
-}
-
-.icon-AIshiyanshi:before {
-	content: '\e609';
-}
-
-.icon-shenqingkaiban:before {
-	content: '\e639';
-}
-
-.icon-zhongyingwenqiehuan:before {
-	content: '\e611';
-}
-
-.icon-zhongyingwen:before {
-	content: '\e605';
-}
-
-.icon-zhongyingzhuanhuan:before {
-	content: '\e6a2';
-}
-
-.icon-zhongyingwenyuyan:before {
-	content: '\e609';
-}
-
-.icon-shuju:before {
-	content: '\e613';
-}
-
-.icon-ico_shuju:before {
-	content: '\e6ff';
-}
-
-.icon-shuju1:before {
-	content: '\e60e';
-}
-
-.icon-fuzhiyemian:before {
-	content: '\e772';
-}
-
-.icon-caozuo-wailian:before {
-	content: '\e711';
-}
-
-.icon-icon-:before {
-	content: '\e620';
-}
-
-.icon-gerenzhongxin:before {
-	content: '\e60d';
-}
-
-.icon-caidan:before {
-	content: '\e652';
-}
-
-.icon-xitongshezhi:before {
-	content: '\e69b';
-}
-
-.icon-neiqianshujuchucun:before {
-	content: '\e62f';
-}
-
-.icon-shouye:before {
-	content: '\e653';
-}
-
-.icon-quanxian:before {
-	content: '\e610';
-}
-
-.icon-zujian:before {
-	content: '\e85e';
-}
-
-.icon-crew_feature:before {
-	content: '\e602';
-}
-
-.icon-gongju:before {
-	content: '\e62d';
-}
-
-.icon-skin:before {
-	content: '\e636';
-}
-
-.icon-shixinyuan:before {
-	content: '\e669';
-}
-
-.icon-webicon318:before {
-	content: '\e6a9';
-}
-
-.icon-dian:before {
-	content: '\e608';
+.icon-gerenxinxi_o:before {
+  content: "\ebcc";
 }
 
 .icon-fullscreen:before {
-	content: '\e623';
+  content: "\e601";
+}
+
+.icon-kaiji:before {
+  content: "\e626";
 }
 
 .icon-tuichuquanping:before {
-	content: '\e641';
+  content: "\e64c";
 }
+
+.icon-lanyalianjie:before {
+  content: "\e6c2";
+}
+
+.icon-select_icon:before {
+  content: "\e661";
+}
+
+.icon-pingmufangda:before {
+  content: "\e7e9";
+}
+
+.icon-daochu1:before {
+  content: "\e682";
+}
+
+.icon-kaiji2:before {
+  content: "\e641";
+}
+
+.icon-fenxiang2:before {
+  content: "\e62e";
+}
+
+.icon-guanbi:before {
+  content: "\e61f";
+}
+
+.icon-shaixuan1:before {
+  content: "\e6aa";
+}
+
+.icon-copy:before {
+  content: "\e6b8";
+}
+
+.icon-buzan:before {
+  content: "\e677";
+}
+
+.icon-dianzan:before {
+  content: "\ec7f";
+}
+
+.icon-yulan:before {
+  content: "\e730";
+}
+
+.icon-guanbiyulan:before {
+  content: "\e788";
+}
+
+.icon-sanweiditu:before {
+  content: "\e605";
+}
+
+.icon-jiankong:before {
+  content: "\e7bd";
+}
+
+.icon-jiegou:before {
+  content: "\e672";
+}
+
+.icon-tuceng1:before {
+  content: "\e645";
+}
+
+.icon-shexiangtou:before {
+  content: "\e620";
+}
+
+.icon-shuibeng:before {
+  content: "\e604";
+}
+
+.icon-24shuidifa-tint-01:before {
+  content: "\e656";
+}
+
+.icon-liuliangji-:before {
+  content: "\e643";
+}
+
+.icon-zhuangtai:before {
+  content: "\e6c3";
+}
+
+.icon-a-appround15:before {
+  content: "\e92f";
+}
+
diff --git a/customer_list/ch/static/fonts/iconfont/iconfont.ttf b/customer_list/ch/static/fonts/iconfont/iconfont.ttf
index 9df435d..ae832f1 100644
--- a/customer_list/ch/static/fonts/iconfont/iconfont.ttf
+++ b/customer_list/ch/static/fonts/iconfont/iconfont.ttf
Binary files differ
diff --git a/customer_list/ch/static/fonts/iconfont/iconfont.woff b/customer_list/ch/static/fonts/iconfont/iconfont.woff
index 4a0251f..5ae5b90 100644
--- a/customer_list/ch/static/fonts/iconfont/iconfont.woff
+++ b/customer_list/ch/static/fonts/iconfont/iconfont.woff
Binary files differ
diff --git a/customer_list/ch/static/fonts/iconfont/iconfont.woff2 b/customer_list/ch/static/fonts/iconfont/iconfont.woff2
index c3d4611..cc6436a 100644
--- a/customer_list/ch/static/fonts/iconfont/iconfont.woff2
+++ b/customer_list/ch/static/fonts/iconfont/iconfont.woff2
Binary files differ
diff --git a/src/api/ai/chat.ts b/src/api/ai/chat.ts
index aa7d9f8..1ca211c 100644
--- a/src/api/ai/chat.ts
+++ b/src/api/ai/chat.ts
@@ -297,3 +297,15 @@
 		},
 	});
 };
+
+
+export const reportHistoryProblem = async (params, req: any = request) => {
+	return req({
+		url: 'history/report_history_problem',
+		method: 'POST',
+		data: params,
+		headers: {
+			'Content-Type': 'application/x-www-form-urlencoded',
+		},
+	});
+};
\ No newline at end of file
diff --git a/src/components/chat/Chat.vue b/src/components/chat/Chat.vue
index 9c14602..25f06fe 100644
--- a/src/components/chat/Chat.vue
+++ b/src/components/chat/Chat.vue
@@ -3,7 +3,7 @@
 		<div class="h-full flex flex-col items-center overflow-y-auto">
 			<div ref="chatListDom" class="h-full" :style="{ width: chatWidth }">
 				<div
-					class="group flex px-4 py-6 hover:bg-slate-100 rounded-lg"
+					class="group flex px-4 py-6 hover:bg-slate-100 rounded-lg relative"
 					:class="{ 'flex-row-reverse': item.role === RoleEnum.user }"
 					v-for="(item, index) of computedMessageList"
 					:key="index"
@@ -17,16 +17,16 @@
 					/>
 					<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="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" :originData="item"/>
+									<component v-else :is="answerTypeMapCom[item.content.type]" :data="item.content.values" :originData="item" />
 								</div>
 
-								<div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 mr-2 mt-2 space-x-2">
+								<div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 mr-4 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"
@@ -45,6 +45,29 @@
 											: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 class="flex items-center justify-center size-[15px] relative">
+										<i
+											class="p-2 ywicon icon-wentifankui cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
+											@click="
+												($event) =>
+													feedbackClick(
+														$event,
+														item,
+														computedMessageList
+															.filter((v) => v.role === RoleEnum.assistant)
+															.findIndex((v) => v.historyId === item.historyId)
+													)
+											"
+										/>
+										<FeedbackPanel
+											v-show="feedbackIsShow && currentFeedbackMapItem === item"
+											ref="feedbackPanelRef"
+											v-model:isShow="feedbackIsShow"
+											v-model:content="feedbackContent"
+											:chatItem="currentFeedbackMapItem"
+											:position="feedbackPosition"
 										/>
 									</div>
 								</div>
@@ -95,6 +118,8 @@
 import { v4 as uuidv4 } from 'uuid';
 import _ from 'lodash';
 import { ErrorCode } from '/@/utils/request';
+import FeedbackPanel from './components/FeedbackPanel.vue';
+import { useClickOther } from '/@/hooks/useClickOther';
 
 const chatWidth = '75%';
 
@@ -414,6 +439,37 @@
 		forbidScroll = false;
 	});
 };
+const feedbackPosition = ref({
+	x: 0,
+	y: 0,
+});
+
+const feedbackIsShow = ref(false);
+const feedbackContent = ref('');
+const feedbackPanelRef = ref<HTMLDivElement>(null);
+const currentFeedbackMapItem = ref(null);
+const curFeedbackIndex = ref(0);
+const feedbackClick = async (e, item, index) => {
+	currentFeedbackMapItem.value = item;
+	curFeedbackIndex.value = index;
+	const offsetX = -4;
+	const offsetY = -8;
+	feedbackIsShow.value = true;
+	nextTick(() => {
+		feedbackPosition.value = {
+			x: -feedbackPanelRef.value[index].$el.clientWidth + offsetX,
+			y: -feedbackPanelRef.value[index].$el.clientHeight + offsetY,
+		};
+	});
+};
+useClickOther(
+	computed(() => feedbackPanelRef.value[curFeedbackIndex.value]),
+	feedbackIsShow,
+	() => {
+		feedbackIsShow.value = false;
+		feedbackContent.value = '';
+	}
+);
 //#endregion
 </script>
 
diff --git a/src/components/chat/chatComponents/summaryCom/SummaryCom.vue b/src/components/chat/chatComponents/summaryCom/SummaryCom.vue
index 490bdbd..8424ecc 100644
--- a/src/components/chat/chatComponents/summaryCom/SummaryCom.vue
+++ b/src/components/chat/chatComponents/summaryCom/SummaryCom.vue
@@ -3,8 +3,8 @@
 		<template v-if="data && data.length > 0">
 			<template v-if="summaryList && summaryList.length > 0">
 				<div class="w-full" v-for="(item, idx) in summaryList" :key="idx">
-					<h3>{{ item.title }}</h3>
-					<el-table ref="tableRefList" class="w-full" :data="[{}]">
+					<h2>{{ item.title }}</h2>
+					<el-table ref="tableRefList" class="w-full mt-5" :data="[{}]">
 						<el-table-column v-for="(col, index) in item.values" :label="col.title" :key="index">
 							<template #default="scope">
 								{{ col?.value }}
diff --git a/src/components/chat/components/FeedbackPanel.vue b/src/components/chat/components/FeedbackPanel.vue
new file mode 100644
index 0000000..12a2b44
--- /dev/null
+++ b/src/components/chat/components/FeedbackPanel.vue
@@ -0,0 +1,52 @@
+<template>
+	<div
+		class="w-64 bg-white absolute p-4 rounded-md border-[1.5px] border-solid border-gray-300 z-10"
+		:style="{ left: position.x + 'px', top: position.y + 'px' }"
+	>
+		<div class="flex justify-between">
+			<h3>浣犵殑鍙嶉灏�<br />甯姪 WI 姘村姟浼樺寲杩涙</h3>
+			<i class="ywicon icon-guanbi right-0 top-0 !text-[20px] text-gray-500 cursor-pointer" @click="closeClick"></i>
+		</div>
+		<div class="mt-6 flex-col flex">
+			<el-input v-model="content" resize="none" class="" type="textarea" :rows="3"></el-input>
+			<el-button :disabled="!content" color="#1d86ff" class="m-auto mt-3" type="primary" @click="submitFeedback">鎻� 浜�</el-button>
+		</div>
+	</div>
+</template>
+
+<script setup lang="ts">
+import { ref, type PropType, nextTick } from 'vue';
+import { reportHistoryProblem } from '/@/api/ai/chat';
+import { ElMessage } from 'element-plus';
+
+const props = defineProps({
+	position: {
+		type: Object as PropType<any>,
+	},
+	chatItem: {
+		type: Object as PropType<any>,
+	},
+});
+const isShow = defineModel('isShow', {
+	type: Boolean,
+});
+const content = defineModel('content', {
+	type: String,
+});
+const submitFeedback = async () => {
+	const res = await reportHistoryProblem({
+		history_id: props.chatItem.historyId,
+		report_note: content.value,
+	});
+	ElMessage.success('鎰熻阿鎮ㄧ殑鍙嶉');
+	nextTick(() => {
+		closeClick();
+	});
+};
+
+const closeClick = () => {
+	isShow.value = false;
+	content.value = '';
+};
+</script>
+<style scoped lang="scss"></style>
diff --git a/src/hooks/useClickOther.ts b/src/hooks/useClickOther.ts
new file mode 100644
index 0000000..0586ea1
--- /dev/null
+++ b/src/hooks/useClickOther.ts
@@ -0,0 +1,29 @@
+import { computed, watch, type Ref, watchEffect, nextTick } from 'vue';
+
+export const useClickOther = (
+	excludeEle: Ref<HTMLElement>[] | Ref<HTMLElement>,
+	isShow: Ref<boolean>,
+	handleClickOther: () => void = () => {
+		isShow.value = false;
+	}
+) => {
+	const domList = computed(() => {
+		const computedEle = Array.isArray(excludeEle) ? excludeEle : [excludeEle];
+		return computedEle.map((item) => item.value.$el);
+	});
+	const listenClickOtherExit = (e) => {
+		if (!domList.value.includes(e.target) && domList.value.every((item) => !item.contains(e.target))) {
+			handleClickOther();
+		}
+	};
+
+	watch(isShow, (val) => {
+		if (val) {
+			setTimeout(() => {
+				document.addEventListener('click', listenClickOtherExit);
+			}, 0);
+		} else {
+			document.removeEventListener('click', listenClickOtherExit);
+		}
+	});
+};
diff --git a/src/hooks/usePageDisplay.ts b/src/hooks/usePageDisplay.ts
index e9cb5f1..78d866d 100644
--- a/src/hooks/usePageDisplay.ts
+++ b/src/hooks/usePageDisplay.ts
@@ -1,23 +1,36 @@
-import { onActivated, onDeactivated, ref } from 'vue';
+import { onActivated, onBeforeUnmount, onDeactivated, onMounted, onUnmounted, ref } from 'vue';
+import router from '../router';
 
 /**
  * 寮�鍚矾鐢辩紦瀛橀〉闈紝绂诲紑鏃讹紝鍜岃繘鍏ユ椂鍙栨秷/寮�鍚闃呬簨浠�
  * @returns
  */
-export const usePageDisplay = (pageShow?: () => void, pageHide?: () => void) => {
-	const haveExecutedMounted = ref(false);
-	onActivated(() => {
-		if (!haveExecutedMounted.value) {
-			return;
-		}
-		pageShow?.();
-	});
+export const usePageDisplay = (pageShow?: () => void, pageHide?: () => void, needExecutedMounted = true) => {
+	const haveExecutedMounted = ref(!needExecutedMounted);
+	const currentRoute = router.currentRoute.value;
 
-	onDeactivated(() => {
-		pageHide?.();
-	});
+	const isKeepAlive = currentRoute.meta.isKeepAlive ?? false;
+	if (isKeepAlive) {
+		onActivated(() => {
+			if (!haveExecutedMounted.value) {
+				return;
+			}
+			pageShow?.();
+		});
+
+		onDeactivated(() => {
+			pageHide?.();
+		});
+	} else {
+		onMounted(() => {
+			pageShow?.();
+		});
+		onBeforeUnmount(() => {
+			pageHide?.();
+		});
+	}
 
 	return {
-        haveExecutedMounted
-    };
+		haveExecutedMounted,
+	};
 };

--
Gitblit v1.9.3