fix(bugcollect): 更新 IssueDetail 视图对齐后端 IssueResponse 字段
移除不存在的字段(status/osVersion/deviceModel/affectedUsers/stackTrace/sourceContext/recentEvents), 改用 isResolved/events[].stack/events 替代,通过 TypeScript 类型检查。 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
这个提交包含在:
父节点
3676241f6a
当前提交
6d6fd3363e
@ -10,56 +10,47 @@
|
||||
<el-tag size="small" :type="issueTypeTag(detail.type)">{{ detail.type }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="平台">{{ detail.platform }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">{{ detail.status }}</el-descriptions-item>
|
||||
<el-descriptions-item label="应用版本">{{ detail.appVersion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="系统版本">{{ detail.osVersion }}</el-descriptions-item>
|
||||
<el-descriptions-item label="设备型号">{{ detail.deviceModel }}</el-descriptions-item>
|
||||
<el-descriptions-item label="状态">
|
||||
<el-tag size="small" :type="detail.isResolved ? 'success' : 'danger'">
|
||||
{{ detail.isResolved ? '已解决' : '未解决' }}
|
||||
</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="应用版本">{{ detail.appVersion ?? '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="总次数">{{ detail.count }}</el-descriptions-item>
|
||||
<el-descriptions-item label="影响用户">{{ detail.affectedUsers }}</el-descriptions-item>
|
||||
<el-descriptions-item label="指纹">
|
||||
<span style="font-family:monospace;font-size:12px">{{ detail.fingerprint ?? '-' }}</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="首次出现">{{ formatTime(detail.firstSeenAt) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="最后出现" :span="2">{{ formatTime(detail.lastSeenAt) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</el-card>
|
||||
|
||||
<!-- Stack Trace -->
|
||||
<el-card style="margin-bottom: 16px">
|
||||
<!-- Stack Trace (from most recent event) -->
|
||||
<el-card v-if="latestStack" style="margin-bottom: 16px">
|
||||
<template #header>Stack Trace</template>
|
||||
<pre class="stack-trace">{{ detail.stackTrace }}</pre>
|
||||
</el-card>
|
||||
|
||||
<!-- Source Context -->
|
||||
<el-card v-if="detail.sourceContext?.length" style="margin-bottom: 16px">
|
||||
<template #header>源码上下文</template>
|
||||
<div class="source-context">
|
||||
<div
|
||||
v-for="(line, idx) in detail.sourceContext"
|
||||
:key="idx"
|
||||
class="source-line"
|
||||
:class="{ highlight: line.highlight }"
|
||||
>
|
||||
<span class="line-number">{{ line.line }}</span>
|
||||
<code>{{ line.content }}</code>
|
||||
</div>
|
||||
</div>
|
||||
<pre class="stack-trace">{{ latestStack }}</pre>
|
||||
</el-card>
|
||||
|
||||
<!-- Recent Events -->
|
||||
<el-card>
|
||||
<template #header>最近事件</template>
|
||||
<el-table :data="detail.recentEvents" border stripe>
|
||||
<el-table-column prop="eventName" label="事件名" width="180" />
|
||||
<el-table-column prop="userId" label="用户 ID" width="200" show-overflow-tooltip />
|
||||
<el-table-column prop="timestamp" label="时间" width="170">
|
||||
<template #default="{ row }">{{ formatTime(row.timestamp) }}</template>
|
||||
<template #header>最近崩溃事件</template>
|
||||
<el-table :data="detail.events ?? []" border stripe>
|
||||
<el-table-column prop="userId" label="用户 ID" width="180" show-overflow-tooltip />
|
||||
<el-table-column prop="platform" label="平台" width="100" />
|
||||
<el-table-column prop="appVersion" label="版本" width="110" />
|
||||
<el-table-column prop="message" label="错误信息" min-width="240" show-overflow-tooltip />
|
||||
<el-table-column prop="createdAt" label="时间" width="170">
|
||||
<template #default="{ row }">{{ formatTime(row.createdAt) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="属性" min-width="200">
|
||||
<el-table-column label="堆栈" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-popover trigger="click" :width="400">
|
||||
<el-popover v-if="row.stack" trigger="click" :width="600">
|
||||
<template #reference>
|
||||
<el-button link type="primary" size="small">查看</el-button>
|
||||
</template>
|
||||
<pre class="props-json">{{ JSON.stringify(row.properties, null, 2) }}</pre>
|
||||
<pre class="props-json">{{ row.stackSymbolicated || row.stack }}</pre>
|
||||
</el-popover>
|
||||
<span v-else style="color:#ccc">-</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@ -70,7 +61,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted } from 'vue'
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useRoute } from 'vue-router'
|
||||
import { bugCollectApi, type BugCollectIssueDetail } from '@/api/bugcollect'
|
||||
|
||||
@ -78,6 +69,15 @@ const route = useRoute()
|
||||
const detail = ref<BugCollectIssueDetail | null>(null)
|
||||
const loading = ref(false)
|
||||
|
||||
const latestStack = computed(() => {
|
||||
const events = detail.value?.events ?? []
|
||||
for (const e of events) {
|
||||
const s = e.stackSymbolicated || e.stack
|
||||
if (s) return s
|
||||
}
|
||||
return null
|
||||
})
|
||||
|
||||
function issueTypeTag(type: string) {
|
||||
const map: Record<string, string> = {
|
||||
CRASH: 'danger',
|
||||
@ -118,36 +118,6 @@ onMounted(async () => {
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
.source-context {
|
||||
background: #1e1e1e;
|
||||
border-radius: 8px;
|
||||
padding: 12px 0;
|
||||
overflow-x: auto;
|
||||
}
|
||||
.source-line {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.6;
|
||||
color: #d4d4d4;
|
||||
padding: 0 12px;
|
||||
}
|
||||
.source-line.highlight {
|
||||
background: rgba(255, 200, 0, 0.15);
|
||||
border-left: 3px solid #ffc800;
|
||||
}
|
||||
.line-number {
|
||||
width: 48px;
|
||||
text-align: right;
|
||||
color: #858585;
|
||||
padding-right: 12px;
|
||||
user-select: none;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
.source-line code {
|
||||
white-space: pre;
|
||||
}
|
||||
.props-json {
|
||||
background: #f5f5f5;
|
||||
padding: 12px;
|
||||
|
||||
正在加载...
在新工单中引用
屏蔽一个用户