<template> <div v-loading="loading" style="padding: 10px"> <!-- <div style="margin-bottom: 10px; padding-left: 65px"> <el-button type="primary" @click="handleSend">发 送</el-button> </div> --> <div style="width: 100%"> <el-form ref="submit" :model="formData.data" :rules="rules" label-width="65px" labelPosition="right" > <el-form-item> <el-button type="primary" @click="handleSend()"> 发 送 </el-button> </el-form-item> <el-form-item label="收件人" prop="to"> <div style="width: 100%"> <div style="display: flex; width: 100%"> <!-- <el-autocomplete v-model="formData.data.to" clearable placeholder="请输入" style="width: 100%" @select="handlePerson" :fetch-suggestions="querySearchPerson" @keyup.enter.native="handleAdd(10)" > </el-autocomplete> --> <el-input v-model="formData.data.to" placeholder="请输入" @keyup.enter.native="handleAdd(10)" /> <!-- <el-button type="primary" @click="handleAdd(10)" style="margin-left: 10px" :disabled="!formData.data.to" >添加</el-button > --> </div> <div style="margin-top: 15px" v-if="to && to.length > 0"> <el-tag style="margin-right: 10px" class="ml-2" type="info" v-for="(item, index) in to" :key="index" closable @close="handleClose(index, 10)" >{{ item.address }}</el-tag > </div> </div> </el-form-item> <el-form-item label="" prop=""> <div style="display: flex"> <span style="color: #666666; cursor: pointer" @click="showcc = !showcc" >抄送</span > <span style="color: ##dddddd; margin: 0 8px">|</span> <span style="color: #666666; cursor: pointer" @click="showbcc = !showbcc" >密送</span > </div> </el-form-item> <el-form-item label="抄送人" prop="cc" v-if="showcc"> <div style="width: 100%"> <div style="display: flex; width: 100%"> <!-- <el-autocomplete v-model="formData.data.cc" clearable class="inline-input w-50" placeholder="请输入" @select="handlePerson" :fetch-suggestions="querySearchPerson" @keyup.enter.native="handleAdd(20)" > </el-autocomplete> --> <el-input v-model="formData.data.cc" placeholder="请输入" @keyup.enter.native="handleAdd(20)" /> <!-- <el-button type="primary" @click="handleAdd(20)" style="margin-left: 10px" :disabled="!formData.data.cc" >添加</el-button > --> </div> <div style="margin-top: 15px" v-if="cc && cc.length > 0"> <el-tag style="margin-right: 10px" class="ml-2" type="info" v-for="(item, index) in cc" :key="index" closable @close="handleClose(index, 20)" >{{ item.address }}</el-tag > </div> </div> </el-form-item> <el-form-item label="密送人" prop="bcc" v-if="showbcc"> <div style="width: 100%"> <div style="display: flex; width: 100%"> <!-- <el-autocomplete v-model="formData.data.bcc" clearable placeholder="请输入" @select="handlePerson" :fetch-suggestions="querySearchPerson" @keyup.enter.native="handleAdd(30)" > </el-autocomplete> --> <el-input v-model="formData.data.bcc" placeholder="请输入" @keyup.enter.native="handleAdd(30)" /> <!-- <el-button type="primary" @click="handleAdd(30)" style="margin-left: 10px" :disabled="!formData.data.bcc" >添加</el-button > --> </div> <div style="margin-top: 15px" v-if="bcc && bcc.length > 0"> <el-tag style="margin-right: 10px" class="ml-2" type="info" v-for="(item, index) in bcc" :key="index" closable @close="handleClose(index, 30)" >{{ item.address }}</el-tag > </div> </div> </el-form-item> <el-form-item label="主题" prop="subject"> <el-input v-model="formData.data.subject" placeholder="请输入" /> </el-form-item> <el-form-item label="附件"> <div style="width: 100%"> <el-upload v-model:fileList="fileList" class="upload-demo" action="https://winfaster.obs.cn-south-1.myhuaweicloud.com" :data="uploadData" drag multiple :show-file-list="false" :before-upload="handleBeforeUpload" > <div> <img src="@/assets/images/icon_attachment.svg" class="att-img" fit="scale-down" /> <span style="padding-left: 8px" >将文件拖到此处,或<span style="color: #409eff" >点击上传</span ></span > </div> </el-upload> <div class="att-box" v-if="fileListCopy && fileListCopy.length > 0"> <div v-for="(itemFile, index) in fileListCopy" :key="index"> <div class="att-item"> <img src="@/assets/images/icon_dz.svg" style="cursor: pointer" fit="scale-down" /> <div class="att-name"> {{ itemFile.fileName }} </div> <img src="@/assets/images/icon_delete.svg" class="att-img" fit="scale-down" /> </div> </div> </div> </div> </el-form-item> <el-form-item label="正文" prop="content"> <div style="width: 100%"> <Editor :value="formData.data.content" @updateValue="updateContent" ref="contentEditor" /> </div> </el-form-item> <el-form-item label="发件人" prop="replyTo"> <el-input v-model="formData.data.replyTo" placeholder="请输入" style="width: 50%" /> </el-form-item> <el-form-item> <el-button type="primary" @click="handleSend()"> 发 送 </el-button> </el-form-item> </el-form> </div> </div> </template> <script setup> import byForm from "@/components/byForm/index"; import { ElMessage, ElMessageBox } from "element-plus"; import Editor from "@/components/Editor/index.vue"; import { validEmail } from "@/utils/validate.js"; import useMailStore from "@/store/modules/mail"; import { nextTick } from "vue"; const mailStore = useMailStore(); const { proxy } = getCurrentInstance(); const loading = ref(false); let uploadData = ref({}); const fileList = ref([]); const fileListCopy = ref([]); const showcc = ref(false); const showbcc = ref(false); const formOption = reactive({ inline: true, labelWidth: 65, itemWidth: 100, labelPosition: "right", }); const formConfig = computed(() => { return [ { type: "slot", slotName: "to", label: "收件人", prop: "to", }, { type: "slot", slotName: "bbcc", }, { type: "slot", slotName: "cc", label: "抄送人", prop: "cc", }, { type: "slot", slotName: "bcc", label: "密送人", prop: "bcc", }, { type: "input", prop: "subject", label: "主题", required: true, itemWidth: 50.1, itemType: "text", }, { type: "slot", slotName: "fileSlot", label: "附件", }, { type: "slot", slotName: "contentSlot", label: "正文", }, { type: "input", prop: "replyTo", label: "发件人", required: true, itemWidth: 50, itemType: "text", }, ]; }); const rules = ref({ subject: [{ required: true, message: "请输入主题", trigger: "blur" }], replyTo: [{ required: true, message: "请输入发件人", trigger: "blur" }], }); const formData = reactive({ data: { content: "", }, }); const to = ref([]); const cc = ref([]); const bcc = ref([]); const replyTo = ref([]); const submit = ref(null); const handleReset = () => { formData.data = { to: "", cc: "", bcc: "", content: "", subject: "", replyTo: "", }; to.value = []; cc.value = []; bcc.value = []; fileList.value = []; fileListCopy.value = []; contentEditor.value.changeHtml(""); }; const handleSend = () => { submit.value.validate((valid) => { if (valid) { const data = { ...formData.data }; if (!to.value.length > 0) { return ElMessage({ message: "请添加收件人", type: "info", }); } if (!validEmail(formData.data.replyTo)) { return ElMessage({ message: "发件人邮箱格式不正确", type: "info", }); } if (data.content) { loading.value = true; let replyTo = [ { address: formData.data.replyTo, personal: null, }, ]; const submitData = { type: mailStore.selectMail.type, mailboxId: mailStore.selectMail.id, subject: data.subject, content: data.content, to: to.value, cc: cc.value, bcc: bcc.value, replyTo: replyTo, fileList: fileListCopy.value.map((x) => ({ fileName: x.fileName, fileUrl: x.fileUrl, })), }; proxy.post("/mailService/sendMail", submitData).then((res) => { ElMessage({ message: "发送成功", type: "success", }); handleReset(); loading.value = false; }); } else { return ElMessage({ message: "请输入正文", type: "info", }); } } }); }; const updateContent = (val) => { formData.data.content = val; }; const handleBeforeUpload = async (file) => { const res = await proxy.post("/fileInfo/getSing", { fileName: file.name }); uploadData.value = res.uploadBody; fileListCopy.value.push({ id: res.id, fileName: res.fileName, path: res.fileUrl, fileUrl: res.fileUrl, uid: file.uid, }); }; const handleClose = (index, val) => { switch (val) { case 10: to.value.splice(index, 1); break; case 20: cc.value.splice(index, 1); break; case 30: bcc.value.splice(index, 1); break; } }; const handleAdd = (val) => { switch (val) { case 10: { if (!validEmail(formData.data.to)) { return ElMessage({ message: "收件人邮箱格式不正确", type: "info", }); } to.value.push({ address: formData.data.to, personal: null, }); formData.data.to = ""; break; } case 20: { if (!validEmail(formData.data.cc)) { return ElMessage({ message: "抄送人邮箱格式不正确", type: "info", }); } cc.value.push({ address: formData.data.cc, personal: null, }); formData.data.cc = ""; break; } case 30: { if (!validEmail(formData.data.bcc)) { return ElMessage({ message: "密送人邮箱格式不正确", type: "info", }); } bcc.value.push({ address: formData.data.bcc, personal: null, }); formData.data.bcc = ""; break; } } }; const handlePerson = () => {}; const createFilter = (queryString) => { return (restaurant) => { return ( restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0 ); }; }; const distributionCenterData = ref([]); const querySearchPerson = (queryString, callback) => { const results = queryString ? distributionCenterData.value.filter(createFilter(queryString)) : distributionCenterData.value; callback(results); }; const contentEditor = ref(null); const handleReplyInit = (allData, pageType) => { let data = allData.details; // 回复功能:则发件人是回复的收件人 if (pageType === "10") { if (data.messageAddressList && data.messageAddressList.length > 0) { to.value = data.messageAddressList .filter((x) => x.type === 4) .map((x) => ({ address: x.email, personal: x.personalName, })); } formData.data.subject = "Re: " + data.subject; } else if (pageType === "20") { to.value = []; formData.data.subject = "Fw: " + data.subject; } else if (pageType === "30") { // 全部回复 if (data.messageAddressList && data.messageAddressList.length > 0) { to.value = data.messageAddressList .filter((x) => x.type !== 1) .map((x) => ({ address: x.email, personal: x.personalName, })); } formData.data.subject = "Re: " + data.subject; } else if (pageType === "40") { if (data.messageAddressList && data.messageAddressList.length > 0) { to.value = data.messageAddressList .filter((x) => x.type === 1) .map((x) => ({ address: x.email, personal: x.personalName, })); const cc = data.messageAddressList .filter((x) => x.type === 2) .map((x) => ({ address: x.email, personal: x.personalName, })); if (cc.length > 0) { showcc.value = true; cc.value = cc; } const bcc = data.messageAddressList .filter((x) => x.type === 2) .map((x) => ({ address: x.email, personal: x.personalName, })); if (bcc.length > 0) { showbcc.value = true; bcc.value = bcc; } } formData.data.subject = data.subject; } else if (pageType === "50") { handleReset(); to.value = [ { address: mailStore.currentMenu.reMail, personal: null, }, ]; } if (pageType !== "50") { contentEditor.value.changeHtml( `<p><br></p><p><br></p>${data.content}`, true ); nextTick(() => { contentEditor.value.getFocus(); }); formData.data.replyTo = mailStore.selectMail.mailUser; } }; // pageType 10为回复 20为转发 30为全部回复 40为再次编辑 0为写信 50为只回填收件人 const init = () => { if (mailStore.currentMenu.pageType === "0") { handleReset(); } else if (mailStore.currentMenu.pageType === "10") { handleReplyInit(mailStore.currentMenu, "10"); } else if (mailStore.currentMenu.pageType === "20") { handleReplyInit(mailStore.currentMenu, "20"); } else if (mailStore.currentMenu.pageType === "30") { handleReplyInit(mailStore.currentMenu, "30"); } else if (mailStore.currentMenu.pageType === "40") { handleReplyInit(mailStore.currentMenu, "40"); } else if (mailStore.currentMenu.pageType === "50") { handleReplyInit(mailStore.currentMenu, "50"); } }; watch( () => mailStore.currentMenu.pageType, (val) => { if (val === "0") { handleReset(); } else if (val === "10") { handleReplyInit(mailStore.currentMenu, "10"); } else if (val === "20") { handleReplyInit(mailStore.currentMenu, "20"); } else if (val === "30") { handleReplyInit(mailStore.currentMenu, "30"); } else if (val === "40") { handleReplyInit(mailStore.currentMenu, "40"); } else if (val === "50") { handleReplyInit(mailStore.currentMenu, "50"); } } ); onMounted(() => { // if (mailStore.currentMenu.reMail) { // to.value.push({ // address: mailStore.currentMenu.reMail, // personal: null, // }); // } }); defineExpose({ initFn: init, }); </script> <style lang="scss" scoped> .att-img { height: 18px; width: 18px; transform: translateY(4px); } .att-box { padding-bottom: 8px; display: flex; flex-wrap: wrap; .att-item { width: 200px; background-color: #eeeeee; height: 28px; line-height: 26px; margin-right: 16px; padding-left: 8px; display: flex; margin-top: 10px; // margin-bottom: 8px; } .att-name { padding-left: 8px; width: 150px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; cursor: pointer; } } :deep(.el-upload-dragger) { width: 250px; height: 40px; line-height: 40px; padding: 0 8px; } // .el-form-item--default { // margin-bottom: 0px; // } </style>