|
@@ -4,6 +4,7 @@ import {
|
|
|
reactive,
|
|
|
onMounted,
|
|
|
watch,
|
|
|
+ computed,
|
|
|
nextTick,
|
|
|
onBeforeUnmount,
|
|
|
} from "vue";
|
|
@@ -174,7 +175,8 @@ async function sendMessage(type = "") {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- qaQuery.push(userMessage.value);
|
|
|
+ let question = userMessage.value;
|
|
|
+ qaQuery.push(question);
|
|
|
|
|
|
let url = "https://api.itri-101-5g.com/v1/qa/";
|
|
|
|
|
@@ -182,7 +184,7 @@ async function sendMessage(type = "") {
|
|
|
// 使用者訊息
|
|
|
messages.value.push({
|
|
|
label: "text",
|
|
|
- body: userMessage.value,
|
|
|
+ body: question,
|
|
|
author: "user",
|
|
|
});
|
|
|
|
|
@@ -207,9 +209,7 @@ async function sendMessage(type = "") {
|
|
|
}
|
|
|
)
|
|
|
.then((response) => {
|
|
|
- // if (showAnchor.value) {
|
|
|
- // getVideo(response.data);
|
|
|
- // }
|
|
|
+ messageSave(question, response.data);
|
|
|
|
|
|
// AI 客服回傳訊息
|
|
|
messages.value.push({
|
|
@@ -1771,6 +1771,10 @@ async function findBrand(value) {
|
|
|
// (item) => (item.info.tags = JSON.parse(item.info.tags))
|
|
|
// );
|
|
|
|
|
|
+ response.data.data = response.data.data.sort(() => Math.random() - 0.5); // 隨機排序
|
|
|
+
|
|
|
+ moveItemToEnd(response.data.data, 199);
|
|
|
+
|
|
|
messages.value.push({
|
|
|
label: "brand",
|
|
|
author: "ai",
|
|
@@ -1957,6 +1961,17 @@ function handleShoppingDialog(value) {
|
|
|
body: brandList,
|
|
|
});
|
|
|
} else if (value === "國際貴賓卡專屬禮遇") {
|
|
|
+ let lang = localStorage.getItem("lang");
|
|
|
+ let type;
|
|
|
+
|
|
|
+ if (lang === "zh-tw") {
|
|
|
+ type = "card";
|
|
|
+ } else if (lang === "en-us") {
|
|
|
+ type = "card-en";
|
|
|
+ }
|
|
|
+
|
|
|
+ clickBtn(type, "", "");
|
|
|
+
|
|
|
messages.value.push({
|
|
|
label: "text",
|
|
|
author: "user",
|
|
@@ -2422,6 +2437,27 @@ const submitContactForm = async () => {
|
|
|
}
|
|
|
};
|
|
|
|
|
|
+// 更改排序 (塵蟎捕快移至最後一筆,ID=199)
|
|
|
+function moveItemToEnd(arr, targetId) {
|
|
|
+ // 找到目標 Index
|
|
|
+ const targetIndex = arr.findIndex((item) => item.info.id === targetId);
|
|
|
+
|
|
|
+ // 如果沒有找到返回原陣列
|
|
|
+ if (targetIndex === -1) {
|
|
|
+ console.error(`Item with id=${targetId} not found`);
|
|
|
+ return arr;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 移除目標項目
|
|
|
+ const [targetItem] = arr.splice(targetIndex, 1);
|
|
|
+
|
|
|
+ // 將目標項目添加到陣列的最後面
|
|
|
+ arr.push(targetItem);
|
|
|
+
|
|
|
+ // 返回更新後的陣列
|
|
|
+ return arr;
|
|
|
+}
|
|
|
+
|
|
|
// Video.js 測試
|
|
|
// let vrVideo = ref(null);
|
|
|
// let player;
|
|
@@ -2453,6 +2489,71 @@ const submitContactForm = async () => {
|
|
|
// player.dispose();
|
|
|
// }
|
|
|
// });
|
|
|
+
|
|
|
+let activityDialog = ref(false);
|
|
|
+let activityContent = ref({});
|
|
|
+
|
|
|
+// 主打商品
|
|
|
+function setActivity(str) {
|
|
|
+ activityDialog.value = true;
|
|
|
+
|
|
|
+ try {
|
|
|
+ activityContent.value = JSON.parse(str);
|
|
|
+ console.log("activityContent.value", activityContent.value);
|
|
|
+ } catch (e) {
|
|
|
+ console.log("無法轉成 JSON 格式");
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log("str", str);
|
|
|
+}
|
|
|
+
|
|
|
+// 儲存問答 Log
|
|
|
+async function messageSave(question, data) {
|
|
|
+ let url = "https://cmm.ai:9101/message_save";
|
|
|
+
|
|
|
+ let parameters = {
|
|
|
+ question: question,
|
|
|
+ answer: data.response,
|
|
|
+ data_list: data.data.length ? JSON.stringify(data.data) : [],
|
|
|
+ };
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await axios.post(url, parameters);
|
|
|
+ console.log("response", response);
|
|
|
+ } catch (error) {
|
|
|
+ console.log("error", error);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+let clickUrl = ref("");
|
|
|
+let clickUrlLink = ref(null);
|
|
|
+
|
|
|
+// 判斷點擊
|
|
|
+async function clickBtn(type, brand, item) {
|
|
|
+ let url = `https://cmm.ai:9101/click?click_type=${type}&brand=${brand}`;
|
|
|
+
|
|
|
+ try {
|
|
|
+ const response = await axios.get(url);
|
|
|
+
|
|
|
+ if (type === "click_url") {
|
|
|
+ clickUrl.value = item.info.url;
|
|
|
+ } else if (type === "click_address") {
|
|
|
+ // Google Map
|
|
|
+ clickUrl.value = `https://www.google.com/maps/search/?api=1&query=${encodeURIComponent(
|
|
|
+ item.info.name || item.info.title
|
|
|
+ )}`;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (type === "click_url" || type === "click_address") {
|
|
|
+ setTimeout(() => {
|
|
|
+ // 觸發隱藏 <a> 標籤的點擊事件
|
|
|
+ clickUrlLink.value.click();
|
|
|
+ }, 0);
|
|
|
+ }
|
|
|
+ } catch (error) {
|
|
|
+ console.log("error", error);
|
|
|
+ }
|
|
|
+}
|
|
|
</script>
|
|
|
|
|
|
<template>
|
|
@@ -3131,11 +3232,22 @@ const submitContactForm = async () => {
|
|
|
</div>
|
|
|
|
|
|
<div class="price-info">
|
|
|
- <span>{{ item.info.floor || item.info.price }}</span>
|
|
|
+ <span v-if="item.info.floor || item.info.price">{{
|
|
|
+ item.info.floor || item.info.price
|
|
|
+ }}</span>
|
|
|
<div class="link-btn">
|
|
|
- <a :href="item.info.url" target="_blank">
|
|
|
- {{ t("ctaGoUrl") }}
|
|
|
- </a>
|
|
|
+ <button
|
|
|
+ @click="
|
|
|
+ clickBtn(
|
|
|
+ 'click_address',
|
|
|
+ item.info.name || item.info.title,
|
|
|
+ item
|
|
|
+ )
|
|
|
+ "
|
|
|
+ >
|
|
|
+ <v-icon icon="mdi-map-marker"></v-icon>
|
|
|
+ Google Map
|
|
|
+ </button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
@@ -3143,6 +3255,36 @@ const submitContactForm = async () => {
|
|
|
{{ item.info.content || item.info.description }}
|
|
|
</p>
|
|
|
</section>
|
|
|
+
|
|
|
+ <div class="bottom-btn">
|
|
|
+ <!-- <a
|
|
|
+ v-if="item.info.url !== ''"
|
|
|
+ :href="item.info.url"
|
|
|
+ target="_blank"
|
|
|
+ >
|
|
|
+ {{ t("official_website") }}
|
|
|
+ </a> -->
|
|
|
+ <button
|
|
|
+ v-if="item.info.url !== ''"
|
|
|
+ @click="
|
|
|
+ clickBtn(
|
|
|
+ 'click_url',
|
|
|
+ item.info.name || item.info.title,
|
|
|
+ item
|
|
|
+ )
|
|
|
+ "
|
|
|
+ >
|
|
|
+ {{ t("ctaGoUrl") }}
|
|
|
+ </button>
|
|
|
+ <a
|
|
|
+ v-if="item.info.activity && item.info.activity !== ''"
|
|
|
+ @click="setActivity(item.info.activity)"
|
|
|
+ href="javascript:;"
|
|
|
+ class="commodity-btn"
|
|
|
+ >
|
|
|
+ {{ t("featured_product") }}
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
</div>
|
|
|
</swiper-slide>
|
|
|
</swiper>
|
|
@@ -3802,7 +3944,9 @@ const submitContactForm = async () => {
|
|
|
|
|
|
<span class="price">
|
|
|
<p>{{ formatPrice(secondaryAd.price) }}</p>
|
|
|
- <a :href="secondaryAd.url">前往官網</a>
|
|
|
+ <a :href="secondaryAd.url">
|
|
|
+ {{ t("ctaGoUrl") }}
|
|
|
+ </a>
|
|
|
</span>
|
|
|
|
|
|
<p class="mb-5" v-html="secondaryAd.content"></p>
|
|
@@ -3992,18 +4136,57 @@ const submitContactForm = async () => {
|
|
|
|
|
|
<v-btn type="submit" color="primary" text="確認送出" variant="tonal">
|
|
|
</v-btn>
|
|
|
-
|
|
|
- <!-- <v-btn
|
|
|
- color="primary"
|
|
|
- text="確認送出"
|
|
|
- variant="tonal"
|
|
|
- @click="dialog = false"
|
|
|
- ></v-btn> -->
|
|
|
</v-card-actions>
|
|
|
</v-form>
|
|
|
</v-card>
|
|
|
</v-dialog>
|
|
|
|
|
|
+ <!-- 主打商品 -->
|
|
|
+ <v-dialog v-model="activityDialog" width="auto">
|
|
|
+ <v-card class="activity-card">
|
|
|
+ <v-card-title class="ma-3 text-center">
|
|
|
+ {{ t("featured_product") }}
|
|
|
+ </v-card-title>
|
|
|
+
|
|
|
+ <v-card-text>
|
|
|
+ <h4>{{ activityContent.title }}</h4>
|
|
|
+
|
|
|
+ <p class="mt-5 mb-3">{{ activityContent.description }}</p>
|
|
|
+
|
|
|
+ <div class="d-flex align-center justify-space-between">
|
|
|
+ <span class="price">
|
|
|
+ <p class="text-primary">價格:{{ activityContent.price }}</p>
|
|
|
+ <p class="text-primary">
|
|
|
+ 活動期間:{{ activityContent.usage_period }}
|
|
|
+ </p>
|
|
|
+ </span>
|
|
|
+
|
|
|
+ <div class="link-btn">
|
|
|
+ <a :href="activityContent.purchase_url" target="_blank">
|
|
|
+ {{ t("ctaGoUrl") }}
|
|
|
+ </a>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </v-card-text>
|
|
|
+
|
|
|
+ <v-card-actions>
|
|
|
+ <v-btn
|
|
|
+ class="ms-auto"
|
|
|
+ text="關閉"
|
|
|
+ @click="activityDialog = false"
|
|
|
+ ></v-btn>
|
|
|
+ </v-card-actions>
|
|
|
+ </v-card>
|
|
|
+ </v-dialog>
|
|
|
+
|
|
|
+ <!-- 立即前往 -->
|
|
|
+ <a
|
|
|
+ :href="clickUrl"
|
|
|
+ target="_blank"
|
|
|
+ ref="clickUrlLink"
|
|
|
+ style="display: none"
|
|
|
+ ></a>
|
|
|
+
|
|
|
<!-- <div
|
|
|
v-show="showAd"
|
|
|
v-for="(item, index) in ad"
|
|
@@ -4352,28 +4535,6 @@ const submitContactForm = async () => {
|
|
|
text-align: center;
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- .link-btn {
|
|
|
- display: flex;
|
|
|
- justify-content: center;
|
|
|
- a {
|
|
|
- display: block;
|
|
|
- width: 100%;
|
|
|
- max-width: 200px;
|
|
|
- margin: 25px 3px;
|
|
|
- padding: 8px;
|
|
|
- text-align: center;
|
|
|
- border-radius: 20px;
|
|
|
- color: white;
|
|
|
- background-color: var(--main-color);
|
|
|
- text-decoration: none;
|
|
|
- transition: all 0.3s;
|
|
|
-
|
|
|
- &:hover {
|
|
|
- opacity: 0.8;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
.store-item {
|
|
@@ -4479,10 +4640,9 @@ const submitContactForm = async () => {
|
|
|
|
|
|
.link-btn {
|
|
|
a {
|
|
|
- max-width: 150px;
|
|
|
margin: 0;
|
|
|
- padding: 8px 12px;
|
|
|
- font-size: 0.75rem;
|
|
|
+ max-width: 150px;
|
|
|
+ font-size: 0.875rem;
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -4599,6 +4759,73 @@ const submitContactForm = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+.link-btn,
|
|
|
+.bottom-btn {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+
|
|
|
+ a,
|
|
|
+ button {
|
|
|
+ display: block;
|
|
|
+ width: 100%;
|
|
|
+ margin: 25px 3px;
|
|
|
+ padding: 7px 17px;
|
|
|
+ font-size: 0.875rem;
|
|
|
+ letter-spacing: 1px;
|
|
|
+ text-align: center;
|
|
|
+ color: white;
|
|
|
+ background-color: var(--main-color);
|
|
|
+ text-decoration: none;
|
|
|
+ transition: all 0.3s;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ opacity: 0.8;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .commodity-btn {
|
|
|
+ margin-left: 5px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: var(--main-color);
|
|
|
+ background-color: white;
|
|
|
+ border: 1px solid var(--main-color);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.link-btn {
|
|
|
+ a,
|
|
|
+ button {
|
|
|
+ max-width: 150px;
|
|
|
+ color: white;
|
|
|
+ background-color: var(--main-color);
|
|
|
+ border-radius: 20px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-btn {
|
|
|
+ // max-width: 200px;
|
|
|
+ margin: 0 20px;
|
|
|
+
|
|
|
+ a,
|
|
|
+ button {
|
|
|
+ color: var(--main-color);
|
|
|
+ background-color: white;
|
|
|
+ border: 1px solid var(--main-color);
|
|
|
+ font-size: 0.875rem;
|
|
|
+ font-weight: 500;
|
|
|
+ border-radius: 5px;
|
|
|
+
|
|
|
+ &:first-child {
|
|
|
+ margin-right: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:last-child {
|
|
|
+ margin-left: 10px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.ad-content {
|
|
|
// width: 90%;
|
|
|
max-height: 95vh;
|
|
@@ -5056,6 +5283,29 @@ const submitContactForm = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+.activity-card {
|
|
|
+ h4,
|
|
|
+ .v-card-title {
|
|
|
+ font-weight: 700;
|
|
|
+ }
|
|
|
+
|
|
|
+ h4 {
|
|
|
+ font-size: 1.125rem;
|
|
|
+ }
|
|
|
+
|
|
|
+ .price {
|
|
|
+ p {
|
|
|
+ font-weight: 500;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .link-btn {
|
|
|
+ a {
|
|
|
+ padding: 7px 30px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
.v-btn {
|
|
|
// &.v-btn--density-default {
|
|
|
// height: auto !important;
|