Skip to content

Commit

Permalink
feat: whole-bundle is done
Browse files Browse the repository at this point in the history
  • Loading branch information
wqcstrong committed Sep 27, 2024
1 parent ef00a9d commit fe20579
Show file tree
Hide file tree
Showing 13 changed files with 809 additions and 39 deletions.
4 changes: 2 additions & 2 deletions packages/page-spy-plugin-data-harbor/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,8 @@ export default class DataHarborPlugin implements PageSpyPlugin {
this.$pageSpyConfig = config;
this.$socketStore = socketStore;

const { api, enableSSL } = config;
if (!api) {
const { api, enableSSL, offline } = config;
if (!offline && !api) {
psLog.warn(
"Cannot upload log to PageSpy for miss 'api' configuration. See: ",
config,
Expand Down
1 change: 1 addition & 0 deletions packages/page-spy-plugin-whole-bundle/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@
</head>
<body>
<script type="module" src="./src/index.ts"></script>
<!-- <script src="./dist/index.min.js#manual"></script> -->
</body>
</html>
4 changes: 3 additions & 1 deletion packages/page-spy-plugin-whole-bundle/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
"description": "Packed 3 packages: page-spy-browser / page-spy-plugin-data-harbor / page-spy-plugin-rrweb. Only available in browser.",
"license": "MIT",
"main": "dist/iife/index.min.js",
"module": "dist/esm/index.min.js",
"types": "dist/types/index.d.ts",
"files": [
"dist"
Expand Down Expand Up @@ -39,7 +40,8 @@
"autoprefixer": "^10.3.4",
"less": "^4.1.1",
"postcss": "^8.4.21",
"vite": "^5.4.8"
"vite": "^5.4.8",
"vite-plugin-dts": "^4.2.2"
},
"prettier": {
"singleQuote": true,
Expand Down
4 changes: 4 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/assets/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
11 changes: 11 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/assets/export.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/assets/replay.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions packages/page-spy-plugin-whole-bundle/src/env.d.ts
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
/// <reference types="vite/client" />

interface Window {
$wholeBundle: any;
}
139 changes: 127 additions & 12 deletions packages/page-spy-plugin-whole-bundle/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,54 @@
import PageSpy from '@huolala-tech/page-spy-browser';
import DataHarborPlugin from '@huolala-tech/page-spy-plugin-data-harbor';
import RRWebPlugin from '@huolala-tech/page-spy-plugin-rrweb';
import { dot, pageSpyExist } from './utils';
import { dot, formatTime, pageSpyExist } from './utils';
import classes from './styles/index.module.less';
import './styles/normalize.less';
import pageSpyLogo from './assets/logo.svg?raw';
import closeSvg from './assets/close.svg?raw';
import exportSvg from './assets/export.svg?raw';
import replaySvg from './assets/replay.svg?raw';
import { moveable, UElement } from './utils/moveable';

interface Config {
floatText?: string;
title?: string;
/**
* Online source: 'https://example.com/xxx.jpg'
* Data url: 'data:image/png;base64,xxxx...'
* Relative source: '../xxx.jpg'
* Plain SVG content: '<svg>xxx</svg>'
*/
logo?: string;
statement?: string;
}

const defaultConfig: Config = {
floatText: '问题反馈',
logo: pageSpyLogo,
};

class WholeBundle {
$pageSpy: PageSpy | null = null;

$harbor: DataHarborPlugin | null = null;

$rrweb: RRWebPlugin | null = null;

constructor(public config: Config = defaultConfig) {
config: Config = {
title: '问题反馈',
logo: pageSpyLogo,
statement:
'声明:「问题反馈」组件处理的所有数据都是保存在您本地,不会主动将数据传输到任何服务器,可放心使用。',
};

startTime = 0;

constructor(userCfg?: Config) {
if (pageSpyExist()) {
console.info(
"[PageSpy] [WholeBundle] Detected that PageSpy already exists in the current context, so I won't be inited.",
);
return;
}
this.config = {
...this.config,
...userCfg,
};
this.init();
this.render();
}
Expand All @@ -53,6 +66,7 @@ class WholeBundle {
offline: true,
autoRender: false,
});
this.startTime = Date.now();
}

render() {
Expand All @@ -65,25 +79,110 @@ class WholeBundle {

startRender() {
const logo = this.getLogo();
const { statement, title } = this.config;

const doc = new DOMParser().parseFromString(
`
<div id="__pageSpyWholeBundle">
<button class="${classes.float}">
${logo ?? ''}
<span>${this.config.floatText}</span>
<span>${title}</span>
</button>
<div class="${classes.modal}">
<div class="${classes.content}"></div>
<div class="${classes.content}">
<div class="${classes.header}">
<div class="${classes.h_left}">
${logo ?? ''}
<div class="${classes.h_title}">
<b>${title}</b>
<br />
<span>操作录制基于 PageSpy 技术实现,<a href="https://github.com/HuolalaTech/page-spy-web" target="_blank">查看详情</a>。</span>
</div>
</div>
<div class="${classes.h_right}">
${closeSvg}
</div>
</div>
<div class="${classes.main}">
<div class="${classes.m_process}">
<div class="${classes.m_p_item}">
${exportSvg}
<b>1. 导出文件到本地</b>
</div>
<div class="${classes.m_p_item}">
${replaySvg}
<b>2. 前往 <a href="https://pagespy.org/#/log-replay" target="_blank">回放实验室</a> 查看</b>
</div>
</div>
<div class="${classes.m_statement}">
${statement}
</div>
</div>
<div class="${classes.footer}">
<div class="${classes.f_left}">
<b>REC</b>
<span class="${classes.f_duration}">--</span>
</div>
<div class="${classes.f_right}">
<button class="${classes.f_export}">导出</button>
</div>
</div>
</div>
</div>
</div>
`,
'text/html',
);

const $c = (name: string) => {
return doc.querySelector.bind(doc)(dot(name)) as HTMLElement;
};
const root = doc.querySelector('#__pageSpyWholeBundle') as HTMLDivElement;
const float = root.querySelector(dot(classes.float)) as UElement;
const float = $c(classes.float) as UElement;
const modal = $c(classes.modal);
const close = $c(classes.h_right);
const content = $c(classes.content);
const duration = $c(classes.f_duration);
const exportBtn = $c(classes.f_export) as HTMLButtonElement;

const openModal = () => {
if (float.isMoveEvent) return;
modal.classList.add(classes.show);
};
float.addEventListener('click', openModal);
moveable(float);
const closeModal = () => {
modal.classList.remove(classes.show);
modal.classList.add(classes.leaving);
setTimeout(() => {
modal.classList.remove(classes.leaving);
}, 300);
};
close.addEventListener('click', closeModal);
modal.addEventListener('click', closeModal);
content.addEventListener('click', (e) => {
e.stopPropagation();
});
if (this.startTime && duration) {
setInterval(() => {
const seconds = parseInt(
String((Date.now() - this.startTime) / 1000),
10,
);
duration.textContent = formatTime(seconds);
}, 1000);
}
exportBtn.addEventListener('click', async () => {
exportBtn.disabled = true;
exportBtn.textContent = '处理中';
await this.$harbor?.onOfflineLog('download');
exportBtn.textContent = '导出成功';
setTimeout(() => {
exportBtn.disabled = false;
exportBtn.textContent = '导出';
}, 1500);
});

document.body.insertAdjacentElement('beforeend', root);
}

Expand All @@ -96,11 +195,27 @@ class WholeBundle {

try {
const url = new URL(logo, window.location.href);
return url.href;
return `<img src="${url.href}" alt="logo" />`;
} catch (e) {
return null;
}
}
}

const src = (document.currentScript as HTMLScriptElement)?.src;
// prettier-ignore
(function main() {
if (!src) return;
try {
const { hash } = new URL(src, window.location.href);
const userManual = hash.slice(1) === 'manual';
if (!userManual) {
window.$wholeBundle = new WholeBundle();
}
} catch (e) {
//
}
}());

// export default WholeBundle;
export default new WholeBundle();
Loading

0 comments on commit fe20579

Please sign in to comment.