阅读量:0
一直正开发时,又优化了相关的表,现在的表结构为:
/* Navicat Premium Data Transfer Source Server : localhost Source Server Type : MySQL Source Server Version : 80012 (8.0.12) Source Host : localhost:3306 Source Schema : chat Target Server Type : MySQL Target Server Version : 80012 (8.0.12) File Encoding : 65001 Date: 03/08/2024 19:27:31 */ SET NAMES utf8mb4; SET FOREIGN_KEY_CHECKS = 0; -- ---------------------------- -- Table structure for blacklists -- ---------------------------- DROP TABLE IF EXISTS `blacklists`; CREATE TABLE `blacklists` ( `user_id` int(11) NULL DEFAULT NULL, `blocked_user_id` int(11) NULL DEFAULT NULL, `created_at` datetime NULL DEFAULT NULL, INDEX `user_id`(`user_id` ASC) USING BTREE, INDEX `blocked_user_id`(`blocked_user_id` ASC) USING BTREE, CONSTRAINT `blacklists_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `blacklists_ibfk_2` FOREIGN KEY (`blocked_user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for chatgroups -- ---------------------------- DROP TABLE IF EXISTS `chatgroups`; CREATE TABLE `chatgroups` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `description` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `avatar_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `owner_id` int(11) NULL DEFAULT NULL, `created_at` datetime NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `owner_id`(`owner_id` ASC) USING BTREE, CONSTRAINT `chatgroups_ibfk_1` FOREIGN KEY (`owner_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB AUTO_INCREMENT = 10 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for friends -- ---------------------------- DROP TABLE IF EXISTS `friends`; CREATE TABLE `friends` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NULL DEFAULT NULL, `group_friend_id` int(11) NULL DEFAULT NULL, `type` enum('user','group') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `status` enum('pending','accepted','blocked') CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'pending', `created_at` datetime NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `user_id`(`user_id` ASC) USING BTREE, CONSTRAINT `friends_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for invites -- ---------------------------- DROP TABLE IF EXISTS `invites`; CREATE TABLE `invites` ( `id` int(11) NOT NULL AUTO_INCREMENT, `inviter_id` int(11) NULL DEFAULT NULL, `invitee_id` int(11) NULL DEFAULT NULL, `group_id` int(11) NULL DEFAULT NULL, `group_avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `inviter_avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `invitee_avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `status` enum('pending','accepted','declined') CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'pending', `created_at` datetime NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, INDEX `inviter_id`(`inviter_id` ASC) USING BTREE, INDEX `invitee_id`(`invitee_id` ASC) USING BTREE, INDEX `group_id`(`group_id` ASC) USING BTREE, CONSTRAINT `invites_ibfk_1` FOREIGN KEY (`inviter_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `invites_ibfk_2` FOREIGN KEY (`invitee_id`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT, CONSTRAINT `invites_ibfk_3` FOREIGN KEY (`group_id`) REFERENCES `chatgroups` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for messages -- ---------------------------- DROP TABLE IF EXISTS `messages`; CREATE TABLE `messages` ( `id` int(11) NOT NULL AUTO_INCREMENT, `fid` int(11) NULL DEFAULT NULL, `tid` int(11) NULL DEFAULT NULL, `receiver_type` enum('user','group') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `type` enum('text','audio','video','image','join','left','broadcast','kick') CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `content` text CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `is_retracted` tinyint(1) NULL DEFAULT 0, `retracted_at` datetime NULL DEFAULT NULL, `created_at` datetime NULL DEFAULT NULL, `sn` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '唯一码', `group_name` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '用户名', PRIMARY KEY (`id`) USING BTREE, INDEX `sender_id`(`fid` ASC) USING BTREE, CONSTRAINT `messages_ibfk_1` FOREIGN KEY (`fid`) REFERENCES `users` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB AUTO_INCREMENT = 16 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -- ---------------------------- -- Table structure for users -- ---------------------------- DROP TABLE IF EXISTS `users`; CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `username` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `password` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL, `email` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `avatar_url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, `brief` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL, `created_at` datetime NULL DEFAULT NULL, PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `username`(`username` ASC) USING BTREE, UNIQUE INDEX `email`(`email` ASC) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 6 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; SET FOREIGN_KEY_CHECKS = 1;
用express 开发相关的model:
module.exports = (sequelize, DataTypes) => { const User = require('./User')(sequelize, DataTypes); // 确保 User 模型正确导入 const Blacklist = sequelize.define('Blacklist', { user_id: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, }, blocked_user_id: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, }, { timestamps: false, primaryKey: false, }); // 移除默认的主键 'id' Blacklist.removeAttribute('id'); return Blacklist; };
module.exports = (sequelize, DataTypes) => { const User = require('./User')(sequelize, DataTypes); // 确保 User 模型正确导入 const ChatGroup = sequelize.define('ChatGroup', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, name: { type: DataTypes.STRING(100), allowNull: false, }, description: { type: DataTypes.TEXT, }, avatar_url: { type: DataTypes.STRING(255), }, owner_id: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, }, { timestamps: false, }); return ChatGroup; };
module.exports = (sequelize, DataTypes) => { const User = require('./User')(sequelize, DataTypes); // 确保 User 模型正确导入 const Friend = sequelize.define('Friend', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, user_id: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, }, group_friend_id: { type: DataTypes.INTEGER, }, type: { type: DataTypes.ENUM('user', 'group'), allowNull: false, }, status: { type: DataTypes.ENUM('pending', 'accepted', 'blocked'), defaultValue: 'pending', }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, }, { timestamps: false, primaryKey: false, }); //Friend.removeAttribute('id'); return Friend; };
const Sequelize = require('sequelize'); const sequelize = new Sequelize('chat', 'root', 'asd123', { host: 'localhost', dialect: 'mysql', // 或 'postgres', 'sqlite', 'mssql' }); const User = require('./user')(sequelize, Sequelize.DataTypes); const Friend = require('./friend')(sequelize, Sequelize.DataTypes); const ChatGroup = require('./chatGroup')(sequelize, Sequelize.DataTypes); const Blacklist = require('./blacklist')(sequelize, Sequelize.DataTypes); const Invite = require('./invite')(sequelize, Sequelize.DataTypes); const Message = require('./message')(sequelize, Sequelize.DataTypes); const db = { sequelize, Sequelize, User, Friend, ChatGroup, Blacklist, Invite, Message }; module.exports = db;
module.exports = (sequelize, DataTypes) => { const User = require('./User')(sequelize, DataTypes); // 确保 User 模型正确导入 const ChatGroup = require('./ChatGroup')(sequelize, DataTypes); // 确保 ChatGroup 模型正确导入 const Invite = sequelize.define('Invite', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, inviter_id: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, }, invitee_id: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, }, group_id: { type: DataTypes.INTEGER, references: { model: ChatGroup, key: 'id', }, }, group_avatar: { type: DataTypes.STRING(255), }, inviter_avatar: { type: DataTypes.STRING(255), }, invitee_avatar: { type: DataTypes.STRING(255), }, status: { type: DataTypes.ENUM('pending', 'accepted', 'declined'), defaultValue: 'pending', }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, }, { timestamps: false, }); return Invite; };
module.exports = (sequelize, DataTypes) => { const User = require('./User')(sequelize, DataTypes); // 确保 User 模型正确导入 const ChatGroup = require('./ChatGroup')(sequelize, DataTypes); // 确保 ChatGroup 模型正确导入 const Message = sequelize.define('Message', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, fid: { type: DataTypes.INTEGER, references: { model: User, key: 'id', }, allowNull: true, }, tid: { type: DataTypes.INTEGER, allowNull: true, }, type: { type: DataTypes.ENUM('text', 'audio', 'video', 'image','broadcast','left','kick','withdraw','join'), allowNull: false, }, content: { type: DataTypes.TEXT, allowNull: false, }, avatar: { type: DataTypes.STRING(255), allowNull: true, }, is_retracted: { type: DataTypes.BOOLEAN, defaultValue: false, }, retracted_at: { type: DataTypes.DATE, allowNull: true, }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, group_name:{ type:DataTypes.STRING(10), allowNull: true, }, user_name:{ type: DataTypes.STRING(255), allowNull: true, }, sn: { type: DataTypes.STRING(255), allowNull: true, }, }, { timestamps: false, underscored: true, // 使用下划线风格以符合数据库字段命名 }); return Message; };
module.exports = (sequelize, DataTypes) => { const User = sequelize.define('User', { id: { type: DataTypes.INTEGER, autoIncrement: true, primaryKey: true, }, username: { type: DataTypes.STRING(50), allowNull: false, unique: true, }, password: { type: DataTypes.STRING(100), allowNull: false, }, email: { type: DataTypes.STRING(100), unique: true, }, avatar_url: { type: DataTypes.STRING(255), }, brief: { type: DataTypes.TEXT, }, created_at: { type: DataTypes.DATE, defaultValue: DataTypes.NOW, }, }, { timestamps: false, }); return User; };
聊天代码进行了调整:
const socketIo = require('socket.io'); function setupChat(server) { const io = socketIo(server, { cors: { origin: "*", methods: ["GET", "POST"] } }); const groups = {}; // 存储用户与群组的映射 const kickedUsers = {}; // 存储被踢出用户的信息 const groupUsers = {}; // 存储每个群组中的用户列表 io.on('connection', (socket) => { // console.log('New user connected'); // 用户加入群组 socket.on('joinGroup', ({ groupName, userName }) => { if (!kickedUsers[groupName] || !kickedUsers[groupName].includes(userName)) { socket.join(groupName); // 更新用户列表 if (!groupUsers[groupName]) { groupUsers[groupName] = []; } if (!groupUsers[groupName].includes(userName)) { groupUsers[groupName].push(userName); } groups[socket.id] = { groupName, userName }; console.log( `${userName} has joined the group`) socket.to(groupName).emit('message',{'type':'join',content:`${userName} 加入`}); // 发送当前用户列表到群组 io.to(groupName).emit('userList', groupUsers[groupName]); console.log(`${userName} joined group ${groupName}`); } else { socket.emit('message', `您已被踢出群组 ${groupName}, 无法重新加入。`); } }); // 发送消息 socket.on('sendMessage', ({sn, group_name,avatar, content, user_name,type,fid,tid ,created_at}) => { if (!kickedUsers[group_name] || !kickedUsers[group_name].includes(user_name)) { io.to(group_name).emit('message', {sn, group_name,avatar, content, user_name,type,fid,tid ,created_at}); io.emit('message', {sn, group_name,avatar, content, user_name,'type':'broadcast',fid,tid ,created_at}); console.log({sn, group_name,avatar, content, user_name,type,fid,tid ,created_at}); } else { socket.emit('message', `您已被踢出群组 ${group_name}, 无法发送消息。`); } }); // 踢人 socket.on('kickUser', ({ groupName, userName }) => { for (let id in groups) { if (groups[id].userName === userName && groups[id].groupName === groupName) { io.sockets.sockets.get(id).leave(groupName); io.to(groupName).emit('message', `${userName} 已被踢出群组`); // 从用户列表中删除 if (groupUsers[groupName]) { groupUsers[groupName] = groupUsers[groupName].filter(user => user !== userName); io.to(groupName).emit('userList', groupUsers[groupName]); } console.log(`${userName} 被踢出群组 ${groupName}`); if (!kickedUsers[groupName]) { kickedUsers[groupName] = []; } kickedUsers[groupName].push(userName); break; } } }); // 用户断开连接 socket.on('disconnect', () => { if (groups[socket.id]) { const { groupName, userName } = groups[socket.id]; // 从用户列表中删除 if (groupUsers[groupName]) { groupUsers[groupName] = groupUsers[groupName].filter(user => user !== userName); io.to(groupName).emit('userList', groupUsers[groupName]); } socket.to(groupName).emit('message', {'type':'left',content:`${userName} 离开`}); delete groups[socket.id]; console.log(`${userName} 已离开群组 ${groupName}`); } }); }); return io; } module.exports = setupChat;
启动页为:
const express = require('express'); const http = require('http'); const cors = require('cors'); const bodyParser = require('body-parser'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const db = require('./src/models'); const { User, Friend, ChatGroup, Blacklist, Invite, Message, sequelize } = require('./src/models'); const multer = require('multer'); const path = require('path'); const fs = require('fs'); const { Op } = require('sequelize'); const setupChat = require('./src/chat'); const app = express(); const server = http.createServer(app); // 设置聊天 const io = setupChat(server); // 使用中间件 app.use(cors()); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); const port = 3000; const SECRET_KEY = 'mykeyssssssd%#@##$#@$#$@$#@$$'; // 更改为实际的密钥 const authenticateToken = (req, res, next) => { const authHeader = req.headers['authorization']; const token = authHeader && authHeader.split(' ')[1]; if (token == null) return res.json({code:-1,message:'expire'}); jwt.verify(token, SECRET_KEY, (err, user) => { if (err) return res.json({code:-1,message:'expire'}); req.user = user; next(); }); }; // 设置文件存储配置 const storage = multer.diskStorage({ destination: (req, file, cb) => { cb(null, 'uploads/'); }, filename: (req, file, cb) => { cb(null, `${Date.now()}-${file.originalname}`); } }); const upload = multer({ storage: storage }); // 创建 uploads 目录 const uploadsDir = path.join(__dirname, 'uploads'); if (!fs.existsSync(uploadsDir)) { fs.mkdirSync(uploadsDir); } // 文件上传接口 app.post('/upload', upload.single('avatar'), (req, res) => { if (!req.file) { return res.status(400).json({ error: 'No file uploaded' }); } const fileUrl = `http://localhost:3000/uploads/${req.file.filename}`; res.json({code:0,message:'图片上传成功', data: fileUrl }); }); // 提供静态文件服务 app.use('/uploads', express.static(path.join(__dirname, 'uploads'))); app.post('/register', async (req, res) => { try { const { username, password } = req.body; console.log('Received registration request for:', username); if (username.length < 6 || username.length > 10 || password.length < 6 || password.length > 10) { console.log('Invalid username or password length'); return res.status(400).json({ error: 'Username and password must be 6-10 characters long' }); } const hashedPassword = await bcrypt.hash(password, 10); console.log('Password hashed successfully'); console.log('Attempting to create user in database'); const user = await User.create({ username, password: hashedPassword }); console.log('User created:', user.toJSON()); res.status(201).json({ message: 'User registered successfully' }); } catch (error) { console.error('Error in registration:', error); if (error.name === 'SequelizeUniqueConstraintError') { return res.status(400).json({ error: 'Username already exists' }); } res.status(500).json({ error: error.message || 'An error occurred during registration' }); } }); // 用户登录 app.post('/login', async (req, res) => { try { const { username, password } = req.body; console.log({ username, password }); if (username.length < 6 || username.length > 10 || password.length < 6 || password.length > 10) { return res.status(400).json({ code: 0, msg: '用户名和密码必须是6-10个字符长', data: null }); } const user = await User.findOne({ where: { username } }); console.log(user); if (!user || !await bcrypt.compare(password, user.password)) { return res.status(401).json({ code: 0, msg: '无效凭证', data: null }); } const token = jwt.sign({ id: user.id }, SECRET_KEY, { expiresIn: '1h' }); res.json({ code: 1, msg: '登录成功', data: { token } }); } catch (error) { console.log(error); res.status(500).json({ code: 0, msg: '登录时出错', data: null }); } }); // 添加好友 app.post('/addFriend', authenticateToken, async (req, res) => { const { friendId } = req.body; const userId = req.user.id; try { const friend = await User.findByPk(friendId); if (!friend){ return res.status(404).json({ error:'未找到朋友' }); } await Friend.create({ user_id: userId, friend_id: friendId }); res.json({ message:'成功添加好友' }); }catch (error){ res.status(500).json({ error:'添加好友时出错' }); } }); // 获取好友列表 app.get('/friends', authenticateToken, async (req, res) => { try { const userId = req.user.id; const { page = 1, perPage = 20 } = req.query; // 计算分页参数 const offset = (page - 1) * perPage; const limit = parseInt(perPage); const friends = await Friend.findAndCountAll({ where: { [Op.or]: [ { type: 'user', [Op.or]: [ { user_id: userId }, { group_friend_id: userId } ] }, { type: 'group', user_id: userId } ] }, offset, limit }); // 判断是否还有更多数据 const hasMoreFriends = friends.count > offset + limit; const friendDataPromises = friends.rows.map(async (item) => { if (item.type == 'user') { const user = await User.findOne({ where: { id: item.group_friend_id }, attributes: ['id', 'username', 'email', 'avatar_url', 'brief'] }); return { ...item.get(), user }; } if (item.type == 'group') { const group = await ChatGroup.findOne({ where: { id: item.group_friend_id }, attributes: ['id', 'name', 'description', 'avatar_url'] }); return { ...item.get(), group }; } }); const friendsData = await Promise.all(friendDataPromises); return res.json({ code: 0, message: '返回成功', data: friendsData, hasMoreFriends }); } catch (error) { return res.json({ code: -1, message: error }); } }); app.get('/checkFriend', authenticateToken, async (req, res) => { try { const userId = req.user.id; let { Id } = req.query; if( /^g_\d+$/.test(Id)){ //是group Id = Id.replace("g_", ""); const isFriend = await Friend.findOne({ where: { user_id: userId, group_friend_id:Id}, attributes: ['id', 'user_id', 'group_friend_id','type'] }); if(isFriend){ return res.json({ code: 0, message: 'User is a friend', data: isFriend }); }else{ return res.json({ code: 1, message: 'User is not a friend' }); } } const isFriend = await Friend.findOne({ where: { id: Id,type:'user' }, attributes: ['id', 'user_id', 'group_friend_id','type'] }); if (isFriend){ if(isFriend.user_id==userId ||isFriend.group_friend_id==userId){ return res.json({ code: 0, message: 'User is a friend', data: isFriend }); } return res.json({ code: 1, message: 'User is not a friend' }); }else{ return res.json({ code: 1, message: 'User is not a friend' }); } } catch (error) { return res.json({ code: -1, message: error.message }); } }); app.post('/addmessage', authenticateToken, async (req, res) => { const { sn, group_name, avatar, content, type, user_name, fid, tid } = req.body; try { // 插入新消息 const newMessage = await Message.create({ sn, group_name, avatar, content, type, user_name, fid, tid, is_retracted:0, }); res.json({ code: 0, message: '消息添加成功', data: newMessage }); } catch (error) { console.error('添加消息失败:', error); res.json({ code: -1, message: '消息添加失败' }); } }); // 获取用户信息接口 app.get('/user', authenticateToken, async (req, res) => { try { // 确保 `req.user` 和 `req.user.id` 存在 if (!req.user || !req.user.id) { return res.status(400).json({ error: '用户 ID 未找到' }); } const user = await User.findByPk(req.user.id, { attributes: ['id', 'username', 'email', 'avatar_url', 'brief', 'created_at'] }); if (!user) { //console.warn("User not found with ID:", req.user.id); return res.status(404).json({ error: '用户未找到' }); } res.json(user); } catch (error) { res.status(500).json({ error: '获取用户信息时出错' }); } }); app.post('/user/updateAvatar', authenticateToken, async (req, res) => { const { avatar_url } = req.body; try { await User.update({ avatar_url }, { where: { id: req.user.id } }); res.json({code:0, message:'头像更新成功',data:avatar_url }); } catch (error) { res.json({code:-1, message:'头象更新失败A'}); } }); app.post('/user/updateBrief', authenticateToken, async (req, res) => { const { brief } = req.body; const userId = req.user.id; // Assuming the user ID is stored in the token if (!brief) { return res.status(400).json({ code: 1, message: 'Brief is required' }); } try { // Update the user's brief in the database const [affectedRows] = await User.update( { brief }, // Fields to update { where: { id: userId } } // Condition to find the user ); if (affectedRows === 0) { return res.status(404).json({ code: 1, message: 'User not found' }); } res.status(200).json({ code: 0, message: 'Brief updated successfully' }); } catch (error) { //console.error('Error updating brief:', error); res.status(500).json({ code: 1, message: 'Internal server error' }); } }); // 创建群组接口 app.post('/groups', authenticateToken, upload.single('avatar'), async (req, res) => { try { //console.log('req.body:', req.body); // 调试输出请求体 const { name, description ,avatar_url} = req.body; const owner_id = req.user.id; if (name.length < 3 || name.length > 10) { return res.status(400).json({ error: '群名必须在3到10个汉字之间' }); } if (description.length < 5 || description.length > 50) { return res.status(400).json({ error: '群说明必须在5到50个汉字之间' }); } const existingGroup = await ChatGroup.findOne({ where: { name } }); if (existingGroup) { return res.json({code:-1, message: '群名已存在' }); } const group = await ChatGroup.create({ name, description, avatar_url, owner_id }); await Friend.create({ user_id: owner_id, group_friend_id: group.id, type: 'group', status: 'accepted' }); return res.json({ code: 0, message: '群组创建成功', group }); } catch (error) { return res.json({code:-1, message: '创建群组时出错' }); } }); // 获取群组信息接口 app.get('/groups/:id', authenticateToken, async (req, res) => { try { const group = await ChatGroup.findByPk(req.params.id); if (!group){ return res.status(404).json({ error:'群组未找到' }); } res.json(group); }catch (error){ res.status(500).json({ error:'获取群组信息时出错' }); } }); app.get('/groups', authenticateToken, async (req, res) => { try { const userId = req.user.id; //console.log('userId',userId) const groups = await ChatGroup.findAll({ where: { owner_id: userId } }); //console.log('groups',groups) return res.json({ code: 0, data: groups }); } catch (error) { //console.error('Error fetching groups:', error); return res.json({ code: -1, message: 'Failed to fetch groups' }); } }); app.post('/group/update', authenticateToken, async (req, res) => { try { const { id, name, description, avatar_url } = req.body; // Check if the group name already exists and is not the current group being updated const existingGroup = await ChatGroup.findOne({ where: { name, id: { [Op.ne]: id } // Use Op from Sequelize } }); // // console.log('Op:', Op); // Should not be undefined // console.log('Query:', { // name, // id: { [Op.ne]: id } // }); if (existingGroup) { return res.json({ code: -2, message: '群名重复' }); } await ChatGroup.update({ name, description, avatar_url }, { where: { id } }); return res.json({ code: 0, message: '群名创建成功' }); } catch (error) { // console.error('Error updating group:', error); return res.json({ code: -1, message: '创建失败' }); } }); app.post('/user/updateEmail', authenticateToken, async (req, res) => { try { const userId = req.user.id; const { email } = req.body; await User.update({ email }, { where: { id: userId } }); return res.json({ code: 0, message: 'Email updated successfully' }); } catch (error) { // console.error('Error updating email:', error); return res.json({ code: -1, message: 'Failed to update email' }); } }); app.get('/user', authenticateToken, async (req, res) => { try { const user = await User.findByPk(req.user.id, { attributes: ['id', 'username', 'email', 'avatar'] }); if (!user) { return res.status(404).json({ error: '用户未找到' }); } res.json(user); } catch (error) { res.status(500).json({ error: '获取用户信息时出错' }); } }); app.post('/logout', authenticateToken, (req, res) => { // 这里可以添加一些服务器端的登出逻辑 // 比如清除服务器端的 session 或标记 token 为无效 res.json({ message: '成功登出' }); }); const PORT = process.env.PORT || port; server.listen(PORT, () => { console.log(`Server is running on port ${PORT}`); });