vue2 +富文本(wangeditor)
附件待完善
<template>
<a-modal
:width="1000"
:visible="value"
:title="'发送邮件'"
:confirm-loading="loading"
@cancel="handleCancel"
@ok="handleSubmit"
>
<template slot="footer">
<a-button @click="handleCancel"> 取消 </a-button>
<a-button type="primary" :loading="btnLoading" @click="handleSubmit">
发送
</a-button>
</template>
<a-form
class="g-form"
:label-col="{ span: 3 }"
:wrapper-col="{ span: 20 }"
:form="formModal"
>
<a-row :gutter="[0, 0]" justify="center" align="middle">
<a-col span="24">
<a-form-item label="发件人:"
><label> {{ getSendName }} </label>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item required label="收件人:">
<a-select
:allowClear="true"
mode="multiple"
label-in-value
:value="receiverList"
placeholder="填写选择收件人"
style="width: 100%"
:filter-option="false"
:not-found-content="notContent"
@search="fetchUser"
@change="(e, option) => handleChange(e, false, option)"
>
<a-spin v-if="fetching" slot="notFoundContent" size="small" />
<a-select-option
v-for="d in receiverData"
:item="d"
:label="d.name"
:key="d.value"
>
{{ d.text }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item label="已选择收件人:">
<a-tag color="#108ee9" :key="i" v-for="(v, i) in receiverList">
{{ `${v.name}` }}
</a-tag>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item label="抄送:">
<a-select
:allowClear="true"
mode="multiple"
label-in-value
:value="carbonCopyList"
placeholder="填写选择抄送人"
style="width: 100%"
:filter-option="false"
:not-found-content="notContent"
@search="fetchUser"
@change="(e, option) => handleChange(e, true, option)"
>
<a-spin v-if="fetching" slot="notFoundContent" size="small" />
<a-select-option
:item="d"
v-for="d in receiverData"
:label="d.name"
:key="d.value"
>
{{ d.text }}
</a-select-option>
</a-select>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item label="已选择抄送人:">
<a-tag color="#2db7f5" :key="i" v-for="(v, i) in carbonCopyList">
{{ `${v.name}` }}
</a-tag>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item label="主题:">
<a-input
allowClear
autoComplete="off"
@change="(e) => changeForm(e.target.value, 'topic')"
v-decorator="[
'topic',
{
rules: [
{
required: true,
message: '必填',
},
],
initialValue: detail.topic,
},
]"
/></a-form-item>
</a-col>
</a-row>
<a-row :gutter="[16, 16]">
<a-col span="24">
<a-form-item label="邮件内容:">
<div style="border: 1px solid #ccc">
<Toolbar
style="border-bottom: 1px solid #ccc"
:editor="editor"
:defaultConfig="toolbarConfig"
:mode="mode"
/>
<Editor
style="height: 300px; overflow-y: hidden; z-index: 999"
v-model="html"
:defaultConfig="editorConfig"
:mode="mode"
@onCreated="onCreated"
@onChange="onChange"
@onDestroyed="onDestroyed"
@onMaxLength="onMaxLength"
@onFocus="onFocus"
@onBlur="onBlur"
@customAlert="customAlert"
@customPaste="customPaste"
/>
</div>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item label="文件上传:">
<a-button type="primary" @click="uploadFile"
>上传excel文件</a-button
>
</a-form-item>
</a-col>
<a-col span="24">
<a-form-item label="已上传文件:">
<a
style="margin-right: 16px"
@click="downloadFile(v.url, v.title)"
v-for="(v, i) in attachmentList"
:key="i"
>
{{ v.title }}
</a>
</a-form-item>
</a-col>
</a-row>
</a-form>
<upload-modal
v-if="isShow.upload"
:from="'common'"
:bizType="'2'"
:name="'请上传excel文件'"
:accept="'.xls,.xlsx'"
:checkData="checkData"
:isShow="isShow.upload"
@cancel="uploadClose"
/>
</a-modal>
</template>
<script>
import { mapState } from 'vuex'
import { PriceColumns, extraData } from './data'
import mixin from '@/views/mixin'
import { valuesTrim, timeShow, newGuid } from '@/utils'
import { costApi, commonApi, holidayApi, onLineEndApi } from '@/api'
import UploadModal from '@/views/components/uploader/upload-modal.vue'
import { Editor, Toolbar } from '@wangeditor/editor-for-vue'
import { IToolbarConfig, createToolbar } from '@wangeditor/editor'
import debounce from 'lodash/debounce'
import { uniqWith, isEqual } from 'lodash'
export default {
components: {
UploadModal,
Editor,
Toolbar,
},
mixins: [mixin],
computed: {
...mapState('dictionary', [
'GeneralChooseType',
'ClaimPreserveFieldSource',
]),
...mapState('user', ['userInfo']),
notContent() {
return this.fetching ? undefined : null
},
getSendName() {
let { name, uid } = this.userInfo
return `${name}(${uid})<quotation@ztn.com>`
},
},
props: {
value: {
type: Boolean,
default: false,
},
type: String,
checkRow: {
type: Object,
default: () => {
return {}
},
},
selectRows: {
type: Array,
default: () => {
return []
},
},
},
data() {
this.lastFetchId = 0
this.fetchUser = debounce(this.fetchUser, 800)
return {
carbonCopyData: [],
carbonCopyList: [],
receiverData: [],
receiverList: [],
fetching: false,
isEditor: false,
editor: null,
isReset: false,
html: '<p></p>',
toolbarConfig: {},
editorConfig: { placeholder: '请输入内容...' },
mode: 'default',
checkData: {},
isShow: {
upload: false,
},
channelList: [],
dictArr: [],
detail: this.checkRow,
channelSource,
columns: PriceColumns,
formModal: this.$form.createForm(this, { name: 'priceModal' }),
resetKey: false,
loading: false,
btnLoading: false,
dataSource: [],
CountryList: [],
attachmentList: [],
allSearchList: [],
}
},
created() {
this.initEditConfig()
if (this.selectRows.length) {
this.getConfig()
}
},
mounted() {
this.$nextTick(() => {})
},
beforeDestroy() {
const editor = this.editor
if (editor == null) return
editor.destroy()
},
methods: {
getDictName,
newGuid,
packageArr(arr) {
console.log(arr, 123)
return arr.map((user, i) => {
return {
key: user.employeeCode,
label: `${user.name}<${user.email}>`,
text: `${user.name}<${user.email}>`,
value: user.employeeCode,
employeeCode: user.employeeCode,
name: user.name,
email: user.email,
}
})
},
getConfig() {
onLineEndApi
.onlineEmailDetail({ idList: this.selectRows.map((v) => v.id) })
.then((res) => {
console.log(res)
this.quotationIdList = res.data.quotationIdList
this.attachmentList = res.data.attachmentList || []
this.carbonCopyList = this.packageArr(res.data.carbonCopyList || [])
this.receiverList = this.packageArr(res.data.receiverList || [])
console.log(this.carbonCopyList, this.receiverList, 222)
const arr = uniqWith(
this.carbonCopyList.concat(this.receiverList),
isEqual
)
console.log(arr, 444)
this.allSearchList = this.packageArr(arr || [])
this.receiverData = this.packageArr(arr || [])
console.log(222, this.allSearchList, this.receiverData)
this.detail.topic = res.data.topic || ''
this.html = `<p>${res.data.content || ''}</p>`
})
.catch((err) => {})
},
handleChange(value, isCarbonCopy, option) {
console.log(value, option, this.allSearchList)
let receiverData = []
value.map((v, i) => {
const target = this.allSearchList.find((m) => v.key === m.value)
if (target) {
const { name, email, employeeCode } = target
receiverData.push({
...v,
name: name,
email: email,
employeeCode: employeeCode,
})
}
})
console.log(receiverData, 111)
if (isCarbonCopy) {
Object.assign(this, {
carbonCopyList: receiverData,
fetching: false,
})
} else {
Object.assign(this, {
receiverList: receiverData,
fetching: false,
})
}
console.log(this.receiverList, this.carbonCopyList)
},
fetchUser(value) {
let params = { current: 1, fuzzy: value, size: 999 }
this.lastFetchId += 1
const fetchId = this.lastFetchId
this.data = []
this.fetching = true
onLineEndApi
.employeePage(params)
.then((res) => {
console.log(res, 11)
if (fetchId !== this.lastFetchId) {
return
}
const data =
(res &&
res.data &&
res.data.records.map((user) => ({
text: `${user.employeeName}<${user.email}>`,
value: user.employeeCode,
employeeCode: user.employeeCode,
name: user.employeeName,
email: user.email,
}))) ||
[]
this.receiverData = data
this.allSearchList = this.allSearchList.concat(this.receiverData)
this.fetching = false
console.log(this.receiverData, 11)
})
.catch((err) => {
this.fetching = false
})
},
initEditConfig() {
const editorConfig = { MENU_CONF: {} }
editorConfig.placeholder = '请输入内容...'
editorConfig.MENU_CONF['uploadImage'] = {
allowedFileTypes: ['image/*'],
onBeforeUpload(file) {
return file
},
onProgress(progress) {
console.log('progress', progress)
},
onSuccess(file, res) {
console.log(`${file.name} 上传成功`, res)
},
onFailed(file, res) {
console.log(`${file.name} 上传失败`, res)
},
onError(file, err, res) {
console.log(`${file.name} 上传出错`, err, res)
},
async customUpload(file, insertFn) {
const formData = new FormData()
formData.append('file', file)
formData.append('bizType', '3')
const { code, data, Message } = await commonApi.commonUpload(formData)
insertFn(data, file.name, data)
},
}
this.editorConfig = editorConfig
},
onCreated(editor) {
this.editor = Object.seal(editor)
console.log('onCreated', editor)
},
onChange(editor) {
console.log('onChange', editor.getHtml())
this.content = editor.getHtml()
},
insertTextHandler() {
const editor = this.editor
if (editor == null) return
editor.insertText('')
},
printEditorHtml() {
const editor = this.editor
if (editor == null) return
console.log(editor.getHtml())
},
disableHandler() {
const editor = this.editor
if (editor == null) return
editor.disable()
},
onDestroyed(editor) {
console.log('onDestroyed', editor)
},
onMaxLength(editor) {
console.log('onMaxLength', editor)
},
onFocus(editor) {
console.log('onFocus', editor)
},
onBlur(editor) {
console.log('onBlur', editor)
},
customAlert(info, type) {
},
customPaste(editor, event, callback) {
return true
},
uploadClose(flag, data) {
if (data) {
const { fileName, fileUrl } = data
this.attachmentList.push({ title: fileName, url: fileUrl })
}
this.isShow.upload = false
},
uploadFile() {
this.isShow.upload = true
},
changeForm(e, field) {
this.detail[field] = e
},
handleSubmit() {
if (!this.receiverList.length) {
return this.$message.warn('请填写选择收件人')
}
this.formModal.validateFields((error, values) => {
if (error) {
return
}
if (this.editor.isEmpty()) {
return this.$message.warn('请填写富文本内容')
}
valuesTrim(values)
const { topic } = this.detail
let params = {
quotationIdList: this.selectRows.length
? this.quotationIdList
: undefined,
attachmentList: this.attachmentList,
carbonCopyList: this.carbonCopyList,
content: this.content,
receiverList: this.receiverList,
senderEmail: this.userInfo.uid,
senderName: `${this.userInfo.name}<${this.userInfo.uid}>`,
topic,
}
this.btnLoading = true
onLineEndApi
.emailSend(params)
.then((res) => {
this.btnLoading = false
this.$message.success('邮件发送成功')
this.$emit('cancel', true)
})
.catch((err) => {
this.btnLoading = false
this.$message.error(err.Message || '邮件发送失败')
})
})
},
handleCancel() {
this.$emit('cancel')
},
},
}
</script>
<style src="@wangeditor/editor/dist/css/style.css"></style>
<style lang="less">
.w-e-modal {
width: 400px !important;
padding-top: 32px;
.babel-container {
display: flex;
margin-bottom: 8px;
span {
// width: 200px;
padding: 0 8px;
margin: 0;
}
input {
flex: 1;
padding: 0 11px;
}
}
.button-container {
text-align: right;
button {
height: auto;
padding: 4px 16px;
}
}
}
</style>