src/App.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/api/email/userList.ts | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/email/Utils/blacklist.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/email/Utils/index.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
src/views/email/components/ListPage/drawerDetail.vue | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
src/App.vue
@@ -26,7 +26,7 @@ // 先检查proxy是否存在,再进行操作 if (proxy && proxy.$cookies) { proxy.$cookies.remove('JSESSIONID'); proxy.$cookies.set('JSESSIONID', 'C7CD0C74AFDEF1C09705415FFD0E2299.jvm_59_9010', '1d'); proxy.$cookies.set('JSESSIONID', '23542F948D2C450599CF5850631B432D.jvm_59_9010', '1d'); } else { console.error('proxy对象未初始化或不包含$cookies属性'); } src/api/email/userList.ts
@@ -40,10 +40,14 @@ DELETE_FOLDER = '/crm/mail/folder/deleteFolder.do', GET_FOLDER = '/crm/mail/folder/getFolder.do', GET_ROW_ID = '/getRowid.do', ADD_TAG = '/crm/mail/tag/addTag.do', ADD_TAG = '/crm/mail/blacklist/getBlackList.do', UPDATE_TAG = '/crm/mail/tag/updateTag.do', DELETE_TAG = '/crm/mail/tag/deleteTag.do', GET_TAG = '/crm/mail/tag/getTagList.do', ADD_BLACKLIST = '/crm/mail/blacklist/addBlackList.do', UPDATE_BLACKLIST = '/crm/mail/blacklist/updateBlackList.do', DELETE_BLACKLIST = '/crm/mail/blacklist/deleteBlackList.do', GET_BLACKLIST = '/crm/mail/blacklist/getBlackList.do', } // 获取邮件路由列表 export const getEmailModuleApi = () => defHttp.get({ url: Api.GET_EMAIL_MODULE }); @@ -246,3 +250,32 @@ url: Api.GET_TAG, params, }); // 新增黑名单 export const addBlackListApi = (params) => defHttp.post({ url: Api.ADD_BLACKLIST, params, }); // 修改黑名单 export const updateBlackListApi = (params) => defHttp.post({ url: Api.UPDATE_BLACKLIST, params, }); // 删除黑名单 export const deleteBlackListApi = (params) => defHttp.post({ url: Api.DELETE_BLACKLIST, params, }); // 查询黑名单 export const getBlackListApi = (params) => defHttp.get({ url: Api.GET_BLACKLIST, params, }); src/views/email/Utils/blacklist.vue
New file @@ -0,0 +1,242 @@ <template> <div class="p-2"> <div> <vxe-toolbar> <template #buttons> <div style="display: flex; align-items: flex-end"> <span style="font-size: 1.25rem; font-weight: 600">邮箱地址黑名单</span ><span style="margin-left: 5px; padding-bottom: 4px; font-size: 12px" >黑名单中邮箱对应的邮件将自动收取到垃圾邮件(不会收到新邮件提醒)</span > </div> </template> <template #tools> <a-button type="primary" @click="showModal('mail')">添加邮箱地址</a-button> </template> </vxe-toolbar> <a-input-search v-model:value="searchMail" placeholder="请输入关键字搜索" style="width: 300px; margin-bottom: 20px" @search="onSearch($event, 'mail')" /> <a-table :columns="columns" :data-source="demo.mail" :scroll="{ y: 220 }" size="small"> <template #bodyCell="{ column, record }"> <template v-if="column.field == 'operate'"> <a class="ant-dropdown-link" @click="fnDelete(record)">删除</a> </template> <template v-else-if="column.field == 'mail'"> {{ record.blackContent }} </template> </template> </a-table> </div> <div> <vxe-toolbar> <template #buttons> <div style="display: flex; align-items: flex-end"> <span style="font-size: 1.25rem; font-weight: 600">域名黑名单</span ><span style="margin-left: 5px; padding-bottom: 4px; font-size: 12px" >黑名单中域名对应的邮件将自动收取到垃圾邮件(不会收到新邮件提醒)</span > </div> </template> <template #tools> <a-button type="primary" @click="showModal('domainName')">添加域名</a-button> </template> </vxe-toolbar> <a-input-search v-model:value="searchDomainName" placeholder="请输入关键字搜索" style="width: 300px; margin-bottom: 20px" @search="onSearch($event, 'domainName')" /> <a-table :columns="columnsDomainName" :data-source="demo.domain" :scroll="{ y: 220 }" size="small" > <template #bodyCell="{ column, record }"> <template v-if="column.field == 'operate'"> <a class="ant-dropdown-link" @click="fnDelete(record)">删除</a> </template> <template v-else-if="column.field == 'domainName'"> {{ record.blackContent }} </template> </template> </a-table> </div> <a-modal :width="600" v-model:open="open" :title="`新建${formTypeName}黑名单`" @ok="handleOk"> <a-form ref="formRef" :model="form" style="margin-top: 20px"> <a-form-item v-if="formType === 'mail'" label="邮箱地址" name="blackContent" :rules="[{ required: true, type: 'email', message: '请输入邮箱地址', trigger: 'blur' }]" > <a-input v-model:value="form.blackContent" placeholder="请输入邮箱地址" /> </a-form-item> <a-form-item v-else label="域名地址" name="blackContent" :rules="[{ required: true, validator: validatorDomainName }]" > <a-input v-model:value="form.blackContent" placeholder="请输入域名地址" /> </a-form-item> </a-form> </a-modal> </div> </template> <script lang="ts" setup> import { ref, onMounted, onUnmounted, reactive } from 'vue'; import { getBlackListApi, addBlackListApi, deleteBlackListApi } from '@/api/email/userList'; onUnmounted(() => {}); function fnGetList() { getBlackListApi({}).then((res) => { console.log(res); demo.mail = res.data.mail; demo.domain = res.data.domain; }); } import { useMessage } from '@/hooks/web/useMessage'; const { createMessage } = useMessage(); const open = ref(false); const formRef = ref(); const columns = [ { title: '邮箱地址', field: 'mail', minWidth: 200, }, { title: '操作', field: 'operate', width: 200, }, ]; const columnsDomainName = [ { title: '域名地址', field: 'domainName', minWidth: 200, }, { title: '操作', field: 'operate', width: 200, }, ]; function validatorDomainName(rule, value, callback) { if (!value) { callback(new Error('请输入域名地址')); } else { if (!/[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/.test(value)) { callback(new Error('域名地址格式不正确!')); } else { callback(); } } } const form = reactive({ blackContent: '', }); const formTypeName = ref('邮箱地址'); const formType = ref('mail'); const demo = reactive({ mail: [], domain: [], }); const searchMail = ref(''); const searchDomainName = ref(''); function showModal(blackType) { open.value = true; if (blackType === 'mail') { formTypeName.value = '邮箱地址'; formType.value = 'mail'; } else { formTypeName.value = '域名地址'; formType.value = 'domainName'; } } function handleOk() { formRef.value.validate().then(() => { addBlackListApi({ blackContent: form.blackContent, blackType: formType.value === 'mail' ? false : true, }).then((res) => { createMessage.success('添加成功'); open.value = false; fnGetList(); }); }); } function fnDelete(row) { deleteBlackListApi({ blackId: row.blackId, }).then((res) => { createMessage.success('删除成功'); fnGetList(); }); } function onSearch(e, type) { console.log(e, type,'---3333'); const data = { search: e, type: type === 'mail' ? 0 : 1, }; if (type === 'mail') { getBlackListApi(data).then((res) => { demo.mail = res.data.mail; }); } else { getBlackListApi(data).then((res) => { demo.domain = res.data.domain; }); } } onMounted(() => { fnGetList(); }); </script> <style scoped> .sortable-row-demo .drag-btn { font-size: 12px; cursor: move; } .sortable-row-demo .vxe-body--row.sortable-ghost, .sortable-row-demo .vxe-body--row.sortable-chosen { background-color: #dfecfb; } .bookmark { display: inline-block; position: relative; width: 14px; height: 18px; margin-right: 5px; border-radius: 2px 2px 0 0; /* Rounded top corners */ } .bookmark::after { content: ''; position: absolute; right: 0; bottom: 0; left: 0; height: 8px; background-color: #fff; clip-path: polygon(50% 60%, 0% 100%, 100% 100%); /* Triangle at the bottom */ } </style> src/views/email/Utils/index.vue
@@ -12,7 +12,7 @@ ></a-tab-pane> <a-tab-pane key="4" tab="文件夹"><Folder v-if="activeKey === '4'" /></a-tab-pane> <a-tab-pane key="5" tab="标签"><Label v-if="activeKey==='5'" /></a-tab-pane> <a-tab-pane key="6" tab="黑名单">Content of Tab Pane 3</a-tab-pane> <a-tab-pane key="6" tab="黑名单"><Blacklist v-if="activeKey === '6'" /></a-tab-pane> </a-tabs> </div> </template> @@ -25,6 +25,7 @@ import Convention from './convention.vue'; import QuickText from './quickText.vue'; import Folder from './folder.vue'; import Label from './label.vue'; import Label from './label.vue'; import Blacklist from './blacklist.vue' </script> <style scoped lang="less"></style> src/views/email/components/ListPage/drawerDetail.vue
@@ -2,31 +2,76 @@ <a-drawer v-model:open="drawerOpen" :placement="placement" width="72%" width="1200" :body-style="{ paddingBottom: '80px' }" :footer-style="{ textAlign: 'right' }" @after-open-change="afterOpenChange" @close="drawerClose" > <template #title> <pageHeadLeft :checked="true" :selectAllRow="[{ docCode }]" @nextNum="drawerClose" ></pageHeadLeft> <div class="left"> <span style="margin-right: 20px; font-size: 24px; font-weight: 700"> <a-tooltip placement="bottom"> <template #title> <span>{{ tableRowData.subject }}</span> </template> {{ truncateString(tableRowData.subject, 23) }} </a-tooltip> </span> <span style="margin-right: 10px; font-size: 16px"> <PushpinOutlined /> </span> <div class="ctb"> <pageHeadLeft :checked="true" :selectAllRow="[{ docCode }]" @nextNum="drawerClose" ></pageHeadLeft> <div class="ct-top"> <div class="title" style="margin-bottom: 20px"> <div class="left"> <span style="margin-right: 20px; font-size: 24px; font-weight: 700"> <a-tooltip placement="bottom"> <template #title> <span>{{ tableRowData.subject }}</span> </template> {{ truncateString(tableRowData.subject, 23) }} </a-tooltip> </span> <span style="margin-right: 10px; font-size: 16px"> <PushpinOutlined /> </span> </div> <div class="right"> <div class="tate">{{ formatToDateDay(tableRowData.receiveTime) }}</div> <div> <a-dropdown-button> <span> <a-tooltip placement="bottom"> <template #title> <span>回复</span> </template> <LeftOutlined @click="replyEmail(tableRowData)" /> </a-tooltip> </span> <a-divider type="vertical" /> <span> <a-tooltip placement="bottom"> <template #title> <span>快速回复</span> </template> <DoubleLeftOutlined /> </a-tooltip> </span> <template #overlay> <a-menu> <a-menu-item key="1"> <UserOutlined /> 1st menu item </a-menu-item> <a-menu-item key="2"> <UserOutlined /> 2nd menu item </a-menu-item> <a-menu-item key="3"> <UserOutlined /> 3rd item </a-menu-item> </a-menu> </template> </a-dropdown-button> </div> </div> </div> </div></div> </template> <template #extra> <div style="font-size: 16px"> @@ -35,46 +80,6 @@ <LeftOutlined style="padding: 0 20px" @click="fnPrev" /> <RightOutlined @click="fnNext" /> </div> <div class="my-d-f"> <div class="tate">{{ formatToDateDay(tableRowData.receiveTime) }}</div> <div> <a-dropdown-button> <span> <a-tooltip placement="bottom"> <template #title> <span>回复</span> </template> <LeftOutlined @click="replyEmail(tableRowData)" /> </a-tooltip> </span> <a-divider type="vertical" /> <span> <a-tooltip placement="bottom"> <template #title> <span>快速回复</span> </template> <DoubleLeftOutlined /> </a-tooltip> </span> <template #overlay> <a-menu> <a-menu-item key="1"> <UserOutlined /> 1st menu item </a-menu-item> <a-menu-item key="2"> <UserOutlined /> 2nd menu item </a-menu-item> <a-menu-item key="3"> <UserOutlined /> 3rd item </a-menu-item> </a-menu> </template> </a-dropdown-button> </div> </div> </template> <template #footer> <div style="display: flex"> @@ -87,65 +92,60 @@ >发送 </a-button> </div> </template> <div> <div class="title" style="margin-bottom: 20px"> </div> </div> <div class="flex-between"> <div class="ct-left p-2" :class="isOpen ? 'isOpen' : 'onOpen'"> <div class="user p-1"> <div style="display: flex; align-items: center"> <a-avatar size="small" style="margin-right: 8px" src="#" /> {{ tableRowData.sender }} <span>{{ `<${tableRowData.sender}>` }}</span> <span style="margin: 0 10px">发送</span> <a-popover placement="bottom"> <template #content> <div class="p-2" style=" display: flex; align-items: center; border-bottom: 1px solid rgb(5 5 5 / 6%); " > <a-avatar size="small" style="margin-right: 8px" src="#" /> <span style="color: #000; font-weight: 700"> {{ `${tableRowData.receiver}` }}</span > <CopyOutlined /> </div> <div class="display-flex p-2"> <a-button type="link" size="small">往来邮件</a-button> </div> </template> <div class="flex-between"> <div class="ct-left p-2" :class="isOpen ? 'isOpen' : 'onOpen'"> <div class="user p-1"> <div style="display: flex; align-items: center"> <a-avatar size="small" style="margin-right: 8px" src="#" /> {{ `${tableRowData.receiver}` }}<span>{{ `<${tableRowData.receiver}>` }}</span> </a-popover> </div> <div type="info" class="p-2" style="margin-top: 10px; background-color: #e4f1ff; font-size: 14px" > <span>{{ `<${tableRowData.sender}>` }}</span> <span>暂未查询到该客户的当地时间</span> <!-- <span>2024-06-08 22:22</span> --> </div> <div class="ct" v-if="tableRowData.content"> <TinymcePw ref="TinymcePwRef" v-model="tableRowData.content" /> {{ tableRowData.sender }} <span>{{ `<${tableRowData.sender}>` }}</span> <span style="margin: 0 10px">发送</span> <a-popover placement="bottom"> <template #content> <div class="p-2" style=" display: flex; align-items: center; border-bottom: 1px solid rgb(5 5 5 / 6%); " > <a-avatar size="small" style="margin-right: 8px" src="#" /> <span style="color: #000; font-weight: 700"> {{ `${tableRowData.receiver}` }}</span > <CopyOutlined /> </div> <div class="display-flex p-2"> <a-button type="link" size="small">往来邮件</a-button> </div> </template> <a-avatar size="small" style="margin-right: 8px" src="#" /> {{ `${tableRowData.receiver}` }}<span>{{ `<${tableRowData.receiver}>` }}</span> </a-popover> </div> <div type="info" class="p-2" style="margin-top: 10px; background-color: #e4f1ff; font-size: 14px" > <span>{{ `<${tableRowData.sender}>` }}</span> <span>暂未查询到该客户的当地时间</span> <!-- <span>2024-06-08 22:22</span> --> </div> <div class="ct" v-if="tableRowData.content"> <TinymcePw ref="TinymcePwRef" v-model="tableRowData.content" /> </div> </div> </div> <div v-show="isOpen" class="ct-right p-2">sssss</div> </div> <div v-show="isOpen" class="ct-right p-2">sssss</div> </div> <div @click="fuToggleContent" class="toggle-btn" :class="isOpen ? 'onIconOpen' : 'iconOpen'"> <LeftOutlined v-if="!isOpen" /> <RightOutlined v-else /> <div @click="fuToggleContent" class="toggle-btn" :class="isOpen ? 'onIconOpen' : 'iconOpen'"> <LeftOutlined v-if="!isOpen" /> <RightOutlined v-else /> </div> </div> </a-drawer> </template> @@ -304,10 +304,10 @@ } }); } import {useRouter} from 'vue-router' import { useRouter } from 'vue-router'; const router = useRouter(); function replyEmail(row){ router.push({ path: '/email/edit', query: { docCode: row.docCode,type: 'reply' } }); function replyEmail(row) { router.push({ path: '/email/edit', query: { docCode: row.docCode, type: 'reply' } }); } </script> @@ -362,7 +362,7 @@ .flex-between { display: flex; margin-top: 4%; padding-top: 4%; } .ct-left { @@ -403,4 +403,18 @@ .onIconOpen { right: 32%; } .ctb { position: relative; } .ctb .ct-top { position: absolute; z-index: 99; top: 41px; left: -28px; width: 116%; padding: 10px; background: #fff; } </style>