过去两年,我主导了三个云原生产品的前端架构——一个 Kubernetes 多集群管理平台、一个 AI 模型训练控制台、一个低代码 DevOps 编排工具。它们看似领域迥异,却共享同一个核心挑战:用户需要在同一界面中完成结构化操作与非结构化对话
正是在这种“人机共舞”的复杂场景中,我深刻体会到:传统前端方案已无法满足效率与体验的双重需求。而 DevUI 与 MateChat 的组合,不是又一个 UI 库的堆砌,而是对“前端角色”的一次重新定义——从“展示层”升级为“智能工作流的调度中枢”。


一、云原生深水区:前端的新战场

五年前,前端的核心命题是“如何让页面跑得更快”。今天,在云原生进入深水区后,命题已变为:

如何让用户在一个界面里,既高效操作复杂系统,又能自然地与 AI 协同?

我们观察到三类典型场景:

  1. 运维工程师打开控制台,一边查看 Pod 状态表格,一边问:“为什么这个 Deployment 卡在 ImagePullBackOff?”
  2. 算法工程师在训练面板中调整超参,同时向助手提问:“上次实验的 loss 曲线能对比吗?”
  3. 平台开发者拖拽组件搭建流水线,随后说:“帮我生成这段 YAML 的校验逻辑。”

这些行为背后,是结构化操作(点击、填写、拖拽)与非结构化交互(自然语言、上下文推理)的深度融合。传统前端架构对此束手无策:

  • 用 Ant Design / Element Plus 构建操作界面;
  • 自己手写一套聊天组件(气泡、输入框、加载动画);
  • 主题、响应式、无障碍各自为战;
  • AI 能力以“弹窗”形式突兀插入,破坏工作流连续性。

结果?体验割裂、维护成本高、智能能力难以沉淀。

直到我们引入 DevUI + MateChat,才真正打通“操作”与“对话”的任督二脉。


二、DevUI:企业级系统的骨架,不是又一个组件库

DevUI 最初吸引我的,是它在华为内部支撑 CodeArts、CloudIDE 等大型产品的稳定性。但深入使用后,我发现它的真正价值在于工程克制与体验一致性

2.1 表格:不只是渲染,而是操作入口

在 Kubernetes 控制台,我们需要展示数百个 Pod,每行包含状态、日志、事件、操作按钮。很多人会直接上虚拟滚动,但 DevUI 的 d-table 让我们走得更远。

<template>
  <d-table
    :data="podList"
    :columns="columns"
    row-key="metadata.name"
    virtual-scroll
    style="height: 600px"
  />
</template>

<script setup lang="ts">
import { h } from 'vue';
import { Button, Tag, Tooltip } from 'vue-devui';

const columns = [
  {
    title: '名称',
    field: 'metadata.name',
    width: 200,
    render: (row) => {
      return h(Tooltip, {
        content: row.metadata.namespace
      }, () => row.metadata.name);
    }
  },
  {
    title: '状态',
    width: 120,
    render: (row) => {
      const phase = row.status.phase;
      const colorMap = {
        Running: 'success',
        Pending: 'warning',
        Failed: 'danger'
      };
      return h(Tag, {
        color: colorMap[phase] || 'default'
      }, () => phase);
    }
  },
  {
    title: '容器',
    width: 150,
    render: (row) => {
      const ready = row.status.containerStatuses?.filter(c => c.ready).length || 0;
      const total = row.spec.containers?.length || 0;
      return `${ready}/${total}`;
    }
  },
  {
    title: '操作',
    width: 220,
    fixed: 'right',
    render: (row) => {
      return h('div', { class: 'pod-ops' }, [
        h(Button, {
          size: 'sm',
          onClick: () => viewLogs(row)
        }, () => '日志'),
        h(Button, {
          size: 'sm',
          status: 'primary',
          onClick: () => execCommand(row)
        }, () => '命令'),
        h(Button, {
          size: 'sm',
          status: 'danger',
          onClick: () => deletePod(row)
        }, () => '删除')
      ]);
    }
  }
];

function viewLogs(pod) {
  console.log('查看日志:', pod.metadata.name);
}

function execCommand(pod) {
  console.log('执行命令:', pod.metadata.name);
}

function deletePod(pod) {
  if (confirm(`确定删除 Pod ${pod.metadata.name}?`)) {
    // 调用 API
  }
}
</script>

<style scoped>
.pod-ops {
  display: flex;
  gap: 8px;
}
</style>

这段代码的价值不在“炫技”,而在可维护性

  • 所有 UI 元素通过 h() 函数创建,避免字符串拼接;
  • virtual-scroll 开箱即用,600 行数据滚动流畅;
  • 按钮、标签自动继承 DevUI 主题,无需额外样式;
  • 三个月后加“重启”按钮?只需在 render 中追加一行。

更重要的是,用户感知不到这是“表格”,只觉得“所有操作都在手边”


2.2 表单:联动校验,拒绝“填完再报错”

在模型部署表单中,用户选择“GPU 类型”后,应自动填充“驱动版本”并禁用某些字段。

<template>
  <d-form :model="formModel" label-size="medium">
    <d-form-item label="GPU 类型" field="gpuType">
      <d-select v-model="formModel.gpuType" :options="gpuOptions" />
    </d-form-item>

    <d-form-item label="驱动版本" field="driverVersion">
      <d-input v-model="formModel.driverVersion" :disabled="!formModel.gpuType" />
    </d-form-item>

    <d-form-item label="启用调试" field="enableDebug">
      <d-switch v-model="formModel.enableDebug" :disabled="isDebugDisabled" />
    </d-form-item>

    <d-button type="submit" @click="submit">部署</d-button>
  </d-form>
</template>

<script setup lang="ts">
import { reactive, computed } from 'vue';

const formModel = reactive({
  gpuType: '',
  driverVersion: '',
  enableDebug: true
});

const gpuOptions = [
  { label: 'NVIDIA A100', value: 'A100' },
  { label: 'NVIDIA V100', value: 'V100' },
  { label: '无 GPU', value: '' }
];

const isDebugDisabled = computed(() => {
  return formModel.gpuType === 'A100';
});

// 监听 GPU 类型变化,自动填充驱动
watch(() => formModel.gpuType, (type) => {
  if (type === 'A100') {
    formModel.driverVersion = '535.86.05';
    formModel.enableDebug = false;
  } else if (type === 'V100') {
    formModel.driverVersion = '470.182.03';
    formModel.enableDebug = true;
  } else {
    formModel.driverVersion = '';
    formModel.enableDebug = true;
  }
});
</script>

关键点:

  • 使用 computed 和 watch 实现字段联动;
  • d-switch 的 disabled 绑定动态计算值;
  • 用户永远不知道背后有逻辑,只感受到“系统懂我”。

这比“提交后再校验”提升的不仅是体验,更是任务完成率


2.3 主题系统:不是换色,而是多环境适配

我们在同一套代码中支持三种主题:

  • 白天模式(默认)
  • 夜间运维模式(暗黑)
  • 客户定制品牌色(如金融蓝)

实现方式极简:

/* src/assets/theme.css */
:root,
[data-theme='light'] {
  --devui-brand-color: #5e7ce0;
  --devui-bg-color: #ffffff;
  --devui-text-color: #252b3a;
}

[data-theme='dark'] {
  --devui-bg-color: #1a1a1a;
  --devui-text-color: #e0e0e0;
  --devui-border-color: #333;
}

[data-theme='finance'] {
  --devui-brand-color: #0052D9;
  --devui-primary-color: #0052D9;
}

切换逻辑:

// composables/useTheme.ts
export function useTheme() {
  const setTheme = (theme: string) => {
    document.documentElement.setAttribute('data-theme', theme);
    localStorage.setItem('user-theme', theme);
  };

  const initTheme = () => {
    const saved = localStorage.getItem('user-theme') || 'light';
    setTheme(saved);
  };

  return { setTheme, initTheme };
}

App.vue 中初始化:

import { onMounted } from 'vue';
import { useTheme } from '@/composables/useTheme';

onMounted(() => {
  useTheme().initTheme();
});

所有 DevUI 组件自动适配。没有 SCSS 变量覆盖,没有 webpack loader,只有 CSS Variables 的优雅。这才是企业级主题系统的正确打开方式。


2.4 响应式布局:不只是适配屏幕,而是适配场景

在移动端,我们不简单“缩小桌面版”,而是重构交互:

  • 导航栏折叠为汉堡菜单;
  • 表格转为卡片列表;
  • 操作按钮聚合到浮动菜单。

DevUI 的 d-layout + d-drawer 让这一切变得简单:

<template>
  <d-layout style="height: 100vh">
    <!-- 移动端抽屉导航 -->
    <d-drawer v-model:visible="showDrawer" placement="left">
      <d-menu :items="menuItems" />
    </d-drawer>

    <d-layout-header>
      <d-button v-if="isMobile" icon="icon-menu" @click="showDrawer = true" />
      <span>云原生控制台</span>
    </d-layout-header>

    <d-layout-content>
      <component :is="currentView" />
    </d-layout-content>
  </d-layout>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';

const showDrawer = ref(false);

const isMobile = computed(() => window.innerWidth < 768);

const menuItems = [
  { title: '集群', id: 'clusters' },
  { title: '工作负载', id: 'workloads' },
  { title: 'AI 助手', id: 'ai' }
];

const currentView = computed(() => {
  // 根据路由返回对应组件
});
</script>

响应式不是技术问题,而是产品思维。DevUI 提供了工具,但决策权在你手中。


三、MateChat:让 AI 对话成为“一等公民”

如果说 DevUI 解决了“操作界面”的问题,那么 MateChat 则解决了“对话界面”的标准化难题。

过去,每个团队都要重复造轮子:

  • 气泡怎么对齐?
  • 加载动画放哪里?
  • 快捷提示如何响应输入?

MateChat 直接给出答案。

3.1 一个可运行的智能助手核心

<template>
  <mc-layout style="height: 100vh; max-width: 900px; margin: 0 auto">
    <mc-header title="AI 运维助手" />

    <div class="chat-messages">
      <mc-bubble
        v-for="(msg, index) in messages"
        :key="index"
        :from="msg.role"
        :loading="msg.loading"
        :avatar-config="{ name: msg.role === 'user' ? 'U' : 'A' }"
      >
        {{ msg.content }}
      </mc-bubble>
    </div>

    <mc-input
      ref="inputRef"
      placeholder="例如:查看最近失败的 Job"
      @send="handleSend"
      :max-length="2000"
      :show-send-button="true"
    />
  </mc-layout>
</template>

<script setup lang="ts">
import { ref, nextTick } from 'vue';
import OpenAI from 'openai';

interface Message {
  role: 'user' | 'model';
  content: string;
  loading?: boolean;
}

const messages = ref<Message[]>([]);
const inputRef = ref();

// 初始化 OpenAI 客户端(仅用于开发测试)
const client = new OpenAI({
  apiKey: import.meta.env.VITE_AI_API_KEY,
  baseURL: import.meta.env.VITE_AI_BASE_URL || 'https://api.openai.com/v1',
  dangerouslyAllowBrowser: true
});

async function handleSend(text: string) {
  if (!text.trim()) return;

  // 添加用户消息
  messages.value.push({ role: 'user', content: text });

  // 清空输入框(需 nextTick 确保 DOM 更新)
  nextTick(() => {
    if (inputRef.value) inputRef.value.clear();
  });

  // 添加模型 loading 占位
  messages.value.push({ role: 'model', content: '', loading: true });

  try {
    const stream = await client.chat.completions.create({
      model: 'gpt-4o-mini',
      messages: [{ role: 'user', content: text }],
      stream: true
    });

    // 关闭 loading
    messages.value[messages.value.length - 1].loading = false;

    // 流式接收
    for await (const chunk of stream) {
      const delta = chunk.choices[0]?.delta?.content || '';
      messages.value[messages.value.length - 1].content += delta;
    }
  } catch (error) {
    console.error('AI 请求失败:', error);
    messages.value[messages.value.length - 1].content = '服务暂时不可用,请稍后重试。';
    messages.value[messages.value.length - 1].loading = false;
  }
}
</script>

<style scoped>
.chat-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>

这段代码能跑起来吗?。前提是:

  • 已安装 @matechat/core 和 @devui-design/icons
  • 在 main.ts 中注册了 MateChat 插件;
  • .env 中配置了合法 API Key。

它没有花哨的装饰,但完整实现了流式对话的核心闭环:发送 → loading → 流式追加 → 错误兜底。


3.2 为什么不用自己写 McBubble?

因为细节决定体验:

  • 气泡圆角是否与 DevUI 一致?(是,共用 --devui-border-radius
  • “model” 消息左对齐,“user” 右对齐?(是,内置逻辑)
  • 加载动画是否使用 DevUI 的 spinner?(是)
  • 内容是否自动识别 Markdown 并渲染?(可通过插槽扩展)

MateChat 全部内置。你省下的不是几行 CSS,而是跨团队体验不一致的沟通成本

更关键的是,它专为研发场景优化

  • 支持代码块高亮(需配合 highlight.js);
  • 快捷提示(McPrompt)可动态生成;
  • 输入框支持多行、快捷键(Ctrl+Enter 发送)。

3.3 集成上下文:让 AI 真正“理解”当前任务

在 IDE 插件中,用户问:“帮我修复这个函数”,模型必须知道当前文件内容。

我们通过 MCP(Model Context Protocol)传递上下文:

// 获取当前编辑器状态
const editorContext = {
  fileName: 'src/utils/network.ts',
  code: editor.getValue(),
  cursorLine: editor.getCursor().line,
  selectedText: editor.getSelection()
};

// 构造系统消息
const systemMsg = {
  role: 'system',
  content: JSON.stringify({
    type: 'editor_context',
    data: editorContext
  })
};

// 发送给模型
const response = await client.chat.completions.create({
  model: 'code-assist-v2',
  messages: [systemMsg, { role: 'user', content: userQuery }]
});

前端无需解析,只需透传。模型侧负责理解上下文,前端负责准确传递。这就是职责分离。


四、DevUI 与 MateChat 的协同:构建统一的工作流

二者共享同一套设计语言:

  • 图标来自 @devui-design/icons
  • 间距、圆角、阴影遵循 DevUI Design Tokens;
  • 暗黑模式通过同一套 CSS Variables 控制。

这意味着:
你在顶部用 d-button 触发一个操作,底部用 mc-input 发起一个对话——用户感知不到这是两个库,只觉得“这产品很整”

4.1 在 DevUI 布局中嵌入 MateChat

<template>
  <d-layout style="height: 100vh">
    <d-layout-header>AI 运维控制台</d-layout-header>
    
    <d-layout-content style="display: flex">
      <!-- 左侧资源树 -->
      <d-tree
        :data="clusterTree"
        style="width: 240px; border-right: 1px solid var(--devui-dividing-line)"
      />

      <!-- 右侧主区域 -->
      <div style="flex: 1; display: flex; flex-direction: column">
        <d-tabs v-model:active-id="activeTab">
          <d-tab-panel id="overview">概览</d-tab-panel>
          <d-tab-panel id="logs">日志</d-tab-panel>
          <d-tab-panel id="ai">AI 助手</d-tab-panel>
        </d-tabs>

        <!-- 在 Tab 中嵌入 MateChat -->
        <div v-if="activeTab === 'ai'" style="flex: 1; position: relative">
          <mc-layout style="height: 100%">
            <div class="ai-messages">
              <mc-bubble
                v-for="(msg, i) in aiMessages"
                :key="i"
                :from="msg.from"
                :loading="msg.loading"
              >
                {{ msg.content }}
              </mc-bubble>
            </div>
            <mc-input @send="sendToAI" />
          </mc-layout>
        </div>

        <!-- 其他 Tab 内容 -->
        <div v-else style="padding: 16px">
          <slot :name="activeTab" />
        </div>
      </div>
    </d-layout-content>
  </d-layout>
</template>

<script setup lang="ts">
import { ref } from 'vue';

const activeTab = ref('overview');
const aiMessages = ref([
  { from: 'model', content: '你好!我是你的 AI 运维助手,有什么可以帮您?' }
]);

function sendToAI(text: string) {
  aiMessages.value.push({ from: 'user', content: text });
  // 模拟回复
  setTimeout(() => {
    aiMessages.value.push({ from: 'model', content: '正在分析您的请求...' });
  }, 300);
}
</script>

<style scoped>
.ai-messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>

界面与智能,在同一个 DOM 树中共生。用户无需跳转,即可在操作与对话间无缝切换。


4.2 自然语言生成 UI:NL2UI 的初步尝试

用户输入:“创建一个用户管理表格,包含姓名、邮箱、操作列。”

我们解析后动态渲染 DevUI 表格:

function parseNLToTable(nl: string): { columns: any[] } {
  if (nl.includes('用户管理表格')) {
    return {
      columns: [
        { title: '姓名', field: 'name' },
        { title: '邮箱', field: 'email' },
        {
          title: '操作',
          render: (row) => h(Button, { size: 'sm' }, () => '编辑')
        }
      ]
    };
  }
  throw new Error('无法解析指令');
}

// 在组件中使用
const { columns } = parseNLToTable(userInput);

虽然目前只是规则匹配,但方向已明确:自然语言将成为 UI 构建的新入口。而 DevUI 的声明式 API,天然适合被程序生成。


五、工程实践:从零搭建一个智能控制台

下面是一个最小可运行的整合示例。

5.1 项目初始化

npm create vite@latest cloud-console -- --template vue-ts
cd cloud-console
npm install

5.2 安装依赖

npm install vue-devui @devui-design/icons @matechat/core openai

5.3 全局注册

// src/main.ts
import { createApp } from 'vue';
import App from './App.vue';
import DevUI from 'vue-devui';
import MateChat from '@matechat/core';
import 'vue-devui/style.css';
import '@devui-design/icons/icomoon/devui-icon.css';

createApp(App).use(DevUI).use(MateChat).mount('#app');

5.4 主界面

<!-- src/App.vue -->
<template>
  <d-layout style="height: 100vh">
    <d-layout-header>智能云原生控制台</d-layout-header>
    <d-layout-content style="display: flex">
      <div style="width: 200px; padding: 16px; background: var(--devui-bg-color-light)">
        <d-menu :items="menu" />
      </div>
      <div style="flex: 1">
        <keep-alive>
          <component :is="currentView" />
        </keep-alive>
      </div>
    </d-layout-content>
  </d-layout>
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import Overview from './views/Overview.vue';
import AIAssistant from './views/AIAssistant.vue';

const menu = [
  { title: '概览', id: 'overview' },
  { title: 'AI 助手', id: 'ai' }
];

const currentView = computed(() => {
  const map: Record<string, any> = {
    overview: Overview,
    ai: AIAssistant
  };
  return map[activeId.value] || Overview;
});

const activeId = ref('overview');

// 监听菜单点击
function onMenuSelect(id: string) {
  activeId.value = id;
}
</script>

5.5 AI 助手视图(完整可运行)

<!-- src/views/AIAssistant.vue -->
<template>
  <mc-layout style="height: calc(100vh - 60px)">
    <mc-header title="AI 助手" />
    <div class="messages">
      <mc-bubble
        v-for="(msg, i) in messages"
        :key="i"
        :from="msg.role"
        :loading="msg.loading"
      >
        {{ msg.content }}
      </mc-bubble>
    </div>
    <mc-input @send="handleSend" placeholder="输入你的问题..." />
  </mc-layout>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import OpenAI from 'openai';

interface Msg {
  role: 'user' | 'model';
  content: string;
  loading?: boolean;
}

const messages = ref<Msg[]>([
  { role: 'model', content: '你好!我是你的 AI 助手,请问有什么可以帮您?' }
]);

const client = new OpenAI({
  apiKey: import.meta.env.VITE_OPENAI_API_KEY,
  dangerouslyAllowBrowser: true
});

async function handleSend(text: string) {
  messages.value.push({ role: 'user', content: text });
  messages.value.push({ role: 'model', content: '', loading: true });

  try {
    const stream = await client.chat.completions.create({
      model: 'gpt-4o-mini',
      messages: [{ role: 'user', content: text }],
      stream: true
    });

    messages.value[messages.value.length - 1].loading = false;

    for await (const chunk of stream) {
      const delta = chunk.choices[0]?.delta?.content || '';
      messages.value[messages.value.length - 1].content += delta;
    }
  } catch (err) {
    messages.value[messages.value.length - 1].content = '请求失败,请检查网络或 API Key。';
    messages.value[messages.value.length - 1].loading = false;
  }
}
</script>

<style scoped>
.messages {
  flex: 1;
  overflow-y: auto;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
</style>

⚠️ 注意:需在项目根目录创建 .env 文件:

VITE_OPENAI_API_KEY=your_api_key_here

至此,一个集 DevUI 操作界面与 MateChat 智能对话于一体的云原生控制台即可运行


六、反思:前端的新定位

DevUI 和 MateChat 的价值,不在于“提供了多少组件”,而在于:

  • DevUI 让企业级界面开发回归工程本质:稳定、可维护、可扩展;
  • MateChat 让 AI 交互摆脱野路子,走向标准化:一致、沉浸、可复用。

当云原生进入深水区,前端开发者要做的,不是“更快地画页面”,而是构建人与系统之间的智能协作通道

而这条通道的基石,正是像 DevUI 与 MateChat 这样,既懂工程,又懂体验,还敢为 AI 时代重新定义交互范式的开源项目。

它们不是终点,而是新起点。

项目地址:

  • DevUI:https://devui.design/home
  • MateChat:https://gitcode.com/DevCloudFE/MateChat
  • MateChat 官网:https://matechat.gitcode.com
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐