You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Global-sales/src/actions/EmailActions.js

344 lines
13 KiB
JavaScript

import { fetchJSON, postForm, postJSON } from '@/utils/request';
import { API_HOST, DATE_FORMAT, DATEEND_FORMAT, DATETIME_FORMAT, EMAIL_HOST } from '@/config';
import { buildTree, groupBy, isEmpty, objectMapper, omitEmpty, readIndexDB, uniqWith, writeIndexDB } from '@/utils/commons';
import dayjs from 'dayjs';
7 months ago
const parseHTMLString = (html, needText = false) => {
7 months ago
const parser = new DOMParser()
const doc = parser.parseFromString(html, 'text/html')
let bodyContent = doc.body.innerHTML
// bodyContent = bodyContent.replace(/<img/g, '<img onerror="this.onerror=null;this.src=\'https://hiana-crm.oss-accelerate.aliyuncs.com/WAMedia/afe412d4-3acf-4e79-a623-048aeb4d696a.png\';"')
const bodyText = (doc.body.innerText);
return needText ? { html, bodyContent, bodyText } : bodyContent
7 months ago
}
/**
* 获取顾问签名
* @param {object} { opi_sn }
*/
export const getSalesSignatureAction = async (params) => {
try {
const { result } = await fetchJSON(`${EMAIL_HOST}/email_sign`, params)
const { SignContent: html } = result
const bodyContent = parseHTMLString(html);
return bodyContent;
} catch (error) {
return '';
}
};
/**
* 发送邮件
*/
export const postSendEmail = async (body) => {
const { attaList=[], atta, content, ...bodyData } = body;
bodyData.ordertype = 227001;
const formData = new FormData();
Object.keys(bodyData).forEach(function (key) {
formData.append(key, bodyData[key]);
});
attaList.forEach(function (item) {
formData.append('attachment', item);
});
const { result } = await postForm(`${EMAIL_HOST}/sendmail`, formData);
return result;
};
/**
* 重发邮件
* @param {object} { mai_sn }
*/
export const postResendEmailAction = async (body) => {
const { attaList, atta, content, ...bodyData } = body;
const formData = new FormData();
Object.keys(bodyData).forEach(function (key) {
formData.append(key, bodyData[key]);
});
return await postForm(`${EMAIL_HOST}/email_resend`, formData);
};
const encodeEmailInfo = (info) => {
const encodeQuote = (str = '') => str.replace(/"/g, ''); //.replace(/</g,'&lt;').replace(/>/g,'&gt;')
const CSsClean = encodeQuote(info.MAI_CS).includes(',') ? encodeQuote(info.MAI_CS).split(',') : encodeQuote(info.MAI_CS).split(';');
const tosClean = (encodeQuote(info.MAI_To).includes(',') ? encodeQuote(info.MAI_To).split(',') : encodeQuote(info.MAI_To).split(';')).concat(CSsClean).filter(s => s);
const replyTo = info.MAI_Direction === 1 ? info.MAI_To : info.MAI_From;
const replyToAll = (tosClean.length > 1) ?
(info.MAI_Direction === 1 ? tosClean.join(',') : [...tosClean, info.MAI_From].join(','))
: (info.MAI_Direction === 1 ? info.MAI_To : info.MAI_From)
return {
...info,
MAI_From: encodeQuote(info.MAI_From),
MAI_To: encodeQuote(info.MAI_To),
tos: [...new Set(tosClean)],
replyToAll,
replyTo,
}
};
/**
* 邮件详情
* @param {object} { mai_sn }
*/
export const getEmailDetailAction = async (params) => {
// const cacheKey = params.mai_sn;
// const readCache = await readIndexDB(cacheKey, 'mailinfo', 'mailbox');
// if (!isEmpty(readCache)) { // todo: 除了草稿
// return readCache.data;
// }
const { result } = await fetchJSON(`${EMAIL_HOST}/getmail`, params);
let mailType = result.MailInfo?.[0]?.MAI_ContentType || '';
mailType = mailType === '' && (result.MailContent||'').includes('<html') ? 'text/html' : mailType;
const emailInfo = encodeEmailInfo(result.MailInfo?.[0] || {});
const isFromHub = emailInfo.MAI_From.includes('info@chinahighlights.net');
const delLinefeed = mailType === 'text/html' ? (result.MailContent||'').includes('<html') ? true : false : true;
const cleanContent = (result.MailContent || '').replace(/\r\n/g, delLinefeed ? '' : (isFromHub ? '<br>' : ''));
const { html, bodyContent, bodyText } = mailType === 'text/html' ? parseHTMLString(cleanContent, true) : { html: '', bodyContent: '', bodyText: '' };
const attachments = (isEmpty(result?.AttachList) ? [] : result.AttachList).filter(ele => isEmpty(ele.ATI_ContentID));
const ret = {
info: { ...encodeEmailInfo(result.MailInfo?.[0] || {}), mailType },
content: mailType === 'text/html' ? html : result.MailContent || '',
abstract: bodyText || result.MailContent || '',
attachments,
}
// writeIndexDB([{key: cacheKey, data: ret}], 'mailinfo', 'mailbox')
return ret;
}
export const getEmailOrderAction = async ({ colisn }) => {
const { errcode, result } = await fetchJSON(`${API_HOST}/getorderinfo`, { colisn })
return errcode === 0 ? { ...result[0], customerDetail: result[0].contact[0] } : {}
}
/**
* 主动收邮件, 单个账户
* @param {object} { opi_sn, }
*/
export const getEmailFetchAction = async (params) => {
const { opi_sn, } = params
const { result } = await fetchJSON(`${EMAIL_HOST}/email_fetch`, {
opi_sn,
})
return result
};
/**
* 报价信邮件草稿
* @param {object} { sfi_sn, coli_sn, lgc }
*/
export const getEmailQuotationDraftAction = async (params) => {
const { result } = await fetchJSON(`${EMAIL_HOST}/QuotationLetter`, params)
7 months ago
return { subject: (result.Subject || ''), content: parseHTMLString((result.MailContent || '').replace(/\r\n/g, '')) }
}
/**
* 单个邮件绑定订单
* @param {object} { conversationid, mai_sn, coli_sn, coli_id, sourcetype }
*/
export const fetchEmailBindOrderAction = async (params) => {
const { errcode, result } = await fetchJSON(`${API_HOST}/mailinfo_bindorder`, params)
return errcode === 0 ? true : false;
}
const todoTypes = {
// 1新订单2未读消息3需一催4需二催5需三催6未处理邮件入境提醒coli_ordertype=7余款提醒coli_ordertype=8
1: '新订单',
2: '未读',
3: '一催',
4: '二催',
5: '三催',
6: '未处理',
7: '入境提醒',
8: '余款提醒',
}
/**
* 顾问的邮箱目录
* @param {object} { opi_sn }
*/
export const getEmailDirAction = async (params = { opi_sn: '' }) => {
const defaultParams = { opi_sn: 0, year: dayjs().year(), by_start_date: -1, by_success: -1, important: -1, if_want_book: -1, if_thinking: -1 }
const { errcode, result } = await fetchJSON(`http://202.103.68.144:8889/v3/email_dir`, { ...defaultParams, ...params })
const mailboxSort = result //.sort(sortBy('MDR_Order'));
let tree = buildTree(mailboxSort, { key: 'VKey', parent: 'VParent', name: 'VName', iconIndex: 'ImageIndex', rootKeys: [1], ignoreKeys: [-227001, -227002] })
tree = tree.filter((ele) => ele.key !== 1)
return errcode === 0 ? tree : [];
};
export const getTodoOrdersAction = async (params) => {
const opi_arr = params.opisn.split(',');
const defaultStickyTree = opi_arr.reduce(
(a, ele) => ({
...a,
[ele]: [
{
key: ele + '-today',
title: '今日任务',
getMails: false,
iconIndex: 'star',
children: [],
COLI_SN: 0,
},
{
key: ele + '-todo',
title: '待办任务',
getMails: false,
iconIndex: 'calendar',
children: [],
COLI_SN: 0,
},
// {
// key: ele.OPI_DEI_SN + '-reminder',
// title: '催信',
// getMails: false,iconIndex: 'reminder',
// icon: <BellTwoTone />,
// children: [], COLI_SN: 0,
// },
],
}),
{},
)
const { errcode, result } = await fetchJSON(`${API_HOST}/getwlorder`, params)
const orderList = errcode === 0 ? result : [];
const byOPI = groupBy(orderList, 'OPI_SN');
const byState = Object.keys(byOPI).reduce((acc, key) => {
const sticky = groupBy(byOPI[key], (ele) => ([1, 2, 6].includes(ele.coli_ordertype) ? 0 : ([3,4,5].includes(ele.coli_ordertype) ? 1 : 2)))
const treeNode = [
{
key: key + '-today',
title: '今日任务',
getMails: false,iconIndex: 'star',
_raw: {COLI_SN: 0, IsTrue: 0,},
children: (sticky[0] || []).map((o) => ({
key: `today-${o.COLI_SN}`,
title: `(${todoTypes[o.coli_ordertype] || o.COLI_State}) ${o.COLI_ID}`,
iconIndex: 13,
parent: key + '-today',
parentTitle: '今日任务',
parentIconIndex: 'star',
_raw: { ...o, VKey: o.COLI_SN, VName: o.COLI_ID, VParent:-1, IsTrue: 0, ApplyDate: '', OrderSourceType: 227001, parent: -1 },
})),
},
{
key: key + '-todo',
title: '待办任务',
getMails: false,iconIndex: 'calendar',
_raw: {COLI_SN: 0, IsTrue: 0,},
children: (sticky[2] || []).map((o) => ({
key: `todo-${o.COLI_SN}`,
title: `(${todoTypes[o.coli_ordertype] || o.COLI_State}) ${o.COLI_ID}`,
iconIndex: 13,
parent: key + '-todo',
parentTitle: '待办任务',
parentIconIndex: 'calendar',
_raw: { ...o, VKey: o.COLI_SN, VName: o.COLI_ID, VParent:-1, IsTrue: 0, ApplyDate: '', OrderSourceType: 227001, parent: -1 },
})),
},
...(!isEmpty(sticky[1] || []) ? [{
key: key + '-reminder',
title: '催信',
getMails: false,iconIndex: 'reminder',
_raw: {COLI_SN: 0, IsTrue: 0,},
children: (sticky[1] || []).map((o) => ({
key: `reminder-${o.COLI_SN}`,
title: `(${todoTypes[o.coli_ordertype] || o.COLI_State}) ${o.COLI_ID}`,
iconIndex: 13,
parent: key + '-reminder',
parentTitle: '催信',
parentIconIndex: 'reminder',
_raw: { ...o, VKey: o.COLI_SN, VName: o.COLI_ID, VParent:-1, IsTrue: 0, ApplyDate: '', OrderSourceType: 227001, parent: -1 },
})),
}] : []),
]
return { ...acc, [key]: treeNode }
}, defaultStickyTree)
return errcode === 0 ? byState : defaultStickyTree;
};
/**
* 获取待办目录和邮箱目录
* @param {object} params { opi_sn, userIdStr }
* @param {number} params.opi_sn
* @param {string} params.userIdStr - 用户ID字符串默认为空
*/
export const getRootMailboxDirAction = async ({ opi_sn = 0, userIdStr = '' } = {}) => {
const [stickyTree, mailboxDir] = await Promise.all([getTodoOrdersAction({ opisn: userIdStr || String(opi_sn), otype: 'today' }), getEmailDirAction({ opi_sn: opi_sn })])
const rootTree = Object.keys(stickyTree).map((opi) => ({ key: Number(opi), tree: [...stickyTree[opi], ...mailboxDir] }))
writeIndexDB(rootTree, 'dirs', 'mailbox')
const _mapped = groupBy(rootTree, 'key')
return _mapped[opi_sn]?.[0]?.tree || []
}
/**
* 获取邮件列表
* @usage 邮件目录下的邮件列表
* @usage 订单的邮件列表
* @usage 高级搜索
*/
export const queryEmailListAction = async ({ opi_sn = '', pagesize = 10, last_id = '', node = {}, } = {}) => {
const _params = {
vkey: 0,
vparent: 0,
order_source_type: 0,
mai_senddate1: dayjs().subtract(1, 'year').startOf('year').format(DATE_FORMAT),
mai_senddate2: dayjs().format(DATEEND_FORMAT),
...omitEmpty({
...node,
opi_sn,
}),
}
_params.mai_senddate1 = dayjs(_params.mai_senddate1).format(DATE_FORMAT)
const cacheKey = isEmpty(_params.coli_sn) ? `dir-${node.vkey}` : `order-${node.vkey}`;
const { errcode, result } = await fetchJSON(`http://202.103.68.144:8889/v3/mail_list`, _params)
const ret = errcode === 0 ? result : []
if (!isEmpty(ret)) {
writeIndexDB([{key: cacheKey, data: ret}], 'maillist', 'mailbox')
}
return ret;
}
/**
* 更新邮件属性
*/
export const updateEmailAction = async (params = { mai_sn_list: [], set: {} }) => {
const { errcode, result } = await postJSON(`${EMAIL_HOST}/email/update`, params)
return errcode === 0 ? {} : result
}
/**
* 获取邮件模板
*/
export const getEmailTemplateAction = async (template_name, params = { coli_sn: 0, lgc: 1 }) => {
const { errcode, result } = await fetchJSON(`${EMAIL_HOST}/email/template/${template_name}`, params)
return errcode === 0 ? {} : result
}
/**
* 保存邮件草稿
*/
export const saveEmailDraftAction = async (body) => {
const { attaList=[], atta, content, ...bodyData } = body;
bodyData.ordertype = 227001;
const formData = new FormData();
Object.keys(bodyData).forEach(function (key) {
formData.append(key, bodyData[key]);
});
attaList.forEach(function (item) {
formData.append('attachment', item);
});
const { result } = await postForm(`${EMAIL_HOST}/email-draft/save`, formData);
return result;
};
/**
* 删除邮件草稿
*/
export const deleteEmailDraftAction = async (id) => {
const { errcode, result } = await postJSON(`${EMAIL_HOST}/email-draft/delete`, { id })
return errcode === 0 ? {} : result
};