🔥Angular开发者看过来:不止于Vue,MateChat智能化UI库现已全面支持Angular!

DevUI团队重磅推出~MateChat/Angular V20.1.0 版本正式发布

源码:gitcode.com/DevCloudFE/...

官网:matechat.gitcode.com

今天给大家推荐一款专为Angular生态打造的智能对话UI库------MateChat/Angular!作为MateChat跨框架系列的全新成员,其Vue版本自开源来,在GitCode收获1.7k+星标,积累了近千条用户issue反馈与PR贡献,成为众多前端团队开发AI对话应用的首选组件库之一。如今Angular版本正式上线,不仅延续了Vue版的优秀基因,更实现了跨框架体验一致性,开箱即用的三大核心组件,让Angular开发者也能快速搭建起生产级别的AI对话应用。

MateChat 简介

MateChat 设计理念:体验无边界 业务无侵害

作为DevUI团队重磅推出的开源项目,MateChat致力于构建不同业务场景下高一致性的GenAI体验系统语言,同时匹配各种工具/平台的原生业务场景和界面特征, 提供更适合研发工具领域的对话组件,打造流畅亲和、跨界一致、易学易用的用户体验,以及易接入、易维护、易扩展的开发体验。

MateChat为您提供了快速搭建网站智能化场景的AI解决方案,无论您是初创企业,还是已经成熟的公司,借助MateChat,您可以轻松实现自定义的AI助手,迅速提升网站的互动性与用户体验。

🎯 为什么选择MateChat/Angular?

作为面向智能化场景的组件库,它解决了传统UI库在AI对话场景下的「水土不服」:

  • 天生适配 Angular 生态:不是通用 UI 库套壳适配 Angular,而是Angular原生开发,基于跨框架组件架构设计对核心逻辑的复用
  • 跨框架「无缝衔接」,多端团队狂喜 :与MateChat/Vue版本实现UI样式、API设计、功能特性高度统一,多框架项目开发无需重新适配,降低团队协作成本。
  • 场景化组件设计 :拒绝通用组件堆砌,BubbleInputMarkdownCard三大核心组件完美匹配对话流场景,支持流式增量DOM渲染、打字机效果及深度思考,复杂格式内容也能流畅展示;bubble组件支持头像、对齐方式控制,input组件适配对话输入场景,整体完美匹配对话流需求。
  • 多主题与扩展性:无缝对接DevUI主题系统,支持自定义配色;组件API设计灵活,可快速适配不同业务需求。
  • 流式响应友好:天然支持大模型流式返回,无需额外封装,轻松实现「打字机」效果。
  • 社区兜底,持续演进: MateChat团队维护,文档实时更新、bug 修复不拖沓,与Vue版本同步演进

了解更多请访问MateChat网站:MateChat

🧩 MateChat 跨框架组件架构:从 Vue 到 Angular,我们如何实现原生级组件复用?

在前端团队规模扩大的过程中,「技术栈碎片化」带来的代码复用难题几乎是绕不开的坎。我们团队也不例外:早期基于 Vue 开发了 MateChat 组件库,支撑了多个业务线;但随着新业务引入 Angular 技术栈,重复开发相似组件、维护多套逻辑的成本急剧上升 ------UI 不一致、功能不同步、团队协作效率低,这些问题逐渐成为业务迭代的绊脚石。

于是,我们决定构建「跨框架组件架构」,在 MateChat/Vue 的基础上开发 MateChat/Angular 组件库。但我们从一开始就明确:不做 "套壳适配",而是追求原生体验与核心逻辑复用的平衡。现在 MateChat/Angular 已正式落地,今天就来聊聊这套架构的设计思路与实现细节。

1. 为什么不选 "套壳"?聊聊跨框架组件的本质需求

在决定做 Angular 版本前,我们调研了市面上常见的跨框架方案,发现很多多框架 UI 库采用 "核心逻辑 + 框架桥接层" 的套壳模式(比如用 Vue 核心包亦或是Svelte开发组件,再通过桥接工具适配 Angular)。但这种模式在企业级场景下有明显短板:

  • 框架生态割裂:Angular 有自己的依赖注入、变更检测、指令系统等特性,套壳模式很难贴合这些原生能力,导致组件在 Angular 项目中显得 "格格不入";
  • 性能损耗:桥接层会增加额外的渲染链路和状态同步成本,在复杂组件(如表格、表单)中表现尤为明显;
  • API 设计妥协 :为了兼容多框架,API 往往会取各框架的 "交集",难以利用目标框架的特性(比如 Angular 的双向绑定语法糖[(ngModel)])。

对我们而言,跨框架组件的核心需求是 "体验一致、复用高效、生态融合" ------ 既要有统一的 UI 和功能,又要让每个框架的开发者用得 "顺手",还要能大幅降低维护成本。因此,我们选择了另一条路:核心逻辑与框架解耦,为每个框架开发原生适配层

2. "核心层 + 适配层" 的分层设计架构

MateChat/Angular 的组件完全基于 Angular 的最佳实践开发,而非简单移植 Vue 的实现。对 Angular 开发者来说,使用 MateChat 组件就像用官方组件一样自然,无需额外学习成本。

在跨框架架构的设计上,我们深受了semi design、Tiny、Headless等组件库架构启发,其 "核心逻辑抽象与框架适配分离" 的思路,为我们提供了重要的参考。站在这个基础上,结合团队的企业级场景需求,我们进一步细化出了MateChat的分层架构模型:

基于这套跨框架架构落地,给团队带来的改变是显著的:

  • 跨框架一致性 :从 UI 到 API 的 "无缝衔接",所有框架组件共享同一套 CSS 变量和样式文件(通过 SCSS 模块化管理),确保颜色、间距、动画在不同框架中表现一致,用户在不同技术栈开发的页面中,不会感受到组件交互的差异。
  • API 设计对齐 :组件的属性、事件、方法尽可能保持同名。例如 Vue 的<mc-input @change="handleChange" />和 Angular 的<mc-input (change)="handleChange($event)" />,开发者切换框架时几乎不用改代码;
  • 协作成本降低:多技术栈团队无需为组件适配反复沟通,设计稿→组件实现的链路统一;
  • 维护效率提升 :核心逻辑 bug 修复一次到位,避免多框架重复改代码,核心代码复用率70%以上
  • 技术生态兼容 :后续如果引入 React、Svelte 等新框架,只需开发轻量适配层(预估工作量仅为从零开发的 30%);

对大型企业来说,这种架构尤其有价值 ------ 它既尊重了业务对技术栈的灵活选择,又通过 "核心复用" 守住了研发效率和产品体验的底线。如果你也在面临多技术栈组件复用的难题,希望这套架构能给你带来一些启发。欢迎在评论区交流你的经验~

🚀 快速上手

话不多说,直接上实操步骤------从环境搭建到简易对话界面实现,全程不超过10分钟,即使是Angular新手也能快速上手。

1. 安装

先初始化Angular项目(已有项目可跳过此步,支持Angular20版本),再安装@mateChat/ng

java 复制代码
npm install -g @angular/cli@latest
ng new matechat-demo
npm i @matechat/ng

2. 引入

app.ts文件中引入模块:

ts 复制代码
import { Component } from "@angular/core";
import { CommonModule } from "@angular/common";
import { BubbleModule } from "@matechat/ng";

@Component({
  selector: "app-root",
  standalone: true,
  imports: [CommonModule, BubbleModule],
  templateUrl: "./app.component.html",
  styleUrl: "./app.component.css",
})
export class AppComponent {}

3. 使用

app.html文件中使用 MateChat 组件,如:

html 复制代码
<mc-bubble [content]="'Hello, MateChat'" [avatarConfig]="{ name: 'matechat' }"></mc-bubble>

在模板中组合Bubble、Input、MarkdownCard组件,即可实现简单的对话界面搭建:

在app.html使用如下代码:

html 复制代码
<div class="mc-layout">
  <div class="chat-container">
    <div class="chat-header" :title="'MateChat'">
      <img src="https://matechat.gitcode.com/logo.svg" />
      <span>MateChat</span>
    </div>
    @if (newPage) {
    <div class="welcom-page">
      <div class="content-wrapper">
        <div class="mc-introduction">
          <div class="mc-introduction-logo-container">
            <img src="https://matechat.gitcode.com/logo2x.svg" alt="MateChat" />
            <div class="mc-introduction-title">MateChat</div>
          </div>
          <div class="mc-introduction-description">
            <div>MateChat 可以辅助研发人员编码、查询知识和相关作业信息、编写文档等。</div>
            <div>
              作为AI模型,MateChat 提供的答案可能不总是确定或准确的,但您的反馈可以帮助 MateChat
              做的更好。
            </div>
          </div>
        </div>
        <div class="guess-question">
          <div class="guess-title">
            <div>猜你想问</div>
          </div>
          <div class="guess-content">
            <ng-container *ngFor="let item of questionList">
              <span (click)="onSubmit(item)">{{ item }}</span>
            </ng-container>
          </div>
        </div>
      </div>
    </div>
    } @else {
    <div class="chat-list">
      <ng-container *ngFor="let msg of messages">
        @if (msg.from === 'user') {
        <mc-bubble class="user-bubble" [align]="'right'" [content]="msg.content" [avatarConfig]="avatarConfig"></mc-bubble>
        } @else if (msg.from === 'model') {
        <mc-bubble class="model-bubble" [align]="'left'" [loading]="msg.loading" [avatarConfig]="modelAvatar">
          <mc-markdown-card [content]="msg.content" [enableMermaid]="true"></mc-markdown-card>
        </mc-bubble>
        }
      </ng-container>
    </div>
    }
    <div class="chat-footer">
      <mc-input (submit)="onSubmit($event)"> </mc-input>
      <div class="statement-box">
        <span>内容由AI生成,无法确保准确性和完整性,仅供参考</span>
      </div>
    </div>
  </div>
</div>

在app.ts中使用如下代码:

ts 复制代码
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { BubbleModule, InputModule, MarkdownCardModule } from '@matechat/ng';
@Component({
  selector: 'app-root',
  imports: [CommonModule, BubbleModule, InputModule, MarkdownCardModule],
  templateUrl: './app.html',
  styleUrl: './app.scss',
})
export class App {
  inputValue = '';
  messages: any = [];
  newPage = true;
  questionList = [
    '帮我写一篇文章',
    '你可以帮我做些什么?',
    '帮我写一个快速排序',
    '使用 js 格式化时间',
  ];
  avatarConfig = {
    imgSrc: 'https://matechat.gitcode.com/png/demo/userAvatar.svg',
  };
  modelAvatar = {
    imgSrc: 'https://matechat.gitcode.com/logo.svg',
  };

  onSubmit = (evt: any) => {
    this.newPage = false;
    this.inputValue = '';
    // 用户发送消息
    this.messages.push({
      from: 'user',
      content: evt,
    });
    setTimeout(() => {
      // 模型返回消息
      this.messages.push({
        from: 'model',
        content: evt,
      });
    }, 200);
  };
}

在将模板应用中的app.css修改成app.scss,使用如下代码:

scss 复制代码
::ng-deep body {
  margin: 0;
  color: var(--devui-text, #252b3a);
}

.mc-layout {
  height: 100vh;
  width: 100%;
  padding: 12px;
  box-sizing: border-box;
  background: linear-gradient(
    to bottom,
    #d0c9ff 0%,
    #e6d6f0 8%,
    #f1dbea 12%,
    #c8dcfb 40%,
    #abc6f6 60%,
    #87aefe 90%
  );
}

::ng-deep body[ui-theme='galaxy-theme'] .mc-layout {
  background: var(--devui-global-bg, #f6f6f8);

  .chat-container {
    background: transparent;
    border: none;
  }
}

.chat-container {
  display: flex;
  flex-direction: column;
  box-sizing: border-box;
  gap: 8px;
}

.welcom-page {
  display: flex;
  flex-direction: column;
  flex: 1;
  max-width: 1200px;
  margin: 0 auto;
  overflow: auto;
  width: 100%;
  max-width: 1200px;
  padding: 0 12px;
  box-sizing: border-box;
  gap: 24px;
}

.guess-title {
  display: flex;
  justify-content: space-between;
  align-items: center;
  color: var(--devui-text, #252b3a);
  margin-bottom: 16px;
}

.guess-content {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
}

.mc-introduction-logo-container {
  display: flex;
  align-items: center;
  gap: 8px;
}

.mc-introduction-description {
  text-align: center;
  font-size: 14px;
  color: var(--devui-text, #252b3a);
}

.mc-introduction-title {
  font-weight: 700;
  font-size: 32px;
  letter-spacing: 1px;
  color: var(--devui-text, #252b3a);
}

.guess-question {
  width: 100%;
  margin-top: 24px;
  padding: 24px;
  border-radius: 24px;
  box-sizing: border-box;
  background-color: var(--devui-base-bg, #ffffff);
}

.guess-question-title {
  font-size: 24px;
  font-weight: 700;
  color: var(--devui-text, #252b3a);
  margin-bottom: 16px;
}

.guess-question span {
  font-size: var(--devui-font-size, 12px);
  color: var(--devui-aide-text, #71757f);
  padding: 10px 16px;
  border-radius: var(--devui-border-radius-full, 100px);
  background-color: var(--devui-dividing-line, #f2f2f3);
  cursor: pointer;
}

.content-wrapper {
  margin: auto 0;
}

.chat-container {
  width: 100%;
  height: 100%;
  padding: 12px;
  border-radius: 20px;
  margin: 0 auto;
  border: 1px solid #e5e5e5;
  background: linear-gradient(180deg, #fffffff2, #f8fafff2 99%);
}

.chat-header {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 8px;

  img {
    width: 32px;
    height: 32px;
  }

  span {
    font-size: 20px;
    color: var(--devui-text, #252b3a);
  }
}

.mc-introduction {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}

.chat-list {
  flex: 1;
  width: 100%;
  max-width: 1200px;
  margin: 0 auto 12px;
  overflow: auto;

  .user-bubble,
  .model-bubble {
    display: block;
    margin-top: 8px;
  }
}

.chat-footer {
  width: 100%;
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 12px 12px;
  box-sizing: border-box;
}

.statement-box {
  font-size: 12px;
  margin-top: 8px;
  color: var(--devui-aide-text, #71757f);
  text-align: center;
}

参数上述代码,此处你已经可以搭起一个基础的智能对话界面了,如果你需要更多丰富的主题样式,或者对接真实大模型,可以参考第 4、5 点进行使用。

4. 主题化

main.ts中初始化主题,更多用法可参考 devui-theme

ts 复制代码
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { App } from './app/app';
import { ThemeServiceInit, infinityTheme, galaxyTheme } from 'devui-theme';

ThemeServiceInit(
  {
    'galaxy-theme': galaxyTheme, // 暗黑主题
    'infinity-theme': infinityTheme,
  },
  'galaxy-theme'
);
bootstrapApplication(App, appConfig).catch((err) => console.error(err));

基础效果如下,需要注意的是MarkdownCard组件的主题需要主动传入,更多用法请参考官网演示。

5. 对接模型服务

在搭建完成页面后,可以开始对接模型服务,如 DeepSeekChatGPT 等优秀大模型,在注册并生成对应模型的调用API_Key后,可以参考如下方法进行调用:

  1. 通过 npm 安装 openai:

    npm install openai

  2. 使用OpenAI初始化并调用模型接口,如下为一段代码示例:

javascript 复制代码
import OpenAI from 'openai';

const client = new OpenAI({
  apiKey: '', // 模型APIKey
  baseURL: '', // 模型API地址
  dangerouslyAllowBrowser: true,
});

const fetchData = (ques) => {
  const completion = await client.chat.completions.create({
    model: 'my-model', // 替换为自己的model名称
    messages: [
      { role: 'user', content: ques },
    ],
    stream: true, // 为 true 则开启接口的流式返回
  });

  for await (const chunk of completion) {
    console.log('content: ', chunk.choices[0]?.delta?.content || '');
    console.log('chatId: ', chunk.id);
  }
}

那么参考以上步骤,【快速开始】中示例可调整下代码。

将以下代码:

ini 复制代码
onSubmit = (evt) => {
  this.newPage = false;
  this.inputValue = '';
  // 用户发送消息
  this.messages.push({
    from: 'user',
    content: evt,
  });
  setTimeout(() => {
    // 模型返回消息
    this.messages.push({
      from: 'model',
      content: evt,
    });
  }, 200);
};

修改为:

kotlin 复制代码
import OpenAI from 'openai';

client = new OpenAI({
  apiKey: '', // 模型APIKey
  baseURL: '', // 模型API地址
  dangerouslyAllowBrowser: true,
});

 onSubmit = async (evt) => {
  this.newPage = false;
  this.inputValue = '';
  // 用户发送消息
  this.messages.push({
    from: 'user',
    content: evt,
    avatarConfig: { name: 'user' },
  });

  this.fetchData(evt);
};

fetchData = async (ques) => {
  this.messages.push({
    from: 'model',
    content: '',
    avatarConfig: { name: 'model' },
    id: '',
    loading: true,
  });
  const completion = await this.client.chat.completions.create({
    model: 'my-model', // 替换为自己的model名称
    messages: [{ role: 'user', content: ques }],
    stream: true, // 为 true 则开启接口的流式返回
  });
  for await (const chunk of completion) {
    this.messages[this.messages.length - 1].loading = false;
    const content = chunk.choices[0]?.delta?.content || '';
    const chatId = chunk.id;
    this.messages[this.messages.length - 1].content += content;
    this.messages[this.messages.length - 1].id = chatId;
  }
};

完成模型API地址与APIKey填充并配置model名称后,即拥有了一个对接大模型的简单应用。如果你想要参考更完整的页面示例,可参考演示场景

📝 提出意见&建议

我们非常欢迎您的建议,您的每一个想法都可能帮助我们改进这个项目。如果您有任何关于功能改进、特性新增、文档补充或者其他方面的建议,随时在 issues 提交。

🔧 本地开发

scss 复制代码
git clone git@gitcode.com:DevCloudFE/MateChat.git
cd matechat
pnpm i
pnpm run docs:dev

📅 特性规划

目前 MateChat 已支持 Vue 和 Angular,后续我们也将推出React版本,你可在这里更多了解我们的计划:MateChat 特性计划

🏆 贡献者荣誉

感谢本期这些优秀的贡献者(GitCode ID):

  • @liuguolin ------ 新增@matechat/ng组件库
  • @dd-code-dd ------ 新增MateChat主页网站Angular版本

我们诚挚地邀请您加入 MateChat 社区,一起参与项目的建设。无论您是经验丰富的开发者,还是刚刚起步的编程爱好者,您的贡献都对我们至关重要,这里是我们的【贡献指南】

📣 加入我们

MateChat 正在快速发展,我们欢迎更多开发者加入:

广纳贤士:AI赋能各行各业,MateChat期待更多感兴趣的小伙伴加入我们~

相关推荐
北京青翼科技2 小时前
【HD200IS A2 DK 】昇腾 310B 高可靠智能计算开发套件
图像处理·人工智能·信号处理·智能硬件
智算菩萨2 小时前
从 0 到 1 搭建 AI 智能体:从创建、知识库与提示词,到 MCP 接入和多智能体协作的全流程实践与评测
人工智能
onebound_noah2 小时前
电商图片搜索:技术破局与商业落地,重构“视觉到交易”全链路
大数据·前端·网络·人工智能·重构·php
得贤招聘官2 小时前
AI得贤面试智能体:重构企业招聘新范式
人工智能
SEO_juper2 小时前
谷歌搜索全面AI化:SGE如何重构我们的搜索体验与营销格局
人工智能·ai·重构·数字营销
好多渔鱼好多2 小时前
【音视频】AI自适应均衡器的调节精度提升方法
人工智能·音视频
昨日之日20062 小时前
InfiniteTalk V2版 - 声音驱动图片生成高度逼真的说话/唱歌视频 支持50系显卡 ComfyUI+WebUI 一键整合包下载
人工智能·深度学习·音视频
老蒋新思维2 小时前
破局与重构:借 “创始人 IP + AI” 开启智能商业新征程|创客匠人
网络·人工智能·网络协议·tcp/ip·重构·知识付费·创客匠人
KKKlucifer2 小时前
智能越进化,防线越脆弱?AI 时代数据安全的底层挑战与重构
人工智能·重构