feat: 添加 FingerprintJS 依赖,集成访客 ID 和指纹数据功能
This commit is contained in:
+14
-22
@@ -2,50 +2,42 @@
|
||||
<v-app>
|
||||
<!-- 正常路由 -->
|
||||
<router-view v-slot="{ Component, route }">
|
||||
<transition
|
||||
mode="out-in"
|
||||
name="md3"
|
||||
>
|
||||
<component
|
||||
:is="Component"
|
||||
:key="route.path"
|
||||
/>
|
||||
<transition mode="out-in" name="md3">
|
||||
<component :is="Component" :key="route.path" />
|
||||
</transition>
|
||||
</router-view>
|
||||
<global-message/>
|
||||
<rate-limit-modal/>
|
||||
<global-message />
|
||||
<rate-limit-modal />
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {onMounted} from "vue";
|
||||
import {useTheme} from "vuetify";
|
||||
import {getSetting} from "@/utils/settings";
|
||||
import { onMounted } from "vue";
|
||||
import { useTheme } from "vuetify";
|
||||
import { getSetting } from "@/utils/settings";
|
||||
import RateLimitModal from "@/components/RateLimitModal.vue";
|
||||
import Clarity from "@microsoft/clarity";
|
||||
import { getVisitorId } from "@/utils/fingerprint";
|
||||
|
||||
const theme = useTheme();
|
||||
|
||||
onMounted(() => {
|
||||
onMounted(async () => {
|
||||
// 应用保存的主题设置
|
||||
const savedTheme = getSetting("theme.mode");
|
||||
theme.global.name.value = savedTheme;
|
||||
|
||||
const visitorId = await getVisitorId();
|
||||
console.log("Visitor ID:", visitorId);
|
||||
// Clarity 标识(保留在 App 层)
|
||||
Clarity.identify(
|
||||
getSetting("device.uuid"),
|
||||
getSetting("server.domain"),
|
||||
getSetting("server.provider"),
|
||||
getSetting("server.classNumber")
|
||||
);
|
||||
Clarity.identify(visitorId);
|
||||
Clarity.setTag("fingerprintjs", visitorId);
|
||||
});
|
||||
|
||||
</script>
|
||||
<style>
|
||||
.md3-enter-active,
|
||||
.md3-leave-active {
|
||||
transition: opacity 0.3s cubic-bezier(0.4, 0, 0.2, 1),
|
||||
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
transform 0.3s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
.md3-enter-from {
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<template>
|
||||
<v-container>
|
||||
<v-card class="mb-4">
|
||||
<v-card-title>调试信息</v-card-title>
|
||||
<v-card-text>
|
||||
<div class="text-h6 mb-2">访客 ID</div>
|
||||
<v-code class="d-block pa-2 bg-grey-lighten-4 rounded mb-4">
|
||||
{{ visitorId || '加载中...' }}
|
||||
</v-code>
|
||||
|
||||
|
||||
</v-card-text>
|
||||
<v-card-actions>
|
||||
<v-btn color="primary" @click="loadData" :loading="loading">
|
||||
Refresh
|
||||
</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-container>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { getVisitorId, getFingerprintData } from '@/utils/fingerprint'
|
||||
|
||||
const visitorId = ref('')
|
||||
const fingerprintData = ref({})
|
||||
const loading = ref(false)
|
||||
|
||||
const loadData = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
visitorId.value = await getVisitorId()
|
||||
fingerprintData.value = await getFingerprintData()
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
visitorId.value = 'Error loading visitor ID'
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadData()
|
||||
})
|
||||
</script>
|
||||
@@ -0,0 +1,22 @@
|
||||
import FingerprintJS from '@fingerprintjs/fingerprintjs'
|
||||
|
||||
let fpPromise
|
||||
|
||||
export const loadFingerprint = () => {
|
||||
if (!fpPromise) {
|
||||
fpPromise = FingerprintJS.load()
|
||||
}
|
||||
return fpPromise
|
||||
}
|
||||
|
||||
export const getVisitorId = async () => {
|
||||
const fp = await loadFingerprint()
|
||||
const result = await fp.get()
|
||||
return result.visitorId
|
||||
}
|
||||
|
||||
export const getFingerprintData = async () => {
|
||||
const fp = await loadFingerprint()
|
||||
const result = await fp.get()
|
||||
return result
|
||||
}
|
||||
Reference in New Issue
Block a user