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/hooks/useEmail.js

299 lines
11 KiB
JavaScript

import { useState, useEffect, useCallback } from 'react'
import { isEmpty, objectMapper, olog, readIndexDB, } from '@/utils/commons'
import { getEmailDetailAction, postResendEmailAction, getSalesSignatureAction, getEmailOrderAction, queryEmailListAction, getEmailTemplateAction } from '@/actions/EmailActions'
import { App } from 'antd'
import useConversationStore from '@/stores/ConversationStore';
import { msgStatusRenderMapped } from '@/channel/bubbleMsgUtils';
import { POPUP_FEATURES } from '@/config';
export const useEmailSignature = (opi_sn) => {
const [signature, setSignature] = useState('')
const getSignature = useCallback(async () => {
if (isEmpty(Number(opi_sn))) {
return false
}
try {
const data = await getSalesSignatureAction({ opi_sn })
setSignature(data)
} catch (err) {
console.error(err)
}
}, [opi_sn])
useEffect(() => {
getSignature()
}, [getSignature])
return { signature }
}
/**
* @param mai_sn 邮件编号ID
* @param data 直接传递, 不重复获取
* * 在详情点击`回复`呼出编辑时
*/
export const useEmailDetail = (mai_sn, data={}, oid=0) => {
const {notification} = App.useApp()
const [loading, setLoading] = useState(false)
const [mailData, setMailData] = useState({ loading, info: { MAI_COLI_SN: 0 }, content: '', attachments: [], AttachList: [] })
const [coliSN, setColiSN] = useState(oid);
const [orderDetail, setOrderDetail] = useState({});
const [updateMessageItem] = useConversationStore(state => [state.updateMessageItem]);
useEffect(() => {
const getEmailDetail = async () => {
if (isEmpty(Number(mai_sn))) {
return false
}
try {
setLoading(true)
const data = await getEmailDetailAction({ mai_sn })
// console.log(data)
setMailData(data)
setColiSN(data.info.MAI_COLI_SN)
// if (!isEmpty(data.info.MAI_COLI_SN)) {
// const orderData = await getEmailOrderAction({ colisn: data.info.MAI_COLI_SN })
// setOrderDetail(orderData)
// // console.log(orderData)
// }
setLoading(false)
} catch (err) {
setLoading(false)
notification.error({
message: "请求失败",
description: err.message || '网络异常',
placement: "top",
duration: 3,
});
}
}
if (isEmpty(data)) getEmailDetail()
else setMailData(data)
}, [mai_sn])
useEffect(() => {
console.log(coliSN, '====colisn======')
const getOrderDetail = async () => {
if (isEmpty(coliSN)) {
return false
}
try {
setLoading(true)
const data = await getEmailOrderAction({ colisn: coliSN })
setOrderDetail(data)
setLoading(false)
} catch (err) {
setLoading(false)
notification.error({
message: "请求失败",
description: err.message || '网络异常',
placement: "top",
duration: 3,
});
}
}
getOrderDetail()
}, [coliSN])
const postEmailResend = async ({ mai_sn, conversationid: externalid, actionId: actionid, ...body }) => {
if (isEmpty(mai_sn)) {
return false
}
await postResendEmailAction({ mai_sn, externalid, actionid, token: 0 })
// 重发没有状态返回值, 此处前端处理为'待发送', todo: 刷新页面后消息仍为上一个状态'失败'
updateMessageItem({ conversationid: externalid, actionid, id: actionid, status: msgStatusRenderMapped['accepted'] })
}
return { loading, mailData, orderDetail, postEmailResend }
}
export const EmailBuilder = ({subject, content}) => {
return `<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html lang="en"><head><title></title><meta http-equiv="Content-Type" content="text/html charset=UTF-8" /><meta content="width=device-width" name="viewport"><meta charset="UTF-8"><meta content="IE=edge" http-equiv="X-UA-Compatible"><meta content="width=device-width" name="viewport"><meta charset="UTF-8"><meta content="IE=edge" http-equiv="X-UA-Compatible"><meta content="telephone=no,address=no,email=no,date=no,url=no" name="format-detection"><meta content="light" name="color-scheme"><meta content="light" name="supported-color-schemes"><style id="font">body#highlights-email{ font-family: Verdana, sans-serif;} table{ border-collapse: collapse; border-spacing: 0;} </style></head><body id="highlights-email" style="margin: 0 auto; padding: 0; width: 900px; background-color: #fcfcfc;">${content}</body></html>`;
}
export const openPopup = (url, target,) => {
window.open(url, target, POPUP_FEATURES);
};
export const useEmailList = (mailboxDirNode) => {
const [loading, setLoading] = useState(false)
const [mailList, setMailList] = useState([])
const [error, setError] = useState(null)
const [isFreshData, setIsFreshData] = useState(false)
const [refreshTrigger, setRefreshTrigger] = useState(0);
const refresh = useCallback(() => {
setRefreshTrigger(prev => prev + 1);
}, []);
const { OPI_SN: opi_sn, COLI_SN, VKey, VParent, ApplyDate, OrderSourceType, IsTrue } = mailboxDirNode
const getMailList = useCallback(async () => {
console.log('getMailList', mailboxDirNode)
if (!opi_sn || !VKey || (!IsTrue && !COLI_SN)) {
setMailList([])
setLoading(false)
setError(null)
setIsFreshData(false)
return
}
setLoading(true)
setError(null)
setIsFreshData(false)
const cacheKey = isEmpty(COLI_SN) ? `dir-${VKey}` : `order-${VKey}`
const readCache = await readIndexDB(cacheKey, 'maillist', 'mailbox')
if (!isEmpty(readCache)) {
const _x = readCache.data.map((ele) => ({
...ele,
key: ele.MAI_SN,
}))
setMailList(_x)
setLoading(false)
}
try {
const nodeParam = { coli_sn: COLI_SN, order_source_type: OrderSourceType, vkey: VKey, vparent: VParent, mai_senddate1: ApplyDate }
const x = await queryEmailListAction({ opi_sn, node: nodeParam })
// 配合List的结构
const _x = x.map((ele) => ({
...ele,
key: ele.MAI_SN,
}))
setMailList(_x)
} catch (networkError) {
setError(new Error(`Failed to get mail list: ${networkError.message}.`))
} finally {
setLoading(false)
}
}, [VKey, refreshTrigger])
useEffect(() => {
getMailList()
}, [getMailList])
return { loading, isFreshData, error, mailList, refresh }
}
const orderMailTypes = new Map([
['48001', '发送一催'],
['48002', '发送二催'],
['48003', '发送三催'],
['48004', '发送已收客人付款通知'],
['48005', '发送FAQ及PreSurvey'],
['48006', '发送降价邮件'],
['48007', '发送亚马逊津贴'],
['48008', '发送报价信'],
['48009', '提交调度'],
['48010', '发送确认信'],
['48011', '发送余款提醒信'],
['48012', '发送入境提醒'],
['48013', '首站关怀'],
['48014', '抵桂面谈'],
['48015', '末站关怀'],
['48016', '发送计划'],
['48017', '报价中'],
['48018', '以后联系'],
['48019', '成行'],
['48020', '团款收讫'],
['48021', '取消'],
['48022', '丢失'],
['48023', '已做计划'],
['48024', '一催回复'],
['48025', '二催回复'],
['48026', '第一次报价回复'],
['48027', '发送商务感谢信'],
['48028', '商务酒店房满邮件'],
['48029', '商务预订传真'],
['48030', '商务取消邮件'],
['48031', '商务单团财务表'],
['48032', '商务收款单'],
['48033', '商务退款单'],
['48034', '商务财务转帐申请'],
['48035', '商务未订先确认'],
['48036', '商务等待确认'],
['48037', '商务已确认'],
['48038', '商务已付款'],
['48039', '商务成功订单'],
['48040', '商务取消订单'],
['48041', '商务不成行订单'],
['48042', '商务已付款未出票'],
['48043', '商务已付款并出票'],
['48044', '商务无效订单'],
['48045', '问候提醒'],
['48046', '发送邮件'],
['48047', '来华一周年问候'],
['48048', '来华二周年提醒'],
['48049', 'CH Phone询问邮件'],
['48050', '订单电话销售'],
['48051', '等待付订金'],
['48052', '商务订单预订中'],
['48053', '客户需求调查'],
['48054', '发送TourCredits通知邮件'],
['48055', 'GH海外PostSurvey'],
])
export const emailTemplates = [
{ type: 'RemindOneWL', index: 1, key: '1@RemindOneWL', value: '1@RemindOneWL', label: '一催模板一,询问客人是否收到报价信' },
{ type: 'RemindOneWL', index: 2, key: '2@RemindOneWL', value: '2@RemindOneWL', label: '一催模板二,询问客人是否修改行程' },
{ type: 'divider' },
{ type: 'RemindTwoWL', index: 1, key: '1@RemindTwoWL', value: '1@RemindTwoWL', label: '二催模板一,询问客人对行程的看法' },
{ type: 'RemindTwoWL', index: 2, key: '2@RemindTwoWL', value: '2@RemindTwoWL', label: '二催模板二,表达服务的意识' },
{ type: 'divider' },
{ type: 'RemindThreeWL', index: 1, key: '1@RemindThreeWL', value: '1@RemindThreeWL', label: '三催模板三,强调价格有效期' },
];
export const emailTemplateMap = emailTemplates.reduce((acc, cur) => {
if (cur.type === 'divider') {
return acc
}
acc[cur.key] = cur
return acc
}, {});
/**
*
* @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.
*/
export const useEmailTemplate = (templateKey, params) => {
const [loading, setLoading] = useState(false)
const [error, setError] = useState(null)
const [templateContent, setTemplateContent] = useState({ mailtype: '', mailtypeName: '', subject: '', mailcontent: '' })
const getTemplateContent = useCallback(async () => {
if (!templateKey || !Number(params.coli_sn) || !Number(params.opi_sn)) {
setTemplateContent({ mailtype: '', mailtypeName: '', subject: '', mailcontent: '' })
setLoading(false)
setError(null)
return
}
setLoading(true)
setError(null)
try {
const { index: remind_index, type: remind_type } = emailTemplateMap[templateKey] || {};
const _params = { ...params, remind_index, remind_type};
const x = await getEmailTemplateAction(_params)
const lowerCaseShallow = Object.keys(x).reduce((acc, key) => ({...acc, [key.toLowerCase()]: x[key]}), {})
setTemplateContent({...lowerCaseShallow, mailtypeName: orderMailTypes.get(lowerCaseShallow.mailtype)})
} catch (networkError) {
setError(new Error(`Failed to get template content: ${networkError.message}.`))
} finally {
setLoading(false)
}
}, [templateKey, params.opi_sn, params.coli_sn, params.lgc])
useEffect(() => {
getTemplateContent()
}, [getTemplateContent])
return { loading, error, templateContent };
}