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'; export const parseHTMLString = (html, needText = false) => { const parser = new DOMParser() const doc = parser.parseFromString(html, 'text/html') let bodyContent = doc.body.innerHTML // bodyContent = bodyContent.replace(/ { 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,'>') 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('' : '')); 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) || !ele.ATI_Name.includes('ContentFile')); const insideAttachments = (isEmpty(result?.AttachList) ? [] : result.AttachList).filter(ele => !isEmpty(ele.ATI_ContentID) && ele.ATI_Name.includes('ContentFile')); const ret = { info: { ...encodeEmailInfo(result.MailInfo?.[0] || {}), mailType }, content: mailType === 'text/html' ? html : result.MailContent || '', abstract: bodyText || result.MailContent || '', attachments, insideAttachments, AttachList: isEmpty(result?.AttachList) ? [] : result.AttachList, } // 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) 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(`${API_HOST}/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 ? { [`${params.opi_sn}`]: tree } : { [`${params.opi_sn}`]: [] } }; 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: , // children: [], COLI_SN: 0, // }, ], }), {}, ) const { errcode, result } = await fetchJSON(`${API_HOST}/getwlorder`, params) // 取后一个状态, 因此翻转两次 const _result_unique = uniqWith(result.reverse(), (a, b) => a.COLI_SN === b.COLI_SN).reverse(); const orderList = errcode === 0 ? _result_unique : [] 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' }), ...(userIdStr.split(',').map(_opi => getEmailDirAction({ opi_sn: _opi }))), ]) const mailboxDirByOPI = mailboxDir.reduce((a, c) => ({...a, ...c}), {}); const rootTree = Object.keys(stickyTree).map((opi) => ({ key: Number(opi), tree: [...stickyTree[opi], ...(mailboxDirByOPI?.[opi] || [])] })) 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(`${API_HOST}/mail_list`, _params) const ret = errcode === 0 ? result : [] if (!isEmpty(ret)) { const listids = [...new Set(ret.map(ele => ele.MAI_SN))]; writeIndexDB([{key: cacheKey, data: listids}], 'maillist', 'mailbox') writeIndexDB(ret.map(ele => ({ data: ele, key: ele.MAI_SN})), 'listrow', '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 } /** * 获取邮件模板 * @param {object} params - Parameters for the email template request. * @param {number} [params.coli_sn] - Customer order line item serial number. * @param {number} [params.lgc] - Language code. * @param {number} [params.opi_sn] - Order product item serial number. * @param {string} [params.remind_type] - Type of reminder. * @param {number} [params.remind_index] - Index of the reminder. */ export const getEmailTemplateAction = async (params = { coli_sn: 0, lgc: 1, opi_sn: 0, remind_type: '', remind_index: 0 }) => { const { errcode, result } = await fetchJSON(`${API_HOST}/reminder_letter`, params) const { html, bodyContent, bodyText } = parseHTMLString(result?.MailContent, true) ; return errcode === 0 ? {...result, bodyContent }: {} } /** * 保存邮件草稿 * @param {object} body - The body of the email. * @param {boolean} [isDraft=false] - Whether the email is a draft. */ export const saveEmailDraftOrSendAction = async (body, isDraft = false) => { const url = isDraft !== false ? `${API_HOST}/email_draft_save` : `${EMAIL_HOST}/sendmail`; 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.filter(ele => !ele.fullPath).forEach(function (item) { formData.append('attachment', item); }); const { errcode, result } = await postForm(url, formData); return errcode === 0 ? (result || {}) : {} }; /** * 删除邮件附件 */ export const deleteEmailAttachmentAction = async (ati_sn_list) => { const { errcode, result } = await postJSON(`${API_HOST}/mail_attachment_delete`, { ati_sn_list }) return errcode === 0 ? result : {} };