package store import ( "database/sql" "fmt" "time" _ "github.com/lib/pq" ) // User 用户模型 type User struct { ID int `json:"id"` Username string `json:"username"` Nickname string `json:"nickname"` PasswordHash string `json:"-"` IsAdmin bool `json:"is_admin"` CreatedAt time.Time `json:"created_at"` UpdatedAt time.Time `json:"updated_at"` } // CreateUsersTable 创建 users 表(如果不存在) func CreateUsersTable(db *sql.DB) error { query := `CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(255) UNIQUE NOT NULL, nickname VARCHAR(255) DEFAULT '', password_hash VARCHAR(255) NOT NULL, is_admin BOOLEAN DEFAULT FALSE, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() )` if _, err := db.Exec(query); err != nil { return fmt.Errorf("创建 users 表失败: %w", err) } // 迁移:为已有 users 表添加 nickname 列 db.Exec(`ALTER TABLE users ADD COLUMN IF NOT EXISTS nickname VARCHAR(255) DEFAULT ''`) // 创建索引 indexQueries := []string{ `CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)`, } for _, q := range indexQueries { if _, err := db.Exec(q); err != nil { return fmt.Errorf("创建 users 索引失败: %w", err) } } return nil } // GetUserByUsername 按用户名查询用户 // 如果用户不存在,返回 (nil, nil) func GetUserByUsername(db *sql.DB, username string) (*User, error) { var u User err := db.QueryRow( `SELECT id, username, COALESCE(nickname, '') as nickname, password_hash, is_admin, created_at, updated_at FROM users WHERE username = $1`, username, ).Scan(&u.ID, &u.Username, &u.Nickname, &u.PasswordHash, &u.IsAdmin, &u.CreatedAt, &u.UpdatedAt) if err == sql.ErrNoRows { return nil, nil } if err != nil { return nil, fmt.Errorf("查询用户失败: %w", err) } return &u, nil } // ListUsers 列出所有用户 func ListUsers(db *sql.DB) ([]User, error) { rows, err := db.Query( `SELECT id, username, COALESCE(nickname, '') as nickname, password_hash, is_admin, created_at, updated_at FROM users ORDER BY id`, ) if err != nil { return nil, fmt.Errorf("查询用户列表失败: %w", err) } defer rows.Close() var users []User for rows.Next() { var u User if err := rows.Scan(&u.ID, &u.Username, &u.Nickname, &u.PasswordHash, &u.IsAdmin, &u.CreatedAt, &u.UpdatedAt); err != nil { return nil, fmt.Errorf("扫描用户行失败: %w", err) } users = append(users, u) } if err := rows.Err(); err != nil { return nil, fmt.Errorf("遍历用户行出错: %w", err) } if users == nil { users = []User{} } return users, nil } // DeleteUser 按 ID 删除用户 func DeleteUser(db *sql.DB, userID int) error { result, err := db.Exec(`DELETE FROM users WHERE id = $1`, userID) if err != nil { return fmt.Errorf("删除用户失败: %w", err) } affected, _ := result.RowsAffected() if affected == 0 { return fmt.Errorf("用户不存在 (id=%d)", userID) } return nil } // CreateUser 创建新用户 func CreateUser(db *sql.DB, username, nickname, passwordHash string, isAdmin bool) (*User, error) { now := time.Now() var u User err := db.QueryRow( `INSERT INTO users (username, nickname, password_hash, is_admin, created_at, updated_at) VALUES ($1, $2, $3, $4, $5, $5) ON CONFLICT (username) DO UPDATE SET nickname = $2, updated_at = $5 RETURNING id, username, COALESCE(nickname, '') as nickname, password_hash, is_admin, created_at, updated_at`, username, nickname, passwordHash, isAdmin, now, ).Scan(&u.ID, &u.Username, &u.Nickname, &u.PasswordHash, &u.IsAdmin, &u.CreatedAt, &u.UpdatedAt) if err != nil { return nil, fmt.Errorf("创建用户失败: %w", err) } return &u, nil }