fix: 添加邮箱抄送密发功能
This commit is contained in:
@@ -1,92 +0,0 @@
|
|||||||
# Email组件外部表格保存功能测试说明
|
|
||||||
|
|
||||||
## 功能概述
|
|
||||||
|
|
||||||
已为Email组件实现了模仿Setting组件的外部表格保存功能。当用户在Email组件中进行设置时,配置数据会自动保存到store中,当关闭弹窗时,外部的EmailForm会从store中获取这些数据并显示在表格中。
|
|
||||||
|
|
||||||
## 实现细节
|
|
||||||
|
|
||||||
### 1. 创建了Email Store (`src/store/modules/email.ts`)
|
|
||||||
|
|
||||||
- `emailFormList`: 存储邮件配置数据的数组
|
|
||||||
- `addEmailData()`: 添加邮件配置数据
|
|
||||||
- `updateEmailData()`: 更新邮件配置数据
|
|
||||||
- `removeEmailData()`: 删除邮件配置数据
|
|
||||||
- `clearEmailData()`: 清空所有邮件配置数据
|
|
||||||
|
|
||||||
### 2. 创建了Email消息发送函数 (`src/components/Email/index.ts`)
|
|
||||||
|
|
||||||
- `sendEmailMsg()`: 将邮件设置数据保存到store中
|
|
||||||
- 格式化数据:支持boolean类型显示为"打开/关闭",其他类型直接显示值
|
|
||||||
- 数据结构:`{ contentIn: "设置描述", content: "category@key@value" }`
|
|
||||||
- 避免重复:相同category@key的数据会被更新而不是重复添加
|
|
||||||
|
|
||||||
### 3. 修改了Email Setting组件 (`src/components/Email/components/setting.vue`)
|
|
||||||
|
|
||||||
- 导入了`sendEmailMsg`函数
|
|
||||||
- 为所有设置项的变更事件添加了数据保存调用:
|
|
||||||
- 语言设置:`common@language@value`
|
|
||||||
- 文字大小:`common@fontSize@value`
|
|
||||||
- 邮件数量:`common@emailCount@value`
|
|
||||||
- 邮件选项:`common@checkList@value`
|
|
||||||
- 天气显示:`common@weather@value`
|
|
||||||
- 生日提醒:`common@birthdayRemind@value`
|
|
||||||
- 邮件昵称:`account@nickname@value`
|
|
||||||
- 生日信息:`account@birthYear/birthMonth/birthDay@value`
|
|
||||||
- 生日可见性:`account@birthdayVisible@value`
|
|
||||||
- 默认账户:`account@defaultAccount@value`
|
|
||||||
|
|
||||||
### 4. 修改了Email子组件 (`src/components/Email/children/components/skinSettings.vue`)
|
|
||||||
|
|
||||||
- 为皮肤设置功能添加了数据保存:
|
|
||||||
- 选择皮肤:`skin@selectedSkin@value`
|
|
||||||
- 应用皮肤:`skin@appliedSkin@value`
|
|
||||||
- 恢复默认:`skin@resetSkin@default`
|
|
||||||
|
|
||||||
### 5. 修改了EmailForm组件 (`src/views/paper/question/EmailForm.vue`)
|
|
||||||
|
|
||||||
- 导入了`useEmailStore`
|
|
||||||
- 添加了`handleEmailForm()`函数,在dialog关闭时从store获取数据
|
|
||||||
- 修改了dialog的`@close`事件,绑定到`handleEmailForm`
|
|
||||||
- 调整了表格显示:
|
|
||||||
- 将"试题考点"改为"邮件配置"
|
|
||||||
- 将"考点"列改为"配置项"列
|
|
||||||
- 将"权值"列改为"配置值"列
|
|
||||||
- 将"添加"按钮改为"设置"按钮
|
|
||||||
|
|
||||||
## 使用流程
|
|
||||||
|
|
||||||
1. 用户在EmailForm中点击"设置"按钮
|
|
||||||
2. 打开Email组件的设置弹窗
|
|
||||||
3. 用户在Email组件中进行各种设置(语言、皮肤、账户等)
|
|
||||||
4. 每次设置都会通过`sendEmailMsg()`保存到`emailStore.emailFormList`中
|
|
||||||
5. 用户关闭弹窗时,触发`handleEmailForm()`函数
|
|
||||||
6. `handleEmailForm()`从store中获取数据并更新外部表格`list.value`
|
|
||||||
7. 表格显示格式化的配置信息,如:
|
|
||||||
- "设置邮件界面语言: 中文" | "common@language@zh_cn"
|
|
||||||
- "设置邮件应用皮肤: default" | "skin@appliedSkin@default"
|
|
||||||
- "设置邮件邮件昵称: demo" | "account@nickname@demo"
|
|
||||||
|
|
||||||
## 数据格式说明
|
|
||||||
|
|
||||||
每个配置项在store中的数据格式:
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
{
|
|
||||||
contentIn: "设置邮件界面语言: 中文", // 用户友好的描述
|
|
||||||
content: "common@language@zh_cn" // 结构化的数据标识
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 测试验证
|
|
||||||
|
|
||||||
可以按以下步骤测试功能:
|
|
||||||
|
|
||||||
1. 打开EmailForm页面
|
|
||||||
2. 点击"邮件配置"标签页中的"设置"按钮
|
|
||||||
3. 在Email组件中修改各种设置(语言、皮肤等)
|
|
||||||
4. 关闭设置弹窗
|
|
||||||
5. 检查外部表格是否显示了相应的配置项
|
|
||||||
6. 通过浏览器开发者工具查看console.log输出确认数据保存
|
|
||||||
|
|
||||||
这样就完成了Email组件的外部表格保存功能,与Setting组件的实现模式完全一致。
|
|
@@ -45,8 +45,8 @@
|
|||||||
封邮件
|
封邮件
|
||||||
</div>
|
</div>
|
||||||
<el-checkbox-group v-model="commonForm.checkList" @change="handleCheckboxChange">
|
<el-checkbox-group v-model="commonForm.checkList" @change="handleCheckboxChange">
|
||||||
<el-checkbox label="main">显示邮件摘要</el-checkbox>
|
<el-checkbox label="显示邮件摘要">显示邮件摘要</el-checkbox>
|
||||||
<el-checkbox label="size">显示邮件大小</el-checkbox>
|
<el-checkbox label="显示邮件大小">显示邮件大小</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="在首页上:">
|
<el-form-item label="在首页上:">
|
||||||
@@ -260,7 +260,7 @@ const handleLanguageChange = (value: string) => {
|
|||||||
// 文字大小变更处理
|
// 文字大小变更处理
|
||||||
const handleFontSizeChange = (value: number) => {
|
const handleFontSizeChange = (value: number) => {
|
||||||
const sizeText = ['标准', '中号', '大号'][value]
|
const sizeText = ['标准', '中号', '大号'][value]
|
||||||
sendEmailMsg(name.value, '文字大小', 'common', 'fontSize', value)
|
sendEmailMsg(name.value, '文字大小', 'common', 'fontSize', sizeText)
|
||||||
ElMessage.success(`文字大小已设置为: ${sizeText}`)
|
ElMessage.success(`文字大小已设置为: ${sizeText}`)
|
||||||
console.log('文字大小变更:', value, sizeText)
|
console.log('文字大小变更:', value, sizeText)
|
||||||
}
|
}
|
||||||
|
@@ -19,13 +19,27 @@
|
|||||||
<span class="text-label">收件人</span>
|
<span class="text-label">收件人</span>
|
||||||
<el-input v-model="recipient" class="row-input" />
|
<el-input v-model="recipient" class="row-input" />
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 抄送输入框 -->
|
||||||
|
<div v-if="showCc" class="row flex" style="margin-bottom: 5px">
|
||||||
|
<span class="text-label">抄送</span>
|
||||||
|
<el-input v-model="cc" class="row-input" placeholder="请输入抄送邮箱地址" />
|
||||||
|
</div>
|
||||||
|
<!-- 密送输入框 -->
|
||||||
|
<div v-if="showBcc" class="row flex" style="margin-bottom: 5px">
|
||||||
|
<span class="text-label">密送</span>
|
||||||
|
<el-input v-model="bcc" class="row-input" placeholder="请输入密送邮箱地址" />
|
||||||
|
</div>
|
||||||
<div
|
<div
|
||||||
class="row flex"
|
class="row flex"
|
||||||
style="justify-content: flex-start; padding-left: 7.5%; margin-bottom: 8px"
|
style="justify-content: flex-start; padding-left: 7.5%; margin-bottom: 8px"
|
||||||
>
|
>
|
||||||
<div class="text-button" style="margin-right: 8px">添加抄送</div>
|
<div class="text-button" style="margin-right: 8px" @click="toggleCc">
|
||||||
|
{{ showCc ? '隐藏抄送' : '添加抄送' }}
|
||||||
|
</div>
|
||||||
<div class="text-divider" style="margin-right: 8px">-</div>
|
<div class="text-divider" style="margin-right: 8px">-</div>
|
||||||
<div class="text-button" style="margin-right: 8px">添加密送</div>
|
<div class="text-button" style="margin-right: 8px" @click="toggleBcc">
|
||||||
|
{{ showBcc ? '隐藏密送' : '添加密送' }}
|
||||||
|
</div>
|
||||||
<div class="text-divider" style="margin-right: 8px; color: #ccc6bf">|</div>
|
<div class="text-divider" style="margin-right: 8px; color: #ccc6bf">|</div>
|
||||||
<div class="text-button">分别发送</div>
|
<div class="text-button">分别发送</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -37,7 +51,7 @@
|
|||||||
class="row flex"
|
class="row flex"
|
||||||
style="justify-content: flex-start; padding-left: 7.5%; margin-bottom: 5px"
|
style="justify-content: flex-start; padding-left: 7.5%; margin-bottom: 5px"
|
||||||
>
|
>
|
||||||
<div class="text-button flex" style="margin-right: 10px">
|
<div class="text-button flex" style="margin-right: 10px" @click="handleAddAttachment">
|
||||||
<img src="../img/annex_logo.png" style="width: 14px; height: 14px; margin-right: 3px" />
|
<img src="../img/annex_logo.png" style="width: 14px; height: 14px; margin-right: 3px" />
|
||||||
添加附件
|
添加附件
|
||||||
</div>
|
</div>
|
||||||
@@ -82,6 +96,57 @@
|
|||||||
格式
|
格式
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 附件显示区域 -->
|
||||||
|
<div
|
||||||
|
v-if="attachments.length > 0"
|
||||||
|
class="row flex"
|
||||||
|
style="flex-direction: column; align-items: flex-start; margin-bottom: 8px"
|
||||||
|
>
|
||||||
|
<span class="text-label" style="margin-bottom: 5px; margin-left: 7.5%"
|
||||||
|
>附件 ({{ attachments.length }})</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
|
width: 93%;
|
||||||
|
margin-left: 7.5%;
|
||||||
|
border: 1px solid #707070;
|
||||||
|
background: #fff;
|
||||||
|
padding: 8px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-for="(attachment, index) in attachments"
|
||||||
|
:key="attachment.id"
|
||||||
|
class="attachment-item flex"
|
||||||
|
style="
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
background: #f5f5f5;
|
||||||
|
border-radius: 3px;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div class="attachment-info flex" style="align-items: center">
|
||||||
|
<img
|
||||||
|
src="../img/annex_logo.png"
|
||||||
|
style="width: 16px; height: 16px; margin-right: 5px"
|
||||||
|
/>
|
||||||
|
<span style="font-size: 14px; color: #333">{{ attachment.name }}</span>
|
||||||
|
<span style="font-size: 12px; color: #666; margin-left: 10px"
|
||||||
|
>({{ attachment.size }})</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<el-button
|
||||||
|
type="danger"
|
||||||
|
size="small"
|
||||||
|
@click="removeAttachment(index)"
|
||||||
|
style="padding: 2px 5px; font-size: 12px"
|
||||||
|
>删除</el-button
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="row flex" style="flex: 1; align-items: flex-start; margin-bottom: 8px">
|
<div class="row flex" style="flex: 1; align-items: flex-start; margin-bottom: 8px">
|
||||||
<span class="text-label">正文</span>
|
<span class="text-label">正文</span>
|
||||||
<el-input v-model="content" type="textarea" class="row-input" />
|
<el-input v-model="content" type="textarea" class="row-input" />
|
||||||
@@ -121,6 +186,56 @@ const recipient = ref('')
|
|||||||
const subject = ref('')
|
const subject = ref('')
|
||||||
const content = ref('')
|
const content = ref('')
|
||||||
|
|
||||||
|
// CC和BCC相关
|
||||||
|
const showCc = ref(false)
|
||||||
|
const cc = ref('')
|
||||||
|
const showBcc = ref(false)
|
||||||
|
const bcc = ref('')
|
||||||
|
|
||||||
|
// 附件相关
|
||||||
|
const attachments = ref<Array<{ id: number; name: string; size: string; file: File }>>([])
|
||||||
|
|
||||||
|
// 切换CC显示
|
||||||
|
const toggleCc = () => {
|
||||||
|
showCc.value = !showCc.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 切换BCC显示
|
||||||
|
const toggleBcc = () => {
|
||||||
|
showBcc.value = !showBcc.value
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加附件
|
||||||
|
const handleAddAttachment = () => {
|
||||||
|
// 创建文件输入元素
|
||||||
|
const input = document.createElement('input')
|
||||||
|
input.type = 'file'
|
||||||
|
input.multiple = true
|
||||||
|
input.onchange = (event: Event) => {
|
||||||
|
const target = event.target as HTMLInputElement
|
||||||
|
const files = target?.files
|
||||||
|
if (files) {
|
||||||
|
for (let i = 0; i < files.length; i++) {
|
||||||
|
const file = files[i]
|
||||||
|
attachments.value.push({
|
||||||
|
id: Date.now() + i,
|
||||||
|
name: file.name,
|
||||||
|
size: (file.size / 1024 / 1024).toFixed(2) + 'MB',
|
||||||
|
file: file
|
||||||
|
})
|
||||||
|
}
|
||||||
|
ElMessage.success(`已添加 ${files.length} 个附件`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input.click()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 删除附件
|
||||||
|
const removeAttachment = (index: number) => {
|
||||||
|
attachments.value.splice(index, 1)
|
||||||
|
ElMessage.info('已删除附件')
|
||||||
|
}
|
||||||
|
|
||||||
// 发送邮件
|
// 发送邮件
|
||||||
const handleSend = () => {
|
const handleSend = () => {
|
||||||
if (!recipient.value.trim()) {
|
if (!recipient.value.trim()) {
|
||||||
@@ -141,6 +256,22 @@ const handleSend = () => {
|
|||||||
sendEmailMsg(name.value, '邮件主题', 'write', 'subject', subject.value)
|
sendEmailMsg(name.value, '邮件主题', 'write', 'subject', subject.value)
|
||||||
sendEmailMsg(name.value, '邮件正文', 'write', 'content', content.value)
|
sendEmailMsg(name.value, '邮件正文', 'write', 'content', content.value)
|
||||||
|
|
||||||
|
// 保存CC信息
|
||||||
|
if (cc.value.trim()) {
|
||||||
|
sendEmailMsg(name.value, '抄送', 'write', 'cc', cc.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存BCC信息
|
||||||
|
if (bcc.value.trim()) {
|
||||||
|
sendEmailMsg(name.value, '密送', 'write', 'bcc', bcc.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存附件信息
|
||||||
|
if (attachments.value.length > 0) {
|
||||||
|
const attachmentNames = attachments.value.map((att) => att.name).join(', ')
|
||||||
|
sendEmailMsg(name.value, '附件', 'write', 'attachments', attachmentNames)
|
||||||
|
}
|
||||||
|
|
||||||
ElMessage.success('邮件发送成功!')
|
ElMessage.success('邮件发送成功!')
|
||||||
|
|
||||||
// 清空表单
|
// 清空表单
|
||||||
@@ -206,6 +337,11 @@ const clearForm = () => {
|
|||||||
recipient.value = ''
|
recipient.value = ''
|
||||||
subject.value = ''
|
subject.value = ''
|
||||||
content.value = ''
|
content.value = ''
|
||||||
|
cc.value = ''
|
||||||
|
bcc.value = ''
|
||||||
|
attachments.value = []
|
||||||
|
showCc.value = false
|
||||||
|
showBcc.value = false
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@@ -26,8 +26,8 @@ export function sendEmailMsg(pageName: string, description: string, category: st
|
|||||||
// 拼接 content 字符串
|
// 拼接 content 字符串
|
||||||
const content = `${category}@${key}@${value}`
|
const content = `${category}@${key}@${value}`
|
||||||
|
|
||||||
// 创建数据对象并添加到 store(包含scoreRate权值字段,默认为空,由用户填写)
|
// 创建数据对象并添加到 store(包含scoreRate权值字段,默认为1)
|
||||||
const data = { contentIn, content, scoreRate: '' };
|
const data = { contentIn, content, scoreRate: 1 };
|
||||||
|
|
||||||
// 为了避免重复,可以先查找并更新,如果不存在再添加
|
// 为了避免重复,可以先查找并更新,如果不存在再添加
|
||||||
const existingIndex = emailStore.emailFormList.findIndex(item => item.content.startsWith(`${category}@${key}@`));
|
const existingIndex = emailStore.emailFormList.findIndex(item => item.content.startsWith(`${category}@${key}@`));
|
||||||
|
@@ -515,7 +515,7 @@ const open = async (queryParams: any, type: string, id?: number) => {
|
|||||||
dialogVisible.value = true
|
dialogVisible.value = true
|
||||||
dialogTitle.value = t('action.' + type)
|
dialogTitle.value = t('action.' + type)
|
||||||
formType.value = type
|
formType.value = type
|
||||||
|
resetForm()
|
||||||
// 修改时,设置数据
|
// 修改时,设置数据
|
||||||
if (id) {
|
if (id) {
|
||||||
formLoading.value = true
|
formLoading.value = true
|
||||||
@@ -554,6 +554,12 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
|||||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||||
const submitForm = async () => {
|
const submitForm = async () => {
|
||||||
formData.value.answerList = list.value
|
formData.value.answerList = list.value
|
||||||
|
//默认权值为1
|
||||||
|
formData.value.answerList.forEach((item) => {
|
||||||
|
if (!item.scoreRate) {
|
||||||
|
item.scoreRate = '1' // 设置默认权值为1
|
||||||
|
}
|
||||||
|
})
|
||||||
formData.value.fileUploads = documentList.value
|
formData.value.fileUploads = documentList.value
|
||||||
const values = Object.values(formData)
|
const values = Object.values(formData)
|
||||||
console.log(values)
|
console.log(values)
|
||||||
@@ -600,7 +606,7 @@ const resetForm = () => {
|
|||||||
image: '',
|
image: '',
|
||||||
content: '',
|
content: '',
|
||||||
contentIn: '',
|
contentIn: '',
|
||||||
scoreRate: ''
|
scoreRate: '1'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
fileUploads: [
|
fileUploads: [
|
||||||
|
Reference in New Issue
Block a user