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
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();
|
|
}
|