const pool = require('../config/db'); const UserModel = { // 通过openid查找或创建用户 async findOrCreate(openid, userInfo = {}) { const [existing] = await pool.query( 'SELECT * FROM users WHERE openid = ?', [openid] ); if (existing.length > 0) { return existing[0]; } // 创建新用户 const [result] = await pool.query( 'INSERT INTO users (openid, nickname, avatar_url, gender) VALUES (?, ?, ?, ?)', [openid, userInfo.nickname || '', userInfo.avatarUrl || '', userInfo.gender || 0] ); return { id: result.insertId, openid, nickname: userInfo.nickname || '', avatar_url: userInfo.avatarUrl || '', gender: userInfo.gender || 0 }; }, // 更新用户信息 async updateProfile(userId, userInfo) { await pool.query( 'UPDATE users SET nickname = ?, avatar_url = ?, gender = ? WHERE id = ?', [userInfo.nickname, userInfo.avatarUrl, userInfo.gender, userId] ); }, // 获取用户进度 async getProgress(userId, storyId = null) { let sql = `SELECT up.*, s.title as story_title, s.cover_url FROM user_progress up JOIN stories s ON up.story_id = s.id WHERE up.user_id = ?`; const params = [userId]; if (storyId) { sql += ' AND up.story_id = ?'; params.push(storyId); } sql += ' ORDER BY up.updated_at DESC'; const [rows] = await pool.query(sql, params); return storyId ? rows[0] : rows; }, // 保存用户进度 async saveProgress(userId, storyId, data) { const { currentNodeKey, isCompleted, endingReached } = data; await pool.query( `INSERT INTO user_progress (user_id, story_id, current_node_key, is_completed, ending_reached) VALUES (?, ?, ?, ?, ?) ON DUPLICATE KEY UPDATE current_node_key = VALUES(current_node_key), is_completed = VALUES(is_completed), ending_reached = VALUES(ending_reached), play_count = play_count + 1`, [userId, storyId, currentNodeKey, isCompleted || false, endingReached || ''] ); // 如果完成了,记录结局 if (isCompleted && endingReached) { await pool.query( `INSERT IGNORE INTO user_endings (user_id, story_id, ending_name) VALUES (?, ?, ?)`, [userId, storyId, endingReached] ); // 更新用户统计 await pool.query( 'UPDATE users SET total_play_count = total_play_count + 1, total_endings = (SELECT COUNT(*) FROM user_endings WHERE user_id = ?) WHERE id = ?', [userId, userId] ); } }, // 点赞/取消点赞 async toggleLike(userId, storyId, isLiked) { await pool.query( `INSERT INTO user_progress (user_id, story_id, is_liked) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE is_liked = ?`, [userId, storyId, isLiked, isLiked] ); }, // 收藏/取消收藏 async toggleCollect(userId, storyId, isCollected) { await pool.query( `INSERT INTO user_progress (user_id, story_id, is_collected) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE is_collected = ?`, [userId, storyId, isCollected, isCollected] ); }, // 获取收藏列表 async getCollections(userId) { const [rows] = await pool.query( `SELECT s.id, s.title, s.cover_url, s.description, s.category, s.play_count, s.like_count FROM user_progress up JOIN stories s ON up.story_id = s.id WHERE up.user_id = ? AND up.is_collected = 1 ORDER BY up.updated_at DESC`, [userId] ); return rows; }, // 获取用户解锁的结局 async getUnlockedEndings(userId, storyId = null) { let sql = 'SELECT * FROM user_endings WHERE user_id = ?'; const params = [userId]; if (storyId) { sql += ' AND story_id = ?'; params.push(storyId); } const [rows] = await pool.query(sql, params); return rows; }, // 获取我的作品 async getMyWorks(userId) { try { const [rows] = await pool.query( `SELECT id, title, description, category, cover_url, play_count, like_count, comment_count, status, created_at, updated_at, COALESCE(earnings, 0) as earnings FROM stories WHERE author_id = ? ORDER BY created_at DESC`, [userId] ); return rows; } catch (e) { // 表可能还没有author_id字段,返回空数组 return []; } }, // 获取草稿箱 async getDrafts(userId) { try { const [rows] = await pool.query( `SELECT id, title, category, node_count, source, created_at, updated_at FROM story_drafts WHERE user_id = ? ORDER BY updated_at DESC`, [userId] ); return rows; } catch (e) { // 表可能不存在,返回空数组 return []; } }, // 获取最近游玩 async getRecentPlayed(userId, limit = 10) { const [rows] = await pool.query( `SELECT s.id, s.title, s.category, s.description, s.cover_url, up.current_node_key, up.is_completed, CASE WHEN up.is_completed THEN '已完成' ELSE '进行中' END as progress FROM user_progress up JOIN stories s ON up.story_id = s.id WHERE up.user_id = ? ORDER BY up.updated_at DESC LIMIT ?`, [userId, limit] ); return rows; }, // 获取AI创作历史 async getAIHistory(userId, limit = 20) { try { const [rows] = await pool.query( `SELECT id, gen_type, input_prompt, output_content, status, created_at FROM ai_generations WHERE user_id = ? ORDER BY created_at DESC LIMIT ?`, [userId, limit] ); return rows; } catch (e) { return []; } }, // 获取AI配额 async getAIQuota(userId) { try { const [rows] = await pool.query( `SELECT daily_free_total as daily, daily_free_used as used, purchased_quota as purchased, gift_quota as gift FROM user_ai_quota WHERE user_id = ?`, [userId] ); if (rows.length > 0) { return rows[0]; } // 没有记录则返回默认值 return { daily: 3, used: 0, purchased: 0, gift: 0 }; } catch (e) { return { daily: 3, used: 0, purchased: 0, gift: 0 }; } } }; module.exports = UserModel;