|
@@ -3,7 +3,7 @@
|
|
|
<div style="margin-bottom: 10px; padding-left: 65px">
|
|
|
<el-button type="primary" @click="handleSend">发送</el-button>
|
|
|
</div>
|
|
|
- <div style="width: 70%">
|
|
|
+ <div style="width: 100%">
|
|
|
<byForm
|
|
|
:formConfig="formConfig"
|
|
|
:formOption="formOption"
|
|
@@ -11,7 +11,160 @@
|
|
|
:rules="rules"
|
|
|
ref="submit"
|
|
|
>
|
|
|
- <template #contentSlot> 内容插槽 </template>
|
|
|
+ <template #to>
|
|
|
+ <div>
|
|
|
+ <div style="display: flex">
|
|
|
+ <el-autocomplete
|
|
|
+ v-model="formData.data.to"
|
|
|
+ clearable
|
|
|
+ class="inline-input w-50"
|
|
|
+ placeholder="请输入"
|
|
|
+ @select="handlePerson"
|
|
|
+ :fetch-suggestions="querySearchPerson"
|
|
|
+ >
|
|
|
+ </el-autocomplete>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="handleAdd(10)"
|
|
|
+ style="margin-left: 10px"
|
|
|
+ >添加</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div style="margin-top: 15px">
|
|
|
+ <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>
|
|
|
+ </template>
|
|
|
+ <template #cc>
|
|
|
+ <div>
|
|
|
+ <div style="display: flex">
|
|
|
+ <el-autocomplete
|
|
|
+ v-model="formData.data.cc"
|
|
|
+ clearable
|
|
|
+ class="inline-input w-50"
|
|
|
+ placeholder="请输入"
|
|
|
+ @select="handlePerson"
|
|
|
+ :fetch-suggestions="querySearchPerson"
|
|
|
+ >
|
|
|
+ </el-autocomplete>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="handleAdd(20)"
|
|
|
+ style="margin-left: 10px"
|
|
|
+ >添加</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div style="margin-top: 15px">
|
|
|
+ <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>
|
|
|
+ </template>
|
|
|
+ <template #bcc>
|
|
|
+ <div>
|
|
|
+ <div style="display: flex">
|
|
|
+ <el-autocomplete
|
|
|
+ v-model="formData.data.bcc"
|
|
|
+ clearable
|
|
|
+ class="inline-input w-50"
|
|
|
+ placeholder="请输入"
|
|
|
+ @select="handlePerson"
|
|
|
+ :fetch-suggestions="querySearchPerson"
|
|
|
+ >
|
|
|
+ </el-autocomplete>
|
|
|
+ <el-button
|
|
|
+ type="primary"
|
|
|
+ @click="handleAdd(30)"
|
|
|
+ style="margin-left: 10px"
|
|
|
+ >添加</el-button
|
|
|
+ >
|
|
|
+ </div>
|
|
|
+ <div style="margin-top: 15px">
|
|
|
+ <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>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <template #contentSlot>
|
|
|
+ <div style="width: 100%">
|
|
|
+ <Editor
|
|
|
+ :value="formData.data.content"
|
|
|
+ @updateValue="updateContent"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #fileSlot>
|
|
|
+ <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">
|
|
|
+ <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>
|
|
|
+ </template>
|
|
|
</byForm>
|
|
|
</div>
|
|
|
</div>
|
|
@@ -20,59 +173,250 @@
|
|
|
<script setup>
|
|
|
import byForm from "@/components/byForm/index";
|
|
|
import { ElMessage, ElMessageBox } from "element-plus";
|
|
|
-let loading = ref(false);
|
|
|
+import Editor from "@/components/Editor/index.vue";
|
|
|
+import { validEmail } from "@/utils/validate.js";
|
|
|
+import useMailStore from "@/store/modules/mail";
|
|
|
+const mailStore = useMailStore();
|
|
|
+console.log(mailStore, "wda");
|
|
|
+const { proxy } = getCurrentInstance();
|
|
|
+const loading = ref(false);
|
|
|
+let uploadData = ref({});
|
|
|
+const fileList = ref([]);
|
|
|
+const fileListCopy = ref([]);
|
|
|
const formOption = reactive({
|
|
|
inline: true,
|
|
|
labelWidth: 65,
|
|
|
itemWidth: 100,
|
|
|
- labelPosition: "left",
|
|
|
+ labelPosition: "right",
|
|
|
});
|
|
|
const formConfig = computed(() => {
|
|
|
return [
|
|
|
{
|
|
|
- type: "input",
|
|
|
- prop: "aa",
|
|
|
+ type: "slot",
|
|
|
+ slotName: "to",
|
|
|
label: "收件人",
|
|
|
- required: true,
|
|
|
- itemWidth: 100,
|
|
|
- itemType: "text",
|
|
|
+ prop: "to",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "slot",
|
|
|
+ slotName: "cc",
|
|
|
+ label: "抄送人",
|
|
|
+ prop: "cc",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "slot",
|
|
|
+ slotName: "bcc",
|
|
|
+ label: "密送人",
|
|
|
+ prop: "bcc",
|
|
|
},
|
|
|
{
|
|
|
type: "input",
|
|
|
- prop: "bb",
|
|
|
+ prop: "subject",
|
|
|
label: "主题",
|
|
|
required: true,
|
|
|
- itemWidth: 100,
|
|
|
+ itemWidth: 50.1,
|
|
|
itemType: "text",
|
|
|
},
|
|
|
{
|
|
|
type: "slot",
|
|
|
+ slotName: "fileSlot",
|
|
|
+ label: "附件",
|
|
|
+ },
|
|
|
+ {
|
|
|
+ type: "slot",
|
|
|
slotName: "contentSlot",
|
|
|
- label: " ",
|
|
|
+ label: "正文",
|
|
|
},
|
|
|
{
|
|
|
type: "input",
|
|
|
- prop: "cc",
|
|
|
+ prop: "replyTo",
|
|
|
label: "发件人",
|
|
|
required: true,
|
|
|
- itemWidth: 100,
|
|
|
+ itemWidth: 50,
|
|
|
itemType: "text",
|
|
|
},
|
|
|
];
|
|
|
});
|
|
|
const rules = ref({
|
|
|
- aa: [{ required: true, message: "请输入收件人", trigger: "blur" }],
|
|
|
- bb: [{ required: true, message: "请输入主题", trigger: "blur" }],
|
|
|
- cc: [{ required: true, message: "请输入发件人", trigger: "blur" }],
|
|
|
+ subject: [{ required: true, message: "请输入主题", trigger: "blur" }],
|
|
|
+ replyTo: [{ required: true, message: "请输入发件人", trigger: "blur" }],
|
|
|
});
|
|
|
const formData = reactive({
|
|
|
- data: {},
|
|
|
+ data: {
|
|
|
+ content: "",
|
|
|
+ },
|
|
|
});
|
|
|
+const to = ref([]);
|
|
|
+const cc = ref([]);
|
|
|
+const bcc = ref([]);
|
|
|
+const replyTo = ref([]);
|
|
|
const submit = ref(null);
|
|
|
const handleSend = () => {
|
|
|
- submit.value.handleSubmit(() => {});
|
|
|
+ submit.value.handleSubmit(() => {
|
|
|
+ const data = { ...formData.data };
|
|
|
+ if (!to.value.length > 0) {
|
|
|
+ return ElMessage({
|
|
|
+ message: "请添加收件人",
|
|
|
+ type: "info",
|
|
|
+ });
|
|
|
+ }
|
|
|
+ if (data.content) {
|
|
|
+ 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) => {
|
|
|
+ console.log(res, "aa");
|
|
|
+ });
|
|
|
+ } 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,
|
|
|
+ });
|
|
|
+ console.log(to.value, "ada");
|
|
|
+ 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);
|
|
|
};
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
+.att-img {
|
|
|
+ height: 18px;
|
|
|
+ width: 18px;
|
|
|
+ transform: translateY(4px);
|
|
|
+}
|
|
|
+.att-box {
|
|
|
+ padding-bottom: 8px;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ margin-top: 10px;
|
|
|
+ .att-item {
|
|
|
+ width: 200px;
|
|
|
+ background-color: #eeeeee;
|
|
|
+ height: 28px;
|
|
|
+ line-height: 26px;
|
|
|
+ margin-right: 16px;
|
|
|
+ padding-left: 8px;
|
|
|
+ display: flex;
|
|
|
+ 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;
|
|
|
+}
|
|
|
</style>
|