import { v4 as uuidv4 } from 'uuid'; import { query, run, get } from '../database'; export interface User { id: string; name: string; phone: string; password?: string; createdAt: string; } export interface CreateUserData { name: string; phone: string; password?: string; } export class UserModel { static async create(data: CreateUserData): Promise { const id = uuidv4(); const sql = ` INSERT INTO users (id, name, phone, password) VALUES (?, ?, ?, ?) `; try { await run(sql, [id, data.name, data.phone, data.password || '']); return this.findById(id) as Promise; } catch (error: any) { if (error.code === 'SQLITE_CONSTRAINT_UNIQUE') { throw new Error('手机号已存在'); } throw error; } } static async updatePasswordById(id: string, password: string): Promise { const sql = `UPDATE users SET password = ? WHERE id = ?`; await run(sql, [password, id]); } static async delete(id: string): Promise { await run(`DELETE FROM users WHERE id = ?`, [id]); } // 更新用户信息 static async update(id: string, data: Partial): Promise { // 验证数据 const errors = this.validateUserData(data as CreateUserData); if (errors.length > 0) { throw new Error(errors.join(', ')); } // 检查手机号唯一性 if (data.phone !== undefined) { const existingUser = await this.findByPhone(data.phone); if (existingUser && existingUser.id !== id) { throw new Error('手机号已存在'); } } // 构建更新字段 const fields: string[] = []; const values: any[] = []; if (data.name !== undefined) { fields.push('name = ?'); values.push(data.name); } if (data.phone !== undefined) { fields.push('phone = ?'); values.push(data.phone); } if (data.password !== undefined) { fields.push('password = ?'); values.push(data.password); } if (fields.length === 0) { return this.findById(id) as Promise; } values.push(id); const sql = `UPDATE users SET ${fields.join(', ')} WHERE id = ?`; await run(sql, values); const updatedUser = await this.findById(id); if (!updatedUser) { throw new Error('用户不存在'); } return updatedUser; } static async findById(id: string): Promise { const sql = `SELECT id, name, phone, password, created_at as createdAt FROM users WHERE id = ?`; const user = await get(sql, [id]); return user || null; } static async findByPhone(phone: string): Promise { const sql = `SELECT id, name, phone, password, created_at as createdAt FROM users WHERE phone = ?`; const user = await get(sql, [phone]); return user || null; } static async findByName(name: string): Promise { const sql = `SELECT id, name, phone, password, created_at as createdAt FROM users WHERE name = ?`; const users = await query(sql, [name]); return users || []; } static async findAll(limit = 10, offset = 0): Promise<{ users: User[]; total: number }> { const usersSql = ` SELECT id, name, phone, password, created_at as createdAt FROM users ORDER BY created_at DESC LIMIT ? OFFSET ? `; const countSql = `SELECT COUNT(*) as total FROM users`; const [users, countResult] = await Promise.all([ query(usersSql, [limit, offset]), get(countSql) ]); return { users, total: countResult.total }; } // 验证用户数据,支持部分数据验证 static validateUserData(data: Partial): string[] { const errors: string[] = []; // 只验证提供了的数据 if (data.name !== undefined) { if (data.name.length < 2 || data.name.length > 20) { errors.push('姓名长度必须在2-20个字符之间'); } } if (data.phone !== undefined) { if (!/^1[3-9]\d{9}$/.test(data.phone)) { errors.push('手机号格式不正确,请输入11位中国手机号'); } } return errors; } }