- 配置 pnpm workspace + Turborepo - 创建 Next.js 15 前端应用 (apps/web) - 创建 NestJS 10 后端应用 (apps/api) - 集成 Prisma ORM + Swagger + JWT 认证 - 添加共享包 (packages/shared, eslint-config, typescript-config) - 添加项目文档 (README, CLAUDE.md, docs/design.md) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
76 lines
2.2 KiB
TypeScript
76 lines
2.2 KiB
TypeScript
// 日期格式化
|
|
export function formatDate(date: Date | string, format = 'YYYY-MM-DD'): string {
|
|
const d = typeof date === 'string' ? new Date(date) : date;
|
|
const year = d.getFullYear();
|
|
const month = String(d.getMonth() + 1).padStart(2, '0');
|
|
const day = String(d.getDate()).padStart(2, '0');
|
|
const hours = String(d.getHours()).padStart(2, '0');
|
|
const minutes = String(d.getMinutes()).padStart(2, '0');
|
|
const seconds = String(d.getSeconds()).padStart(2, '0');
|
|
|
|
return format
|
|
.replace('YYYY', String(year))
|
|
.replace('MM', month)
|
|
.replace('DD', day)
|
|
.replace('HH', hours)
|
|
.replace('mm', minutes)
|
|
.replace('ss', seconds);
|
|
}
|
|
|
|
// 延迟函数
|
|
export function delay(ms: number): Promise<void> {
|
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
}
|
|
|
|
// 生成随机 ID
|
|
export function generateId(length = 12): string {
|
|
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
|
let result = '';
|
|
for (let i = 0; i < length; i++) {
|
|
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
}
|
|
return result;
|
|
}
|
|
|
|
// 深拷贝
|
|
export function deepClone<T>(obj: T): T {
|
|
if (obj === null || typeof obj !== 'object') {
|
|
return obj;
|
|
}
|
|
return JSON.parse(JSON.stringify(obj));
|
|
}
|
|
|
|
// 判断是否为空对象
|
|
export function isEmpty(obj: unknown): boolean {
|
|
if (obj === null || obj === undefined) return true;
|
|
if (typeof obj === 'string') return obj.trim().length === 0;
|
|
if (Array.isArray(obj)) return obj.length === 0;
|
|
if (typeof obj === 'object') return Object.keys(obj).length === 0;
|
|
return false;
|
|
}
|
|
|
|
// 安全解析 JSON
|
|
export function safeJsonParse<T>(json: string, fallback: T): T {
|
|
try {
|
|
return JSON.parse(json) as T;
|
|
} catch {
|
|
return fallback;
|
|
}
|
|
}
|
|
|
|
// 首字母大写
|
|
export function capitalize(str: string): string {
|
|
if (!str) return '';
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
|
|
// 驼峰转短横线
|
|
export function camelToKebab(str: string): string {
|
|
return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
|
|
}
|
|
|
|
// 短横线转驼峰
|
|
export function kebabToCamel(str: string): string {
|
|
return str.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
|
|
}
|