|
|
|
|
import { fetchJSON, postForm, postJSON } from '@/utils/request';
|
|
|
|
|
import { API_HOST, API_HOST_V3, DATE_FORMAT, DATEEND_FORMAT, DATETIME_FORMAT, EMAIL_HOST, EMAIL_HOST_v3 } from '@/config';
|
|
|
|
|
import { buildTree, groupBy, isEmpty, objectMapper, omitEmpty, uniqWith } from '@/utils/commons';
|
|
|
|
|
import { readIndexDB, writeIndexDB } from '@/utils/indexedDB';
|
|
|
|
|
import dayjs from 'dayjs';
|
|
|
|
|
import { internalEventEmitter } from '@/utils/EventEmitterService';
|
|
|
|
|
|
|
|
|
|
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(/<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
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const EMAIL_CHANNEL_NAME = 'mailbox_changes';
|
|
|
|
|
let emailChangesChannel = null;
|
|
|
|
|
export function getEmailChangesChannel() {
|
|
|
|
|
if (!emailChangesChannel) {
|
|
|
|
|
emailChangesChannel = new BroadcastChannel(EMAIL_CHANNEL_NAME)
|
|
|
|
|
}
|
|
|
|
|
return emailChangesChannel
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 通知邮件列表数据更新
|
|
|
|
|
const notifyMailboxUpdate = (payload) => {
|
|
|
|
|
const notificationPayload = payload
|
|
|
|
|
// - 多个tab
|
|
|
|
|
const channel = getEmailChangesChannel()
|
|
|
|
|
channel.postMessage(notificationPayload)
|
|
|
|
|
// - 当前tab
|
|
|
|
|
internalEventEmitter.emit(EMAIL_CHANNEL_NAME, notificationPayload)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取顾问签名
|
|
|
|
|
* @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,'<').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('<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) || ele.ATI_ContentID == '0');
|
|
|
|
|
const insideAttachments = (isEmpty(result?.AttachList) ? [] : result.AttachList).filter(ele => !isEmpty(ele.ATI_ContentID) && ele.ATI_ContentID != '0');
|
|
|
|
|
|
|
|
|
|
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新订单;2WhatsApp未读消息;3需一催;4需二催;5需三催;6未处理邮件;入境提醒coli_ordertype=7,余款提醒coli_ordertype=8
|
|
|
|
|
1: '新订单',
|
|
|
|
|
2: '未读WhatsApp',
|
|
|
|
|
3: '一催',
|
|
|
|
|
4: '二催',
|
|
|
|
|
5: '三催',
|
|
|
|
|
6: '老邮件',
|
|
|
|
|
7: '入境提醒',
|
|
|
|
|
8: '余款提醒',
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 顾问的邮箱目录
|
|
|
|
|
* @param {object} params { opi_sn, year, by_start_date, by_success, important, if_want_book, if_thinking }
|
|
|
|
|
* @param {boolean} retOrder 是否直接返回订单列表 -- 忽略
|
|
|
|
|
*/
|
|
|
|
|
export const getEmailDirAction = async (params = { opi_sn: '' }, retOrder=false) => {
|
|
|
|
|
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_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)
|
|
|
|
|
const retTree = errcode === 0 ? tree : [];
|
|
|
|
|
const orderList = groupBy(result, row => `${row.IsTrue}`)?.['0'] || [];
|
|
|
|
|
return retOrder !== false ? orderList : { [`${params.opi_sn}`]: retTree }
|
|
|
|
|
};
|
|
|
|
|
export const getMailboxCountAction = async (params = { opi_sn: '' }, update = true) => {
|
|
|
|
|
const defaultParams = {
|
|
|
|
|
opi_sn: 0,
|
|
|
|
|
// date1: dayjs().subtract(1, 'year').startOf('year').format(DATE_FORMAT),
|
|
|
|
|
date1: dayjs().subtract(180, 'days').format(DATE_FORMAT),
|
|
|
|
|
date2: dayjs().format(DATEEND_FORMAT)
|
|
|
|
|
}
|
|
|
|
|
const { errcode, result } = await fetchJSON(`${API_HOST_V3}/dir_count`, {...defaultParams, ...params})
|
|
|
|
|
const ret = errcode !== 0 ? { [`${params.opi_sn}`]: {} } : { [`${params.opi_sn}`]: result }
|
|
|
|
|
// 更新数量
|
|
|
|
|
if (update !== false) {
|
|
|
|
|
const readCacheDir = (await readIndexDB(Number(params.opi_sn), 'dirs', 'mailbox')) || {};
|
|
|
|
|
const mailboxDir = isEmpty(readCacheDir) ? [] : readCacheDir.tree.filter(node => node?._raw?.IsTrue === 1);
|
|
|
|
|
const _MapDir = new Map(mailboxDir.map((obj) => [obj.key, obj]))
|
|
|
|
|
Object.keys(result).map(dirKey => {
|
|
|
|
|
_MapDir.set(Number(dirKey), {..._MapDir.get(Number(dirKey)), count: result[dirKey]});
|
|
|
|
|
})
|
|
|
|
|
const _newToUpdate = Array.from(_MapDir.values());
|
|
|
|
|
const _MapRoot = new Map((readCacheDir?.tree || []).map((obj) => [obj.key, obj]))
|
|
|
|
|
_newToUpdate.forEach((row) => {
|
|
|
|
|
_MapRoot.set(row.key, row)
|
|
|
|
|
})
|
|
|
|
|
const _newRoot = Array.from(_MapRoot.values())
|
|
|
|
|
writeIndexDB([{ ...readCacheDir, key: Number(params.opi_sn), tree: _newRoot }], 'dirs', 'mailbox')
|
|
|
|
|
notifyMailboxUpdate({ type: 'dirs', key: Number(params.opi_sn) })
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
};
|
|
|
|
|
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 _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, 6].includes(ele.coli_ordertype) ? 0 : [2, 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: key + '-today', IsTrue: 0, ApplyDate: '', OrderSourceType: 227001, parent: key + '-today' },
|
|
|
|
|
})),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
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: key + '-todo', IsTrue: 0, ApplyDate: '', OrderSourceType: 227001, parent: key + '-todo' },
|
|
|
|
|
})),
|
|
|
|
|
},
|
|
|
|
|
...(!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: key + '-reminder', IsTrue: 0, ApplyDate: '', OrderSourceType: 227001, parent: key + '-reminder' },
|
|
|
|
|
})),
|
|
|
|
|
},
|
|
|
|
|
]
|
|
|
|
|
: []),
|
|
|
|
|
]
|
|
|
|
|
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 mailBoxCount = await Promise.all(userIdStr.split(',').map(_opi => getMailboxCountAction({ opi_sn: _opi }, false)));
|
|
|
|
|
const mailboxDirCountByOPI = mailBoxCount.reduce((a, c) => ({ ...a, ...c, }), {})
|
|
|
|
|
const mailboxDirByOPI = mailboxDir.reduce((a, c) => ({ ...a, ...(Object.keys(c).reduce((a, opi) => ({...a, [opi]: c[`${opi}`].map((dir) => ({ ...dir, count: mailboxDirCountByOPI[opi][`${dir.key}`] })) }), {} )) }), {})
|
|
|
|
|
const rootTree = Object.keys(stickyTree).map((opi) => ({ key: Number(opi), tree: [...stickyTree[opi], ...(mailboxDirByOPI?.[opi] || [])], treeTimestamp: Date.now() }))
|
|
|
|
|
writeIndexDB(rootTree, 'dirs', 'mailbox')
|
|
|
|
|
const _mapped = groupBy(rootTree, 'key')
|
|
|
|
|
return _mapped[opi_sn]?.[0]?.tree || []
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取邮件列表
|
|
|
|
|
* @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_senddate1: dayjs().subtract(180, 'days').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_V3}/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, listKey: cacheKey }, key: ele.MAI_SN})), 'listrow', 'mailbox')
|
|
|
|
|
}
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const searchEmailListAction = async ({opi_sn = '', mailboxtype = 'ALL', sender = '', receiver = '', subject = '', content=''}={}) => {
|
|
|
|
|
const formData = new FormData()
|
|
|
|
|
formData.append('opi_sn', opi_sn)
|
|
|
|
|
formData.append('mailboxtype', mailboxtype)
|
|
|
|
|
formData.append('sender', sender)
|
|
|
|
|
formData.append('receiver', receiver)
|
|
|
|
|
formData.append('subject', subject)
|
|
|
|
|
// formData.append('content', content)
|
|
|
|
|
const { errcode, result } = await postForm(`${API_HOST_V3}/mail_search`, formData)
|
|
|
|
|
const ret = errcode === 0 ? result : []
|
|
|
|
|
notifyMailboxUpdate({ type: 'maillist-search-result', query: [sender, receiver, subject].filter(s => s).join(' '), data: ret.map(ele => ({...ele, key: ele.MAI_SN, showFolder: true })) })
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const removeFromCurrentList = async (params) => {
|
|
|
|
|
const readRow0 = await readIndexDB(params.mai_sn_list[0], 'listrow', 'mailbox')
|
|
|
|
|
const listKey = readRow0?.data?.listKey || ''
|
|
|
|
|
if (listKey) {
|
|
|
|
|
const readCache = await readIndexDB(listKey, 'maillist', 'mailbox')
|
|
|
|
|
const updatedMailList = readCache.data.filter((mai_sn) => !params.mai_sn_list.includes(mai_sn))
|
|
|
|
|
writeIndexDB([{ key: listKey, data: updatedMailList }], 'maillist', 'mailbox')
|
|
|
|
|
notifyMailboxUpdate({ type: 'listrow', listKey, affectKeys: params.mai_sn_list })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const updateEmailKeyMap = { read: 'MOI_ReadState' };
|
|
|
|
|
const updateEmailKeyFun = {
|
|
|
|
|
read: async (params) => {
|
|
|
|
|
const readCache = await readIndexDB(params.mai_sn_list, 'listrow', 'mailbox')
|
|
|
|
|
const updateField = Object.keys(params.set).reduce((a, c) => ({ ...a, [updateEmailKeyMap[c]]: params.set[c] }), {})
|
|
|
|
|
writeIndexDB(
|
|
|
|
|
params.mai_sn_list.map((ele) => ({ data: { ...(readCache.get(ele)?.data || {}), ...updateField }, key: ele })),
|
|
|
|
|
'listrow',
|
|
|
|
|
'mailbox',
|
|
|
|
|
)
|
|
|
|
|
// 通知邮件列表数据更新
|
|
|
|
|
const listKey = readCache.get(params.mai_sn_list[0])?.data?.listKey || '';
|
|
|
|
|
const notificationPayload = { type: 'listrow', listKey, affectKeys: params.mai_sn_list }
|
|
|
|
|
notifyMailboxUpdate(notificationPayload)
|
|
|
|
|
},
|
|
|
|
|
processed: removeFromCurrentList,
|
|
|
|
|
delete: removeFromCurrentList
|
|
|
|
|
}
|
|
|
|
|
/**
|
|
|
|
|
* 更新邮件属性
|
|
|
|
|
*/
|
|
|
|
|
export const updateEmailAction = async (params = { opi_sn: 0, mai_sn_list: [], set: {} }) => {
|
|
|
|
|
if (isEmpty(params.mai_sn_list)) {
|
|
|
|
|
throw new Error('没有需要更新的邮件');
|
|
|
|
|
}
|
|
|
|
|
const { errcode, result } = await postJSON(`${API_HOST_V3}/mail_update`, params)
|
|
|
|
|
if (errcode === 0 ) {
|
|
|
|
|
for (const [key, value] of Object.entries(params.set)) {
|
|
|
|
|
const updateFun = updateEmailKeyFun[key] || (() => {});
|
|
|
|
|
updateFun(params)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
getMailboxCountAction({ opi_sn: params.opi_sn });
|
|
|
|
|
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 getReminderEmailTemplateAction = async (params = { coli_sn: 0, lgc: 1, opi_sn: 0, remind_type: '', remind_index: 0 }) => {
|
|
|
|
|
const { errcode, result } = await fetchJSON(`${API_HOST_V3}/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_V3}/email_draft_save` : `${EMAIL_HOST_v3}/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_V3}/mail_attachment_delete`, { ati_sn_list })
|
|
|
|
|
return errcode === 0 ? result : {}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const queryHTOrderListAction = async (params) => {
|
|
|
|
|
const { errcode, result } = await fetchJSON(`${API_HOST}/query_order`, params)
|
|
|
|
|
return errcode !== 0 ? [] : result
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export const queryOPIOrderAction = async (params) => {
|
|
|
|
|
const { errcode, result } = await fetchJSON(`${API_HOST}/getdvancedwlorder`, params)
|
|
|
|
|
return errcode !== 0 ? [] : result
|
|
|
|
|
};
|
|
|
|
|
|