AI 助手集成实战指南

本文档将手把手教你在 Angular + DevUI 电商后台管理系统中集成 AI 聊天助手功能

📋 前置准备

环境要求

  • Node.js 18.x+
  • Angular CLI 18.x
  • 已有的 DevUI 电商后台项目

预计完成时间

  • 基础集成:30 分钟
  • 完整功能:60 分钟

第一步:创建 AI 数据模型(5分钟)

1.1 创建模型文件

在项目根目录执行:

# 如果 models 目录不存在,先创建
mkdir src/app/models

# 创建 AI 模型文件
touch src/app/models/ai.model.ts

1.2 编写模型代码

打开 src/app/models/ai.model.ts,复制以下代码:

// AI 对话消息模型
export interface ChatMessage {
  id: string;
  role: 'user' | 'assistant' | 'system';
  content: string;
  timestamp: Date;
  isLoading?: boolean;
}

// AI 响应
export interface AIResponse {
  content: string;
  usage?: {
    promptTokens: number;
    completionTokens: number;
    totalTokens: number;
  };
}

// AI 请求配置
export interface AIRequestConfig {
  model?: string;
  temperature?: number;
  maxTokens?: number;
  stream?: boolean;
}

// 商品描述生成请求
export interface GenerateDescriptionRequest {
  name: string;
  category: string;
  price: number;
  stock?: number;
}

// AI 功能类型
export type AIFeatureType = 'chat' | 'generate-description' | 'search-suggest';

说明:这些接口定义了 AI 功能所需的所有数据结构。


第二步:创建 AI 服务(10分钟)

2.1 创建服务文件

# 如果 services 目录不存在,先创建
mkdir src/app/services

# 创建 AI 服务文件
touch src/app/services/ai.service.ts

2.2 编写服务代码

打开 src/app/services/ai.service.ts,复制以下完整代码:

注意:由于代码较长,请访问项目中的 src/app/services/ai.service.ts 文件查看完整代码。

核心方法说明

// 发送聊天消息
chat(messages: ChatMessage[]): Observable<AIResponse>

// 生成商品描述
generateProductDescription(request: GenerateDescriptionRequest): Observable<string>

// 获取搜索建议
getSearchSuggestions(query: string): Observable<string[]>

重要提示

  • 当前使用 Mock 数据,可直接测试
  • 后续可替换为真实 AI API(OpenAI、文心一言等)
  • 所有方法都返回 Observable,支持异步处理

第三步:创建换行符管道(3分钟)

3.1 生成管道

ng generate pipe pipes/nl2br --skip-tests

3.2 编写管道代码

打开 src/app/pipes/nl2br.pipe.ts,替换为以下代码:

import { Pipe, PipeTransform } from '@angular/core';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';

@Pipe({
  name: 'nl2br',
  standalone: true
})
export class Nl2brPipe implements PipeTransform {
  constructor(private sanitizer: DomSanitizer) {}

  transform(value: string): SafeHtml {
    if (!value) {
      return '';
    }
    // 将换行符转换为 <br> 标签
    const html = value.replace(/\n/g, '<br>');
    return this.sanitizer.bypassSecurityTrustHtml(html);
  }
}

作用:让 AI 的多行回复能够正确显示换行。


第四步:创建 AI 助手组件(15分钟)

4.1 生成组件

ng generate component components/ai-assistant --skip-tests

4.2 编写组件 TypeScript

打开 src/app/components/ai-assistant/ai-assistant.component.ts,完整替换为:

请查看项目文件获取完整代码,或复制以下核心结构:

import { Component, OnInit } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
import { ButtonModule } from 'ng-devui/button';
import { AiService } from '../../services/ai.service';
import { I18nService } from '../../services/i18n.service';
import { ChatMessage } from '../../models/ai.model';
import { Nl2brPipe } from '../../pipes/nl2br.pipe';

@Component({
  selector: 'app-ai-assistant',
  standalone: true,
  imports: [
    CommonModule,
    FormsModule,
    ButtonModule,
    Nl2brPipe
  ],
  templateUrl: './ai-assistant.component.html',
  styleUrl: './ai-assistant.component.scss'
})
export class AiAssistantComponent implements OnInit {
  isOpen = false;
  isMinimized = false;
  messages: ChatMessage[] = [];
  userInput = '';
  isLoading = false;
  
  quickQuestions = [
    '如何添加商品?',
    '如何编辑商品?',
    '如何删除商品?',
    '如何搜索商品?'
  ];

  constructor(
    private aiService: AiService,
    public i18n: I18nService
  ) {}

  ngOnInit(): void {
    // 添加欢迎消息
    this.addMessage({
      id: this.generateId(),
      role: 'assistant',
      content: '你好!我是电商后台管理系统的 AI 助手 🤖\n\n我可以帮您:\n• 解答系统使用问题\n• 生成商品描述\n• 提供操作指导\n\n有什么可以帮您的吗?',
      timestamp: new Date()
    });
  }

  toggleChat(): void {
    this.isOpen = !this.isOpen;
    if (this.isOpen) {
      this.isMinimized = false;
      setTimeout(() => this.scrollToBottom(), 100);
    }
  }

  sendMessage(content?: string): void {
    const messageContent = content || this.userInput.trim();
    if (!messageContent) return;

    // 添加用户消息
    const userMessage: ChatMessage = {
      id: this.generateId(),
      role: 'user',
      content: messageContent,
      timestamp: new Date()
    };
    this.addMessage(userMessage);
    this.userInput = '';

    // 添加加载消息
    const loadingMessage: ChatMessage = {
      id: this.generateId(),
      role: 'assistant',
      content: '',
      timestamp: new Date(),
      isLoading: true
    };
    this.addMessage(loadingMessage);
    this.isLoading = true;

    // 调用 AI 服务
    this.aiService.chat(this.messages.filter(m => !m.isLoading)).subscribe({
      next: (response) => {
        this.messages = this.messages.filter(m => !m.isLoading);
        const aiMessage: ChatMessage = {
          id: this.generateId(),
          role: 'assistant',
          content: response.content,
          timestamp: new Date()
        };
        this.addMessage(aiMessage);
        this.isLoading = false;
      },
      error: (error) => {
        console.error('AI 响应错误:', error);
        this.messages = this.messages.filter(m => !m.isLoading);
        const errorMessage: ChatMessage = {
          id: this.generateId(),
          role: 'assistant',
          content: '抱歉,我遇到了一些问题。请稍后再试。',
          timestamp: new Date()
        };
        this.addMessage(errorMessage);
        this.isLoading = false;
      }
    });
  }

  selectQuickQuestion(question: string): void {
    this.sendMessage(question);
  }

  minimizeChat(): void {
    this.isMinimized = !this.isMinimized;
  }

  closeChat(): void {
    this.isOpen = false;
    this.isMinimized = false;
  }

  clearChat(): void {
    this.messages = [];
    this.ngOnInit();
  }

  private addMessage(message: ChatMessage): void {
    this.messages.push(message);
    setTimeout(() => this.scrollToBottom(), 100);
  }

  private scrollToBottom(): void {
    const messagesContainer = document.querySelector('.chat-messages');
    if (messagesContainer) {
      messagesContainer.scrollTop = messagesContainer.scrollHeight;
    }
  }

  private generateId(): string {
    return `msg_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }

  formatTime(date: Date): string {
    const hours = date.getHours().toString().padStart(2, '0');
    const minutes = date.getMinutes().toString().padStart(2, '0');
    return `${hours}:${minutes}`;
  }
}

4.3 编写组件 HTML

打开 src/app/components/ai-assistant/ai-assistant.component.html,完整替换为:

请查看项目文件获取完整 HTML 代码

核心结构

<!-- 悬浮按钮 -->
<div class="ai-fab" (click)="toggleChat()">
  <span class="ai-fab-text">AI</span>
</div>

<!-- 聊天窗口 -->
<div class="ai-chat-container" *ngIf="isOpen">
  <!-- 头部 -->
  <div class="chat-header">...</div>
  
  <!-- 消息列表 -->
  <div class="chat-messages">...</div>
  
  <!-- 输入区域 -->
  <div class="chat-input-container">...</div>
</div>

4.4 编写组件样式

打开 src/app/components/ai-assistant/ai-assistant.component.scss,完整替换为:

请查看项目文件获取完整样式代码

核心样式

  • 悬浮按钮:紫色渐变、圆形、右下角固定
  • 聊天窗口:白色背景、圆角、阴影
  • 消息气泡:用户右对齐紫色、AI左对齐白色
  • 动画效果:滑入、打字指示器

第五步:集成到主组件(5分钟)

5.1 修改主组件 TypeScript

打开 src/app/app.component.ts,在文件顶部添加导入:

import { AiService } from './services/ai.service';
import { AiAssistantComponent } from './components/ai-assistant/ai-assistant.component';

imports 数组中添加:

@Component({
  // ...
  imports: [
    // ... 现有的导入
    AiAssistantComponent  // 添加这一行
  ]
})

5.2 修改主组件 HTML

打开 src/app/app.component.html,在文件末尾(<router-outlet /> 之后)添加:

<router-outlet />

<!-- AI 助手 -->
<app-ai-assistant></app-ai-assistant>

第六步:启动测试(2分钟)

6.1 启动开发服务器

ng serve

6.2 访问应用

打开浏览器访问:http://localhost:4200

6.3 测试 AI 助手

  1. 查看悬浮按钮:页面右下角应该有一个紫色圆形按钮,显示"AI"
  2. 打开聊天窗口:点击悬浮按钮,聊天窗口从底部滑入
  3. 查看欢迎消息:AI 自动发送欢迎消息
  4. 测试快捷问题:点击"如何添加商品?"等按钮
  5. 自由对话:输入"你好"并发送
  6. 测试窗口控制:尝试最小化、清空、关闭功能

常见问题排查

问题 1:悬浮按钮不显示

检查

  1. 确认 <app-ai-assistant></app-ai-assistant> 已添加到 HTML
  2. 确认组件已导入到 app.component.tsimports 数组
  3. 打开浏览器控制台查看是否有错误

问题 2:点击按钮没反应

检查

  1. 打开浏览器控制台查看错误信息
  2. 确认 ai.service.ts 文件存在且无语法错误
  3. 确认所有依赖都已正确导入

问题 3:消息不显示换行

检查

  1. 确认 nl2br.pipe.ts 已创建
  2. 确认管道已导入到 AI 助手组件的 imports 数组
  3. 确认 HTML 中使用了 [innerHTML]="message.content | nl2br"

问题 4:样式显示异常

检查

  1. 确认 .scss 文件内容完整
  2. 清除浏览器缓存(Ctrl+Shift+R)
  3. 检查是否有 CSS 冲突

扩展功能实现

扩展 1:商品描述 AI 生成

在商品表单的描述字段添加 AI 生成按钮。

步骤

  1. app.component.html 中找到描述字段,修改为:
<div class="form-group">
  <label class="form-label">{{ i18n.t('product.description') }}</label>
  <div class="description-with-ai">
    <textarea 
      class="form-control"
      [(ngModel)]="productForm.description"
      name="description"
      rows="4">
    </textarea>
    <button 
      class="ai-generate-btn"
      type="button"
      (click)="generateDescription()"
      [disabled]="!productForm.name || !productForm.category || isGeneratingDescription">
      <span *ngIf="!isGeneratingDescription">🤖 AI 生成描述</span>
      <span *ngIf="isGeneratingDescription">⏳ 生成中...</span>
    </button>
  </div>
</div>
  1. app.component.ts 中添加方法:
isGeneratingDescription = false;

generateDescription(): void {
  if (!this.productForm.name || !this.productForm.category) {
    this.toastService.open({
      value: [{ severity: 'warning', summary: '请先填写商品名称和分类' }]
    });
    return;
  }

  this.isGeneratingDescription = true;

  this.aiService.generateProductDescription({
    name: this.productForm.name,
    category: this.productForm.category,
    price: this.productForm.price,
    stock: this.productForm.stock
  }).subscribe({
    next: (description) => {
      this.productForm.description = description;
      this.isGeneratingDescription = false;
      this.toastService.open({
        value: [{ severity: 'success', summary: 'AI 描述生成成功!' }]
      });
    },
    error: (error) => {
      console.error('生成描述失败:', error);
      this.isGeneratingDescription = false;
      this.toastService.open({
        value: [{ severity: 'error', summary: '生成失败,请重试' }]
      });
    }
  });
}
  1. app.component.ts 的构造函数中注入 AI 服务:
constructor(
  // ... 现有的依赖
  private aiService: AiService  // 添加这一行
) {}
  1. app.component.scss 中添加样式:
.description-with-ai {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ai-generate-btn {
  align-self: flex-end;
  padding: 8px 16px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  border: none;
  border-radius: 6px;
  font-size: 13px;
  cursor: pointer;
  transition: all 0.2s;

  &:hover:not(:disabled) {
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4);
  }

  &:disabled {
    opacity: 0.6;
    cursor: not-allowed;
  }
}

对接真实 AI API

方案 1:OpenAI API

ai.service.ts 中修改 chat 方法:

import { HttpClient } from '@angular/common/http';

constructor(private http: HttpClient) {}

chat(messages: ChatMessage[]): Observable<AIResponse> {
  const headers = {
    'Content-Type': 'application/json',
    'Authorization': `Bearer YOUR_OPENAI_API_KEY`
  };

  const body = {
    model: 'gpt-3.5-turbo',
    messages: messages.map(m => ({
      role: m.role,
      content: m.content
    })),
    temperature: 0.7,
    max_tokens: 500
  };

  return this.http.post<any>(
    'https://api.openai.com/v1/chat/completions', 
    body, 
    { headers }
  ).pipe(
    map(response => ({
      content: response.choices[0].message.content,
      usage: response.usage
    }))
  );
}

注意

  • 需要在 app.config.ts 中添加 provideHttpClient()
  • API Key 不应暴露在前端,建议通过后端代理

方案 2:通过后端代理(推荐)

chat(messages: ChatMessage[]): Observable<AIResponse> {
  return this.http.post<AIResponse>('/api/ai/chat', { messages });
}

总结

你已经完成了:

✅ 创建了完整的 AI 数据模型
✅ 实现了 AI 服务层(支持聊天、描述生成、搜索建议)
✅ 创建了美观的 AI 聊天助手组件
✅ 集成到主应用中
✅ 测试了所有功能

效果图

在这里插入图片描述

下一步建议:

  1. 对接真实 AI API
  2. 添加更多预设问题
  3. 实现商品描述生成功能
  4. 添加智能搜索建议
  5. 支持语音输入
  6. 保存对话历史

🎉 恭喜!你已经成功为电商后台系统集成了 AI 助手功能!

框架文档地址

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

源代码
https://gitcode.com/daleishen/DevUI

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐