Preview Updated 2026-05-10

Protocol pane

Protocol monitor shell with SSE / MQTT / Kafka / gRPC tabs.

Basic usage

4 predefined tabs (ids: sse, mqtt, kafka, grpc). Each tab’s content is filled in by the consumer via the named slot #panel-{tabId} (Vue) / slots["panel-{tabId}"] (React). You can also override the default list via the tabs prop.

Source: 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 />,
}} />

Real content composition

Replace the placeholders with concrete visualizations — one per tab: SSE timeline / MQTT topic tree / Kafka partition table / gRPC method list.

背景
  • 14:32:01connection.established
  • 14:32:08order.created · #1842
  • 14:32:14order.paid · #1842
  • 14:32:30heartbeat
  • 14:32:45connection.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

PropTypeDefaultDescription
modelValue / valuestringFirst tab idActive tab
tabsTemplatePaneTab[]presetCustom tab list
size'sm' | 'md' | 'lg''md'

The preset tab id lists are exported as constants PROTOCOL_TABS / NETWORK_TABS / SQL_TABS, ready to reuse when customizing tabs.

Template components are a thin semantic wrapper over CfTabs. If you don’t need a predefined tab set, use CfTabs directly.

反馈与讨论

Protocol pane · Discussion

0
0 / 600
一键发送
正在加载评论...