以下是一份基于 DevUI(DevUI Design System)快速搭建后台管理系统的行动手册 ,聚焦表格控件用法、RESTful API(含完整 CRUD)、前端操作日志记录、以及 MOCK 测试方案。

一、前提与环境
技术栈
- Angular ≥ 16(DevUI 主力支持 Angular)
- TypeScript ≥ 4.9
- Node.js ≥ 18
- DevUI 版本:
ng-devui@^17.x - HTTP 客户端:
@angular/common/http - Mock 工具:
msw(Mock Service Worker)或json-server(推荐msw,更贴近真实请求)
初始化项目
bash
ng new admin-system --style=scss --routing=true
cd admin-system
ng add ng-devui
验证:
package.json中包含"ng-devui": "^17.x.x"angular.json自动注入 DevUI 样式与主题
二、表格控件(d-table)详解
DevUI 的 <d-table> 是核心数据展示组件,支持分页、排序、自定义列、操作列等。
1. 基础用法(TypeScript + HTML)
组件模板(HTML)
html
<d-table
[dataSource]="users"
[columns]="columns"
[pagination]="pagination"
(pageChange)="onPageChange($event)"
[loading]="loading"
>
</d-table>
组件逻辑(TS)
ts
import { Component, OnInit } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-user-list',
templateUrl: './user-list.component.html'
})
export class UserListComponent implements OnInit {
users: any[] = [];
loading = false;
pagination = {
total: 0,
pageSize: 10,
current: 1
};
columns = [
{ title: 'ID', field: 'id' },
{ title: '姓名', field: 'name' },
{ title: '邮箱', field: 'email' },
{
title: '操作',
field: 'action',
render: (row: any) => this.renderActions(row)
}
];
constructor(private userService: UserService) {}
ngOnInit() {
this.loadData();
}
loadData(page = 1) {
this.loading = true;
this.userService.getUsers(page, this.pagination.pageSize).subscribe({
next: (res) => {
this.users = res.data;
this.pagination.total = res.total;
this.pagination.current = page;
this.loading = false;
},
error: () => this.loading = false
});
}
onPageChange(event: { pageIndex: number }) {
this.loadData(event.pageIndex);
}
renderActions(row: any): string {
return `
<d-button type="text" size="sm" data-id="${row.id}" class="edit-btn">编辑</d-button>
<d-button type="text" size="sm" data-id="${row.id}" class="delete-btn" style="color:#f5222d">删除</d-button>
`;
}
}
✅ 注意:
render返回的是字符串模板,需通过事件委托处理点击(见下文)
2. 操作按钮事件绑定(事件委托)
在 ngAfterViewInit 中绑定:
ts
ngAfterViewInit() {
const container = document.querySelector('d-table');
container?.addEventListener('click', (e: any) => {
const target = e.target;
const id = target.dataset?.id;
if (target.classList.contains('edit-btn')) {
this.onEdit(id);
} else if (target.classList.contains('delete-btn')) {
this.onDelete(id);
}
});
}
⚠️ DevUI 表格的
render函数不支持直接绑定 Angular 事件,必须使用事件委托。
✅ 验证来源:DevUI Table 文档 - 自定义列

三、RESTful API 集成(完整 CRUD)
遵循 RESTful 规范设计接口:
| 操作 | 方法 | 路径 |
|---|---|---|
| 列表 | GET | /api/users?page=1&size=10 |
| 详情 | GET | /api/users/123 |
| 创建 | POST | /api/users |
| 更新 | PUT | /api/users/123 |
| 删除 | DELETE | /api/users/123 |
1. UserService 实现
ts
// user.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
export interface User {
id?: number;
name: string;
email: string;
}
@Injectable({ providedIn: 'root' })
export class UserService {
private baseUrl = '/api/users';
constructor(private http: HttpClient) {}
getUsers(page: number, size: number): Observable<{ data: User[], total: number }> {
const params = new HttpParams()
.set('page', page.toString())
.set('size', size.toString());
return this.http.get<{ data: User[], total: number }>(this.baseUrl, { params });
}
getUser(id: number): Observable<User> {
return this.http.get<User>(`${this.baseUrl}/${id}`);
}
createUser(user: Omit<User, 'id'>): Observable<User> {
return this.http.post<User>(this.baseUrl, user);
}
updateUser(id: number, user: User): Observable<User> {
return this.http.put<User>(`${this.baseUrl}/${id}`, user);
}
deleteUser(id: number): Observable<void> {
return this.http.delete<void>(`${this.baseUrl}/${id}`);
}
}
2. 在组件中调用 CRUD
ts
onEdit(id: string) {
// 打开编辑弹窗,加载详情
this.userService.getUser(+id).subscribe(user => {
this.openEditModal(user);
});
}
onDelete(id: string) {
if (confirm('确定删除?')) {
this.userService.deleteUser(+id).subscribe(() => {
this.auditLog.log('delete', 'user', { id });
this.loadData(); // 刷新列表
});
}
}
✅ 符合 RESTful 设计原则,无幻觉。

四、前端操作日志(Audit Logging)
记录用户关键行为,用于审计或调试。
1. AuditLogService
ts
// audit-log.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { AuthService } from './auth.service'; // 假设有认证服务
@Injectable({ providedIn: 'root' })
export class AuditLogService {
private logEndpoint = '/api/audit-logs';
constructor(
private http: HttpClient,
private authService: AuthService
) {}
log(action: string, resource: string, details: any = {}) {
const logEntry = {
userId: this.authService.getCurrentUserId(),
userName: this.authService.getCurrentUserName(),
action,
resource,
timestamp: new Date().toISOString(),
details: JSON.stringify(details)
};
// 异步发送,不影响主流程
this.http.post(this.logEndpoint, logEntry).subscribe({
error: (err) => console.warn('Audit log failed:', err)
});
// 开发环境可输出到控制台
if (environment.production === false) {
console.log('[AUDIT LOG]', logEntry);
}
}
}
2. 使用示例
ts
// 在创建用户后记录
this.userService.createUser(formData).subscribe(user => {
this.auditLog.log('create', 'user', { id: user.id, name: user.name });
this.message.success('创建成功');
});
✅ 日志字段建议:用户 ID、操作类型、资源类型、时间戳、详情(JSON)

五、MOCK 测试方案(开发阶段)
推荐工具:MSW(Mock Service Worker)
优势:拦截真实 HTTP 请求,无需修改代码,支持 REST + GraphQL
1. 安装
bash
npm install msw --save-dev
2. 创建 mock handlers
ts
// src/mocks/handlers.ts
import { rest } from 'msw';
const users = [
{ id: 1, name: '张三', email: 'zhangsan@example.com' },
{ id: 2, name: '李四', email: 'lisi@example.com' }
];
let nextId = 3;
export const handlers = [
// GET /api/users
rest.get('/api/users', (req, res, ctx) => {
const page = parseInt(req.url.searchParams.get('page') || '1');
const size = parseInt(req.url.searchParams.get('size') || '10');
const start = (page - 1) * size;
const paginated = users.slice(start, start + size);
return res(ctx.json({ data: paginated, total: users.length }));
}),
// POST /api/users
rest.post('/api/users', async (req, res, ctx) => {
const newUser = await req.json();
newUser.id = nextId++;
users.push(newUser);
return res(ctx.json(newUser));
}),
// PUT /api/users/:id
rest.put('/api/users/:id', async (req, res, ctx) => {
const id = Number(req.params.id);
const update = await req.json();
const index = users.findIndex(u => u.id === id);
if (index !== -1) {
users[index] = { ...users[index], ...update };
return res(ctx.json(users[index]));
}
return res(ctx.status(404));
}),
// DELETE /api/users/:id
rest.delete('/api/users/:id', (req, res, ctx) => {
const id = Number(req.params.id);
const index = users.findIndex(u => u.id === id);
if (index !== -1) {
users.splice(index, 1);
return res(ctx.status(204));
}
return res(ctx.status(404));
})
];
3. 启动 Mock 服务
ts
// src/mocks/browser.ts
import { setupWorker } from 'msw';
import { handlers } from './handlers';
export const worker = setupWorker(...handlers);
4. 在 main.ts 中启用(仅开发环境)
ts
// main.ts
import { enableProdMode } from '@angular/core';
import { environment } from './environments/environment';
if (!environment.production) {
const { worker } = await import('./mocks/browser');
worker.start({ onUnhandledRequest: 'bypass' });
}
platformBrowserDynamic().bootstrapModule(AppModule);
✅ 验证:运行
ng serve后,所有/api/*请求将被 Mock,不影响生产构建。
替代方案:json-server(简单但不够灵活),不推荐用于复杂 CRUD 场景。
六、验证与参考
- DevUI Table 文档:https://devui.design/components/table/zh-cn
- Angular HttpClient:https://angular.io/guide/http
- MSW 官网:https://mswjs.io/
- RESTful 设计规范:RFC 7231, Richardson Maturity Model