feat: fix backend sql error;fix frontend i18n display error
This commit is contained in:
parent
32320e1cb0
commit
7ee074249f
|
|
@ -100,7 +100,7 @@ app.delete('/api/messages', async (req, res) => {
|
||||||
return res.status(400).send('Recipient is required');
|
return res.status(400).send('Recipient is required');
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await db.execute('DELETE FROM emails WHERE recipient = ?', [recipient]);
|
await db.execute('DELETE FROM emails WHERE recipient LIKE ?', [`%${recipient}%`]);
|
||||||
logger.info('All messages for recipient deleted successfully', { recipient });
|
logger.info('All messages for recipient deleted successfully', { recipient });
|
||||||
res.status(204).send(); // No Content
|
res.status(204).send(); // No Content
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -142,14 +142,19 @@ wss.on('connection', (ws, req) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
emitter.on('newEmail', (email) => {
|
emitter.on('newEmail', (email) => {
|
||||||
const recipient = email.recipient;
|
const dbRecipient = email.recipient; // 比如 "6471" <6471@shenjianl.cn>
|
||||||
if (clients.has(recipient)) {
|
|
||||||
const ws = clients.get(recipient);
|
// 遍历所有 clients,用 includes 判断
|
||||||
logger.info(`Sending new email notification to`, { recipient });
|
for (const [clientRecipient, ws] of clients.entries()) {
|
||||||
ws.send(JSON.stringify(email));
|
if (dbRecipient.includes(clientRecipient)) {
|
||||||
|
logger.info(`Sending new email notification to`, { recipient: clientRecipient });
|
||||||
|
ws.send(JSON.stringify(email));
|
||||||
|
break; // 如果只想发给第一个匹配的就 break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Start API server
|
// Start API server
|
||||||
server.listen(apiPort, () => {
|
server.listen(apiPort, () => {
|
||||||
logger.info(`Backend API and WebSocket server listening at http://localhost:${apiPort}`);
|
logger.info(`Backend API and WebSocket server listening at http://localhost:${apiPort}`);
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ async function saveEmail(stream) {
|
||||||
|
|
||||||
const recipient = parsed.to ? parsed.to.text : 'undisclosed-recipients';
|
const recipient = parsed.to ? parsed.to.text : 'undisclosed-recipients';
|
||||||
const sender = parsed.from ? parsed.from.text : 'unknown-sender';
|
const sender = parsed.from ? parsed.from.text : 'unknown-sender';
|
||||||
const subject = parsed.subject;
|
const subject = parsed.subject || 'No Subject';
|
||||||
const body = parsed.text || (parsed.html || '');
|
const body = parsed.text || (parsed.html || '');
|
||||||
|
|
||||||
const [result] = await db.execute(
|
const [result] = await db.execute(
|
||||||
|
|
|
||||||
|
|
@ -34,8 +34,13 @@ const messages = {
|
||||||
deleteFailed: '删除邮件失败。',
|
deleteFailed: '删除邮件失败。',
|
||||||
confirmClearAll: '确定要清空这个收件箱的所有邮件吗?此操作不可恢复。',
|
confirmClearAll: '确定要清空这个收件箱的所有邮件吗?此操作不可恢复。',
|
||||||
clearFailed: '清空收件箱失败。',
|
clearFailed: '清空收件箱失败。',
|
||||||
|
generateRandomSuccess: '已生成随机邮箱地址',
|
||||||
|
checkInboxStart: '正在查询收件箱',
|
||||||
copyFailed: '复制失败!',
|
copyFailed: '复制失败!',
|
||||||
|
copySuccess: '复制成功!', // <-- 这里添加
|
||||||
actionCancelled: '操作已取消',
|
actionCancelled: '操作已取消',
|
||||||
|
deleteSuccess: '删除成功!',
|
||||||
|
clearSuccess: '收件箱已清空!',
|
||||||
},
|
},
|
||||||
newMailNotification: '收到新邮件!',
|
newMailNotification: '收到新邮件!',
|
||||||
}
|
}
|
||||||
|
|
@ -73,8 +78,13 @@ const messages = {
|
||||||
deleteFailed: 'Failed to delete email.',
|
deleteFailed: 'Failed to delete email.',
|
||||||
confirmClearAll: 'Are you sure you want to clear all emails in this inbox? This action cannot be undone.',
|
confirmClearAll: 'Are you sure you want to clear all emails in this inbox? This action cannot be undone.',
|
||||||
clearFailed: 'Failed to clear inbox.',
|
clearFailed: 'Failed to clear inbox.',
|
||||||
|
generateRandomSuccess: 'Random email address generated',
|
||||||
|
checkInboxStart: 'Checking inbox',
|
||||||
copyFailed: 'Copy failed!',
|
copyFailed: 'Copy failed!',
|
||||||
|
copySuccess: 'Copied successfully!', // <-- 这里添加
|
||||||
actionCancelled: 'Action cancelled',
|
actionCancelled: 'Action cancelled',
|
||||||
|
deleteSuccess: 'Deleted successfully!',
|
||||||
|
clearSuccess: 'Inbox cleared!',
|
||||||
},
|
},
|
||||||
newMailNotification: 'New mail received!',
|
newMailNotification: 'New mail received!',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -168,6 +168,7 @@ const fetchMessages = async () => {
|
||||||
ElMessage.warning(t('home.alerts.enterEmail'));
|
ElMessage.warning(t('home.alerts.enterEmail'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ElMessage.info(t('home.alerts.checkInboxStart'));
|
||||||
loading.value = true;
|
loading.value = true;
|
||||||
selectedMessage.value = null;
|
selectedMessage.value = null;
|
||||||
attachments.value = [];
|
attachments.value = [];
|
||||||
|
|
@ -326,60 +327,39 @@ const generateRandomEmail = () => {
|
||||||
} else {
|
} else {
|
||||||
prefix = `${word1}${separator}${word2}${number}`;
|
prefix = `${word1}${separator}${word2}${number}`;
|
||||||
}
|
}
|
||||||
|
ElMessage.success(t('home.alerts.generateRandomSuccess'));
|
||||||
recipient.value = `${prefix}@${domain}`;
|
recipient.value = `${prefix}@${domain}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const copyEmail = () => {
|
const copyEmail = async () => {
|
||||||
if (!recipient.value) return;
|
if (!recipient.value) return;
|
||||||
|
|
||||||
const textToCopy = recipient.value;
|
|
||||||
|
|
||||||
if (navigator.clipboard && window.isSecureContext) {
|
|
||||||
navigator.clipboard.writeText(textToCopy).then(() => {
|
|
||||||
showCopySuccess();
|
|
||||||
}).catch(err => {
|
|
||||||
console.error('Modern copy failed: ', err);
|
|
||||||
fallbackCopy(textToCopy);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
fallbackCopy(textToCopy);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const fallbackCopy = (text) => {
|
|
||||||
const textArea = document.createElement('textarea');
|
|
||||||
textArea.value = text;
|
|
||||||
|
|
||||||
textArea.style.position = 'fixed';
|
|
||||||
textArea.style.top = '-9999px';
|
|
||||||
textArea.style.left = '-9999px';
|
|
||||||
|
|
||||||
document.body.appendChild(textArea);
|
|
||||||
textArea.focus();
|
|
||||||
textArea.select();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const successful = document.execCommand('copy');
|
if (navigator.clipboard && window.isSecureContext) {
|
||||||
if (successful) {
|
await navigator.clipboard.writeText(recipient.value);
|
||||||
showCopySuccess();
|
|
||||||
} else {
|
} else {
|
||||||
throw new Error('Fallback copy was unsuccessful');
|
// fallback 方案
|
||||||
|
const textArea = document.createElement('textarea');
|
||||||
|
textArea.value = recipient.value;
|
||||||
|
textArea.style.position = 'fixed'; // 防止滚动时跳动
|
||||||
|
textArea.style.left = '-9999px';
|
||||||
|
textArea.style.top = '-9999px';
|
||||||
|
document.body.appendChild(textArea);
|
||||||
|
textArea.focus();
|
||||||
|
textArea.select();
|
||||||
|
const success = document.execCommand('copy');
|
||||||
|
document.body.removeChild(textArea);
|
||||||
|
if (!success) throw new Error('Fallback copy failed');
|
||||||
}
|
}
|
||||||
|
copyStatus.value = 'copied';
|
||||||
|
ElMessage.success(t('home.alerts.copySuccess'));
|
||||||
|
setTimeout(() => copyStatus.value = 'idle', 2000);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error('Fallback copy failed: ', err);
|
console.error('Copy failed:', err);
|
||||||
ElMessage.error(t('home.alerts.copyFailed'));
|
ElMessage.error(t('home.alerts.copyFailed'));
|
||||||
}
|
}
|
||||||
|
|
||||||
document.body.removeChild(textArea);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const showCopySuccess = () => {
|
|
||||||
copyStatus.value = 'copied';
|
|
||||||
setTimeout(() => {
|
|
||||||
copyStatus.value = 'idle';
|
|
||||||
}, 2000);
|
|
||||||
};
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue