Commit 6e6af76f by niuxing

调整监听配置

1 parent ed210527
......@@ -11,7 +11,7 @@ import schedulerRouter from './routes/scheduler.js'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const app = express()
const PORT = 4000
const HOSTNAME = "localhost"
const HOSTNAME = "0.0.0.0"
// 中间件
app.use(cors())
......
......@@ -198,10 +198,10 @@ router.post('/:id/run', async (req, res) => {
}
})
// 手动发送邮件(可指定收件人)
// 手动发送邮件(可指定收件人,支持群发/逐个发送
router.post('/:id/send-mail', async (req, res) => {
try {
const { recipientEmails, emailSubject } = req.body
const { recipientEmails, emailSubject, sendMode } = req.body
const scripts = loadScripts()
const script = scripts.find(s => s.id === req.params.id)
if (!script) return res.json({ success: false, message: '脚本不存在' })
......@@ -311,25 +311,69 @@ router.post('/:id/send-mail', async (req, res) => {
</div>
`
await sendReportMail({
to: finalRecipients,
subject: finalSubject,
html,
excelBuffer,
fileName,
})
// 逐个发送 vs 群发
const recipientList = finalRecipients.split(',').map(e => e.trim()).filter(e => e)
const isIndividual = (sendMode || 'batch') === 'individual'
if (isIndividual && recipientList.length > 1) {
// 逐个发送:每人一封单独邮件
let successCount = 0
let failList = []
for (const rcpt of recipientList) {
try {
await sendReportMail({
to: rcpt,
subject: finalSubject,
html,
excelBuffer,
fileName,
})
successCount++
} catch (mailErr) {
failList.push(rcpt)
console.error(`发送邮件到 ${rcpt} 失败:`, mailErr.message)
}
}
// 更新脚本状态
const allScripts = loadScripts()
const idx = allScripts.findIndex(s => s.id === script.id)
if (idx >= 0) {
allScripts[idx].lastRunAt = new Date().toISOString()
allScripts[idx].lastRunStatus = 'success'
allScripts[idx].lastRunMessage = `手动发送邮件成功,共${rows.length}条数据,收件人:${finalRecipients}`
saveScripts(allScripts)
}
// 更新脚本状态
const allScripts = loadScripts()
const idx = allScripts.findIndex(s => s.id === script.id)
if (idx >= 0) {
allScripts[idx].lastRunAt = new Date().toISOString()
allScripts[idx].lastRunStatus = failList.length === 0 ? 'success' : (successCount > 0 ? 'partial' : 'failed')
allScripts[idx].lastRunMessage = failList.length === 0
? `逐个发送邮件成功,共${rows.length}条数据,${successCount}人已收到`
: `逐个发送完成,成功${successCount}人,失败${failList.length}人:${failList.join(', ')}`
saveScripts(allScripts)
}
if (failList.length === 0) {
res.json({ success: true, message: `逐个发送邮件成功,共${rows.length}条数据,${successCount}人已收到` })
} else {
res.json({ success: true, message: `逐个发送完成,成功${successCount}人,失败${failList.length}人:${failList.join(', ')}` })
}
} else {
// 群发:一封邮件发送给所有人
await sendReportMail({
to: finalRecipients,
subject: finalSubject,
html,
excelBuffer,
fileName,
})
res.json({ success: true, message: `邮件发送成功,共${rows.length}条数据,收件人:${finalRecipients}` })
// 更新脚本状态
const allScripts = loadScripts()
const idx = allScripts.findIndex(s => s.id === script.id)
if (idx >= 0) {
allScripts[idx].lastRunAt = new Date().toISOString()
allScripts[idx].lastRunStatus = 'success'
allScripts[idx].lastRunMessage = `群发邮件成功,共${rows.length}条数据,收件人:${finalRecipients}`
saveScripts(allScripts)
}
res.json({ success: true, message: `群发邮件成功,共${rows.length}条数据,收件人:${finalRecipients}` })
}
} catch (e) {
// 更新脚本状态为失败
const allScripts = loadScripts()
......
......@@ -440,7 +440,7 @@ export default function SqlManagerModal({ open, onClose, onLoadSql, currentSql,
{
title: '操作',
key: 'action',
width: 200,
width: 260,
render: (_, record) => (
<Space size={4}>
<Tooltip title="加载到编辑器">
......@@ -451,8 +451,10 @@ export default function SqlManagerModal({ open, onClose, onLoadSql, currentSql,
<Tooltip title="编辑脚本配置">
<Button type="link" size="small" icon={<EditOutlined />} onClick={() => handleEdit(record)} />
</Tooltip>
<Tooltip title="手动发送邮件">
<Button type="link" size="small" icon={<MailOutlined />} onClick={() => handleOpenSendMail(record)} />
<Tooltip title="手动发送邮件(可单独发送/群发)">
<Button type="link" size="small" style={{ color: '#1890ff' }} icon={<MailOutlined />} onClick={() => handleOpenSendMail(record)}>
发邮件
</Button>
</Tooltip>
{record.cronExpression && (
<Tooltip title="手动触发执行">
......@@ -530,12 +532,29 @@ export default function SqlManagerModal({ open, onClose, onLoadSql, currentSql,
}}>
{record.sql}
</pre>
{record.recipientEmails && (
<div style={{ marginTop: 8, fontSize: 12, color: '#666' }}>
<MailOutlined style={{ marginRight: 4 }} />
收件人: {record.recipientEmails}
<div style={{ marginTop: 8, display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
<div>
{record.recipientEmails && (
<span style={{ fontSize: 12, color: '#666', marginRight: 16 }}>
<MailOutlined style={{ marginRight: 4 }} />
收件人: {record.recipientEmails}
</span>
)}
{record.purpose && (
<span style={{ fontSize: 12, color: '#999' }}>
用途: {record.purpose}
</span>
)}
</div>
)}
<Button
type="primary"
size="small"
icon={<MailOutlined />}
onClick={() => handleOpenSendMail(record)}
>
发送邮件
</Button>
</div>
</div>
),
}}
......
Markdown is supported
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!