From 0f9e9285edeee530b560553f7607d0712dc3c6c7 Mon Sep 17 00:00:00 2001 From: "blucas.wu" <15555602203@163.com> Date: Fri, 1 Nov 2024 12:30:12 +0800 Subject: [PATCH 01/23] feat(plugin-harbor): support period in harbor --- .../src/browser.ts | 43 +++++++++++-- .../src/harbor/blob.ts | 63 +++++++++++++++++-- .../src/utils/index.ts | 15 ++++- 3 files changed, 110 insertions(+), 11 deletions(-) diff --git a/packages/page-spy-plugin-data-harbor/src/browser.ts b/packages/page-spy-plugin-data-harbor/src/browser.ts index 9127c401..00d693f8 100644 --- a/packages/page-spy-plugin-data-harbor/src/browser.ts +++ b/packages/page-spy-plugin-data-harbor/src/browser.ts @@ -14,22 +14,27 @@ import { RequestItem, SocketStoreBase, } from '@huolala-tech/page-spy-base'; -import { BlobHarbor } from './harbor/blob'; +import { BlobHarbor, PERIOD_DIVIDE_IDENTIFIER } from './harbor/blob'; import { buttonBindWithDownload, DownloadArgs, startDownload, } from './utils/download'; import { UploadArgs, buttonBindWithUpload, startUpload } from './utils/upload'; -import { getDeviceId, jsonToFile, makeData } from './utils'; +import { getDeviceId, isValidPeriod, jsonToFile, makeData } from './utils'; import { UPLOAD_TIPS } from './utils/locale'; import { Actions, CacheMessageItem, DataType } from './harbor/base'; interface DataHarborConfig { // Specify the maximum bytes of single harbor's container. - // Default 10MB. + // Default 10 * 1024 * 1024, 10MB. + // If a period is specified, it will use the period. maximum?: number; + // Set the duration of each period in milliseconds. + // Default is `null`, indicating no period division. + period?: number | null; + // Specify which types of data to collect. caredData?: Record; @@ -43,6 +48,7 @@ interface DataHarborConfig { const defaultConfig: DataHarborConfig = { maximum: 10 * 1024 * 1024, + period: null, caredData: { console: true, network: true, @@ -67,6 +73,8 @@ export default class DataHarborPlugin implements PageSpyPlugin { public isPaused = false; + private periodTimer: ReturnType | null = null; + public $socketStore: SocketStoreBase | null = null; public $pageSpyConfig: InitConfigBase | null = null; @@ -83,7 +91,10 @@ export default class DataHarborPlugin implements PageSpyPlugin { ...config, } as Required; - this.harbor = new BlobHarbor({ maximum: this.$harborConfig.maximum }); + this.harbor = new BlobHarbor({ + maximum: this.$harborConfig.maximum, + period: this.$harborConfig.period, + }); } public async onInit({ socketStore, config }: OnInitParams) { @@ -104,6 +115,8 @@ export default class DataHarborPlugin implements PageSpyPlugin { this.apiBase = removeEndSlash(`${apiScheme}${api}`); } + this.initPeriodTimer(); + this.$socketStore.addListener('public-data', (message) => { if (this.isPaused || !this.isCaredPublicData(message)) return; @@ -116,6 +129,19 @@ export default class DataHarborPlugin implements PageSpyPlugin { }); } + private initPeriodTimer() { + if (isValidPeriod(this.$harborConfig.period)) { + if (this.periodTimer) { + clearInterval(this.periodTimer); + } + this.periodTimer = setInterval(() => { + this.harbor.add(PERIOD_DIVIDE_IDENTIFIER); + // Notify other plugins to resend a full snapshot. + this.$socketStore?.dispatchEvent('harbor-clear', null); + }, this.$harborConfig.period); + } + } + public onMounted({ content }: OnMountedParams) { if (DataHarborPlugin.hasMounted) return; DataHarborPlugin.hasMounted = true; @@ -166,8 +192,8 @@ export default class DataHarborPlugin implements PageSpyPlugin { } } - onOfflineLog(type: 'download', clearCache: boolean): Promise; - onOfflineLog(type: 'upload', clearCache: boolean): Promise; + onOfflineLog(type: 'download', clearCache?: boolean): Promise; + onOfflineLog(type: 'upload', clearCache?: boolean): Promise; async onOfflineLog(type: Actions, clearCache = true): Promise { try { let result; @@ -194,6 +220,10 @@ export default class DataHarborPlugin implements PageSpyPlugin { } onReset() { + if (this.periodTimer) { + clearInterval(this.periodTimer); + this.periodTimer = null; + } this.harbor.clear(); DataHarborPlugin.hasInited = false; DataHarborPlugin.hasMounted = false; @@ -213,6 +243,7 @@ export default class DataHarborPlugin implements PageSpyPlugin { // Drop data in harbor and re-record public reharbor() { + this.initPeriodTimer(); this.harbor.clear(); this.$socketStore?.dispatchEvent('harbor-clear', null); if (this.isPaused) { diff --git a/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts b/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts index 6e281283..22e5c5e0 100644 --- a/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts +++ b/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts @@ -1,13 +1,31 @@ -import { isBrowser, isNumber } from '@huolala-tech/page-spy-base'; +import { isBrowser } from '@huolala-tech/page-spy-base'; +import { isValidMaximum, isValidPeriod } from '../utils'; interface HarborConfig { - maximum?: number; + maximum: number; + period: number | null; } let currentContainerSize = 0; +export const PERIOD_DIVIDE_IDENTIFIER = 'PERIOD_DIVIDE_IDENTIFIER'; + export class BlobHarbor { // Object URL list + // + // If add with 'maximum': + // [ + // , // the total size of each blob has been to the maximum + // , + // ... + // ] + // + // If add with 'period': + // [ + // , // the duration of each blob equals to the period + // , + // ..., + // ] stock: string[] = []; container: any[] = []; @@ -16,10 +34,19 @@ export class BlobHarbor { // 0 means no limitation. maximum = 0; + // Specify the duration of one period, unit is millisecond. + // Minimum period is 60 * 1000, 1 minute. + // Maximum period is 30 * 60 * 1000, 30 minutes. + // Default null, indicates no period division. + period: number | null = null; + constructor(config?: HarborConfig) { - if (config && isNumber(config.maximum) && config.maximum >= 0) { + if (isValidMaximum(config?.maximum)) { this.maximum = config.maximum; } + if (isValidPeriod(config?.period)) { + this.period = config.period; + } if (isBrowser()) { window.addEventListener('beforeunload', () => { this.stock.forEach((i) => { @@ -30,6 +57,25 @@ export class BlobHarbor { } public add(data: any) { + return this.period ? this.addByPeriod(data) : this.addByMaximum(data); + } + + private addByPeriod(data: any) { + if (data === PERIOD_DIVIDE_IDENTIFIER && this.container.length) { + const data2objectUrl = URL.createObjectURL( + new Blob([JSON.stringify(this.container)], { + type: 'application/json', + }), + ); + this.stock.push(data2objectUrl); + this.container = []; + } else { + this.container.push(data); + } + return true; + } + + private addByMaximum(data: any) { try { if (this.maximum === 0) { this.container.push(data); @@ -72,11 +118,20 @@ export class BlobHarbor { }), ); const validStockData = stockData.filter(Boolean); + if (this.period) { + return { + type: 'period', + data: validStockData.concat(this.container), + }; + } const combinedData = validStockData.reduce( (acc, cur) => acc.concat(cur), [], ); - return combinedData.concat(this.container); + return { + type: 'maximum', + data: combinedData.concat(this.container), + }; } clear() { diff --git a/packages/page-spy-plugin-data-harbor/src/utils/index.ts b/packages/page-spy-plugin-data-harbor/src/utils/index.ts index 92cf588d..4ff09f2a 100644 --- a/packages/page-spy-plugin-data-harbor/src/utils/index.ts +++ b/packages/page-spy-plugin-data-harbor/src/utils/index.ts @@ -1,4 +1,8 @@ -import { isBrowser, ROOM_SESSION_KEY } from '@huolala-tech/page-spy-base'; +import { + isBrowser, + isNumber, + ROOM_SESSION_KEY, +} from '@huolala-tech/page-spy-base'; import type { SpyMessage } from '@huolala-tech/page-spy-types'; import { strFromU8, zlibSync, strToU8 } from 'fflate'; @@ -40,3 +44,12 @@ export const jsonToFile = (data: any, filename: string) => { }); return file; }; + +// Valid duration of each period is 1 minute ~ 30 minutes. +export const isValidPeriod = (period: unknown): period is number => { + return isNumber(period) && period >= 60 * 1000 && period <= 30 * 60 * 1000; +}; + +export const isValidMaximum = (maximum: unknown): maximum is number => { + return isNumber(maximum) && maximum >= 0; +}; From e0ed6f0caf5465edfa30bf741c1235f79e9cc388 Mon Sep 17 00:00:00 2001 From: "blucas.wu" <15555602203@163.com> Date: Mon, 4 Nov 2024 17:21:50 +0800 Subject: [PATCH 02/23] feat(browser): add modal helper --- .../src/assets/modal-logo.svg | 5 + packages/page-spy-browser/src/env.d.ts | 4 + .../src/helpers/modal/index.module.less | 0 .../src/helpers/modal/index.ts | 101 ++++++++++++++++++ .../src/browser.ts | 15 +-- .../src/harbor/blob.ts | 26 +++-- .../src/utils/download.ts | 6 +- 7 files changed, 132 insertions(+), 25 deletions(-) create mode 100644 packages/page-spy-browser/src/assets/modal-logo.svg create mode 100644 packages/page-spy-browser/src/helpers/modal/index.module.less create mode 100644 packages/page-spy-browser/src/helpers/modal/index.ts diff --git a/packages/page-spy-browser/src/assets/modal-logo.svg b/packages/page-spy-browser/src/assets/modal-logo.svg new file mode 100644 index 00000000..4462dcef --- /dev/null +++ b/packages/page-spy-browser/src/assets/modal-logo.svg @@ -0,0 +1,5 @@ + + + \ No newline at end of file diff --git a/packages/page-spy-browser/src/env.d.ts b/packages/page-spy-browser/src/env.d.ts index 61821344..bd609a5e 100644 --- a/packages/page-spy-browser/src/env.d.ts +++ b/packages/page-spy-browser/src/env.d.ts @@ -13,6 +13,10 @@ declare global { const content: string; export default content; } + declare module '*.module.less' { + const content: any; + export default content; + } interface CookieChangeEvent extends Event { changed: CookieStoreValue[]; deleted: CookieStoreValue[]; diff --git a/packages/page-spy-browser/src/helpers/modal/index.module.less b/packages/page-spy-browser/src/helpers/modal/index.module.less new file mode 100644 index 00000000..e69de29b diff --git a/packages/page-spy-browser/src/helpers/modal/index.ts b/packages/page-spy-browser/src/helpers/modal/index.ts new file mode 100644 index 00000000..d7cc5862 --- /dev/null +++ b/packages/page-spy-browser/src/helpers/modal/index.ts @@ -0,0 +1,101 @@ +import { isString } from '@huolala-tech/page-spy-base'; +import logoSvg from '../assets/modal-logo.svg'; +import classes from './index.module.less'; + +interface ModalConfig { + logo: string; + title: string; + content: string | HTMLElement; + footer: (string | HTMLElement)[]; +} + +interface ShowParams { + content?: string | HTMLElement; + footer?: (string | HTMLElement)[]; +} + +const defaultConfig: ModalConfig = { + logo: logoSvg, + title: 'PageSpy', + content: document.createElement('div'), + footer: [], +}; + +export class modal { + constructor() { + if (new.target === modal) { + throw new Error('Init not allowed'); + } + } + + private static template = new DOMParser().parseFromString( + ` +
+
+
+ + +
+
+
+
+ +
+ +
+ `, + 'text/html', + ); + + private static query(className: string) { + return modal.template.querySelector.call( + modal.template, + `.${className}`, + ) as HTMLElement; + } + + public static config = defaultConfig; + + public static build(cfg: Partial) { + modal.config = { ...modal.config, ...cfg }; + } + + public static show(args?: ShowParams) { + const { logo, title, content, footer } = modal.config; + const main = args?.content ?? content; + const footerBtns = args?.footer ?? footer; + + const logoEl = modal.query(classes.logo) as HTMLImageElement; + const titleEl = modal.query(classes.title); + const contentEl = modal.query(classes.content); + const footerEl = modal.query(classes.footer); + + logoEl.setAttribute('src', logo); + titleEl.textContent = title; + contentEl.innerHTML = isString(main) ? main : main.outerHTML; + footerEl.innerHTML = footerBtns + .map((i) => (isString(i) ? i : i.outerHTML)) + .join('\n'); + + const root = modal.query(classes.modal); + const exist = document.body.contains(root); + if (!exist) { + document.body.appendChild(root); + } + root.classList.add('show'); + } + + public static close() { + const root = modal.query(classes.modal); + const exist = document.body.contains(root); + if (!exist) return; + + root.classList.remove('show'); + root.classList.add('leaving'); + setTimeout(() => { + root.classList.remove('leaving'); + }, 300); + } +} diff --git a/packages/page-spy-plugin-data-harbor/src/browser.ts b/packages/page-spy-plugin-data-harbor/src/browser.ts index 00d693f8..db0b2931 100644 --- a/packages/page-spy-plugin-data-harbor/src/browser.ts +++ b/packages/page-spy-plugin-data-harbor/src/browser.ts @@ -172,16 +172,18 @@ export default class DataHarborPlugin implements PageSpyPlugin { deviceId: getDeviceId(), userAgent: navigator.userAgent, }; + const data = await this.harbor.getAll(); + // TODO + // 需要区分 data ,如果分段了需要有更多操作 if (type === 'download') { return { - harbor: this.harbor, + data, filename, customDownload: onDownload, } as DownloadArgs; } if (type === 'upload') { - const data = await this.harbor.getAll(); const file = jsonToFile(data, filename()); const form = new FormData(); form.append('log', file); @@ -257,17 +259,10 @@ export default class DataHarborPlugin implements PageSpyPlugin { const { caredData } = this.$harborConfig; switch (type) { case 'console': - if (caredData.console) return true; - return false; case 'storage': - if (caredData.storage) return true; - return false; case 'system': - if (caredData.system) return true; - return false; case 'rrweb-event': - if (caredData['rrweb-event']) return true; - return false; + return caredData[type]; case 'network': const { url } = message.data as RequestItem; const isFetchHarborStockUrl = this.harbor.stock.includes(url); diff --git a/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts b/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts index 22e5c5e0..674e8e36 100644 --- a/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts +++ b/packages/page-spy-plugin-data-harbor/src/harbor/blob.ts @@ -61,18 +61,22 @@ export class BlobHarbor { } private addByPeriod(data: any) { - if (data === PERIOD_DIVIDE_IDENTIFIER && this.container.length) { - const data2objectUrl = URL.createObjectURL( - new Blob([JSON.stringify(this.container)], { - type: 'application/json', - }), - ); - this.stock.push(data2objectUrl); - this.container = []; - } else { - this.container.push(data); + try { + if (data === PERIOD_DIVIDE_IDENTIFIER && this.container.length) { + const data2objectUrl = URL.createObjectURL( + new Blob([JSON.stringify(this.container)], { + type: 'application/json', + }), + ); + this.stock.push(data2objectUrl); + this.container = []; + } else { + this.container.push(data); + } + return true; + } catch (e) { + return false; } - return true; } private addByMaximum(data: any) { diff --git a/packages/page-spy-plugin-data-harbor/src/utils/download.ts b/packages/page-spy-plugin-data-harbor/src/utils/download.ts index 1923c988..4f142ebd 100644 --- a/packages/page-spy-plugin-data-harbor/src/utils/download.ts +++ b/packages/page-spy-plugin-data-harbor/src/utils/download.ts @@ -1,21 +1,19 @@ import { psLog } from '@huolala-tech/page-spy-base'; -import { BlobHarbor } from '../harbor/blob'; import { DOWNLOAD_TIPS } from './locale'; import { formatFilename } from '.'; import { CacheMessageItem } from '../harbor/base'; export type DownloadArgs = { - harbor: BlobHarbor; + data: any; customDownload?: (data: CacheMessageItem[]) => void; filename: () => string; }; export const startDownload = async ({ - harbor, + data, filename, customDownload, }: DownloadArgs) => { - const data = await harbor.getAll(); if (customDownload) { await customDownload(data); return; From f9a0b86d23543326ae59176d68953ecf728e59ea Mon Sep 17 00:00:00 2001 From: "blucas.wu" <15555602203@163.com> Date: Tue, 5 Nov 2024 17:57:08 +0800 Subject: [PATCH 03/23] update modal component --- packages/page-spy-browser/rollup.config.mjs | 4 + .../page-spy-browser/src/assets/close.svg | 4 + .../src/assets/modal-logo.svg | 2 +- .../src/assets/styles/index.less | 93 +++++ .../src/assets/styles/modal.module.less | 145 +++++++ .../src/assets/styles/toast.module.less | 20 + .../src/assets/styles/variable.less | 42 +++ packages/page-spy-browser/src/config.ts | 7 +- .../page-spy-browser/src/helpers/modal.ts | 119 ++++++ .../src/helpers/modal/index.module.less | 0 .../src/helpers/modal/index.ts | 101 ----- .../page-spy-browser/src/helpers/toast.ts | 4 +- packages/page-spy-browser/src/index.less | 237 ------------ packages/page-spy-browser/src/index.ts | 353 +++++++++--------- .../src/browser.ts | 47 +-- packages/page-spy-types/lib/index.d.ts | 8 +- 16 files changed, 636 insertions(+), 550 deletions(-) create mode 100644 packages/page-spy-browser/src/assets/close.svg create mode 100644 packages/page-spy-browser/src/assets/styles/index.less create mode 100644 packages/page-spy-browser/src/assets/styles/modal.module.less create mode 100644 packages/page-spy-browser/src/assets/styles/toast.module.less create mode 100644 packages/page-spy-browser/src/assets/styles/variable.less create mode 100644 packages/page-spy-browser/src/helpers/modal.ts delete mode 100644 packages/page-spy-browser/src/helpers/modal/index.module.less delete mode 100644 packages/page-spy-browser/src/helpers/modal/index.ts delete mode 100644 packages/page-spy-browser/src/index.less diff --git a/packages/page-spy-browser/rollup.config.mjs b/packages/page-spy-browser/rollup.config.mjs index b3c46107..bac5cb60 100644 --- a/packages/page-spy-browser/rollup.config.mjs +++ b/packages/page-spy-browser/rollup.config.mjs @@ -27,6 +27,10 @@ const plugins = [ preventAssignment: true, }), postcss({ + modules: { + autoModules: true, + generateScopedName: '[local]-[hash:base64:5]' + }, extensions: ['.css', '.less'], extract: false, plugins: [autoprefixer()], diff --git a/packages/page-spy-browser/src/assets/close.svg b/packages/page-spy-browser/src/assets/close.svg new file mode 100644 index 00000000..b2a5b0f5 --- /dev/null +++ b/packages/page-spy-browser/src/assets/close.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/packages/page-spy-browser/src/assets/modal-logo.svg b/packages/page-spy-browser/src/assets/modal-logo.svg index 4462dcef..156f396c 100644 --- a/packages/page-spy-browser/src/assets/modal-logo.svg +++ b/packages/page-spy-browser/src/assets/modal-logo.svg @@ -1,5 +1,5 @@ + fill="white" /> \ No newline at end of file diff --git a/packages/page-spy-browser/src/assets/styles/index.less b/packages/page-spy-browser/src/assets/styles/index.less new file mode 100644 index 00000000..136c3313 --- /dev/null +++ b/packages/page-spy-browser/src/assets/styles/index.less @@ -0,0 +1,93 @@ +@import url(./variable.less); + +#__pageSpy { + font-size: @font-size; + line-height: 1; + .page-spy-logo { + --top-radius: 100%; + --right-radius: 100%; + --bottom-radius: 100%; + --left-radius: 100%; + position: fixed; + right: (40em / @font-size); + bottom: (80em / @font-size); + display: flex; + justify-content: center; + align-items: center; + width: (@size / @font-size); + height: (@size / @font-size); + font-size: (14em / @font-size); + border-radius: (@size / @font-size); + background-color: #fff; + box-shadow: 0px 4px 8px 2px rgba(0, 0, 0, 0.2); + cursor: pointer; + z-index: 13000; + transition: + opacity ease-in-out 0.3s, + transform ease-in-out 0.3s, + background-color ease-in-out 0.3s, + filter ease-in-out 0.3s; + &.inactive { + background-color: #a2a2a2; + filter: grayscale(1); + } + + &::after { + content: ''; + display: block; + position: absolute; + left: 0; + top: 0; + width: 100%; + height: 100%; + transform: rotateZ(45deg); + background-color: white; + border-top-left-radius: var(--top-radius); + border-top-right-radius: var(--right-radius); + border-bottom-right-radius: var(--bottom-radius); + border-bottom-left-radius: var(--left-radius); + transition: border-radius linear 0.15s; + } + + .hidden-mixin { + opacity: 0.35; + } + @logo-hidden-translate: 65%; + @img-hidden-translate: 30%; + &.hidden-in-top { + .hidden-mixin; + transform: translateY(-(@logo-hidden-translate)); + img { + transform: translateY(@img-hidden-translate); + } + } + &.hidden-in-right { + .hidden-mixin; + transform: translateX(@logo-hidden-translate); + img { + transform: translateX(-(@img-hidden-translate)); + } + } + &.hidden-in-bottom { + .hidden-mixin; + transform: translateY(@logo-hidden-translate); + img { + transform: translateY(-(@img-hidden-translate)); + } + } + &.hidden-in-left { + .hidden-mixin; + transform: translateX(-(@logo-hidden-translate)); + img { + transform: translateX(@img-hidden-translate); + } + } + img { + position: relative; + display: block; + z-index: 100; + transition: transform ease-in-out 0.1s 0.4s; + width: 50px; + } + } +} diff --git a/packages/page-spy-browser/src/assets/styles/modal.module.less b/packages/page-spy-browser/src/assets/styles/modal.module.less new file mode 100644 index 00000000..792466f0 --- /dev/null +++ b/packages/page-spy-browser/src/assets/styles/modal.module.less @@ -0,0 +1,145 @@ +@import url(./variable.less); + +@padding: (8em / @font-size) (14em / @font-size); + +.modal { + display: none; + position: fixed; + inset: 0; + z-index: 13000; + font-size: @font-size; + line-height: 1; + &:global { + &.show { + display: block; + :local { + animation: fadeIn 0.3s ease-in-out forwards; + } + @keyframes fadeIn { + 0% { + background-color: rgba(0, 0, 0, 0); + } + 100% { + background-color: rgba(0, 0, 0, 0.3); + } + } + :local(.content) { + :local { + animation: scaleIn 0.3s ease-in forwards; + } + @keyframes scaleIn { + 0% { + opacity: 0; + transform: translate3d(-50%, -50%, 0) scale(0.8); + } + 70% { + opacity: 1; + transform: translate3d(-50%, -50%, 0) scale(1.1); + } + 100% { + transform: translate3d(-50%, -50%, 0) scale(1); + } + } + } + } + &.leaving { + display: block; + :local { + animation: fadeOut 0.3s ease-in-out forwards; + } + @keyframes fadeOut { + 0% { + background-color: rgba(0, 0, 0, 0.3); + } + 100% { + background-color: rgba(0, 0, 0, 0); + } + } + :local(.content) { + :local { + animation: scaleOut 0.3s ease-out forwards; + } + @keyframes scaleOut { + 0% { + opacity: 1; + transform: translate3d(-50%, -50%, 0) scale(1); + } + 30% { + transform: translate3d(-50%, -50%, 0) scale(1.1); + } + 60% { + opacity: 0; + transform: translate3d(-50%, -50%, 0) scale(0.9); + } + 100% { + opacity: 0; + transform: translate3d(-50%, -50%, 0) scale(0.9); + } + } + } + } + } + .content { + position: absolute; + left: 50%; + top: 45%; + transform: translate3d(-50%, -50%, 0); + width: 90%; + background-color: #fafafa; + border-radius: (6em / @font-size); + overflow: hidden; + @media screen and (min-width: 440px) { + max-width: 65%; + } + @media screen and (min-width: 768px) { + max-width: 45%; + } + @media screen and (min-width: 1024px) { + max-width: 35%; + } + @media screen and (min-width: 1920px) { + max-width: 30%; + } + } + + .header { + display: flex; + justify-content: space-between; + align-items: center; + padding: @padding; + color: white; + background-color: @primary-color; + .headerLeft { + display: flex; + align-items: center; + gap: 4px; + .logo { + height: (28em / @font-size); + } + b { + font-size: (20em / @font-size); + } + } + .headerRight { + padding: 6px; + .close { + width: (24em / @font-size); + height: (24em / @font-size); + } + } + } + .main { + padding: @padding; + } + .footer { + display: flex; + justify-content: flex-end; + align-items: center; + gap: 4px; + padding: @padding; + border-top: 1px solid #dedede; + button { + .common-button(); + } + } +} diff --git a/packages/page-spy-browser/src/assets/styles/toast.module.less b/packages/page-spy-browser/src/assets/styles/toast.module.less new file mode 100644 index 00000000..55d7fde0 --- /dev/null +++ b/packages/page-spy-browser/src/assets/styles/toast.module.less @@ -0,0 +1,20 @@ +@import url(./variable.less); + +.toast { + position: fixed; + left: 50%; + top: 10%; + transform: translateX(-50%); + + max-width: 50vw; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + padding: 6px 12px; + color: @primary-color; + font-size: @font-size; + background-color: #fff; + border-radius: 4px; + box-shadow: 0px 2px 5px 2px rgba(0, 0, 0, 0.1); + z-index: 99999; +} diff --git a/packages/page-spy-browser/src/assets/styles/variable.less b/packages/page-spy-browser/src/assets/styles/variable.less new file mode 100644 index 00000000..c5ddfea0 --- /dev/null +++ b/packages/page-spy-browser/src/assets/styles/variable.less @@ -0,0 +1,42 @@ +@primary-color: #8434e9; +@lighten-color: lighten(@primary-color, 10%); +@gradient: linear-gradient(45deg, #efdfff, #4e00b1 52%, #3d0c7c); +@size: 80em; +@hidden-size: 40em; +@font-size: 14px; + +.common-button() { + display: flex; + justify-content: center; + align-items: center; + min-width: (80em / @font-size); + padding: (4em / @font-size); + gap: (4em / @font-size); + letter-spacing: 0.4px; + border: 1px solid #333; + border-radius: (4em / @font-size); + background-color: white; + color: #333; + cursor: pointer; + white-space: nowrap; + transition: all ease-in-out 100ms; + font-size: (13em / @font-size); + &[data-primary] { + border-color: @primary-color; + background-color: @primary-color; + color: white; + } + &:disabled { + border-color: #c8c8c8; + background-color: #c8c8c8; + color: white; + cursor: not-allowed; + } + &:hover { + border-color: @lighten-color; + background-color: @lighten-color; + } + svg { + width: (20em / @font-size); + } +} diff --git a/packages/page-spy-browser/src/config.ts b/packages/page-spy-browser/src/config.ts index bd26af14..92bf4add 100644 --- a/packages/page-spy-browser/src/config.ts +++ b/packages/page-spy-browser/src/config.ts @@ -1,6 +1,7 @@ import { ConfigBase } from '@huolala-tech/page-spy-base'; import { InitConfigBase } from '@huolala-tech/page-spy-types'; import logoUrl from './assets/logo.svg'; +import { modal } from './helpers/modal'; type InternalPlugins = | 'ConsolePlugin' @@ -45,14 +46,14 @@ export interface InitConfig extends InitConfigBase { } export class Config extends ConfigBase { - protected privateKeys: (keyof InitConfig)[] = ['secret']; - /** * NOTE: the 'scriptLink' must be mark static, for * "document.currentScript.src" only valid after + `, diff --git a/yarn.lock b/yarn.lock index ee5b6189..99c1a71f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6931,6 +6931,11 @@ hard-rejection@^2.1.0: resolved "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== +harmony-reflect@^1.4.6: + version "1.6.2" + resolved "https://registry.yarnpkg.com/harmony-reflect/-/harmony-reflect-1.6.2.tgz#31ecbd32e648a34d030d86adb67d4d47547fe710" + integrity sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g== + has-bigints@^1.0.1, has-bigints@^1.0.2: version "1.0.2" resolved "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" @@ -7160,6 +7165,13 @@ icss-utils@^5.0.0: resolved "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz#c6be6858abd013d768e98366ae47e25d5887b1ae" integrity sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA== +identity-obj-proxy@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz#94d2bda96084453ef36fbc5aaec37e0f79f1fc14" + integrity sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA== + dependencies: + harmony-reflect "^1.4.6" + ieee754@^1.1.13: version "1.2.1" resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" @@ -7850,6 +7862,13 @@ jest-config@^29.7.0: slash "^3.0.0" strip-json-comments "^3.1.1" +jest-css-modules@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/jest-css-modules/-/jest-css-modules-2.1.0.tgz#9c25ebe9d0214d8f55861a442268fdd4b01b4781" + integrity sha512-my3Scnt6l2tOll/eGwNZeh1KLAFkNzdl4MyZRdpl46GO6/93JcKKdTjNqK6Nokg8A8rT84MFLOpY1pzqKBEqMw== + dependencies: + identity-obj-proxy "3.0.0" + "jest-diff@>=29.4.3 < 30", jest-diff@^29.2.0, jest-diff@^29.4.1, jest-diff@^29.7.0: version "29.7.0" resolved "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz#017934a66ebb7ecf6f205e84699be10afd70458a" From 0332ee5c82782cba8db786ad44d805f7fc3c6915 Mon Sep 17 00:00:00 2001 From: "blucas.wu" <15555602203@163.com> Date: Wed, 20 Nov 2024 10:54:19 +0800 Subject: [PATCH 23/23] Add 'ua' meta info in period log --- packages/page-spy-plugin-data-harbor/src/browser/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/page-spy-plugin-data-harbor/src/browser/index.ts b/packages/page-spy-plugin-data-harbor/src/browser/index.ts index fe945641..f1760435 100644 --- a/packages/page-spy-plugin-data-harbor/src/browser/index.ts +++ b/packages/page-spy-plugin-data-harbor/src/browser/index.ts @@ -196,6 +196,7 @@ export default class DataHarborPlugin implements PageSpyPlugin { type: 'meta', timestamp: params.endTime, data: minifyData({ + ua: navigator.userAgent, title: document.title, url: window.location.href, ...params,