|
@@ -137,7 +137,14 @@ let messages = ref([]);
|
|
|
|
|
|
watch(messages.value, (val) => {
|
|
|
console.log("messages", val);
|
|
|
- scrollToBottom();
|
|
|
+ // scrollToBottom();
|
|
|
+ // 判斷最後一個值是否為文字訊息
|
|
|
+ if (
|
|
|
+ messages.value.length > 0 &&
|
|
|
+ messages.value[messages.value.length - 1].label !== "brand"
|
|
|
+ ) {
|
|
|
+ scrollToBottom();
|
|
|
+ }
|
|
|
updateMenuHeight();
|
|
|
});
|
|
|
|
|
@@ -328,6 +335,9 @@ function getLang() {
|
|
|
case "ja-jp":
|
|
|
langVal = "jp";
|
|
|
break;
|
|
|
+ case "ko-kr":
|
|
|
+ langVal = "ko";
|
|
|
+ break;
|
|
|
|
|
|
default:
|
|
|
break;
|
|
@@ -358,6 +368,12 @@ async function setAd() {
|
|
|
let video = ref(null);
|
|
|
|
|
|
function videoPlay() {
|
|
|
+ if (videoSrc.value !== videoMuteSources.value) {
|
|
|
+ video.value.loop = false;
|
|
|
+ } else {
|
|
|
+ video.value.loop = true; // 設置循環播放
|
|
|
+ }
|
|
|
+
|
|
|
video.value.load();
|
|
|
video.value.play();
|
|
|
}
|
|
@@ -375,6 +391,7 @@ const onVideoEnded = () => {
|
|
|
|
|
|
// 播放點頭影片
|
|
|
videoSrc.value = videoMuteSources.value;
|
|
|
+ // video.value.loop = true; // 設置循環播放
|
|
|
videoPlay();
|
|
|
isVideoPause.value = true;
|
|
|
};
|
|
@@ -420,6 +437,8 @@ function onLanguageChange(lang) {
|
|
|
chooseLang("en-us");
|
|
|
} else if (lang === "日本語") {
|
|
|
chooseLang("ja-jp");
|
|
|
+ } else if (lang === "한국어") {
|
|
|
+ chooseLang("ko-kr");
|
|
|
}
|
|
|
|
|
|
// 清空音訊
|
|
@@ -1484,22 +1503,20 @@ const loadVideoSources = async () => {
|
|
|
|
|
|
videoSources.value = [
|
|
|
// "https://cmm.ai/101-ai-chatbot-new/video/start_1.mp4",
|
|
|
- "https://cmm.ai/101-ai-chatbot-new/video/start_2.mp4",
|
|
|
+ "https://cmm.ai/101-video/start_2.mp4",
|
|
|
];
|
|
|
videoSourcesEn.value = [
|
|
|
// "https://cmm.ai/101-ai-chatbot-new/video/start_en_1.mp4",
|
|
|
- "https://cmm.ai/101-ai-chatbot-new/video/start_en_2.mp4",
|
|
|
- ];
|
|
|
- videoSourcesJp.value = [
|
|
|
- "https://cmm.ai:9101/static/video_cache/others/final-tmp_2024-08-27_12:33:13.mp4",
|
|
|
+ "https://cmm.ai/101-video/start_en_2.mp4",
|
|
|
];
|
|
|
+ videoSourcesJp.value = ["https://cmm.ai/101-video/start_jp_2.mp4"];
|
|
|
videoMuteSources.value = [
|
|
|
// "https://cmm.ai/101-ai-chatbot-new/video/mute_1.mp4",
|
|
|
- "https://cmm.ai/101-ai-chatbot-new/video/mute_2.mp4",
|
|
|
+ "https://cmm.ai/101-video/mute_2.mp4",
|
|
|
];
|
|
|
videoSpeakSources.value = [
|
|
|
// "https://cmm.ai/101-ai-chatbot-new/video/speak_1.mp4",
|
|
|
- "https://cmm.ai/101-ai-chatbot-new/video/speak_2.mp4",
|
|
|
+ "https://cmm.ai/101-video/speak_2.mp4",
|
|
|
];
|
|
|
};
|
|
|
|
|
@@ -1507,6 +1524,8 @@ let videoSrc = ref("");
|
|
|
let hideAnchorPrologue = ref(false); // 顯示開場白 or 點頭影片
|
|
|
let videoIndex = ref(null); // 影片編號
|
|
|
|
|
|
+let funFilterDialog = ref(false); // 創意濾鏡視窗
|
|
|
+
|
|
|
// 選擇類別
|
|
|
async function selectCategory(value, index) {
|
|
|
assignCategory.value = value;
|
|
@@ -1568,6 +1587,19 @@ async function selectCategory(value, index) {
|
|
|
// }
|
|
|
else if (value === "附近有什麼") {
|
|
|
window.open("https://cmm.ai/101-aiv2/#/brand-search", "_blank"); // 另開頁面
|
|
|
+ } else if (value === "趣味濾鏡") {
|
|
|
+ // messages.value.push({
|
|
|
+ // label: "text",
|
|
|
+ // author: "user",
|
|
|
+ // body: t("fun_filter"),
|
|
|
+ // });
|
|
|
+
|
|
|
+ // messages.value.push({
|
|
|
+ // label: "text",
|
|
|
+ // author: "ai",
|
|
|
+ // body: t("system_under_construction"),
|
|
|
+ // });
|
|
|
+ funFilterDialog.value = true;
|
|
|
} else if (value === "秘境花園觀景台") {
|
|
|
messages.value.push({
|
|
|
label: "text",
|
|
@@ -1735,10 +1767,10 @@ let langList = reactive([
|
|
|
lang: "日本語",
|
|
|
value: "ja-jp",
|
|
|
},
|
|
|
- // {
|
|
|
- // lang: "한국어",
|
|
|
- // value: "ko-kr",
|
|
|
- // },
|
|
|
+ {
|
|
|
+ lang: "한국어",
|
|
|
+ value: "ko-kr",
|
|
|
+ },
|
|
|
]);
|
|
|
|
|
|
const btnList = reactive([
|
|
@@ -1788,7 +1820,8 @@ const menuList = reactive([
|
|
|
[
|
|
|
{ imgSrc: "素材-09.png", text: "food_souvenirs", value: "美食/伴手禮" },
|
|
|
{ imgSrc: "素材-10.png", text: "location_guide", value: "位置導引" },
|
|
|
- { imgSrc: "素材-11.png", text: "what_around", value: "附近有什麼" },
|
|
|
+ { imgSrc: "素材-17.png", text: "fun_filter", value: "趣味濾鏡" },
|
|
|
+ // { imgSrc: "素材-11.png", text: "what_around", value: "附近有什麼" },
|
|
|
],
|
|
|
]);
|
|
|
|
|
@@ -1815,6 +1848,8 @@ async function findBrand(value) {
|
|
|
|
|
|
assignCategoryIndex.value = null;
|
|
|
assignCategory.value = "";
|
|
|
+
|
|
|
+ scrollToLastMessage();
|
|
|
} catch (error) {
|
|
|
console.log("error", error);
|
|
|
}
|
|
@@ -2100,6 +2135,7 @@ let isAudioPlaying = ref(false); // 音訊播放狀態
|
|
|
// 取得語音回覆 mp4
|
|
|
async function cutVideo() {
|
|
|
videoSrc.value = videoSpeakSources.value[videoIndex.value - 1];
|
|
|
+ video.value.loop = false;
|
|
|
video.value.load(); // 重新讀取影片
|
|
|
|
|
|
// 影片和音訊加載完成後播放
|
|
@@ -2134,6 +2170,7 @@ const onAudioEnded = () => {
|
|
|
|
|
|
// 播放點頭影片
|
|
|
videoSrc.value = videoMuteSources.value;
|
|
|
+ // video.value.loop = true; // 設置循環播放
|
|
|
videoPlay();
|
|
|
};
|
|
|
|
|
@@ -2419,6 +2456,7 @@ function handleVideoCache() {
|
|
|
|
|
|
// 播放 Cache 影片
|
|
|
videoSrc.value = `https://cmm.ai:9101${videoCacheData.value.video_url}`;
|
|
|
+ video.value.loop = false;
|
|
|
video.value.load();
|
|
|
|
|
|
// 清空音訊
|
|
@@ -2468,6 +2506,7 @@ function togglePause(val) {
|
|
|
if (video.value) {
|
|
|
video.value.play();
|
|
|
}
|
|
|
+
|
|
|
if (currentAudio.value) {
|
|
|
currentAudio.value.play(); // 播放音訊
|
|
|
currentAudio.value.addEventListener("ended", onAudioEnded);
|
|
@@ -2501,6 +2540,38 @@ async function messageNotInCache(question, answer) {
|
|
|
console.log("error", error);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+const scrollToLastMessage = () => {
|
|
|
+ nextTick(() => {
|
|
|
+ console.log(">>>");
|
|
|
+
|
|
|
+ const lastMessage = chatArea.value?.querySelector(
|
|
|
+ ".message-content:last-child"
|
|
|
+ );
|
|
|
+
|
|
|
+ console.log("lastMessage", lastMessage);
|
|
|
+
|
|
|
+ if (lastMessage) {
|
|
|
+ const scrollTop = lastMessage.offsetTop;
|
|
|
+ console.log("捲軸高度:", scrollTop);
|
|
|
+ setTimeout(() => {
|
|
|
+ chatArea.value.scrollTop = lastMessage.offsetTop - 45;
|
|
|
+ }, 500);
|
|
|
+ console.log("chatArea.value.scrollTop", chatArea.value.scrollTop);
|
|
|
+ }
|
|
|
+ });
|
|
|
+};
|
|
|
+
|
|
|
+// 判斷輸入框狀態
|
|
|
+let inputFocus = ref(false);
|
|
|
+
|
|
|
+const handleFocus = () => {
|
|
|
+ inputFocus.value = true;
|
|
|
+};
|
|
|
+
|
|
|
+const handleBlur = () => {
|
|
|
+ inputFocus.value = false;
|
|
|
+};
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
@@ -2524,7 +2595,7 @@ async function messageNotInCache(question, answer) {
|
|
|
<v-select
|
|
|
density="compact"
|
|
|
:label="`${t('select_language')}`"
|
|
|
- :items="['中文', 'English', '日本語']"
|
|
|
+ :items="['中文', 'English', '日本語', '한국어']"
|
|
|
variant="solo"
|
|
|
@update:modelValue="onLanguageChange"
|
|
|
></v-select>
|
|
@@ -2784,7 +2855,7 @@ async function messageNotInCache(question, answer) {
|
|
|
<div v-else-if="message.label === 'location'">
|
|
|
<!-- 定位點 & 平面圖下拉選單 -->
|
|
|
<div class="d-flex">
|
|
|
- <v-menu location="top">
|
|
|
+ <!-- <v-menu location="top">
|
|
|
<template v-slot:activator="{ props }">
|
|
|
<v-btn class="mt-5 py-2" color="primary" dark v-bind="props">
|
|
|
<p class="me-2">
|
|
@@ -2819,16 +2890,11 @@ async function messageNotInCache(question, answer) {
|
|
|
</v-list-item-title>
|
|
|
</v-list-item>
|
|
|
</v-list>
|
|
|
- </v-menu>
|
|
|
+ </v-menu> -->
|
|
|
|
|
|
<v-menu location="top">
|
|
|
<template v-slot:activator="{ props }">
|
|
|
- <v-btn
|
|
|
- class="ms-5 mt-5 py-2"
|
|
|
- color="primary"
|
|
|
- dark
|
|
|
- v-bind="props"
|
|
|
- >
|
|
|
+ <v-btn class="mt-5 py-2" color="primary" dark v-bind="props">
|
|
|
<p class="me-2">{{ t("view_floor_plan") }}</p>
|
|
|
<svg
|
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
@@ -3503,6 +3569,9 @@ async function messageNotInCache(question, answer) {
|
|
|
|
|
|
<!-- 底部選單 -->
|
|
|
<div ref="menu" class="menu">
|
|
|
+ <p v-if="inputFocus" class="Keyboard-tips">
|
|
|
+ {{ t("close_keyboard") }}
|
|
|
+ </p>
|
|
|
<!-- 對話輸入框 -->
|
|
|
<form
|
|
|
@submit.prevent="sendMessage()"
|
|
@@ -3518,6 +3587,8 @@ async function messageNotInCache(question, answer) {
|
|
|
v-model="userMessage"
|
|
|
type="text"
|
|
|
:placeholder="t('type_message')"
|
|
|
+ @focus="handleFocus"
|
|
|
+ @blur="handleBlur"
|
|
|
/>
|
|
|
<button type="submit" class="submit">
|
|
|
<img width="20" src="../assets/img/paper-plane-solid.svg" alt="" />
|
|
@@ -3751,6 +3822,23 @@ async function messageNotInCache(question, answer) {
|
|
|
</v-card-text>
|
|
|
</v-card>
|
|
|
</v-dialog>
|
|
|
+
|
|
|
+ <!-- 創意濾鏡視窗 -->
|
|
|
+ <v-dialog v-model="funFilterDialog" width="300">
|
|
|
+ <v-card class="pa-5">
|
|
|
+ <v-card-title class="pa-0">
|
|
|
+ <button @click="funFilterDialog = false" class="d-flex ml-auto">
|
|
|
+ <v-icon size="small" icon="mdi-close"></v-icon>
|
|
|
+ </button>
|
|
|
+ </v-card-title>
|
|
|
+
|
|
|
+ <v-card-text>
|
|
|
+ <p class="text-h5 text-center mb-5" style="font-weight: 600">
|
|
|
+ {{ t("system_under_construction") }}
|
|
|
+ </p>
|
|
|
+ </v-card-text>
|
|
|
+ </v-card>
|
|
|
+ </v-dialog>
|
|
|
</template>
|
|
|
|
|
|
<style lang="scss">
|
|
@@ -3777,7 +3865,7 @@ async function messageNotInCache(question, answer) {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
justify-content: center;
|
|
|
- background-color: rgba(0, 0, 0, 0.6);
|
|
|
+ background-color: rgba(0, 0, 0, 0.3);
|
|
|
background-blend-mode: multiply;
|
|
|
background-image: url("@/assets/img/banner.jpg");
|
|
|
background-size: cover;
|
|
@@ -4633,4 +4721,12 @@ async function messageNotInCache(question, answer) {
|
|
|
width: 130px;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+.Keyboard-tips {
|
|
|
+ position: absolute;
|
|
|
+ top: -35px;
|
|
|
+ left: 50%;
|
|
|
+ color: #fff;
|
|
|
+ transform: translate(-50%, 0px);
|
|
|
+}
|
|
|
</style>
|