email登录邮件内容模板支持html

This commit is contained in:
lxy 2024-09-13 13:21:32 +08:00
parent 03891464d5
commit 4b3342c5b2
4 changed files with 90 additions and 59 deletions

View File

@ -1,5 +1,5 @@
import React, { useEffect, useState } from "react"; import React, { useEffect, useState } from "react";
import { Space, Switch, Alert, Typography, Form, Input, Radio, Tag } from 'antd'; import { Switch, Alert, Typography, Form, Input, Radio, Tag } from 'antd';
import Styles from './web.module.less'; import Styles from './web.module.less';
import '@wangeditor/editor/dist/css/style.css'; // 引入 css import '@wangeditor/editor/dist/css/style.css'; // 引入 css
import { Editor, Toolbar } from "@wangeditor/editor-for-react"; import { Editor, Toolbar } from "@wangeditor/editor-for-react";
@ -11,6 +11,7 @@ export default function Email(props) {
const config = passport.config || {}; const config = passport.config || {};
const [subject, setSubject] = useState(config?.subject || ''); const [subject, setSubject] = useState(config?.subject || '');
const [eContentType, setEContentType] = useState('text'); const [eContentType, setEContentType] = useState('text');
const [htmlType, setHtmlType] = useState('html');
const [text, setText] = useState(config?.text || ''); const [text, setText] = useState(config?.text || '');
const [html, setHtml] = useState(config?.html || ''); const [html, setHtml] = useState(config?.html || '');
const [emailCodeDuration, setEmailCodeDuration] = useState(config?.codeDuration || ''); const [emailCodeDuration, setEmailCodeDuration] = useState(config?.codeDuration || '');
@ -77,32 +78,42 @@ export default function Email(props) {
</Form.Item> </Form.Item>
<Form.Item label="邮件内容模板"> <Form.Item label="邮件内容模板">
<> <>
<Space size={8} style={{ marginBottom: 8 }}> <Radio.Group onChange={(e) => setEContentType(e.target.value)} value={eContentType} style={{ marginBottom: 12 }}>
<Radio.Group onChange={(e) => setEContentType(e.target.value)} value={eContentType}> <Radio.Button value="text">纯文本</Radio.Button>
<Radio.Button value="text">纯文本</Radio.Button> <Radio.Button value="html">HTML</Radio.Button>
<Radio.Button value="html">HTML</Radio.Button> </Radio.Group>
</Radio.Group> <Alert message={<div>
<Alert message={<div> <span>请使用</span>
<span>请使用</span> <Text mark> ${'{code}'}</Text>
<Text mark> ${'{code}'}</Text> <span>作为验证码占位符</span>
<span>作为验证码占位符</span> <Text mark> ${'{duration}'}</Text>
<Text mark> ${'{duration}'}</Text> <span>作为验证码有效时间占位符(不包含单位分钟)</span>
<span>作为验证码有效时间占位符(不包含单位分钟)</span> </div>} type="info" style={{ marginBottom: 12 }}/>
</div>} type="info"/> {eContentType === 'text' ? (<TextArea rows={8} value={text} onChange={(e) => {
</Space>
{eContentType === 'text' ? (<TextArea rows={6} value={text} onChange={(e) => {
setText(e.target.value); setText(e.target.value);
}} onBlur={() => { }} onBlur={() => {
if (text !== config?.text) { if (text !== config?.text) {
updateConfig(id, config, 'text', text, 'email'); updateConfig(id, config, 'text', text, 'email');
} }
}}/>) : (<div style={{ border: '1px solid #ccc' }}> }}/>) : (<>
<Toolbar editor={editor} defaultConfig={toolbarConfig} mode="default" style={{ borderBottom: '1px solid #ccc' }}/> <Radio.Group onChange={(e) => setHtmlType(e.target.value)} value={htmlType} style={{ marginBottom: 12 }}>
<Editor defaultConfig={editorConfig} value={html} onCreated={setEditor} onChange={editor => { <Radio value="richText">富文本</Radio>
setHtml(editor.getHtml()); <Radio value="html">HTML</Radio>
updateConfig(id, config, 'html', editor.getHtml(), 'email'); </Radio.Group>
}} mode="default" style={{ height: '260px', overflowY: 'hidden' }}/> {htmlType === 'richText' ? (<div style={{ border: '1px solid #ccc' }}>
</div>)} <Toolbar editor={editor} defaultConfig={toolbarConfig} mode="default" style={{ borderBottom: '1px solid #ccc' }}/>
<Editor defaultConfig={editorConfig} value={html} onCreated={setEditor} onChange={editor => {
setHtml(editor.getHtml());
updateConfig(id, config, 'html', editor.getHtml(), 'email');
}} mode="default" style={{ height: '260px', overflowY: 'hidden' }}/>
</div>) : (<TextArea rows={8} value={html} onChange={(e) => {
setHtml(e.target.value);
}} onBlur={() => {
if (html !== config?.html) {
updateConfig(id, config, 'html', html, 'email');
}
}}/>)}
</>)}
</> </>
</Form.Item> </Form.Item>
<Form.Item label="验证码有效时间" tooltip="邮箱验证码发送有效时间不填为5分钟"> <Form.Item label="验证码有效时间" tooltip="邮箱验证码发送有效时间不填为5分钟">

View File

@ -170,7 +170,7 @@ export default OakComponent({
warnings.push({ warnings.push({
id, id,
type, type,
tip: '邮箱登录未配置邮件内容模板', tip: '邮箱登录未正确配置邮件内容模板',
}); });
} }
} }

View File

@ -21,6 +21,7 @@ export default function Email(props: {
const config = passport.config as EmailConfig || {}; const config = passport.config as EmailConfig || {};
const [subject, setSubject] = useState(config?.subject || ''); const [subject, setSubject] = useState(config?.subject || '');
const [eContentType, setEContentType] = useState<'text' | 'html'>('text'); const [eContentType, setEContentType] = useState<'text' | 'html'>('text');
const [htmlType, setHtmlType] = useState<'richText' | 'html'>('html');
const [text, setText] = useState(config?.text || ''); const [text, setText] = useState(config?.text || '');
const [html, setHtml] = useState(config?.html || ''); const [html, setHtml] = useState(config?.html || '');
const [emailCodeDuration, setEmailCodeDuration] = useState(config?.codeDuration || ''); const [emailCodeDuration, setEmailCodeDuration] = useState(config?.codeDuration || '');
@ -131,23 +132,21 @@ export default function Email(props: {
label="邮件内容模板" label="邮件内容模板"
> >
<> <>
<Space size={8} style={{ marginBottom: 8 }}> <Radio.Group onChange={(e) => setEContentType(e.target.value)} value={eContentType} style={{ marginBottom: 12 }} >
<Radio.Group onChange={(e) => setEContentType(e.target.value)} value={eContentType} > <Radio.Button value="text"></Radio.Button>
<Radio.Button value="text"></Radio.Button> <Radio.Button value="html">HTML</Radio.Button>
<Radio.Button value="html">HTML</Radio.Button> </Radio.Group>
</Radio.Group> <Alert message={
<Alert message={ <div>
<div> <span>使</span>
<span>使</span> <Text mark> ${'{code}'}</Text>
<Text mark> ${'{code}'}</Text> <span></span>
<span></span> <Text mark> ${'{duration}'}</Text>
<Text mark> ${'{duration}'}</Text> <span>()</span>
<span>()</span> </div>
</div> } type="info" style={{ marginBottom: 12 }} />
} type="info" />
</Space>
{eContentType === 'text' ? ( {eContentType === 'text' ? (
<TextArea rows={6} <TextArea rows={8}
value={text} value={text}
onChange={(e) => { onChange={(e) => {
setText(e.target.value); setText(e.target.value);
@ -159,25 +158,46 @@ export default function Email(props: {
}} }}
/> />
) : ( ) : (
<div style={{ border: '1px solid #ccc' }}> <>
<Toolbar <Radio.Group onChange={(e) => setHtmlType(e.target.value)} value={htmlType} style={{ marginBottom: 12 }} >
editor={editor} <Radio value="richText"></Radio>
defaultConfig={toolbarConfig} <Radio value="html">HTML</Radio>
mode="default" </Radio.Group>
style={{ borderBottom: '1px solid #ccc' }} {htmlType === 'richText' ? (
/> <div style={{ border: '1px solid #ccc' }}>
<Editor <Toolbar
defaultConfig={editorConfig} editor={editor}
value={html} defaultConfig={toolbarConfig}
onCreated={setEditor} mode="default"
onChange={editor => { style={{ borderBottom: '1px solid #ccc' }}
setHtml(editor.getHtml()); />
updateConfig(id, config!, 'html', editor.getHtml(), 'email'); <Editor
}} defaultConfig={editorConfig}
mode="default" value={html}
style={{ height: '260px', overflowY: 'hidden' }} onCreated={setEditor}
/> onChange={editor => {
</div> setHtml(editor.getHtml());
updateConfig(id, config!, 'html', editor.getHtml(), 'email');
}}
mode="default"
style={{ height: '260px', overflowY: 'hidden' }}
/>
</div>
) : (
<TextArea rows={8}
value={html}
onChange={(e) => {
setHtml(e.target.value);
}}
onBlur={() => {
if (html !== (config as EmailConfig)?.html) {
updateConfig(id, config!, 'html', html, 'email');
}
}}
/>
)}
</>
)} )}
</> </>
</Form.Item> </Form.Item>

View File

@ -174,7 +174,7 @@ export default OakComponent({
warnings.push({ warnings.push({
id, id,
type, type,
tip: '邮箱登录未配置邮件内容模板', tip: '邮箱登录未正确配置邮件内容模板',
}); });
} }
} }