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>
|
||||
<el-checkbox-group v-model="commonForm.checkList" @change="handleCheckboxChange">
|
||||
<el-checkbox label="main">显示邮件摘要</el-checkbox>
|
||||
<el-checkbox label="size">显示邮件大小</el-checkbox>
|
||||
<el-checkbox label="显示邮件摘要">显示邮件摘要</el-checkbox>
|
||||
<el-checkbox label="显示邮件大小">显示邮件大小</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="在首页上:">
|
||||
@@ -260,7 +260,7 @@ const handleLanguageChange = (value: string) => {
|
||||
// 文字大小变更处理
|
||||
const handleFontSizeChange = (value: number) => {
|
||||
const sizeText = ['标准', '中号', '大号'][value]
|
||||
sendEmailMsg(name.value, '文字大小', 'common', 'fontSize', value)
|
||||
sendEmailMsg(name.value, '文字大小', 'common', 'fontSize', sizeText)
|
||||
ElMessage.success(`文字大小已设置为: ${sizeText}`)
|
||||
console.log('文字大小变更:', value, sizeText)
|
||||
}
|
||||
|
@@ -19,13 +19,27 @@
|
||||
<span class="text-label">收件人</span>
|
||||
<el-input v-model="recipient" class="row-input" />
|
||||
</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
|
||||
class="row flex"
|
||||
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-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-button">分别发送</div>
|
||||
</div>
|
||||
@@ -37,7 +51,7 @@
|
||||
class="row flex"
|
||||
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" />
|
||||
添加附件
|
||||
</div>
|
||||
@@ -82,6 +96,57 @@
|
||||
格式
|
||||
</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">
|
||||
<span class="text-label">正文</span>
|
||||
<el-input v-model="content" type="textarea" class="row-input" />
|
||||
@@ -121,6 +186,56 @@ const recipient = ref('')
|
||||
const subject = 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 = () => {
|
||||
if (!recipient.value.trim()) {
|
||||
@@ -141,6 +256,22 @@ const handleSend = () => {
|
||||
sendEmailMsg(name.value, '邮件主题', 'write', 'subject', subject.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('邮件发送成功!')
|
||||
|
||||
// 清空表单
|
||||
@@ -206,6 +337,11 @@ const clearForm = () => {
|
||||
recipient.value = ''
|
||||
subject.value = ''
|
||||
content.value = ''
|
||||
cc.value = ''
|
||||
bcc.value = ''
|
||||
attachments.value = []
|
||||
showCc.value = false
|
||||
showBcc.value = false
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@@ -26,8 +26,8 @@ export function sendEmailMsg(pageName: string, description: string, category: st
|
||||
// 拼接 content 字符串
|
||||
const content = `${category}@${key}@${value}`
|
||||
|
||||
// 创建数据对象并添加到 store(包含scoreRate权值字段,默认为空,由用户填写)
|
||||
const data = { contentIn, content, scoreRate: '' };
|
||||
// 创建数据对象并添加到 store(包含scoreRate权值字段,默认为1)
|
||||
const data = { contentIn, content, scoreRate: 1 };
|
||||
|
||||
// 为了避免重复,可以先查找并更新,如果不存在再添加
|
||||
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
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
@@ -554,6 +554,12 @@ defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
formData.value.answerList = list.value
|
||||
//默认权值为1
|
||||
formData.value.answerList.forEach((item) => {
|
||||
if (!item.scoreRate) {
|
||||
item.scoreRate = '1' // 设置默认权值为1
|
||||
}
|
||||
})
|
||||
formData.value.fileUploads = documentList.value
|
||||
const values = Object.values(formData)
|
||||
console.log(values)
|
||||
@@ -600,7 +606,7 @@ const resetForm = () => {
|
||||
image: '',
|
||||
content: '',
|
||||
contentIn: '',
|
||||
scoreRate: ''
|
||||
scoreRate: '1'
|
||||
}
|
||||
],
|
||||
fileUploads: [
|
||||
|
Reference in New Issue
Block a user