DevUI 实战教程:从零构建电商后台管理系统(完整版)

DevUI 实战教程:从零构建电商后台管理系统(完整版)

本教程将带你使用 Angular 18 和 DevUI 组件库,从零开始构建一个功能完整的电商后台管理系统。

📚 教程目录


🎯 项目效果预览

完成本教程后,你将获得:

  • ✅ 商品列表展示(表格形式)
  • ✅ 添加新商品(模态框表单)
  • ✅ 编辑商品信息
  • ✅ 删除商品(带确认对话框)
  • ✅ 搜索商品功能
  • ✅ 多语言切换(中文/英文)
  • ✅ 响应式布局(支持桌面和移动端)

📋 前置要求

在开始之前,请确保你的开发环境满足以下要求:

  • Node.js: 18.x 或更高版本
  • npm: 9.x 或更高版本
  • Angular CLI: 18.x
  • 代码编辑器: VS Code(推荐)

第一章:项目初始化

1.1 安装 Angular CLI

首先,全局安装 Angular CLI:

bash 复制代码
npm install -g @angular/cli@18

验证安装:

bash 复制代码
ng version

1.2 创建新项目

使用 Angular CLI 创建新项目:

bash 复制代码
ng new devui-project

在创建过程中,选择以下选项:

  • Would you like to add Angular routing?No(本教程不需要路由)
  • Which stylesheet format would you like to use?SCSS

1.3 进入项目目录

bash 复制代码
cd devui-project

1.4 启动开发服务器

bash 复制代码
ng serve

打开浏览器访问 http://localhost:4200,你应该能看到 Angular 的欢迎页面。


第二章:安装和配置 DevUI

2.1 安装 DevUI

在项目根目录下执行:

bash 复制代码
npm install ng-devui --save
npm install @devui-design/icons --save
npm install @angular/localize@18 --save --legacy-peer-deps

2.2 配置 DevUI 样式

打开 angular.json 文件,在 styles 数组中添加 DevUI 的 CSS 文件。

需要在两个地方添加(buildtest 配置中):

json 复制代码
"styles": [
  "src/styles.scss",
  "node_modules/ng-devui/devui.min.css"
]

2.3 配置动画支持

打开 src/app/app.config.ts,添加动画支持:

typescript 复制代码
import { ApplicationConfig, provideZoneChangeDetection } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideAnimations } from '@angular/platform-browser/animations';

import { routes } from './app.routes';

export const appConfig: ApplicationConfig = {
  providers: [
    provideZoneChangeDetection({ eventCoalescing: true }), 
    provideRouter(routes),
    provideAnimations()  // 添加这一行
  ]
};

2.4 禁用 SSR(可选)

如果遇到 SSR 相关问题,可以在 angular.json 中移除 SSR 配置:

找到 build 配置下的这几行并删除:

json 复制代码
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
  "entry": "server.ts"
}

第三章:创建数据模型

3.1 创建 models 目录

bash 复制代码
mkdir src/app/models

3.2 创建商品模型

创建文件 src/app/models/product.model.ts

typescript 复制代码
export interface Product {
  id: number;
  name: string;
  category: string;
  price: number;
  stock: number;
  description: string;
  status: 'active' | 'inactive';
  createdAt: Date;
}

export interface ProductFormData {
  name: string;
  category: string;
  price: number;
  stock: number;
  description: string;
  status: 'active' | 'inactive';
}

代码说明:

  • Product: 完整的商品数据模型,包含 ID 和创建时间
  • ProductFormData: 表单数据模型,用于添加和编辑商品时的数据绑定

第四章:实现国际化服务

4.1 创建 services 目录

bash 复制代码
mkdir src/app/services

4.2 创建国际化服务

创建文件 src/app/services/i18n.service.ts

由于代码较长,这里展示核心结构:

typescript 复制代码
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';

export type Language = 'zh-CN' | 'en-US';

@Injectable({
  providedIn: 'root'
})
export class I18nService {
  private currentLang = new BehaviorSubject<Language>('zh-CN');
  public currentLang$: Observable<Language> = this.currentLang.asObservable();

  private translations: Record<Language, any> = {
    'zh-CN': {
      app: { title: '电商后台管理系统', language: '语言' },
      product: {
        title: '商品管理',
        add: '添加商品',
        edit: '编辑商品',
        delete: '删除商品',
        // ... 更多翻译
      }
    },
    'en-US': {
      app: { title: 'E-commerce Admin System', language: 'Language' },
      product: {
        title: 'Product Management',
        add: 'Add Product',
        // ... 更多翻译
      }
    }
  };

  constructor() {
    // 从 localStorage 读取保存的语言设置(需要处理 SSR)
    if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {
      const savedLang = localStorage.getItem('language') as Language;
      if (savedLang && (savedLang === 'zh-CN' || savedLang === 'en-US')) {
        this.currentLang.next(savedLang);
      }
    }
  }

  setLanguage(lang: Language): void {
    this.currentLang.next(lang);
    if (typeof window !== 'undefined' && typeof localStorage !== 'undefined') {
      localStorage.setItem('language', lang);
    }
  }

  translate(key: string, params?: any[]): string {
    const keys = key.split('.');
    let value: any = this.translations[this.currentLang.value];
    
    for (const k of keys) {
      value = value?.[k];
    }
    
    if (typeof value === 'string' && params) {
      params.forEach((param, index) => {
        value = value.replace(`{${index}}`, param);
      });
    }
    
    return value || key;
  }

  t(key: string, params?: any[]): string {
    return this.translate(key, params);
  }
}

完整的翻译内容请参考项目源码中的 i18n.service.ts 文件。

代码说明:

  • 使用 BehaviorSubject 管理当前语言状态
  • 支持中英文两种语言
  • 提供参数化翻译功能(如:'共 {0} 条'
  • 使用 localStorage 持久化语言选择
  • SSR 兼容性处理

第五章:构建商品服务

5.1 创建商品服务文件

创建文件 src/app/services/product.service.ts

typescript 复制代码
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Product, ProductFormData } from '../models/product.model';

@Injectable({
  providedIn: 'root'
})
export class ProductService {
  private products = new BehaviorSubject<Product[]>([]);
  public products$: Observable<Product[]> = this.products.asObservable();

  constructor() {
    this.initMockData();
  }

  private initMockData(): void {
    const mockProducts: Product[] = [
      {
        id: 1,
        name: 'iPhone 15 Pro',
        category: '电子产品',
        price: 7999,
        stock: 50,
        status: 'active',
        description: '最新款苹果手机,搭载A17 Pro芯片',
        createdAt: new Date('2024-01-15')
      },
      // ... 更多示例数据
    ];
    this.products.next(mockProducts);
  }

  getProducts(): Observable<Product[]> {
    return this.products$;
  }

  addProduct(formData: ProductFormData): void {
    const currentProducts = this.products.value;
    const newId = Math.max(...currentProducts.map(p => p.id), 0) + 1;
    
    const newProduct: Product = {
      ...formData,
      id: newId,
      createdAt: new Date()
    };
    
    this.products.next([...currentProducts, newProduct]);
  }

  updateProduct(id: number, formData: ProductFormData): void {
    const currentProducts = this.products.value;
    const index = currentProducts.findIndex(p => p.id === id);
    
    if (index !== -1) {
      const updatedProduct: Product = {
        ...currentProducts[index],
        ...formData
      };
      currentProducts[index] = updatedProduct;
      this.products.next([...currentProducts]);
    }
  }

  deleteProduct(id: number): void {
    const currentProducts = this.products.value;
    this.products.next(currentProducts.filter(p => p.id !== id));
  }

  getProductById(id: number): Product | undefined {
    return this.products.value.find(p => p.id === id);
  }
}

代码说明:

  • 使用 BehaviorSubject 实现响应式数据管理
  • initMockData() 初始化 5 个示例商品
  • 提供完整的 CRUD 操作方法
  • 所有数据变更都会自动通知订阅者

由于篇幅限制,完整教程内容请查看项目中的以下文件:

  • 第六章到第十章的详细内容
  • 完整的代码示例
  • 样式文件的完整代码

或访问项目源码查看 app.component.tsapp.component.htmlapp.component.scss 文件。


快速参考:核心代码结构

组件类结构 (app.component.ts)

typescript 复制代码
export class AppComponent implements OnInit {
  // 数据属性
  products: Product[] = [];
  filteredProducts: Product[] = [];
  searchText = '';
  showProductModal = false;
  
  // 表单相关
  isEditMode = false;
  editingProductId: number | null = null;
  productForm: ProductFormData = { /* ... */ };

  // 下拉选项
  categories = [/* ... */];
  statusOptions = [/* ... */];
  languages = [/* ... */];

  // 核心方法
  ngOnInit(): void { /* 订阅数据 */ }
  onSearch(): void { /* 搜索过滤 */ }
  openAddModal(): void { /* 打开添加表单 */ }
  openEditModal(product: Product): void { /* 打开编辑表单 */ }
  submitForm(): void { /* 提交表单 */ }
  deleteProduct(product: Product): void { /* 删除商品 */ }
  changeLanguage(lang: Language): void { /* 切换语言 */ }
}

模板结构 (app.component.html)

html 复制代码
<d-layout>
  <d-header><!-- 头部:标题 + 语言切换 --></d-header>
  <d-content>
    <!-- 工具栏:添加按钮 + 搜索框 -->
    <!-- 商品列表表格 -->
    <!-- 表格底部统计 -->
  </d-content>
</d-layout>

<!-- 商品表单模态框 -->
<div class="modal-overlay" *ngIf="showProductModal">
  <!-- 表单内容 -->
</div>

总结与扩展

🎉 恭喜完成!

通过本教程,你已经学会了:

  1. Angular 18 项目搭建 - 使用 CLI 创建和配置项目
  2. DevUI 组件库集成 - 安装和使用 DevUI 组件
  3. 数据模型设计 - TypeScript 接口定义
  4. 服务层开发 - 使用 RxJS 管理状态
  5. 国际化实现 - 多语言切换功能
  6. CRUD 操作 - 完整的增删改查功能
  7. 响应式设计 - 适配多种屏幕尺寸
  8. 用户体验优化 - Toast 提示、确认对话框等

🚀 扩展建议

功能扩展
  • 分页功能 - 使用 DevUI 的 Pagination 组件
  • 批量操作 - 添加复选框和批量删除
  • 数据导出 - 导出为 Excel 或 CSV
  • 图片上传 - 为商品添加图片
  • 权限管理 - 添加用户登录和权限控制
  • 数据统计 - 使用图表展示销售数据
技术优化
  • 状态管理 - 集成 NgRx 或 Akita
  • 后端集成 - 连接真实的 REST API
  • 单元测试 - 使用 Jasmine 和 Karma
  • E2E 测试 - 使用 Cypress 或 Playwright
  • PWA 支持 - 添加离线功能
  • 性能优化 - 虚拟滚动、懒加载等

📚 学习资源

MateChat:https://gitcode.com/DevCloudFE/MateChat

MateChat官网:https://matechat.gitcode.com

DevUI官网:https://devui.design/home

💡 最佳实践

  1. 组件化开发 - 将大组件拆分为小组件
  2. 类型安全 - 充分利用 TypeScript 的类型系统
  3. 响应式编程 - 使用 Observable 而不是 Promise
  4. 代码复用 - 提取公共逻辑到服务或工具函数
  5. 性能优化 - 使用 OnPush 变更检测策略
  6. 可维护性 - 保持代码简洁,添加必要的注释

💡 效果图


源代码

https://gitcode.com/daleishen/DevUI

感谢学习本教程!完整详细的代码请查看项目源文件。如有问题,欢迎交流讨论。 🎓

相关推荐
崔庆才丨静觅12 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606113 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了13 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅13 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅14 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅14 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment14 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅14 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊15 小时前
jwt介绍
前端
爱敲代码的小鱼15 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax