Files
geo/apps/desktop-client/src/renderer/views/DiagnosticsView.vue
T
root b16e9f0bd1 feat(desktop): implement workspace foundation + desktop-client skeleton
Plan 0 (workspaces): add workspaces + workspace_memberships schema, extend
JWT/Actor/claims with primary_workspace_id, seed default workspace per tenant,
thread workspace_id through tenant monitoring quota.

Plan A (desktop skeleton): new Electron app (apps/desktop-client) with main/
preload/renderer, shared Vue component package (packages/ui-shared), and server
surface — desktop client registration + token rotation + heartbeat, SSE task
event stream, desktop accounts/tasks/content handlers, publish job endpoint,
and supporting repositories, services, sqlc queries, and migrations.

Hard cutover per plan: remove browser-extension monitoring callback endpoints,
stub legacy media API in admin-web, and delete monitoring_callback_handler.go.
2026-04-19 14:18:20 +08:00

189 lines
3.9 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup lang="ts">
import { computed, ref } from "vue";
import { useDesktopRuntime } from "../composables/useDesktopRuntime";
const { snapshot } = useDesktopRuntime();
const subsystemEntries = computed(() =>
Object.entries(snapshot.value?.subsystems ?? {}).map(([key, value]) => ({
key,
value: JSON.stringify(value, null, 2),
})),
);
const copied = ref(false);
function copyLogs() {
if (!snapshot.value) return;
const payload = JSON.stringify(snapshot.value, null, 2);
navigator.clipboard.writeText(payload).then(() => {
copied.value = true;
setTimeout(() => {
copied.value = false;
}, 2500);
});
}
</script>
<template>
<section class="page">
<header class="hero">
<div class="hero-copy">
<p class="eyebrow">SYSTEM DIAGNOSTICS</p>
<h2>系统诊断</h2>
<p class="hero-summary">
桌面客户端底层运行环境与依赖项巡检此页面记录的任务补偿日志本地路由锁与异常状态主要用于开发侧进行问题上卷与 Trace 回顾
</p>
<div class="actions">
<a-button type="primary" :ghost="copied" @click="copyLogs">
{{ copied ? "已复制到剪贴板" : "一键包复制发给研发排查" }}
</a-button>
</div>
</div>
</header>
<section class="panel">
<div class="panel-header">
<h3>运行时底层快照日志</h3>
</div>
<div class="panel-body">
<a-collapse :bordered="false" class="custom-collapse">
<a-collapse-panel
v-for="entry in subsystemEntries"
:key="entry.key"
:header="`Subsystem: ${entry.key}`"
class="collapse-item"
>
<pre class="json-code">{{ entry.value }}</pre>
</a-collapse-panel>
<a-collapse-panel
key="raw"
header="完整 Runtime 原始快照 (Full Engine Snapshot)"
class="collapse-item"
>
<pre class="json-code">{{ JSON.stringify(snapshot, null, 2) }}</pre>
</a-collapse-panel>
</a-collapse>
</div>
</section>
</section>
</template>
<style scoped>
.page {
display: grid;
gap: 20px;
}
.hero {
display: block;
}
.hero-copy {
padding: 24px;
border-radius: 12px;
border: 1px solid #e6edf5;
background: #ffffff;
}
.eyebrow,
.hero-summary,
h2 {
margin: 0;
}
.eyebrow {
color: #8c8c8c;
font-size: 11px;
letter-spacing: 0.1em;
text-transform: uppercase;
}
h2 {
margin-top: 8px;
font-size: 24px;
font-weight: 600;
color: #1a1a1a;
line-height: 1.4;
}
.hero-summary {
margin-top: 12px;
max-width: 800px;
color: #8c8c8c;
line-height: 1.6;
font-size: 13px;
}
.actions {
margin-top: 20px;
}
.panel {
background: #ffffff;
border-radius: 12px;
border: 1px solid #e6edf5;
display: flex;
flex-direction: column;
}
.panel-header {
padding: 20px 24px;
border-bottom: 1px solid #e6edf5;
}
.panel-header h3 {
margin: 0;
font-size: 16px;
font-weight: 600;
color: #1a1a1a;
}
.panel-body {
padding: 24px;
}
.custom-collapse {
background: transparent !important;
}
.collapse-item {
border-radius: 8px !important;
border: 1px solid #e6edf5 !important;
margin-bottom: 12px;
background: #fafafb;
overflow: hidden;
}
:deep(.ant-collapse-item:last-child) {
margin-bottom: 0;
}
:deep(.ant-collapse-header) {
font-weight: 500;
color: #1a1a1a !important;
padding: 12px 16px !important;
}
:deep(.ant-collapse-content) {
border-top: 1px dashed #e6edf5 !important;
background: #ffffff !important;
}
.json-code {
margin: 0;
padding: 16px;
background: #f8fafc;
border-radius: 6px;
border: 1px solid #e2e8f0;
color: #334155;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
white-space: pre-wrap;
word-break: break-all;
max-height: 500px;
overflow-y: auto;
}
</style>