feat: 添加埋点

This commit is contained in:
zyronon
2025-08-10 19:57:40 +08:00
parent ab8d1f4fce
commit 89c6178fca
5 changed files with 26 additions and 69 deletions

View File

@@ -5,6 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/logo.jpg"/>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<title>Type Words</title>
<script defer src="https://cloud.umami.is/script.js" data-website-id="160308c9-7900-4b1d-a0b1-c3b25a9530f6"></script>
<script>
;(function () {
var src = '//cdn.jsdelivr.net/npm/eruda';

View File

@@ -34,7 +34,6 @@
"tesseract.js": "^4.1.4",
"unplugin-element-plus": "^0.10.0",
"vue": "^3.5.17",
"vue-activity-calendar": "^1.2.2",
"vue-router": "^4.5.1",
"vue-virtual-scroller": "2.0.0-beta.8"
},

8
src/global.d.ts vendored
View File

@@ -1,5 +1,3 @@
import {cloneDeep} from "@/utils"
export {}
declare global {
@@ -8,6 +6,12 @@ declare global {
json(v: any, space: number): void
}
interface Window {
umami: {
track(name:string,data?:any):void
}
}
}
console.json = function (v: any, space = 0) {
const json = JSON.stringify(

View File

@@ -37,8 +37,15 @@ function startStudy() {
if (!base.sbook.articles.length) {
return ElMessage.warning('没有文章可学习!')
}
window.umami.track('startStudyArticle', {
name: base.sbook.name,
index: base.sbook.lastLearnIndex,
custom: base.sbook.custom,
complete: base.sbook.complete,
})
nav('/study-article')
} else {
window.umami.track('no-book')
ElMessage.warning('请先选择一本书籍')
}
}

View File

@@ -1,12 +1,10 @@
<script setup lang="ts">
import {useBaseStore} from "@/stores/base.ts";
import {Icon} from '@iconify/vue'
import {ActivityCalendar} from "vue-activity-calendar";
import "vue-activity-calendar/style.css";
import {useRouter} from "vue-router";
import BaseIcon from "@/components/BaseIcon.vue";
import Dialog from "@/pages/pc/components/dialog/Dialog.vue";
import {_dateFormat, _getAccomplishDate, _getAccomplishDays, _getDictDataByUrl, useNav} from "@/utils";
import {_getAccomplishDate, _getAccomplishDays, _getDictDataByUrl, useNav} from "@/utils";
import BasePage from "@/pages/pc/components/BasePage.vue";
import {DictResource} from "@/types/types.ts";
import {onMounted, watch} from "vue";
@@ -50,8 +48,16 @@ function startStudy() {
if (!store.sdict.words.length) {
return ElMessage.warning('没有单词可学习!')
}
window.umami.track('startStudyDict', {
name: store.sdict.name,
index: store.sdict.lastLearnIndex,
perDayStudyNumber: store.sdict.perDayStudyNumber,
custom: store.sdict.custom,
complete: store.sdict.complete,
})
nav('study-word', {}, currentStudy)
} else {
window.umami.track('no-dict')
ElMessage.warning('请先选择一本词典')
}
}
@@ -107,50 +113,6 @@ function toggleSelect(item) {
}
}
// 统计所有词典的学习日期
const allStudyDays = $computed(() => {
const dateCountMap = new Map<string, { count: number, spend: number }>();
store.word.bookList.forEach(dict => {
if (Array.isArray(dict.statistics)) {
dict.statistics.forEach(stat => {
// 格式化为 'YYYY-MM-DD'
const date = _dateFormat(stat.startDate, 'YYYY-MM-DD');
if (!date) return;
// spend 直接累加原始毫秒数
const spend = Number(stat.spend || stat.speed) || 0;
if (!dateCountMap.has(date)) {
dateCountMap.set(date, {count: 1, spend});
} else {
const v = dateCountMap.get(date)!;
v.count += 1;
v.spend += spend;
}
});
}
});
// 转为 [{ date, count, spend }]
return Array.from(dateCountMap.entries()).map(([date, {count, spend}]) => ({date, count, spend}));
});
function clickActivityEvent(e) {
// e.date 是 'YYYY-MM-DD'
const day = allStudyDays.find(item => item.date === e.date);
if (day) {
// 这里将毫秒转为分钟和小时
const min = Math.round(day.spend / 1000 / 60);
let msg = '';
if (min < 60) {
msg = ` 学习了${min}分钟`;
} else {
const hour = (min / 60).toFixed(1);
msg = ` 学习了${min}分钟(约${hour}小时)`;
}
ElMessage.success(e.date + msg);
} else {
ElMessage.info('当天无学习记录');
}
}
const progressTextLeft = $computed(() => {
if (store.sdict.complete) return '已学完,进入总复习阶段'
return '已学习' + store.currentStudyProgress + '%'
@@ -168,8 +130,9 @@ const progressTextRight = $computed(() => {
<div class="card flex gap-10">
<div class="flex-1 flex flex-col gap-2">
<div class="flex">
<div class="bg-third px-3 h-14 rounded-md flex items-center " >
<span @click="goDictDetail(store.sdict)" class="text-xl font-bold cursor-pointer">{{ store.sdict.name || '请选择词典开始学习' }}</span>
<div class="bg-third px-3 h-14 rounded-md flex items-center ">
<span @click="goDictDetail(store.sdict)"
class="text-xl font-bold cursor-pointer">{{ store.sdict.name || '请选择词典开始学习' }}</span>
<BaseIcon title="切换词典"
:icon="store.sdict.name ? 'gg:arrows-exchange' : 'fluent:add-20-filled'"
class="ml-4"
@@ -248,23 +211,6 @@ const progressTextRight = $computed(() => {
</div>
</div>
<div class="card">
<div class="title">
已学习 <span class="text-3xl">{{ allStudyDays.length }}</span> 天
</div>
<div class="center">
<ActivityCalendar :data="allStudyDays"
:width="40"
:height="7"
:cellLength="16"
:cellInterval="8"
:fontSize="12"
:showLevelFlag="true"
:showWeekDayFlag="true"
:clickEvent="clickActivityEvent"/>
</div>
</div>
<Dialog v-model="show" title="每日目标" :footer="true" @ok="changePerDayStudyNumber">
<div class="target-modal color-main">
<div class="center text-2xl gap-2">