1
0
mirror of https://github.com/ZeroCatDev/Classworks.git synced 2025-12-07 13:03:59 +00:00

feat: 添加 FingerprintJS 依赖,集成访客 ID 和指纹数据功能

This commit is contained in:
Sunwuyuan 2025-11-30 16:23:43 +08:00
parent ba96069a9b
commit 5f363aba38
No known key found for this signature in database
GPG Key ID: A6A54CF66F56BB64
5 changed files with 91 additions and 22 deletions

View File

@ -12,6 +12,7 @@
"dependencies": {
"@examaware-cs/core": "^1.0.0",
"@examaware-cs/player": "^1.0.2",
"@fingerprintjs/fingerprintjs": "^5.0.1",
"@mdi/font": "7.4.47",
"@microsoft/clarity": "^1.0.2",
"@vueuse/core": "^14.1.0",

8
pnpm-lock.yaml generated
View File

@ -14,6 +14,9 @@ importers:
'@examaware-cs/player':
specifier: ^1.0.2
version: 1.0.2(tdesign-vue-next@1.17.5(vue@3.5.25(typescript@5.9.3)))(vue@3.5.25(typescript@5.9.3))
'@fingerprintjs/fingerprintjs':
specifier: ^5.0.1
version: 5.0.1
'@mdi/font':
specifier: 7.4.47
version: 7.4.47
@ -871,6 +874,9 @@ packages:
tdesign-vue-next: ^1.15.5
vue: ^3.0.0
'@fingerprintjs/fingerprintjs@5.0.1':
resolution: {integrity: sha512-KbaeE/rk2WL8MfpRP6jTI4lSr42SJPjvkyrjP3QU6uUDkOMWWYC2Ts1sNSYcegHC8avzOoYTHBj+2fTqvZWQBA==}
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
engines: {node: '>=18.18.0'}
@ -4559,6 +4565,8 @@ snapshots:
tdesign-vue-next: 1.17.5(vue@3.5.25(typescript@5.9.3))
vue: 3.5.25(typescript@5.9.3)
'@fingerprintjs/fingerprintjs@5.0.1': {}
'@humanfs/core@0.19.1': {}
'@humanfs/node@0.16.7':

View File

@ -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 {

46
src/pages/debug.vue Normal file
View File

@ -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>

22
src/utils/fingerprint.js Normal file
View File

@ -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
}