diff --git a/src/main.ts b/src/main.ts index adac019..75c620a 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,6 +6,7 @@ import router from './renderer/router' import ElementUI from 'element-plus' import 'element-plus/dist/index.css' import VueLazyLoad from 'vue3-lazyload' +import { initTalkingData } from './renderer/utils/analytic' import vue3PhotoPreview from 'vue3-photo-preview' import 'vue3-photo-preview/dist/index.css' import VueVideoPlayer from '@videojs-player/vue' @@ -83,3 +84,5 @@ console.log(hljsCommon.highlightAuto('

Highlight.js has been registered succe app.use(hljsVuePlugin) app.use(VueVideoPlayer) app.mount('#app') + +initTalkingData() diff --git a/src/main/apis/app/uploader/index.ts b/src/main/apis/app/uploader/index.ts index e45b75e..8815ace 100644 --- a/src/main/apis/app/uploader/index.ts +++ b/src/main/apis/app/uploader/index.ts @@ -18,7 +18,7 @@ import { import picgo from '@core/picgo' import db from '~/main/apis/core/datastore' import windowManager from 'apis/app/window/windowManager' -import { showNotification, getClipboardFilePath } from '~/main/utils/common' +import { showNotification, getClipboardFilePath, calcDurationRange } from '~/main/utils/common' import logger from '@core/picgo/logger' import { T } from '~/main/i18n' import { CLIPBOARD_IMAGE_FOLDER } from '~/universal/utils/static' @@ -30,7 +30,8 @@ import { IWindowList } from '#/types/enum' import { IPicGo } from 'piclist' import { GET_RENAME_FILE_NAME, - RENAME_FILE_NAME + RENAME_FILE_NAME, + TALKING_DATA_EVENT } from '~/universal/events/constants' const waitForRename = (window: BrowserWindow, id: number): Promise => { @@ -48,6 +49,20 @@ const waitForRename = (window: BrowserWindow, id: number): Promise }) } +const handleTalkingData = (webContents: WebContents, options: IAnalyticsData) => { + const data: ITalkingDataOptions = { + EventId: 'upload', + Label: options.type, + MapKv: { + by: options.fromClipboard ? 'clipboard' : 'files', // 上传剪贴板图片还是选择的文文件 + count: options.count, // 上传的数量 + duration: calcDurationRange(options.duration || 0), // 上传耗时 + type: options.type + } + } + webContents.send(TALKING_DATA_EVENT, data) +} + class Uploader { private webContents: WebContents | null = null // private uploading: boolean = false @@ -142,8 +157,17 @@ class Uploader { async upload (img?: IUploadOption): Promise { try { + const startTime = Date.now() const output = await picgo.upload(img) if (Array.isArray(output) && output.some((item: ImgInfo) => item.imgUrl)) { + if (this.webContents) { + handleTalkingData(this.webContents, { + fromClipboard: !img, + type: db.get('picBed.uploader') || db.get('picBed.current') || 'smms', + count: img ? img.length : 1, + duration: Date.now() - startTime + } as IAnalyticsData) + } output.forEach((item: ImgInfo) => { item.config = JSON.parse(JSON.stringify(db.get(`picBed.${item.type}`))) }) diff --git a/src/main/utils/common.ts b/src/main/utils/common.ts index 67450e3..e958380 100644 --- a/src/main/utils/common.ts +++ b/src/main/utils/common.ts @@ -57,6 +57,30 @@ export const showMessageBox = (options: any) => { }) } +export const calcDurationRange = (duration: number) => { + if (duration < 1000) { + return 500 + } else if (duration < 1500) { + return 1000 + } else if (duration < 3000) { + return 2000 + } else if (duration < 5000) { + return 3000 + } else if (duration < 7000) { + return 5000 + } else if (duration < 10000) { + return 8000 + } else if (duration < 12000) { + return 10000 + } else if (duration < 20000) { + return 15000 + } else if (duration < 30000) { + return 20000 + } + // max range + return 100000 +} + /** * macOS public.file-url will get encoded file path, * so we need to decode it diff --git a/src/renderer/utils/analytic.ts b/src/renderer/utils/analytic.ts new file mode 100644 index 0000000..1c85a4d --- /dev/null +++ b/src/renderer/utils/analytic.ts @@ -0,0 +1,23 @@ +/* eslint-disable camelcase */ +import { + TALKING_DATA_APPID, TALKING_DATA_EVENT +} from '~/universal/events/constants' +import pkg from 'root/package.json' +import { ipcRenderer } from 'electron' +import { handleTalkingDataEvent } from './common' +const { version } = pkg + +export const initTalkingData = () => { + setTimeout(() => { + const talkingDataScript = document.createElement('script') + + talkingDataScript.src = `http://sdk.talkingdata.com/app/h5/v1?appid=${TALKING_DATA_APPID}&vn=${version}&vc=${version}` + + const head = document.getElementsByTagName('head')[0] + head.appendChild(talkingDataScript) + }, 0) +} + +ipcRenderer.on(TALKING_DATA_EVENT, (_, data: ITalkingDataOptions) => { + handleTalkingDataEvent(data) +}) diff --git a/src/renderer/utils/common.ts b/src/renderer/utils/common.ts index 7021872..a846f28 100644 --- a/src/renderer/utils/common.ts +++ b/src/renderer/utils/common.ts @@ -2,6 +2,16 @@ import { isReactive, isRef, toRaw, unref } from 'vue' import { ipcRenderer } from 'electron' import { OPEN_URL } from '~/universal/events/constants' +const isDevelopment = process.env.NODE_ENV !== 'production' +export const handleTalkingDataEvent = (data: ITalkingDataOptions) => { + const { EventId, Label = '', MapKv = {} } = data + MapKv.from = window.location.href + window.TDAPP.onEvent(EventId, Label, MapKv) + if (isDevelopment) { + console.log('talkingData', data) + } +} + /** * get raw data from reactive or ref */ diff --git a/src/universal/events/constants.ts b/src/universal/events/constants.ts index 6867181..b2062a4 100644 --- a/src/universal/events/constants.ts +++ b/src/universal/events/constants.ts @@ -1,6 +1,8 @@ export const SHOW_INPUT_BOX = 'SHOW_INPUT_BOX' export const SHOW_INPUT_BOX_RESPONSE = 'SHOW_INPUT_BOX_RESPONSE' export const TOGGLE_SHORTKEY_MODIFIED_MODE = 'TOGGLE_SHORTKEY_MODIFIED_MODE' +export const TALKING_DATA_APPID = 'B743C16E2989419A9B02EDE9D1E6A530' +export const TALKING_DATA_EVENT = 'TALKING_DATA_EVENT' export const C1N = 'WjJoeFdWWklhVTlXYVRKTU5EUmFOVkEwUlVRPQ==' export const PICGO_SAVE_CONFIG = 'PICGO_SAVE_CONFIG' export const PICGO_GET_CONFIG = 'PICGO_GET_CONFIG' diff --git a/src/universal/types/types.d.ts b/src/universal/types/types.d.ts index 3482907..62fe170 100644 --- a/src/universal/types/types.d.ts +++ b/src/universal/types/types.d.ts @@ -128,6 +128,12 @@ interface IBounds { y: number } +interface ITalkingDataOptions { + EventId: string + Label?: string + MapKv?: IStringKeyMap +} + // PicGo Types type ICtx = import('piclist').PicGo interface IPicGoPlugin {