diff --git a/src/assets/js/useProjectTracking.js b/src/assets/js/useProjectTracking.js index 49eca66..77bce22 100644 --- a/src/assets/js/useProjectTracking.js +++ b/src/assets/js/useProjectTracking.js @@ -1,173 +1,186 @@ -import { ref, onMounted, onBeforeUnmount, watch } from 'vue' -import { useRouter } from 'vue-router' -import { computedUsersAPI, useAiGodAPI, updateStayTimeAPI,addUsageAPI } from '@/api/AIxiaocaishen' +import { ref, onMounted, onBeforeUnmount, watch } from "vue"; +import { useRouter } from "vue-router"; +import { + computedUsersAPI, + useAiGodAPI, + updateStayTimeAPI, + addUsageAPI, +} from "@/api/AIxiaocaishen"; export function useProjectTracking(projectRoutes) { - const router = useRouter() - const entryTime = ref(Date.now()) - const isInProject = ref(true) - const hasRecordedEntry = ref(sessionStorage.getItem('hasRecordedEntry') === 'true') - // const parentUrl = window.parent.location.href - // console.log('Link平台地址:', parentUrl) - - let isPageRefreshing = false // 标志位:是否刷新页面 - - // 记录用户进入项目的时间 - const recordEntryTime = () => { - if (hasRecordedEntry.value) { - return - } - - entryTime.value = Date.now() - const date = new Date(entryTime.value) - const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1) - .toString() - .padStart(2, '0')}-${date.getDate().toString().padStart(2, '0')} ${date - .getHours() - .toString() - .padStart(2, '0')}:${date.getMinutes().toString().padStart(2, '0')}:${date - .getSeconds() - .toString() - .padStart(2, '0')}` - sessionStorage.setItem('projectEntryTime', formattedDate) - sessionStorage.setItem('hasRecordedEntry', 'true') - isInProject.value = true - hasRecordedEntry.value = true - - const token = localStorage.getItem('localToken') - if (token) { - const result = useAiGodAPI({ - token: token - }) - console.log(result); - // const result2 = addUsageAPI({ - // token: token, - // }) - // console.log(result2); - }else{ - console.log('没有token'); - } - console.log('记录首次进入时间:', formattedDate) - } - - // 发送追踪数据到后端 - const sendTrackingData = async () => { - if (!isInProject.value) return - - const storedEntryTime = sessionStorage.getItem('projectEntryTime') - if (!storedEntryTime) { - console.warn('未找到存储的进入时间,取消发送跟踪数据') - return - } - - let timestamp - try { - timestamp = new Date(storedEntryTime.replace(' ', 'T')).getTime() - if (isNaN(timestamp)) throw new Error('无效日期') - } catch (error) { - console.error('解析存储的进入时间时出错:', error) - return - } - - const exitTime = Date.now() - const duration = Math.floor((exitTime - timestamp) / 1000) - const localToken = localStorage.getItem('localToken') - console.log('进入项目的时间', storedEntryTime) - console.log('停留时间', duration) - - const params = { - stayTime: duration, - // loginTime: storedEntryTime, - token: localToken - } - - if (localToken) { - try { - const res = await updateStayTimeAPI(params) - console.log('跟踪数据已发送:', res) - sessionStorage.removeItem('projectEntryTime') - sessionStorage.removeItem('hasRecordedEntry') - isInProject.value = false - hasRecordedEntry.value = false - } catch (error) { - console.error('发送跟踪数据失败:', error) - } - } - } - - // 页面可见性变化时触发 - const handleVisibilityChange = () => { - // console.log(window.location.pathname.includes('duobaoqibing'), '路径是否包含了页面不可见触发') - // if (window.location.pathname.includes('duobaoqibing')) { - // console.log('在 searchCode.html 页面,不发送数据') - // return - // } - if (document.visibilityState === 'hidden') { - console.log('页面不可见,用户可能离开或切换标签页') - sendTrackingData() - } - } - - // 页面关闭或刷新时触发 - const handleBeforeUnload = (event) => { - // console.log(window.location.pathname) - // console.log( - // window.location.pathname.includes('duobaoqibing'), - // '路径是否包含了页面关闭了啦啦啦啦啦啦触发' - // ) - // if (window.location.pathname.includes('duobaoqibing')) { - // console.log('在 searchCode.html 页面,不发送数据') - // return - // } - if (isPageRefreshing) { - console.log('页面刷新,不触发数据发送') - return - } - localStorage.clear(); - console.log('页面即将关闭或跳转') - sendTrackingData() - } - - const handleRefreshDetection = () => { - isPageRefreshing = true - } - - // 监听路由变化 - watch( - () => router.currentRoute.value.path, - (newPath) => { - const isProjectRoute = projectRoutes.some((route) => newPath.startsWith(route)) - let isProjectRouteName = projectRoutes[0] - console.log(isProjectRouteName) - // 判断是否是 searchCode.html 的访问 - const isSearchCodePage = window.location.pathname.includes('duobaoqibing') - if (!isProjectRoute && !isSearchCodePage) { - console.log('离开项目路由:', newPath) - sendTrackingData() - } else if (isProjectRouteName && !hasRecordedEntry.value) { - console.log('首次进入项目路由:', newPath) - recordEntryTime() - } - } - ) - - // 添加事件监听 - onMounted(() => { - document.addEventListener('visibilitychange', handleVisibilityChange) - window.addEventListener('beforeunload', handleBeforeUnload) - window.addEventListener('unload', handleRefreshDetection) - }) - - // 移除事件监听 - onBeforeUnmount(() => { - document.removeEventListener('visibilitychange', handleVisibilityChange) - window.removeEventListener('beforeunload', handleBeforeUnload) - window.removeEventListener('unload', handleRefreshDetection) - }) - - return { - entryTime, - isInProject, - sendTrackingData - } + const router = useRouter(); + const entryTime = ref(Date.now()); + const isInProject = ref(true); + const hasRecordedEntry = ref( + sessionStorage.getItem("hasRecordedEntry") === "true" + ); + // const parentUrl = window.parent.location.href + // console.log('Link平台地址:', parentUrl) + + let isPageRefreshing = false; // 标志位:是否刷新页面 + + // 记录用户进入项目的时间 + const recordEntryTime = () => { + if (hasRecordedEntry.value) { + return; + } + + entryTime.value = Date.now(); + const date = new Date(entryTime.value); + const formattedDate = `${date.getFullYear()}-${(date.getMonth() + 1) + .toString() + .padStart(2, "0")}-${date.getDate().toString().padStart(2, "0")} ${date + .getHours() + .toString() + .padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date + .getSeconds() + .toString() + .padStart(2, "0")}`; + sessionStorage.setItem("projectEntryTime", formattedDate); + sessionStorage.setItem("hasRecordedEntry", "true"); + isInProject.value = true; + hasRecordedEntry.value = true; + + const token = localStorage.getItem("localToken"); + if (token) { + const result = useAiGodAPI({ + token: token, + }); + console.log(result); + // const result2 = addUsageAPI({ + // token: token, + // }) + // console.log(result2); + } else { + console.log("没有token"); + } + console.log("记录首次进入时间:", formattedDate); + }; + + // 发送追踪数据到后端 + const sendTrackingData = async () => { + if (!isInProject.value) return; + + const storedEntryTime = sessionStorage.getItem("projectEntryTime"); + if (!storedEntryTime) { + console.warn("未找到存储的进入时间,取消发送跟踪数据"); + return; + } + + let timestamp; + try { + timestamp = new Date(storedEntryTime.replace(" ", "T")).getTime(); + if (isNaN(timestamp)) throw new Error("无效日期"); + } catch (error) { + console.error("解析存储的进入时间时出错:", error); + return; + } + + const exitTime = Date.now(); + const duration = Math.floor((exitTime - timestamp) / 1000); + const localToken = localStorage.getItem("localToken"); + console.log("进入项目的时间", storedEntryTime); + console.log("停留时间", duration); + + const params = { + stayTime: duration, + // loginTime: storedEntryTime, + token: localToken, + }; + + if (localToken) { + try { + const res = await updateStayTimeAPI(params); + console.log("跟踪数据已发送:", res); + sessionStorage.removeItem("projectEntryTime"); + sessionStorage.removeItem("hasRecordedEntry"); + isInProject.value = false; + hasRecordedEntry.value = false; + } catch (error) { + console.error("发送跟踪数据失败:", error); + } + } + }; + + // 页面可见性变化时触发 + const handleVisibilityChange = () => { + // console.log(window.location.pathname.includes('duobaoqibing'), '路径是否包含了页面不可见触发') + // if (window.location.pathname.includes('duobaoqibing')) { + // console.log('在 searchCode.html 页面,不发送数据') + // return + // } + if (document.visibilityState === "hidden") { + console.log("页面不可见,用户可能离开或切换标签页"); + sendTrackingData(); + } + }; + + // 页面关闭或刷新时触发 + const handleBeforeUnload = (event) => { + // console.log(window.location.pathname) + // console.log( + // window.location.pathname.includes('duobaoqibing'), + // '路径是否包含了页面关闭了啦啦啦啦啦啦触发' + // ) + // if (window.location.pathname.includes('duobaoqibing')) { + // console.log('在 searchCode.html 页面,不发送数据') + // return + // } + const isRefresh = + performance.navigation?.type === 1 || + performance.getEntriesByType("navigation")[0]?.type === "reload"; + if (isRefresh) { + console.log("页面刷新,不触发数据发送"); + return; + } + + console.log("页面即将关闭或跳转"); + sendTrackingData(); + }; + + const handleRefreshDetection = () => { + isPageRefreshing = true; + }; + + // 监听路由变化 + watch( + () => router.currentRoute.value.path, + (newPath) => { + const isProjectRoute = projectRoutes.some((route) => + newPath.startsWith(route) + ); + let isProjectRouteName = projectRoutes[0]; + console.log(isProjectRouteName); + // 判断是否是 searchCode.html 的访问 + const isSearchCodePage = + window.location.pathname.includes("duobaoqibing"); + if (!isProjectRoute && !isSearchCodePage) { + console.log("离开项目路由:", newPath); + sendTrackingData(); + } else if (isProjectRouteName && !hasRecordedEntry.value) { + console.log("首次进入项目路由:", newPath); + recordEntryTime(); + } + } + ); + + // 添加事件监听 + onMounted(() => { + document.addEventListener("visibilitychange", handleVisibilityChange); + window.addEventListener("beforeunload", handleBeforeUnload); + window.addEventListener("unload", handleRefreshDetection); + }); + + // 移除事件监听 + onBeforeUnmount(() => { + document.removeEventListener("visibilitychange", handleVisibilityChange); + window.removeEventListener("beforeunload", handleBeforeUnload); + window.removeEventListener("unload", handleRefreshDetection); + }); + + return { + entryTime, + isInProject, + sendTrackingData, + }; } diff --git a/src/main.js b/src/main.js index e56ea96..8b0e022 100644 --- a/src/main.js +++ b/src/main.js @@ -1,25 +1,24 @@ -import { createApp } from 'vue' -import App from './App.vue' -import router from './router' -import ElementPlus from 'element-plus' -import 'element-plus/dist/index.css' -import * as ElementPlusIconsVue from '@element-plus/icons-vue' -// import 'reset-css'; -import { createPinia } from 'pinia' -import piniaPluginPersistedstate from 'pinia-plugin-persistedstate' -import { useAppBridge } from './assets/js/useAppBridge.js' -const { packageFun, fullClose } = useAppBridge() +import { createApp } from "vue"; +import App from "./App.vue"; +import router from "./router"; +import ElementPlus from "element-plus"; +import "element-plus/dist/index.css"; +import * as ElementPlusIconsVue from "@element-plus/icons-vue"; +// import 'reset-css'; +import { createPinia } from "pinia"; +import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; +import { useAppBridge } from "./assets/js/useAppBridge.js"; +const { packageFun, fullClose } = useAppBridge(); - -const app = createApp(App) -const pinia = createPinia() -pinia.use(piniaPluginPersistedstate) +const app = createApp(App); +const pinia = createPinia(); +pinia.use(piniaPluginPersistedstate); for (const [key, component] of Object.entries(ElementPlusIconsVue)) { - app.component(key, component) + app.component(key, component); } -app.use(router) -app.use(ElementPlus) -app.use(pinia) -app.provide('packageFun', packageFun) -app.provide('fullClose', fullClose) -app.mount('#app') \ No newline at end of file +app.use(router); +app.use(ElementPlus); +app.use(pinia); +app.provide("packageFun", packageFun); +app.provide("fullClose", fullClose); +app.mount("#app"); diff --git a/src/store/chat.js b/src/store/chat.js index dbf5685..f8f9f0b 100644 --- a/src/store/chat.js +++ b/src/store/chat.js @@ -1,6 +1,6 @@ -import { defineStore } from 'pinia'; -import { getUserCountAPI } from '@/api/AIxiaocaishen' -export const useChatStore = defineStore('chat', { +import { defineStore } from "pinia"; +import { getUserCountAPI } from "@/api/AIxiaocaishen"; +export const useChatStore = defineStore("chat", { state: () => ({ messages: [], isLoading: false, // 新增加载状态 @@ -11,13 +11,13 @@ export const useChatStore = defineStore('chat', { actions: { async getUserCount() { const result = await getUserCountAPI({ - token: localStorage.getItem('localToken'), - source: '1' - }) - this.UserCount = result.data + token: localStorage.getItem("localToken"), + source: "1", + }); + this.UserCount = result.data; }, setLoading(status) { - this.isLoading = status + this.isLoading = status; }, isLoadingT() { this.isLoading = true; @@ -27,16 +27,11 @@ export const useChatStore = defineStore('chat', { }, addKLineData(data) { this.kLineData.push(data); - } + }, }, persist: { - enabled: true, - strategies: [ - { - key: 'chat_messages', - storage: localStorage, - paths: ['messages', 'kLineData'] - } - ] - } -}); \ No newline at end of file + key: "chat_messages", + storage: sessionStorage, + paths: ["messages", "kLineData"], + }, +});