issues-reporter-plugin 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +599 -0
- package/dist/html2canvas.esm-CzwMv54K.js +4871 -0
- package/dist/html2canvas.esm-CzwMv54K.js.map +1 -0
- package/dist/index-Jh6bUIWx.js +31385 -0
- package/dist/index-Jh6bUIWx.js.map +1 -0
- package/dist/index.cjs +13 -0
- package/dist/index.es-Dq4QjyXr.js +5648 -0
- package/dist/index.es-Dq4QjyXr.js.map +1 -0
- package/dist/issues-reporter.auto.es.js +41918 -0
- package/dist/issues-reporter.auto.es.js.map +1 -0
- package/dist/issues-reporter.auto.umd.js +413 -0
- package/dist/issues-reporter.auto.umd.js.map +1 -0
- package/dist/issues-reporter.es.js +49 -0
- package/dist/issues-reporter.es.js.map +1 -0
- package/dist/issues-reporter.umd.js +413 -0
- package/dist/issues-reporter.umd.js.map +1 -0
- package/dist/purify.es-CesKVqev.js +472 -0
- package/dist/purify.es-CesKVqev.js.map +1 -0
- package/dist/style.css +1 -0
- package/dist/vite.svg +1 -0
- package/package.json +75 -0
package/README.md
ADDED
|
@@ -0,0 +1,599 @@
|
|
|
1
|
+
# issues-reporter-plugin 项目描述
|
|
2
|
+
|
|
3
|
+
## 1. 项目概述
|
|
4
|
+
|
|
5
|
+
`issues-reporter-plugin` 是一个**独立的外部前端插件**,用于嵌入到各个业务子系统(如 BDC 不动产登记中心各模块)中,实现**自动化提取报错信息**,并将 Bug 信息固化为标准结构,为下游团队提供可直接复现、信息完整的标准文档。
|
|
6
|
+
|
|
7
|
+
插件以 **TypeScript + 原生 DOM** 构建,零前端框架依赖,一套代码可同时支持 Vue 2/3、React、Angular 以及原生 JS 项目接入。
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## 2. 技术选型
|
|
12
|
+
|
|
13
|
+
| 维度 | 选型 | 说明 |
|
|
14
|
+
|------|------|------|
|
|
15
|
+
| 技术栈 | TypeScript + 原生 DOM | 零框架依赖,一套代码支持 Vue 2/3、React、Angular、原生 JS |
|
|
16
|
+
| 构建工具 | Vite | 极速冷启动,HMR 更快,原生 ES Module 支持 |
|
|
17
|
+
| 截图引擎 | html-to-image | 12KB 轻量,CSS 还原度高 |
|
|
18
|
+
| 样式 | 原生 CSS | 无预处理器依赖,浏览器原生支持,避免与宿主样式冲突 |
|
|
19
|
+
| UI 实现 | 原生 DOM API | `createElement` / `appendChild` / `addEventListener`,无框架绑定 |
|
|
20
|
+
| Word 导出 | docx 库 | 纯 JS 生成,样式精确可控 |
|
|
21
|
+
| PDF 导出 | jspdf + autotable | 原生支持中文,表格插件成熟 |
|
|
22
|
+
|
|
23
|
+
> **设计原则:** UI 层采用纯原生 DOM + TypeScript 实现,不依赖 Vue、React、Angular 等任何前端框架。核心逻辑层(异常捕获、Bug 构建器、截图引擎、导出服务)本来就是纯 TS,零框架依赖,可在任何技术栈的项目中一致使用。
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## 3. 架构设计
|
|
28
|
+
|
|
29
|
+
采用**三层架构**设计,各层职责清晰:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
┌─────────────────────────────────────────────────────────┐
|
|
33
|
+
│ 第 1 层:核心逻辑层(纯 TS,零框架依赖) │
|
|
34
|
+
│ ├── HTTP 拦截器(axios / fetch 双拦截) │
|
|
35
|
+
│ ├── 统一异常捕获协调器(HttpInterceptor) │
|
|
36
|
+
│ │ ├── JS 运行时错误监听 │
|
|
37
|
+
│ │ ├── Vue 错误处理(Vue 2/3) │
|
|
38
|
+
│ │ ├── Promise 未捕获拒绝监听 │
|
|
39
|
+
│ │ ├── XMLHttpRequest 拦截器 │
|
|
40
|
+
│ │ ├── console.error 拦截器 │
|
|
41
|
+
│ │ └── 资源加载错误监听(img/script/css) │
|
|
42
|
+
│ ├── 错误分类器(按来源与严重程度分类) │
|
|
43
|
+
│ ├── 截图引擎(html-to-image) │
|
|
44
|
+
│ ├── Bug 构建器(标准结构) │
|
|
45
|
+
│ └── 导出服务(JSON / MD / CSV / Word / PDF) │
|
|
46
|
+
├─────────────────────────────────────────────────────────┤
|
|
47
|
+
│ 第 2 层:UI 层(纯 DOM + TypeScript) │
|
|
48
|
+
│ ├── 悬浮工具栏(两个入口:创建 / 列表) │
|
|
49
|
+
│ ├── Bug 弹窗 │
|
|
50
|
+
│ │ ├── 模块一:我的问题清单(issueList) │
|
|
51
|
+
│ │ │ └── 展示当前用户已提交到后端的问题列表 │
|
|
52
|
+
│ │ └── 模块二:创建问题(createPreflight) │
|
|
53
|
+
│ │ └── 选取本地捕获的 Bug → 填写标题/描述 → 提交后端 │
|
|
54
|
+
│ └── 截图标注画布(矩形 / 箭头 / 文字 / 马赛克) │
|
|
55
|
+
├─────────────────────────────────────────────────────────┤
|
|
56
|
+
│ 第 3 层:分发适配层 │
|
|
57
|
+
│ ├── npm 模式(插件完全控制截图) │
|
|
58
|
+
│ └── iframe 模式(宿主提供截图钩子,插件调用) │
|
|
59
|
+
└─────────────────────────────────────────────────────────┘
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
所有异常捕获模块统一输出 `CaptureErrorInfo`,由 `NpmAdapter.handleCaptureError()` 统一处理:分类 → 去重 → 截图 → 构建 Bug 报告 → 存储到本地 → 回调通知。用户点击"创建"时,本地 Bug 作为候选数据带入创建表单,最终提交到后端。
|
|
63
|
+
|
|
64
|
+
---
|
|
65
|
+
|
|
66
|
+
## 4. 核心能力
|
|
67
|
+
|
|
68
|
+
### 4.1 自动异常捕获(后台静默运行)
|
|
69
|
+
|
|
70
|
+
插件启动后自动监听以下七类异常,捕获到的 Bug 暂存于本地内存,等待用户通过"创建问题"提交到后端:
|
|
71
|
+
|
|
72
|
+
| 来源 | 监听方式 | 捕获内容 | 默认是否开启 |
|
|
73
|
+
|------|---------|---------|------------|
|
|
74
|
+
| `http-error` | axios / fetch 拦截 | URL、method、status、请求参数、响应体 | 是 |
|
|
75
|
+
| `js-error` | `window.onerror` | message、filename、lineno、colno、stack | 是 |
|
|
76
|
+
| `vue-error` | `Vue.config.errorHandler` / `app.config.errorHandler` | 组件名、props、info、error.stack | 否(需显式设置 Vue 实例) |
|
|
77
|
+
| `promise-error` | `window.unhandledrejection` | reason、reason.stack | 是 |
|
|
78
|
+
| `xhr-error` | monkey-patch `XMLHttpRequest` | URL、method、headers、body、status、错误类型 | 是 |
|
|
79
|
+
| `console-error` | monkey-patch `console.error` | 调用参数列表 | 否 |
|
|
80
|
+
| `resource-error` | `window.addEventListener('error', ..., true)` | 资源标签名、src / href | 是 |
|
|
81
|
+
|
|
82
|
+
每类异常都生成统一的 `CaptureErrorInfo`,保留完整上下文(堆栈、组件、资源 URL、请求参数等),由 `ErrorClassifier` 按来源分级为 `critical` / `high` / `medium` / `low`。
|
|
83
|
+
|
|
84
|
+
**自动截图:** HTTP 错误触发时自动截取当前页面(可配置 `delay` 等待错误提示框弹出)。
|
|
85
|
+
|
|
86
|
+
**忽略规则:** 支持配置忽略特定 URL、状态码、业务码,避免误报。
|
|
87
|
+
|
|
88
|
+
### 4.2 模块一:我的问题清单(issueList)
|
|
89
|
+
|
|
90
|
+
点击悬浮工具栏 **"列表"** 按钮,弹窗展示当前用户已提交到后端的全部问题。
|
|
91
|
+
|
|
92
|
+
- 数据来源:`GET /issues-api/issues`(后端按当前登录用户过滤)
|
|
93
|
+
- 展示字段:问题编号、标题、来源、状态、严重程度、指派给、上报人、创建时间
|
|
94
|
+
- 操作:点击某行可跳转查看问题详情(含截图、接口信息、环境信息等)
|
|
95
|
+
|
|
96
|
+
### 4.3 模块二:创建问题(createPreflight)
|
|
97
|
+
|
|
98
|
+
点击悬浮工具栏 **"创建"** 按钮,弹窗展示本地已捕获的 Bug 列表,用户勾选后填写标题、严重程度、描述,可选截图标注,最终提交到后端生成问题单。
|
|
99
|
+
|
|
100
|
+
- 数据来源:插件运行期间自动捕获并存入本地的 Bug 列表
|
|
101
|
+
- 创建流程:选取 Bug → 填写标题 / 描述 / 严重程度 → 截图标注(可选) → 提交后端(`POST /issues-api/issues`)
|
|
102
|
+
- 支持**截图标注**(矩形框、箭头、文字、马赛克)
|
|
103
|
+
- 支持**撤销 / 重做**操作
|
|
104
|
+
|
|
105
|
+
### 4.4 多格式导出
|
|
106
|
+
|
|
107
|
+
支持批量导出 Bug 为多种格式:
|
|
108
|
+
|
|
109
|
+
| 格式 | 用途 |
|
|
110
|
+
|------|------|
|
|
111
|
+
| JSON | 标准数据,适合系统对接 |
|
|
112
|
+
| Markdown | 文档报告,适合 Git 归档 |
|
|
113
|
+
| CSV | 表格数据,适合 Excel 分析 |
|
|
114
|
+
| Word | 可编辑文档,适合协作打印 |
|
|
115
|
+
| PDF | 只读文档,适合归档提交 |
|
|
116
|
+
|
|
117
|
+
### 4.5 AI 员工 Inbox 导出
|
|
118
|
+
|
|
119
|
+
支持将 Bug 一键推送到**局域网内指定 AI 员工电脑的本地 Inbox 目录**,由该电脑上的集成 AI 自动监听并处理。支持 JSON / Markdown / Word / PDF 四种导出格式后发送。
|
|
120
|
+
|
|
121
|
+
### 4.6 标准化输出结构
|
|
122
|
+
|
|
123
|
+
所有 Bug 信息统一固化为标准 JSON 结构(`BugReport`),包含:
|
|
124
|
+
|
|
125
|
+
- 基础信息(ID、来源、严重程度、时间)
|
|
126
|
+
- 环境信息(子系统、浏览器、路由、分辨率)
|
|
127
|
+
- 接口信息(URL、方法、参数、响应)
|
|
128
|
+
- 描述信息(标题、自动描述、手动描述)
|
|
129
|
+
- 截图标注(Base64 图片 + 标注数据)
|
|
130
|
+
- 扩展信息(标签、上报人、自定义字段、源详情 `errorDetails`)
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## 5. 分发方式
|
|
135
|
+
|
|
136
|
+
插件支持三种集成方式:
|
|
137
|
+
|
|
138
|
+
1. **npm 包引入** — `import IssuesReporter from 'issues-reporter-plugin'`,适用于可修改源码的子项目
|
|
139
|
+
- 插件完全控制截图
|
|
140
|
+
- 直接访问宿主 DOM
|
|
141
|
+
|
|
142
|
+
2. **iframe 嵌入** — 通过 `<iframe src="...">` 方式嵌入,适用于无法修改源码的遗留系统
|
|
143
|
+
- 宿主提供截图钩子(`window.IssuesReporterScreenshot`)
|
|
144
|
+
- 插件通过 postMessage 调用
|
|
145
|
+
- 支持 HTTP/HTTPS 混合环境(协议自适应)
|
|
146
|
+
|
|
147
|
+
3. **`<script>` 自动初始化** — 直接引用构建产物 `issues-reporter.auto.umd.js`,通过 `data-*` 属性完成配置,无需编写业务代码
|
|
148
|
+
- 自动发现 Vue 2 / Vue 3 实例并绑定 `errorHandler`
|
|
149
|
+
- 自动发现页面上的 axios 实例
|
|
150
|
+
- 脚本解析后立即启动所有错误监听器,DOM 就绪后挂载 UI
|
|
151
|
+
|
|
152
|
+
---
|
|
153
|
+
|
|
154
|
+
## 6. 项目集成示例
|
|
155
|
+
|
|
156
|
+
### 6.1 Vue 3 项目
|
|
157
|
+
|
|
158
|
+
```ts
|
|
159
|
+
// main.ts
|
|
160
|
+
import { createApp } from 'vue'
|
|
161
|
+
import App from './App.vue'
|
|
162
|
+
import IssuesReporter from 'issues-reporter-plugin'
|
|
163
|
+
import axios from 'axios'
|
|
164
|
+
|
|
165
|
+
const app = createApp(App)
|
|
166
|
+
app.mount('#app')
|
|
167
|
+
|
|
168
|
+
const issuesReporter = new IssuesReporter({
|
|
169
|
+
projectKey: 'BDC', // 必填:项目标识(对应后端 Project.key)
|
|
170
|
+
projectName: '不动产登记中心', // 必填:项目名称,首次上报时自动创建
|
|
171
|
+
version: 'v2.0.0', // 必填:版本号,对应 Issue.version
|
|
172
|
+
token: 'eyJhbGc...', // 必填(与 externalUserInfo 二选一):JWT token 登录
|
|
173
|
+
// externalUserInfo: { userName: 'admin', userNickname: '管理员' }, // 或传用户信息免密登录
|
|
174
|
+
// server: '', // 后端地址为空时使用当前页面域名;跨域时填写完整前缀
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
// 注入 axios 实例(可选,用于精确提取请求参数)
|
|
178
|
+
issuesReporter.setAxiosInstance(axios)
|
|
179
|
+
|
|
180
|
+
// 注入 Vue 实例,开启 Vue 组件错误监控
|
|
181
|
+
issuesReporter.setVueInstance(app)
|
|
182
|
+
|
|
183
|
+
// 挂载 UI(悬浮工具栏 + Bug 弹窗)
|
|
184
|
+
issuesReporter.mount()
|
|
185
|
+
|
|
186
|
+
window.addEventListener('beforeunload', () => issuesReporter.destroy())
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
> **另一种登录方式**:若外部系统无法提供 JWT,可改为传入 `externalUserInfo`(与 `token` 二选一),插件会调用 `loginByUser` 接口免密登录:
|
|
190
|
+
> ```ts
|
|
191
|
+
> const issuesReporter = new IssuesReporter({
|
|
192
|
+
> projectKey: 'BDC',
|
|
193
|
+
> projectName: '不动产登记中心',
|
|
194
|
+
> version: 'v2.0.0',
|
|
195
|
+
> externalUserInfo: { userName: 'admin', userNickname: '管理员' },
|
|
196
|
+
> })
|
|
197
|
+
> ```
|
|
198
|
+
|
|
199
|
+
其余参数(`screenshotOptions`、`ignore`、`jsError`、`consoleError` 等)均有合理默认值,完整说明见 [6.7 关键配置说明](#67-关键配置说明)。
|
|
200
|
+
|
|
201
|
+
### 6.2 Vue 2 项目
|
|
202
|
+
|
|
203
|
+
```ts
|
|
204
|
+
// main.js
|
|
205
|
+
import Vue from 'vue'
|
|
206
|
+
import App from './App.vue'
|
|
207
|
+
import IssuesReporter from 'issues-reporter-plugin'
|
|
208
|
+
import axios from 'axios'
|
|
209
|
+
|
|
210
|
+
new Vue({ render: h => h(App) }).$mount('#app')
|
|
211
|
+
|
|
212
|
+
const issuesReporter = new IssuesReporter({
|
|
213
|
+
projectKey: 'PUB3',
|
|
214
|
+
projectName: '智治平台',
|
|
215
|
+
version: 'v2.0.0',
|
|
216
|
+
token: 'eyJhbGc...', // 必填(与 externalUserInfo 二选一):JWT token 登录
|
|
217
|
+
// externalUserInfo: { userName: 'admin', userNickname: '管理员' }, // 或传用户信息免密登录
|
|
218
|
+
})
|
|
219
|
+
|
|
220
|
+
issuesReporter.setAxiosInstance(Vue.prototype.$axios || axios)
|
|
221
|
+
issuesReporter.setVueInstance(Vue)
|
|
222
|
+
issuesReporter.mount()
|
|
223
|
+
|
|
224
|
+
window.addEventListener('beforeunload', () => issuesReporter.destroy())
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### 6.3 React 项目
|
|
228
|
+
|
|
229
|
+
```tsx
|
|
230
|
+
// App.tsx
|
|
231
|
+
import { useEffect } from 'react'
|
|
232
|
+
import IssuesReporter from 'issues-reporter-plugin'
|
|
233
|
+
|
|
234
|
+
function App() {
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
const issuesReporter = new IssuesReporter({
|
|
237
|
+
projectKey: 'REACT_APP',
|
|
238
|
+
projectName: 'React 业务系统',
|
|
239
|
+
version: 'v1.0.0',
|
|
240
|
+
token: 'eyJhbGc...', // 必填(与 externalUserInfo 二选一)
|
|
241
|
+
// externalUserInfo: { userName: 'admin', userNickname: '管理员' },
|
|
242
|
+
})
|
|
243
|
+
issuesReporter.mount()
|
|
244
|
+
return () => issuesReporter.destroy()
|
|
245
|
+
}, [])
|
|
246
|
+
|
|
247
|
+
return <div>{/* 业务组件 */}</div>
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
export default App
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
### 6.4 Angular 项目
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
// app.component.ts
|
|
257
|
+
import { Component, OnInit, OnDestroy } from '@angular/core'
|
|
258
|
+
import IssuesReporter from 'issues-reporter-plugin'
|
|
259
|
+
|
|
260
|
+
@Component({
|
|
261
|
+
selector: 'app-root',
|
|
262
|
+
template: '<router-outlet></router-outlet>'
|
|
263
|
+
})
|
|
264
|
+
export class AppComponent implements OnInit, OnDestroy {
|
|
265
|
+
private issuesReporter!: IssuesReporter
|
|
266
|
+
|
|
267
|
+
ngOnInit() {
|
|
268
|
+
this.issuesReporter = new IssuesReporter({
|
|
269
|
+
projectKey: 'NG_APP',
|
|
270
|
+
projectName: 'Angular 业务系统',
|
|
271
|
+
version: 'v1.0.0',
|
|
272
|
+
token: 'eyJhbGc...', // 必填(与 externalUserInfo 二选一)
|
|
273
|
+
// externalUserInfo: { userName: 'admin', userNickname: '管理员' },
|
|
274
|
+
})
|
|
275
|
+
this.issuesReporter.mount()
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
ngOnDestroy() {
|
|
279
|
+
this.issuesReporter.destroy()
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 6.5 自动初始化入口(`<script>` 零代码集成)
|
|
285
|
+
|
|
286
|
+
如果目标系统不想引入 npm 包或在业务代码里实例化插件,可以直接通过 `<script>` 引用自动初始化产物。推荐把脚本放在 `<head>` 或业务 bundle 之前,以便尽早启动错误监听,捕获 Vue 挂载阶段和早期接口错误。
|
|
287
|
+
|
|
288
|
+
```html
|
|
289
|
+
<!DOCTYPE html>
|
|
290
|
+
<html>
|
|
291
|
+
<head>
|
|
292
|
+
<link rel="stylesheet" href="//your-static-server/issues-reporter-plugin/0.2.20/style.css">
|
|
293
|
+
<script
|
|
294
|
+
src="//your-static-server/issues-reporter-plugin/0.2.20/issues-reporter.auto.umd.js"
|
|
295
|
+
data-project-key="PUB3"
|
|
296
|
+
data-token="eyJhbGc..."
|
|
297
|
+
data-delay="600"
|
|
298
|
+
data-vue-error="true"
|
|
299
|
+
data-ignore-urls="/heartbeat/"
|
|
300
|
+
data-ignore-business-codes="401"
|
|
301
|
+
></script>
|
|
302
|
+
</head>
|
|
303
|
+
<body>
|
|
304
|
+
<div id="app"></div>
|
|
305
|
+
<script src="/app.js"></script>
|
|
306
|
+
</body>
|
|
307
|
+
</html>
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
常用 `data-*` 属性:
|
|
311
|
+
|
|
312
|
+
| 属性 | 说明 | 示例 |
|
|
313
|
+
|---|---|---|
|
|
314
|
+
| `data-project-key` | 项目唯一标识,必填 | `PUB3` |
|
|
315
|
+
| `data-project-name` | 项目名称,首次上报时自动创建 | `智治平台` |
|
|
316
|
+
| `data-server` | 后端接口前缀,为空时使用当前页面域名 | `http://192.168.1.100:3000` |
|
|
317
|
+
| `data-token` | JWT token(与 `data-user-name` 二选一),用于 `loginByToken` 免密登录 | `eyJhbGc...` |
|
|
318
|
+
| `data-user-name` | 用户账号(与 `data-token` 二选一),用于 `loginByUser` 免密登录 | `admin` |
|
|
319
|
+
| `data-user-nickname` | 用户昵称(配合 `data-user-name` 使用),首次创建用户时写入 | `管理员` |
|
|
320
|
+
| `data-delay` | 截图延迟 ms | `600` |
|
|
321
|
+
| `data-quality` | 截图质量 0-1 | `0.6` |
|
|
322
|
+
| `data-max-size` | 截图最大字节 | `307200` |
|
|
323
|
+
| `data-show-flash` | 截图闪光提示 | `false` |
|
|
324
|
+
| `data-auto-screenshot` | 是否自动截图 | `true` |
|
|
325
|
+
| `data-js-error` | 监听 JS 运行时错误 | `true` |
|
|
326
|
+
| `data-vue-error` | 监听 Vue 错误 | `true` |
|
|
327
|
+
| `data-promise-error` | 监听 Promise 未捕获拒绝 | `true` |
|
|
328
|
+
| `data-xhr-error` | 监听 XHR 错误 | `true` |
|
|
329
|
+
| `data-console-error` | 监听 `console.error` | `false` |
|
|
330
|
+
| `data-resource-error` | 监听资源加载失败 | `true` |
|
|
331
|
+
| `data-ignore-urls` | 忽略 URL/正则,逗号分隔 | `/heartbeat/,/poll/` |
|
|
332
|
+
| `data-ignore-status-codes` | 忽略 HTTP 状态码 | `401,500` |
|
|
333
|
+
| `data-ignore-business-codes` | 忽略业务错误码 | `401,9999` |
|
|
334
|
+
| `data-ignore-methods` | 忽略 HTTP 方法 | `GET,OPTIONS` |
|
|
335
|
+
|
|
336
|
+
布尔属性写 `true` 或只写属性名都算开启;要关闭直接省略该属性。
|
|
337
|
+
|
|
338
|
+
如需更高优先级覆盖,仍可保留 `window.IssuesReporterConfig`:
|
|
339
|
+
|
|
340
|
+
```html
|
|
341
|
+
<script>
|
|
342
|
+
window.IssuesReporterConfig = { projectKey: 'PUB3', vueError: true }
|
|
343
|
+
</script>
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
配置合并优先级:`window.IssuesReporterConfig` > `<script data-*>`。
|
|
347
|
+
|
|
348
|
+
> **注意:** 自动初始化产物在脚本解析完成后立即启动错误监听器,UI 则在 DOM 就绪后挂载。若把脚本放在页面末尾,仍可能错过 `<head>` 或 body 前半段发生的错误,因此建议放在业务 JS 之前。
|
|
349
|
+
|
|
350
|
+
### 6.6 原生 JS 项目
|
|
351
|
+
|
|
352
|
+
```html
|
|
353
|
+
<!-- index.html -->
|
|
354
|
+
<script type="module">
|
|
355
|
+
import IssuesReporter from 'https://your-cdn.com/issues-reporter-plugin/dist/issues-reporter.es.js'
|
|
356
|
+
|
|
357
|
+
const issuesReporter = new IssuesReporter({
|
|
358
|
+
projectKey: 'NATIVE_APP',
|
|
359
|
+
token: 'eyJhbGc...', // 必填(与 externalUserInfo 二选一)
|
|
360
|
+
enabled: true,
|
|
361
|
+
autoScreenshot: true,
|
|
362
|
+
screenshotOptions: { delay: 500 },
|
|
363
|
+
jsError: true,
|
|
364
|
+
promiseError: true,
|
|
365
|
+
xhrError: true,
|
|
366
|
+
resourceError: true
|
|
367
|
+
})
|
|
368
|
+
|
|
369
|
+
issuesReporter.mount()
|
|
370
|
+
|
|
371
|
+
window.addEventListener('beforeunload', () => {
|
|
372
|
+
issuesReporter.destroy()
|
|
373
|
+
})
|
|
374
|
+
</script>
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### 6.7 关键配置说明
|
|
378
|
+
|
|
379
|
+
| 配置项 | 说明 | 常用值 |
|
|
380
|
+
|--------|------|--------|
|
|
381
|
+
| `projectKey` | 项目唯一标识,对应后端 `Project.key` | `'BDC'` / `'BDCDJ3'` / `'BDCYC2'` / `'BDCQD'` / `'PUB3'` |
|
|
382
|
+
| `projectName` | 项目名称,首次上报时若项目不存在则自动创建 | `'不动产登记中心'` |
|
|
383
|
+
| `version` | 项目版本号,对应后端 `Issue.version` | `'v2.0.0'` |
|
|
384
|
+
| `server` | 后端接口前缀,插件据此拼接 `/issues-api/*` 地址;为空时使用当前页面域名 | `''` / `'http://192.168.1.100:3000'` |
|
|
385
|
+
| `token` | **必填**(与 `externalUserInfo` 二选一),外部系统传入的 JWT token,用于 `loginByToken` 免密登录 | `'eyJhbGc...'` |
|
|
386
|
+
| `externalUserInfo` | **必填**(与 `token` 二选一),外部系统传入的用户信息,用于 `loginByUser` 免密登录(无 JWT 场景) | `{ userName: 'admin', userNickname: '管理员' }` |
|
|
387
|
+
| `enabled` | 是否启用插件 | `true`(默认) |
|
|
388
|
+
| `autoScreenshot` | 接口报错时是否自动截图 | `true`(默认) |
|
|
389
|
+
| `screenshotOptions.delay` | 报错后等待多少毫秒再截图,等待错误提示框弹出 | `500` ~ `1000` |
|
|
390
|
+
| `ignore.urls` | 忽略的 URL 正则/字符串列表 | `[/heartbeat/, /poll/]` |
|
|
391
|
+
| `ignore.statusCodes` | 忽略的 HTTP 状态码 | `[401, 403]` |
|
|
392
|
+
| `ignore.businessCodes` | 忽略的业务错误码 | `['401', '9999']` |
|
|
393
|
+
| `isBackendEnabled` | 是否显示"提交后台"按钮 | `true`(默认),显式 `false` 时隐藏 |
|
|
394
|
+
| `backendApiHeaders` | 提交到后台时的额外请求头 | `{ 'x-gisq-token': 'Bearer ...' }` |
|
|
395
|
+
| `jsError` | 是否监听 `window.onerror` | `true`(默认) |
|
|
396
|
+
| `vueError` | 是否监听 Vue 错误(需调用 `setVueInstance`) | 随 `setVueInstance` 自动开启 |
|
|
397
|
+
| `promiseError` | 是否监听未捕获 Promise 拒绝 | `true`(默认) |
|
|
398
|
+
| `xhrError` | 是否拦截 XMLHttpRequest 错误 | `true`(默认) |
|
|
399
|
+
| `consoleError` | 是否拦截 `console.error` | `false`(默认,避免噪音) |
|
|
400
|
+
| `resourceError` | 是否监听图片/脚本/CSS 加载失败 | `true`(默认) |
|
|
401
|
+
| `onBugCaptured` | Bug 捕获后的回调函数 | `(bug) => { ... }` |
|
|
402
|
+
| `loadPluginConfig` | 异步加载运行时配置的钩子,覆盖默认的 `/system-settings/plugin` 拉取逻辑 | `async () => ({ resourceError: false })` |
|
|
403
|
+
| `setAxiosInstance` / `setAxiosInstances` | 注入 axios 实例;支持单个或数组批量注入多个实例 | `axios` / `[RegAxios, WorkflowAxios]` |
|
|
404
|
+
|
|
405
|
+
### 6.8 AI Inbox 配置(可选)
|
|
406
|
+
|
|
407
|
+
```ts
|
|
408
|
+
const issuesReporter = new IssuesReporter({
|
|
409
|
+
projectKey: 'BDC',
|
|
410
|
+
// ... 其他配置
|
|
411
|
+
aiInbox: {
|
|
412
|
+
enabled: true,
|
|
413
|
+
defaultEmployeeId: '001ai',
|
|
414
|
+
defaultFormat: 'word',
|
|
415
|
+
employees: [
|
|
416
|
+
{
|
|
417
|
+
id: '001ai',
|
|
418
|
+
name: '001号 AI 员工',
|
|
419
|
+
host: '192.168.1.105',
|
|
420
|
+
port: 8765
|
|
421
|
+
}
|
|
422
|
+
]
|
|
423
|
+
}
|
|
424
|
+
})
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
或在运行时动态注入:
|
|
428
|
+
|
|
429
|
+
```ts
|
|
430
|
+
issuesReporter.setAiInboxConfig({
|
|
431
|
+
enabled: true,
|
|
432
|
+
defaultEmployeeId: '001ai',
|
|
433
|
+
defaultFormat: 'word',
|
|
434
|
+
employees: [...]
|
|
435
|
+
})
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
## 7. 业务背景
|
|
440
|
+
|
|
441
|
+
本插件服务于 **BDC 不动产登记中心** 系列子系统,已知子系统包括:
|
|
442
|
+
|
|
443
|
+
| 项目标识 (`projectKey`) | 业务范围 | 接入模式 | 关键配置 |
|
|
444
|
+
|-----------|---------|---------|---------|
|
|
445
|
+
| BDC | 不动产通用(电子证照、纳税申报、评估报告等) | npm (Vue 3) | `delay: 800`,忽略证照刷新轮询 |
|
|
446
|
+
| BDCDJ3 | 登记业务(影像规则、规则检查等) | npm (Vue 3) | `delay: 500`,忽略规则检查轮询 |
|
|
447
|
+
| BDCYC2 | 不动产预告 / 转移 / 抵押 / 变更等全流程 | npm (Vue 3) | `delay: 1000`,忽略流程状态轮询 |
|
|
448
|
+
| BDCQD | 地籍调查(业务中心配置等) | iframe / npm | `delay: 600`,忽略地图瓦片加载 |
|
|
449
|
+
| **PUB3** | **智治平台** | **npm (Vue 2)** | **`delay: 600`,忽略心跳接口** |
|
|
450
|
+
|
|
451
|
+
**HTTP/HTTPS 混合环境:** BDC 系统同时存在 HTTP 和 HTTPS,插件服务需部署两套,配置使用 `//` 协议自适应。
|
|
452
|
+
|
|
453
|
+
常见 Bug 类型:
|
|
454
|
+
|
|
455
|
+
- 表单必填校验缺失(字段标 * 但未校验)
|
|
456
|
+
- 流程步骤间数据传递异常(挂单元重复、数据未刷新)
|
|
457
|
+
- 界面响应异常(无响应、转圈、跳转失败)
|
|
458
|
+
- 国产环境兼容性问题
|
|
459
|
+
- 配置项不生效
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## 8. 目录结构
|
|
464
|
+
|
|
465
|
+
```
|
|
466
|
+
issues-reporter-plugin/
|
|
467
|
+
├── src/ # 主应用(调试 / 演示入口)
|
|
468
|
+
│ ├── main.ts
|
|
469
|
+
│ ├── App.vue
|
|
470
|
+
│ ├── router/
|
|
471
|
+
│ └── views/
|
|
472
|
+
│ └── DemoPage.vue # 插件演示页
|
|
473
|
+
│
|
|
474
|
+
├── packages/ # 插件核心模块
|
|
475
|
+
│ ├── core/ # 📦 核心逻辑层(纯 TS)
|
|
476
|
+
│ │ ├── interceptors/
|
|
477
|
+
│ │ │ ├── http-interceptor.ts # HTTP 拦截(axios / fetch)与统一协调
|
|
478
|
+
│ │ │ ├── error-classifier.ts # 错误分类与分级
|
|
479
|
+
│ │ │ ├── error-capture.ts # 统一捕获接口定义
|
|
480
|
+
│ │ │ ├── js-error-listener.ts # JS 运行时错误监听
|
|
481
|
+
│ │ │ ├── vue-error-handler.ts # Vue 2/3 错误处理
|
|
482
|
+
│ │ │ ├── promise-error-listener.ts # Promise 未捕获拒绝监听
|
|
483
|
+
│ │ │ ├── xhr-interceptor.ts # XMLHttpRequest 拦截
|
|
484
|
+
│ │ │ ├── console-error-interceptor.ts# console.error 拦截
|
|
485
|
+
│ │ │ └── resource-error-listener.ts # 资源加载错误监听
|
|
486
|
+
│ │ ├── services/
|
|
487
|
+
│ │ │ ├── screenshot.service.ts # 截图引擎(html-to-image)
|
|
488
|
+
│ │ │ ├── screenshot/
|
|
489
|
+
│ │ │ │ ├── image-preprocessor.ts # 图片预处理
|
|
490
|
+
│ │ │ │ ├── canvas-handler.ts # Canvas 处理
|
|
491
|
+
│ │ │ │ ├── scroll-sync.ts # 滚动同步
|
|
492
|
+
│ │ │ │ └── iframe-capturer.ts # iframe 截图合成
|
|
493
|
+
│ │ │ ├── bug-builder.service.ts # Bug 构建器(标准结构)
|
|
494
|
+
│ │ │ ├── bug-store.service.ts # 数据存储(内存)
|
|
495
|
+
│ │ │ └── export.service.ts # 导出服务框架
|
|
496
|
+
│ │ ├── exporters/
|
|
497
|
+
│ │ │ ├── json.exporter.ts
|
|
498
|
+
│ │ │ ├── markdown.exporter.ts
|
|
499
|
+
│ │ │ ├── csv.exporter.ts
|
|
500
|
+
│ │ │ ├── word.exporter.ts
|
|
501
|
+
│ │ │ └── pdf.exporter.ts
|
|
502
|
+
│ │ └── index.ts
|
|
503
|
+
│ │
|
|
504
|
+
│ ├── ui/ # 📦 UI 层(纯 DOM + TS)
|
|
505
|
+
│ │ ├── components/
|
|
506
|
+
│ │ │ ├── floating-toolbar.ts # 悬浮工具栏(原生 DOM)
|
|
507
|
+
│ │ │ ├── bug-dialog.ts # Bug 弹窗容器(原生 DOM)
|
|
508
|
+
│ │ │ ├── bug-list.ts # Bug 列表组件(原生 DOM)
|
|
509
|
+
│ │ │ ├── bug-create.ts # 创建 Bug 表单(原生 DOM)
|
|
510
|
+
│ │ │ ├── export-panel.ts # 导出面板(原生 DOM)
|
|
511
|
+
│ │ │ ├── send-ai-dialog.ts # 发送 AI 对话框
|
|
512
|
+
│ │ │ ├── panels/ # 弹窗内各面板
|
|
513
|
+
│ │ │ │ ├── issue-list-panel.ts # 模块一:我的问题清单(后端数据)
|
|
514
|
+
│ │ │ │ ├── issue-edit-panel.ts # 问题详情 / 编辑
|
|
515
|
+
│ │ │ │ ├── bug-create-panel.ts # 模块二:创建问题表单
|
|
516
|
+
│ │ │ │ ├── bug-preflight-panel.ts # 创建预检(选取本地 Bug → 提交)
|
|
517
|
+
│ │ │ │ ├── bug-list-panel.ts # 本地 Bug 列表
|
|
518
|
+
│ │ │ │ ├── bug-detail-panel.ts # 本地 Bug 详情
|
|
519
|
+
│ │ │ │ ├── bug-export-panel.ts # 导出面板
|
|
520
|
+
│ │ │ │ ├── ai-inbox-panel.ts # 发送 AI 对话框
|
|
521
|
+
│ │ │ │ └── dialog-utils.ts # 弹窗工具函数
|
|
522
|
+
│ │ │ └── annotation-canvas.ts # 截图标注画布(原生 DOM)
|
|
523
|
+
│ │ ├── styles/
|
|
524
|
+
│ │ │ ├── toolbar.css # 工具栏样式
|
|
525
|
+
│ │ │ ├── dialog.css # 弹窗样式
|
|
526
|
+
│ │ │ ├── list.css # 列表样式
|
|
527
|
+
│ │ │ └── canvas.css # 画布样式
|
|
528
|
+
│ │ └── index.ts
|
|
529
|
+
│ │
|
|
530
|
+
│ ├── adapters/ # 📦 分发适配层
|
|
531
|
+
│ │ ├── npm-adapter.ts # npm 模式(完全控制截图)
|
|
532
|
+
│ │ └── iframe-adapter.ts # iframe 模式(postMessage)
|
|
533
|
+
│ │
|
|
534
|
+
│ ├── types/ # 📦 类型定义
|
|
535
|
+
│ │ ├── bug-report.ts
|
|
536
|
+
│ │ ├── config.ts
|
|
537
|
+
│ │ └── index.ts
|
|
538
|
+
│ │
|
|
539
|
+
│ ├── index.ts # 统一入口
|
|
540
|
+
│ └── auto-init.ts # <script> 自动初始化入口
|
|
541
|
+
│
|
|
542
|
+
├── scripts/ # 构建与发布脚本
|
|
543
|
+
│ ├── release.js # 交互式 npm 发布脚本
|
|
544
|
+
│ └── chalk.js # 命令行日志工具
|
|
545
|
+
│
|
|
546
|
+
├── ai-inbox-server/ # AI Inbox 接收服务
|
|
547
|
+
│ └── ai-inbox-server.js
|
|
548
|
+
│
|
|
549
|
+
├── vite.config.ts # 主库构建配置
|
|
550
|
+
├── vite.auto.config.ts # 自动初始化入口构建配置
|
|
551
|
+
├── tsconfig.json
|
|
552
|
+
└── package.json
|
|
553
|
+
```
|
|
554
|
+
|
|
555
|
+
---
|
|
556
|
+
|
|
557
|
+
## 9. 开发规范
|
|
558
|
+
|
|
559
|
+
### 9.1 代码风格
|
|
560
|
+
|
|
561
|
+
- 前端技术栈:**TypeScript + 原生 DOM**(零框架依赖)
|
|
562
|
+
- 样式:原生 CSS(无预处理器依赖)
|
|
563
|
+
- UI 实现:原生 DOM API(`createElement`、`appendChild`、`addEventListener`)
|
|
564
|
+
- 接口层:Service 封装,统一管理
|
|
565
|
+
- 组件命名:PascalCase(如 `FloatingToolbar`)
|
|
566
|
+
- 类命名:PascalCase(如 `IssuesReporterService`)
|
|
567
|
+
- 文件名:kebab-case(如 `http-interceptor.service.ts`)
|
|
568
|
+
|
|
569
|
+
## 10. 项目目标
|
|
570
|
+
|
|
571
|
+
> **核心目标:** 固化 Bug 描述标准结构,让下游团队拿到的是**可直接复现、信息完整**的标准文档,而非模糊的口头描述。
|
|
572
|
+
|
|
573
|
+
### 关键指标
|
|
574
|
+
|
|
575
|
+
- [ ] 接口报错自动捕获覆盖率 ≥ 95%
|
|
576
|
+
- [ ] 全端异常捕获覆盖率 ≥ 90%(JS / Vue / Promise / XHR / console / resource)
|
|
577
|
+
- [ ] Bug 信息完整度(接口地址 + 入参 + 路由 + 描述 + 截图)≥ 100%
|
|
578
|
+
- [ ] 支持 npm 包 + iframe 两种分发方式
|
|
579
|
+
- [ ] 自动截图 + 手动标注功能可用
|
|
580
|
+
- [ ] 支持 JSON / Markdown / CSV / Word / PDF 五种导出格式
|
|
581
|
+
- [ ] 支持批量勾选导出
|
|
582
|
+
- [ ] 支持导出到局域网 AI 员工 Inbox(JSON / MD / PDF / Word)
|
|
583
|
+
- [ ] 适配 BDC / BDCDJ3 / BDCYC2 / BDCQD / **PUB3** 五个子系统
|
|
584
|
+
- [ ] 支持 Vue 2 / Vue 3 / React / Angular 项目接入
|
|
585
|
+
- [ ] 支持 HTTP/HTTPS 混合环境
|
|
586
|
+
|
|
587
|
+
---
|
|
588
|
+
|
|
589
|
+
## 11. 注意事项
|
|
590
|
+
|
|
591
|
+
1. 插件作为外部独立模块,**不能侵入宿主业务系统的业务逻辑代码**,仅通过拦截器 / Hook 机制采集信息。
|
|
592
|
+
2. 截图功能需考虑浏览器兼容性,特别是国产环境(html-to-image 基于 SVG,国产信创浏览器基于 Chromium,完美支持)。
|
|
593
|
+
3. iframe 模式下需处理跨域通信(postMessage),宿主提供截图钩子,插件调用。
|
|
594
|
+
4. npm 包模式下需提供完善的配置项,适配不同子系统的技术栈差异(**Vue 2、Vue 3、React、Angular、纯 JS**)。
|
|
595
|
+
5. HTTP/HTTPS 混合环境需部署两套插件服务,配置使用协议自适应(`//plugin.example.com`)。
|
|
596
|
+
6. 异常捕获模块(XHR / console 等)采用 monkey-patch 时,必须保存原始引用并在 `stop()` 时精确恢复,避免与宿主业务代码冲突。
|
|
597
|
+
|
|
598
|
+
---
|
|
599
|
+
|