You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

285 lines
9.9 KiB

const { Sequelize } = require('sequelize');
const fs = require('fs');
const path = require('path');
// 读取环境变量
const envPath = path.join(__dirname, '.env');
if (fs.existsSync(envPath)) {
const envContent = fs.readFileSync(envPath, 'utf8');
const envVars = envContent.split('\n').filter(line => line.trim() && !line.startsWith('#'));
envVars.forEach(line => {
const [key, value] = line.split('=').map(part => part.trim());
process.env[key] = value;
});
}
// 数据库连接配置
const sequelize = new Sequelize(
process.env.DB_NAME || 'wechat_app',
process.env.DB_USER || 'root',
process.env.DB_PASSWORD || '',
{
host: process.env.DB_HOST || 'localhost',
port: process.env.DB_PORT || 3306,
dialect: 'mysql',
logging: false,
timezone: '+08:00' // 设置时区为UTC+8
}
);
/**
* 检查并修复所有用户的关联记录
* 这个函数会扫描所有用户,并为每个用户创建缺失的关联记录
*/
async function checkAndFixAllUserAssociations() {
try {
console.log('========================================');
console.log('检查并修复所有用户的关联记录');
console.log('========================================');
// 连接数据库
await sequelize.authenticate();
console.log('✅ 数据库连接成功');
// 获取所有用户
const users = await sequelize.query(
'SELECT userId, nickName, phoneNumber FROM users',
{ type: sequelize.QueryTypes.SELECT }
);
console.log(`📊 共找到 ${users.length} 个用户记录`);
let totalContactsCreated = 0;
let totalManagementsCreated = 0;
let fullyFixedUsers = 0;
let partiallyFixedUsers = 0;
let alreadyFixedUsers = 0;
// 为每个用户检查并创建关联记录
for (let i = 0; i < users.length; i++) {
const user = users[i];
console.log(`\n🔄 处理用户 ${i + 1}/${users.length}: ${user.userId}`);
let contactsCreated = 0;
let managementsCreated = 0;
// 检查并创建联系人记录
try {
const existingContact = await sequelize.query(
'SELECT * FROM contacts WHERE userId = ?',
{ replacements: [user.userId], type: sequelize.QueryTypes.SELECT }
);
if (existingContact.length === 0) {
await sequelize.query(
'INSERT INTO contacts (userId, nickName, phoneNumber) VALUES (?, ?, ?)',
{ replacements: [user.userId, user.nickName || '默认联系人', user.phoneNumber || ''] }
);
console.log('✅ 创建了联系人记录');
contactsCreated++;
} else {
console.log('✅ 联系人记录已存在');
}
} catch (error) {
console.error('❌ 创建联系人记录失败:', error.message);
}
// 检查并创建用户管理记录
try {
const existingManagement = await sequelize.query(
'SELECT * FROM usermanagements WHERE userId = ?',
{ replacements: [user.userId], type: sequelize.QueryTypes.SELECT }
);
if (existingManagement.length === 0) {
await sequelize.query(
'INSERT INTO usermanagements (userId) VALUES (?)',
{ replacements: [user.userId] }
);
console.log('✅ 创建了用户管理记录');
managementsCreated++;
} else {
console.log('✅ 用户管理记录已存在');
}
} catch (error) {
console.error('❌ 创建用户管理记录失败:', error.message);
}
// 更新统计信息
totalContactsCreated += contactsCreated;
totalManagementsCreated += managementsCreated;
if (contactsCreated === 0 && managementsCreated === 0) {
alreadyFixedUsers++;
} else if (contactsCreated > 0 || managementsCreated > 0) {
if (contactsCreated > 0 && managementsCreated > 0) {
fullyFixedUsers++;
} else {
partiallyFixedUsers++;
}
}
}
console.log('\n========================================');
console.log('修复完成!');
console.log(`📊 总计: ${users.length} 个用户`);
console.log(`✅ 已经完整的用户: ${alreadyFixedUsers}`);
console.log(`🔧 完全修复的用户: ${fullyFixedUsers}`);
console.log(`⚠️ 部分修复的用户: ${partiallyFixedUsers}`);
console.log(`📈 共创建了 ${totalContactsCreated} 条联系人记录`);
console.log(`📈 共创建了 ${totalManagementsCreated} 条用户管理记录`);
console.log('========================================');
} catch (error) {
console.error('❌ 修复过程中发生错误:', error.message);
console.error('错误详情:', error);
} finally {
// 关闭数据库连接
await sequelize.close();
}
}
/**
* 监控新用户并自动创建关联记录
* 这个函数会定期检查新用户,并为其创建关联记录
*/
async function monitorAndAutoFixNewUsers(intervalMinutes = 10) {
console.log(`\n🔄 启动新用户监控,每 ${intervalMinutes} 分钟检查一次`);
// 保存上次检查的最大用户ID
let lastCheckedUserId = '';
async function checkNewUsers() {
try {
// 连接数据库
await sequelize.authenticate();
// 获取最新的用户ID
const latestUser = await sequelize.query(
'SELECT userId FROM users ORDER BY userId DESC LIMIT 1',
{ type: sequelize.QueryTypes.SELECT }
);
if (latestUser.length > 0 && latestUser[0].userId !== lastCheckedUserId) {
console.log(`\n🕵️‍♂️ 检测到可能的新用户活动,运行完整检查`);
// 重新运行修复函数检查所有用户
await checkAndFixAllUserAssociations();
// 更新最后检查的用户ID
lastCheckedUserId = latestUser[0].userId;
}
} catch (error) {
console.error('❌ 监控过程中发生错误:', error.message);
} finally {
// 关闭数据库连接
await sequelize.close();
}
}
// 立即运行一次
await checkNewUsers();
// 设置定期检查(在实际部署时启用)
// setInterval(checkNewUsers, intervalMinutes * 60 * 1000);
}
/**
* 创建一个服务器文件补丁,确保新用户在授权时自动创建关联记录
*/
function createServerPatch() {
console.log('\n========================================');
console.log('创建服务器代码补丁');
console.log('========================================');
const patchContent = `/**
* 用户关联记录创建工具函数
* 用于在用户授权成功后自动创建contacts和usermanagements表关联记录
*/
async function createUserAssociations(user) {
try {
// 确保用户对象有效
if (!user || !user.userId) {
console.error('创建用户关联记录失败: 用户对象或userId无效');
return false;
}
console.log('为用户创建关联记录:', user.userId);
// 1. 创建或更新联系人记录
const [contactResult] = await sequelize.query(
'INSERT INTO contacts (userId, nickName, phoneNumber) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE nickName = ?, phoneNumber = ?',
{ replacements: [user.userId, user.nickName || '默认联系人', user.phoneNumber || '', user.nickName || '默认联系人', user.phoneNumber || ''] }
);
// 2. 创建或更新用户管理记录
const [managementResult] = await sequelize.query(
'INSERT INTO usermanagements (userId) VALUES (?) ON DUPLICATE KEY UPDATE userId = ?',
{ replacements: [user.userId, user.userId] }
);
console.log('用户关联记录创建成功:', user.userId);
return true;
} catch (error) {
console.error('创建用户关联记录失败:', error.message);
return false;
}
}
// 在server-mysql.js文件中的用户授权相关代码后添加:
// 示例:在用户创建或更新成功后调用
// const user = { userId: '...', nickName: '...', phoneNumber: '...' };
// await createUserAssociations(user);`;
const patchFilePath = path.join(__dirname, 'user-association-patch.js');
fs.writeFileSync(patchFilePath, patchContent);
console.log('✅ 服务器补丁已创建:', patchFilePath);
console.log('请将此补丁中的createUserAssociations函数添加到server-mysql.js文件中,');
console.log('并在用户授权成功后调用该函数,以确保自动创建关联记录。');
console.log('========================================');
}
/**
* 主函数
*/
async function main() {
try {
// 1. 先检查并修复所有现有用户
await checkAndFixAllUserAssociations();
// 2. 创建服务器补丁,解决根本问题
createServerPatch();
// 3. 提供使用说明
console.log('\n========================================');
console.log('使用说明:');
console.log('========================================');
console.log('1. 手动修复现有用户:');
console.log(' 已完成,所有用户的关联记录已检查并修复');
console.log('\n2. 长期解决方案:');
console.log(' a. 请将user-association-patch.js中的createUserAssociations函数添加到server-mysql.js文件');
console.log(' b. 在用户授权成功后调用该函数');
console.log(' c. 重启服务器以应用更改');
console.log('\n3. 可选: 定期检查(适用于临时解决方案):');
console.log(' 运行: node user-association-auto-fix.js monitor');
console.log(' 这将每10分钟检查一次新用户并自动修复关联记录');
console.log('========================================');
} catch (error) {
console.error('❌ 执行过程中发生错误:', error);
}
}
// 根据命令行参数决定执行模式
const args = process.argv.slice(2);
const mode = args[0] || 'fix';
if (mode === 'monitor') {
// 监控模式
monitorAndAutoFixNewUsers();
} else {
// 默认修复模式
main();
}