ProtocolPane 协议监视面板
SSE / MQTT / Kafka / gRPC 4 个 tab 的协议监视器外壳。
基础用法
预定义 4 个 tab(id:sse、mqtt、kafka、grpc),每个 tab 内容由消费方通过 named slot
#panel-{tabId}(Vue)/ slots["panel-{tabId}"](React)填入。也可通过 tabs prop 覆盖默认列表。
来源:protocols.html。
背景
这里渲染 SSE EventStream 监视器(事件流时间轴 + 重连状态)。
<script setup lang="ts">
import { CfProtocolPane } from '@chufix-design/vue';
</script>
<template>
<div style="height: 280px;">
<CfProtocolPane>
<template #panel-sse>
<p style="color: var(--fg-2);">这里渲染 SSE EventStream 监视器(事件流时间轴 + 重连状态)。</p>
</template>
<template #panel-mqtt>
<p style="color: var(--fg-2);">这里渲染 MQTT TopicTree(订阅树 + 消息列表)。</p>
</template>
<template #panel-kafka>
<p style="color: var(--fg-2);">这里渲染 Kafka PartitionGrid(partition × offset / lag 矩阵)。</p>
</template>
<template #panel-grpc>
<p style="color: var(--fg-2);">这里渲染 gRPC MethodList(service / method 列表 + 调用历史)。</p>
</template>
</CfProtocolPane>
</div>
</template> <script setup>
import { CfProtocolPane } from '@chufix-design/vue';
</script>
<template>
<div style="height: 280px;">
<CfProtocolPane>
<template #panel-sse>
<p style="color: var(--fg-2);">这里渲染 SSE EventStream 监视器(事件流时间轴 + 重连状态)。</p>
</template>
<template #panel-mqtt>
<p style="color: var(--fg-2);">这里渲染 MQTT TopicTree(订阅树 + 消息列表)。</p>
</template>
<template #panel-kafka>
<p style="color: var(--fg-2);">这里渲染 Kafka PartitionGrid(partition × offset / lag 矩阵)。</p>
</template>
<template #panel-grpc>
<p style="color: var(--fg-2);">这里渲染 gRPC MethodList(service / method 列表 + 调用历史)。</p>
</template>
</CfProtocolPane>
</div>
</template> <CfProtocolPane slots={{
'panel-sse': <PanelA />,
'panel-mqtt': <PanelB />,
}} /> <CfProtocolPane slots={{
'panel-sse': <PanelA />,
'panel-mqtt': <PanelB />,
}} /> 真实内容拼装
替换占位文字,4 个 tab 各放一个具体可视化:SSE 时间轴 / MQTT 主题树 / Kafka partition 表 / gRPC 方法列表。
背景
- 14:32:01●connection.established
- 14:32:08●order.created · #1842
- 14:32:14●order.paid · #1842
- 14:32:30●heartbeat
- 14:32:45●connection.reconnect
<script setup lang="ts">
import { CfProtocolPane, CfTimeline, CfTreeView, CfDataGrid, CfStatusCodeBadge, CfList } from '@chufix-design/vue';
const sseEvents = [
{ id: '1', title: 'connection.established', time: '14:32:01', tone: 'success' as const },
{ id: '2', title: 'order.created · #1842', time: '14:32:08' },
{ id: '3', title: 'order.paid · #1842', time: '14:32:14' },
{ id: '4', title: 'heartbeat', time: '14:32:30', tone: 'info' as const },
{ id: '5', title: 'connection.reconnect', time: '14:32:45', tone: 'warning' as const },
];
const mqttTopics = [
{ id: 'sensors', label: 'sensors/', children: [
{ id: 'sensors-temp', label: 'sensors/temp · 14 msg/s' },
{ id: 'sensors-hum', label: 'sensors/humidity · 7 msg/s' },
]},
{ id: 'orders', label: 'orders/', children: [
{ id: 'orders-new', label: 'orders/new · 0.3 msg/s' },
{ id: 'orders-paid', label: 'orders/paid · 0.2 msg/s' },
]},
];
const kafkaCols = [
{ key: 'partition', title: 'Partition', dataIndex: 'p' },
{ key: 'leader', title: 'Leader', dataIndex: 'l' },
{ key: 'lag', title: 'Lag', dataIndex: 'lag' },
{ key: 'offset', title: 'Offset', dataIndex: 'o' },
];
const kafkaRows = [
{ id: '0', p: '0', l: 'broker-01', lag: 12, o: 184243 },
{ id: '1', p: '1', l: 'broker-02', lag: 0, o: 184510 },
{ id: '2', p: '2', l: 'broker-03', lag: 89, o: 184201 },
{ id: '3', p: '3', l: 'broker-01', lag: 4, o: 184480 },
];
const grpcMethods = [
{ id: '1', label: 'OrderService.GetOrder' },
{ id: '2', label: 'OrderService.CreateOrder' },
{ id: '3', label: 'OrderService.UpdateOrder' },
{ id: '4', label: 'OrderService.ListOrders' },
];
</script>
<template>
<div style="height: 360px;">
<CfProtocolPane>
<template #panel-sse>
<ul style="list-style: none; padding: 0; margin: 0; font-size: 12px;">
<li v-for="e in sseEvents" :key="e.id" style="display: flex; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line-1);">
<span style="color: var(--fg-3); font-family: var(--font-mono);">{{ e.time }}</span>
<span :style="{ color: e.tone === 'success' ? 'var(--status-success)' : e.tone === 'warning' ? 'var(--status-warning)' : e.tone === 'info' ? 'var(--status-info)' : 'var(--fg-1)' }">●</span>
<span style="font-family: var(--font-mono);">{{ e.title }}</span>
</li>
</ul>
</template>
<template #panel-mqtt>
<CfTreeView :nodes="mqttTopics" />
</template>
<template #panel-kafka>
<CfDataGrid :columns="kafkaCols" :rows="kafkaRows" />
</template>
<template #panel-grpc>
<CfList :items="grpcMethods" />
</template>
</CfProtocolPane>
</div>
</template> <script setup>
import { CfProtocolPane, CfTimeline, CfTreeView, CfDataGrid, CfStatusCodeBadge, CfList } from '@chufix-design/vue';
const sseEvents = [
{ id: '1', title: 'connection.established', time: '14:32:01', tone: 'success' },
{ id: '2', title: 'order.created · #1842', time: '14:32:08' },
{ id: '3', title: 'order.paid · #1842', time: '14:32:14' },
{ id: '4', title: 'heartbeat', time: '14:32:30', tone: 'info' },
{ id: '5', title: 'connection.reconnect', time: '14:32:45', tone: 'warning' },
];
const mqttTopics = [
{ id: 'sensors', label: 'sensors/', children: [
{ id: 'sensors-temp', label: 'sensors/temp · 14 msg/s' },
{ id: 'sensors-hum', label: 'sensors/humidity · 7 msg/s' },
]},
{ id: 'orders', label: 'orders/', children: [
{ id: 'orders-new', label: 'orders/new · 0.3 msg/s' },
{ id: 'orders-paid', label: 'orders/paid · 0.2 msg/s' },
]},
];
const kafkaCols = [
{ key: 'partition', title: 'Partition', dataIndex: 'p' },
{ key: 'leader', title: 'Leader', dataIndex: 'l' },
{ key: 'lag', title: 'Lag', dataIndex: 'lag' },
{ key: 'offset', title: 'Offset', dataIndex: 'o' },
];
const kafkaRows = [
{ id: '0', p: '0', l: 'broker-01', lag: 12, o: 184243 },
{ id: '1', p: '1', l: 'broker-02', lag: 0, o: 184510 },
{ id: '2', p: '2', l: 'broker-03', lag: 89, o: 184201 },
{ id: '3', p: '3', l: 'broker-01', lag: 4, o: 184480 },
];
const grpcMethods = [
{ id: '1', label: 'OrderService.GetOrder' },
{ id: '2', label: 'OrderService.CreateOrder' },
{ id: '3', label: 'OrderService.UpdateOrder' },
{ id: '4', label: 'OrderService.ListOrders' },
];
</script>
<template>
<div style="height: 360px;">
<CfProtocolPane>
<template #panel-sse>
<ul style="list-style: none; padding: 0; margin: 0; font-size: 12px;">
<li v-for="e in sseEvents" :key="e.id" style="display: flex; gap: 12px; padding: 6px 0; border-bottom: 1px solid var(--line-1);">
<span style="color: var(--fg-3); font-family: var(--font-mono);">{{ e.time }}</span>
<span :style="{ color: e.tone === 'success' ? 'var(--status-success)' : e.tone === 'warning' ? 'var(--status-warning)' : e.tone === 'info' ? 'var(--status-info)' : 'var(--fg-1)' }">●</span>
<span style="font-family: var(--font-mono);">{{ e.title }}</span>
</li>
</ul>
</template>
<template #panel-mqtt>
<CfTreeView :nodes="mqttTopics" />
</template>
<template #panel-kafka>
<CfDataGrid :columns="kafkaCols" :rows="kafkaRows" />
</template>
<template #panel-grpc>
<CfList :items="grpcMethods" />
</template>
</CfProtocolPane>
</div>
</template> <CfProtocolPane slots={{...}} /> <CfProtocolPane slots={{...}} /> API
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
modelValue / value | string | 第一个 tab id | 活动 tab |
tabs | TemplatePaneTab[] | 预设 | 自定义 tab 列表 |
size | 'sm' | 'md' | 'lg' | 'md' |
预设的 tab id 列表导出为 PROTOCOL_TABS / NETWORK_TABS / SQL_TABS 等常量,可在自定义 tabs 时直接拿来用。
模版组件本质是
CfTabs的语义薄壳。如果你不需要一组预定义 tab,直接用 CfTabs 即可。
反馈与讨论
ProtocolPane 协议监视面板 的讨论