UUID生成技能Skill uuid

UUID生成技能是一个用于在JavaScript/TypeScript应用程序中生成符合RFC9562标准的通用唯一标识符的工具库。该技能提供UUID v4(随机生成)和v7(基于时间戳可排序)两种版本,适用于分布式系统中的实体ID生成、数据库主键、会话管理、文件上传跟踪、审计日志等场景。关键词:UUID生成、唯一标识符、JavaScript开发、TypeScript、分布式系统、数据库主键、实体ID、RFC9562、v4 UUID、v7 UUID、Angular开发、Firestore集成。

前端开发 0 次安装 0 次浏览 更新于 2/28/2026

name: uuid description: ‘UUID生成技能 - 用于实体ID的通用唯一标识符v4和v7版本。适用于ng-events建筑工地进度跟踪系统。’

UUID - 通用唯一标识符

触发模式:“UUID”、“唯一ID”、“标识符”、“v4”、“v7”、“uuidv4”、“uuidv7”

概述

用于在JavaScript/TypeScript应用程序中生成符合RFC9562标准的唯一标识符的UUID库。

: uuid@13.0.0
标准: RFC9562(原RFC4122)

核心功能

1. v4() - 随机UUID(最常用)

使用加密安全随机值生成版本4 UUID。

import { v4 as uuidv4 } from 'uuid';

// 生成随机UUID
const taskId = uuidv4();
// '9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d'

// 在实体创建中使用
interface Task {
  id: string;
  title: string;
  createdAt: Date;
}

function createTask(title: string): Task {
  return {
    id: uuidv4(),
    title,
    createdAt: new Date()
  };
}

使用场景:

  • 实体ID(任务、用户、蓝图)
  • 会话ID
  • 请求跟踪ID
  • 文件上传ID
  • 任何需要唯一标识符的场景

2. v7() - 基于时间戳的UUID(可排序)

生成版本7 UUID,包含Unix时间戳,支持自然时间顺序排序。

import { v7 as uuidv7 } from 'uuid';

// 生成基于时间戳的UUID
const orderId = uuidv7();
// '019a26ab-9a66-71a9-a89e-63c35fce4a5a'

// 多个UUID自然按时间排序
const ids = Array.from({ length: 5 }, () => uuidv7());
// 所有ID将按时间顺序排列

// 用于数据库主键
interface Order {
  id: string; // v7 UUID - 按创建时间排序
  customerId: string;
  createdAt: Date;
}

使用场景:

  • 需要时间顺序排序的数据库主键
  • 时间序列数据中的事件ID
  • 日志条目ID
  • 审计跟踪记录
  • 任何时间顺序重要的场景

优势:

  • 按创建时间自然排序
  • 更好的数据库索引性能
  • 减少B树索引碎片
  • 在存储/API中与UUID v4兼容

实际应用示例

使用UUID的任务仓库

import { Injectable, inject } from '@angular/core';
import { Firestore, collection, doc, setDoc, getDoc } from '@angular/fire/firestore';
import { v4 as uuidv4 } from 'uuid';

export interface Task {
  id: string;
  blueprintId: string;
  title: string;
  description: string;
  status: 'pending' | 'in-progress' | 'completed';
  createdAt: Date;
  updatedAt: Date;
}

@Injectable({ providedIn: 'root' })
export class TaskRepository {
  private firestore = inject(Firestore);
  private tasksCollection = collection(this.firestore, 'tasks');
  
  /**
   * 使用UUID v4创建任务
   */
  async create(task: Omit<Task, 'id' | 'createdAt' | 'updatedAt'>): Promise<Task> {
    const id = uuidv4(); // 生成唯一ID
    const now = new Date();
    
    const newTask: Task = {
      ...task,
      id,
      createdAt: now,
      updatedAt: now
    };
    
    const docRef = doc(this.tasksCollection, id);
    await setDoc(docRef, newTask);
    
    return newTask;
  }
  
  /**
   * 通过UUID查找任务
   */
  async findById(id: string): Promise<Task | null> {
    const docRef = doc(this.tasksCollection, id);
    const snapshot = await getDoc(docRef);
    
    if (!snapshot.exists()) {
      return null;
    }
    
    return { id: snapshot.id, ...snapshot.data() } as Task;
  }
}

使用UUID v7的审计日志

import { Injectable, inject } from '@angular/core';
import { Firestore, collection, doc, setDoc } from '@angular/fire/firestore';
import { v7 as uuidv7 } from 'uuid';

export interface AuditLog {
  id: string; // 用于时间排序的v7 UUID
  userId: string;
  action: string;
  resource: string;
  resourceId: string;
  timestamp: Date;
  metadata?: Record<string, any>;
}

@Injectable({ providedIn: 'root' })
export class AuditLogRepository {
  private firestore = inject(Firestore);
  private logsCollection = collection(this.firestore, 'auditLogs');
  
  /**
   * 使用v7 UUID创建审计日志(按时间排序)
   */
  async log(
    userId: string,
    action: string,
    resource: string,
    resourceId: string,
    metadata?: Record<string, any>
  ): Promise<AuditLog> {
    const id = uuidv7(); // 基于时间戳的UUID
    
    const log: AuditLog = {
      id,
      userId,
      action,
      resource,
      resourceId,
      timestamp: new Date(),
      metadata
    };
    
    const docRef = doc(this.logsCollection, id);
    await setDoc(docRef, log);
    
    return log;
  }
}

会话管理

import { Injectable } from '@angular/core';
import { v4 as uuidv4 } from 'uuid';

export interface Session {
  id: string;
  userId: string;
  token: string;
  createdAt: Date;
  expiresAt: Date;
}

@Injectable({ providedIn: 'root' })
export class SessionService {
  private sessions = new Map<string, Session>();
  
  /**
   * 使用UUID创建新会话
   */
  createSession(userId: string, expiresInMs: number = 3600000): Session {
    const sessionId = uuidv4();
    const now = new Date();
    
    const session: Session = {
      id: sessionId,
      userId,
      token: this.generateToken(),
      createdAt: now,
      expiresAt: new Date(now.getTime() + expiresInMs)
    };
    
    this.sessions.set(sessionId, session);
    return session;
  }
  
  /**
   * 通过ID获取会话
   */
  getSession(sessionId: string): Session | null {
    return this.sessions.get(sessionId) || null;
  }
  
  private generateToken(): string {
    return uuidv4(); // 使用UUID作为令牌
  }
}

文件上传跟踪

import { Injectable, signal } from '@angular/core';
import { v4 as uuidv4 } from 'uuid';

export interface FileUpload {
  id: string;
  fileName: string;
  fileSize: number;
  uploadedBy: string;
  uploadedAt: Date;
  status: 'pending' | 'uploading' | 'completed' | 'failed';
  progress: number;
  url?: string;
}

@Injectable({ providedIn: 'root' })
export class FileUploadService {
  private uploads = signal<Map<string, FileUpload>>(new Map());
  
  /**
   * 使用UUID跟踪开始文件上传
   */
  startUpload(file: File, userId: string): string {
    const uploadId = uuidv4();
    
    const upload: FileUpload = {
      id: uploadId,
      fileName: file.name,
      fileSize: file.size,
      uploadedBy: userId,
      uploadedAt: new Date(),
      status: 'pending',
      progress: 0
    };
    
    this.uploads.update(map => {
      map.set(uploadId, upload);
      return new Map(map);
    });
    
    return uploadId;
  }
  
  /**
   * 更新上传进度
   */
  updateProgress(uploadId: string, progress: number): void {
    this.uploads.update(map => {
      const upload = map.get(uploadId);
      if (upload) {
        upload.progress = progress;
        upload.status = progress === 100 ? 'completed' : 'uploading';
        map.set(uploadId, upload);
      }
      return new Map(map);
    });
  }
  
  /**
   * 通过ID获取上传信息
   */
  getUpload(uploadId: string): FileUpload | undefined {
    return this.uploads().get(uploadId);
  }
}

最佳实践

1. 通用用途用v4,时间序列用v7

应该: 根据使用场景选择

// 通用实体ID - 使用v4
const taskId = uuidv4();
const userId = uuidv4();

// 时间序列或可排序ID - 使用v7
const logId = uuidv7();
const eventId = uuidv7();

2. 使用TypeScript类型

应该: 定义UUID品牌类型以确保安全

type UUID = string & { readonly __brand: unique symbol };

interface Task {
  id: UUID;
  title: string;
}

function createTaskId(): UUID {
  return uuidv4() as UUID;
}

3. 验证UUID

应该: 验证UUID格式

import { validate as uuidValidate, version as uuidVersion } from 'uuid';

function isValidUUID(id: string): boolean {
  return uuidValidate(id);
}

function isV4UUID(id: string): boolean {
  return uuidValidate(id) && uuidVersion(id) === 4;
}

function isV7UUID(id: string): boolean {
  return uuidValidate(id) && uuidVersion(id) === 7;
}

4. 不要将UUID存储为二进制(Firestore)

应该: 在Firestore中存储为字符串

// Firestore自动索引字符串ID
await setDoc(doc(collection, taskId), { /* 数据 */ });

不应该: 在Firestore中转换为二进制

// Firestore中不必要的复杂性
const binaryId = Buffer.from(taskId.replace(/-/g, ''), 'hex');

性能考虑

  1. 生成速度: v4比v7稍快
  2. 索引性能: v7提供更好的数据库索引局部性
  3. 存储: 两者都需要36字节作为字符串(128位+连字符)
  4. 碰撞概率: 两个版本实际上为零

CLI使用

# 生成v4 UUID
$ npx uuid
ddeb27fb-d9a0-4624-be4d-4615062daed4

# 生成v7 UUID
$ npx uuid v7
019a26ab-9a66-71a9-a89e-63c35fce4a5a

# 生成多个UUID
$ npx uuid && npx uuid && npx uuid

集成检查清单

  • [ ] 安装 uuid@13.0.0
  • [ ] 根据使用场景导入v4或v7
  • [ ] 在仓库中用于实体ID
  • [ ] 从外部源接收时验证UUID
  • [ ] 在Firestore中存储为字符串
  • [ ] 添加TypeScript类型以确保类型安全
  • [ ] 在代码注释中记录UUID版本选择

反模式

在分布式系统中使用顺序ID:

let counter = 0;
const id = `task-${++counter}`; // 竞态条件,非全局唯一

使用UUID:

const id = uuidv4(); // 全局唯一,无需协调

手动解析UUID部分:

const timestamp = parseInt(uuid.substring(0, 8), 16); // 脆弱

使用库函数:

import { parse, version } from 'uuid';
const ver = version(uuid); // 正确解析

为安全关键操作在客户端生成UUID:

const sessionToken = uuidv4(); // 如果未正确种子化,可预测

在服务器端生成安全令牌:

// Firebase Auth安全处理令牌生成
const token = await auth.currentUser.getIdToken();

交叉引用

  • firebase-repository - 实体ID的UUID
  • blueprint-integration - 蓝图和成员ID
  • event-bus-integration - 事件ID生成
  • angular-component - 组件状态中的UUID

包信息


版本: 1.0
创建时间: 2025-12-25
维护者: ng-events(GigHub) 开发团队