SendMailModal.jsx 4.63 KB
import React, { useState, useEffect } from 'react'
import { Modal, Form, Input, Button, Space, message, Tag, Alert } from 'antd'
import { SendOutlined, MailOutlined } from '@ant-design/icons'
import request from '../utils/request'

// 验证逗号分隔的多个邮箱
const validateEmails = (rule, value) => {
  if (!value || !value.trim()) return Promise.reject(new Error('请输入收件人邮箱'))
  const emails = value.split(',').map(e => e.trim()).filter(e => e)
  const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  const invalid = emails.find(e => !emailRegex.test(e))
  if (invalid) return Promise.reject(new Error(`邮箱格式不正确: ${invalid}`))
  return Promise.resolve()
}

export default function SendMailModal({ open, onClose, script, onSent }) {
  const [form] = Form.useForm()
  const [sending, setSending] = useState(false)

  useEffect(() => {
    if (open && script) {
      form.resetFields()
      setTimeout(() => {
        form.setFieldsValue({
          recipientEmails: script.recipientEmails || '',
          emailSubject: script.emailSubject || '',
        })
      }, 0)
    }
  }, [open, script])

  const handleSend = async () => {
    try {
      const values = await form.validateFields()
      setSending(true)

      const res = await request.post(`/sql-manage/${script.id}/send-mail`, {
        recipientEmails: values.recipientEmails,
        emailSubject: values.emailSubject,
      })

      if (res.success) {
        message.success(res.message)
        if (onSent) onSent()
        onClose()
      } else {
        message.error(res.message)
      }
    } catch (e) {
      if (e.errorFields) return // 表单验证失败
      message.error(e.message || '发送失败')
    } finally {
      setSending(false)
    }
  }

  if (!script) return null

  // 解析收件人列表用于标签展示
  const parseEmailTags = (text) => {
    if (!text) return []
    return text.split(',').map(e => e.trim()).filter(e => e)
  }

  return (
    <Modal
      title={
        <Space>
          <SendOutlined />
          <span>手动发送邮件</span>
          <Tag color="blue">{script.name}</Tag>
        </Space>
      }
      open={open}
      onCancel={onClose}
      width={560}
      footer={
        <Space>
          <Button onClick={onClose}>取消</Button>
          <Button
            type="primary"
            icon={<SendOutlined />}
            loading={sending}
            onClick={handleSend}
          >
            发送邮件
          </Button>
        </Space>
      }
    >
      <Alert
        type="info"
        showIcon
        style={{ marginBottom: 16 }}
        message="手动发送将执行脚本SQL,生成Excel附件并发送邮件到指定收件人。收件人可与脚本配置的不同。"
      />

      <Form form={form} layout="vertical">
        <Form.Item
          name="recipientEmails"
          label="收件人邮箱"
          tooltip="多个收件人用英文逗号分隔"
          rules={[{ validator: validateEmails }]}
        >
          <Input.TextArea
            placeholder="例如:zhangsan@company.com,lisi@company.com"
            autoSize={{ minRows: 2, maxRows: 4 }}
            onChange={() => {
              // 实时更新标签展示
            }}
          />
        </Form.Item>

        <Form.Item shouldUpdate={(prev, cur) => prev.recipientEmails !== cur.recipientEmails}>
          {({ getFieldValue }) => {
            const emails = parseEmailTags(getFieldValue('recipientEmails'))
            if (emails.length === 0) return null
            return (
              <div style={{ marginTop: -12, marginBottom: 16 }}>
                <span style={{ fontSize: 12, color: '#999', marginRight: 8 }}>收件人预览:</span>
                <Space size={4} wrap>
                  {emails.map((email, i) => (
                    <Tag key={i} color="blue" icon={<MailOutlined />}>{email}</Tag>
                  ))}
                </Space>
              </div>
            )
          }}
        </Form.Item>

        <Form.Item
          name="emailSubject"
          label="邮件主题"
          tooltip="为空则使用脚本配置的主题或自动生成"
        >
          <Input placeholder="例如:月度终端支付明细报表(自定义)" />
        </Form.Item>

        <div style={{ padding: '8px 12px', background: '#f6f6f6', borderRadius: 6, fontSize: 12, color: '#888' }}>
          <div>邮件将自动附带Excel附件,包含脚本查询结果数据。</div>
          {script.purpose && (
            <div style={{ marginTop: 4 }}>
              <span style={{ color: '#666' }}>脚本用途:</span>{script.purpose}
            </div>
          )}
        </div>
      </Form>
    </Modal>
  )
}