|
|
@@ -0,0 +1,275 @@
|
|
|
+<template>
|
|
|
+ <div class="error-test">
|
|
|
+ <h1>错误监控测试页面</h1>
|
|
|
+ <p>点击下方按钮触发各种错误,用于测试监控 SDK</p>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <h2>JavaScript 错误</h2>
|
|
|
+ <div class="button-group">
|
|
|
+ <button @click="triggerTypeError">触发 TypeError</button>
|
|
|
+ <button @click="triggerReferenceError">触发 ReferenceError</button>
|
|
|
+ <button @click="triggerSyntaxError">触发 eval SyntaxError</button>
|
|
|
+ <button @click="triggerRangeError">触发 RangeError</button>
|
|
|
+ <button @click="triggerCustomError">触发自定义 Error</button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <h2>Promise 错误</h2>
|
|
|
+ <div class="button-group">
|
|
|
+ <button @click="triggerUnhandledRejection">未处理的 Promise 拒绝</button>
|
|
|
+ <button @click="triggerAsyncError">Async/Await 错误</button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <h2>Axios 请求错误</h2>
|
|
|
+ <div class="button-group">
|
|
|
+ <button @click="triggerAxios404">404 Not Found</button>
|
|
|
+ <button @click="triggerAxios500">500 Server Error</button>
|
|
|
+ <button @click="triggerAxiosTimeout">请求超时</button>
|
|
|
+ <button @click="triggerAxiosNetworkError">网络错误</button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section>
|
|
|
+ <h2>正常请求(Mock)</h2>
|
|
|
+ <div class="button-group">
|
|
|
+ <button @click="fetchUser">获取用户信息</button>
|
|
|
+ <button @click="fetchList">获取列表数据</button>
|
|
|
+ </div>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section v-if="result">
|
|
|
+ <h2>请求结果</h2>
|
|
|
+ <pre>{{ result }}</pre>
|
|
|
+ </section>
|
|
|
+
|
|
|
+ <section v-if="errorLog.length">
|
|
|
+ <h2>错误日志</h2>
|
|
|
+ <ul class="error-log">
|
|
|
+ <li v-for="(err, index) in errorLog" :key="index" class="error-item">
|
|
|
+ <span class="error-type">{{ err.type }}</span>
|
|
|
+ <span class="error-message">{{ err.message }}</span>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </section>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script setup>
|
|
|
+import { ref } from 'vue';
|
|
|
+import request from '../api/request';
|
|
|
+
|
|
|
+const result = ref(null);
|
|
|
+const errorLog = ref([]);
|
|
|
+
|
|
|
+// 记录错误
|
|
|
+function logError(type, message) {
|
|
|
+ errorLog.value.unshift({ type, message, time: new Date().toLocaleTimeString() });
|
|
|
+ if (errorLog.value.length > 10) {
|
|
|
+ errorLog.value.pop();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ============ JavaScript 错误 ============
|
|
|
+
|
|
|
+function triggerTypeError() {
|
|
|
+ try {
|
|
|
+ const obj = null;
|
|
|
+ obj.someMethod(); // TypeError: Cannot read properties of null
|
|
|
+ } catch (e) {
|
|
|
+ logError('TypeError', e.message);
|
|
|
+ throw e; // 重新抛出让监控 SDK 捕获
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function triggerReferenceError() {
|
|
|
+ try {
|
|
|
+ // eslint-disable-next-line no-undef
|
|
|
+ console.log(undefinedVariable); // ReferenceError
|
|
|
+ } catch (e) {
|
|
|
+ logError('ReferenceError', e.message);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function triggerSyntaxError() {
|
|
|
+ try {
|
|
|
+ eval('const a = {'); // SyntaxError
|
|
|
+ } catch (e) {
|
|
|
+ logError('SyntaxError', e.message);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function triggerRangeError() {
|
|
|
+ try {
|
|
|
+ const arr = new Array(-1); // RangeError: Invalid array length
|
|
|
+ console.log(arr);
|
|
|
+ } catch (e) {
|
|
|
+ logError('RangeError', e.message);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function triggerCustomError() {
|
|
|
+ const error = new Error('这是一个自定义错误消息');
|
|
|
+ logError('CustomError', error.message);
|
|
|
+ throw error;
|
|
|
+}
|
|
|
+
|
|
|
+// ============ Promise 错误 ============
|
|
|
+
|
|
|
+function triggerUnhandledRejection() {
|
|
|
+ // 未处理的 Promise 拒绝
|
|
|
+ Promise.reject(new Error('未处理的 Promise 拒绝错误'));
|
|
|
+ logError('UnhandledRejection', '已触发未处理的 Promise 拒绝');
|
|
|
+}
|
|
|
+
|
|
|
+async function triggerAsyncError() {
|
|
|
+ try {
|
|
|
+ await Promise.reject(new Error('Async/Await 中的错误'));
|
|
|
+ } catch (e) {
|
|
|
+ logError('AsyncError', e.message);
|
|
|
+ throw e;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ============ Axios 请求错误 ============
|
|
|
+
|
|
|
+async function triggerAxios404() {
|
|
|
+ try {
|
|
|
+ await request.get('/not-found');
|
|
|
+ } catch (e) {
|
|
|
+ logError('Axios 404', e.message);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function triggerAxios500() {
|
|
|
+ try {
|
|
|
+ await request.get('/server-error');
|
|
|
+ } catch (e) {
|
|
|
+ logError('Axios 500', e.message);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function triggerAxiosTimeout() {
|
|
|
+ try {
|
|
|
+ await request.get('/timeout');
|
|
|
+ } catch (e) {
|
|
|
+ logError('Axios Timeout', e.message);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function triggerAxiosNetworkError() {
|
|
|
+ try {
|
|
|
+ await request.get('/network-error');
|
|
|
+ } catch (e) {
|
|
|
+ logError('Axios Network', e.message);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// ============ 正常请求 ============
|
|
|
+
|
|
|
+async function fetchUser() {
|
|
|
+ try {
|
|
|
+ const data = await request.get('/user');
|
|
|
+ result.value = JSON.stringify(data, null, 2);
|
|
|
+ } catch (e) {
|
|
|
+ logError('FetchUser', e.message);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+async function fetchList() {
|
|
|
+ try {
|
|
|
+ const data = await request.get('/list');
|
|
|
+ result.value = JSON.stringify(data, null, 2);
|
|
|
+ } catch (e) {
|
|
|
+ logError('FetchList', e.message);
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style scoped>
|
|
|
+.error-test {
|
|
|
+ max-width: 800px;
|
|
|
+ margin: 0 auto;
|
|
|
+ padding: 20px;
|
|
|
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
+}
|
|
|
+
|
|
|
+h1 {
|
|
|
+ color: #333;
|
|
|
+ border-bottom: 2px solid #42b883;
|
|
|
+ padding-bottom: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+h2 {
|
|
|
+ color: #666;
|
|
|
+ font-size: 1.2em;
|
|
|
+ margin-top: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+section {
|
|
|
+ margin-bottom: 24px;
|
|
|
+ padding: 16px;
|
|
|
+ background: #f9f9f9;
|
|
|
+ border-radius: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.button-group {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ gap: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+button {
|
|
|
+ padding: 10px 16px;
|
|
|
+ border: none;
|
|
|
+ border-radius: 6px;
|
|
|
+ background: #42b883;
|
|
|
+ color: white;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ transition: background 0.2s;
|
|
|
+}
|
|
|
+
|
|
|
+button:hover {
|
|
|
+ background: #369970;
|
|
|
+}
|
|
|
+
|
|
|
+pre {
|
|
|
+ background: #282c34;
|
|
|
+ color: #abb2bf;
|
|
|
+ padding: 16px;
|
|
|
+ border-radius: 6px;
|
|
|
+ overflow-x: auto;
|
|
|
+}
|
|
|
+
|
|
|
+.error-log {
|
|
|
+ list-style: none;
|
|
|
+ padding: 0;
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.error-item {
|
|
|
+ display: flex;
|
|
|
+ gap: 12px;
|
|
|
+ padding: 8px 12px;
|
|
|
+ background: #fff;
|
|
|
+ border-left: 4px solid #e74c3c;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ border-radius: 0 4px 4px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.error-type {
|
|
|
+ font-weight: bold;
|
|
|
+ color: #e74c3c;
|
|
|
+ min-width: 120px;
|
|
|
+}
|
|
|
+
|
|
|
+.error-message {
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+</style>
|