|
|
import { LinkOutlined, MailOutlined, PhoneOutlined, UserOutlined, WhatsAppOutlined, FieldNumberOutlined } from "@ant-design/icons";
|
|
|
import { App, Button, Card, Empty, Flex, Select, Spin, Typography, Divider, Modal, List, Row, Col, Tag } from "antd";
|
|
|
import { useEffect, useState, useRef, useCallback } from "react";
|
|
|
import { useNavigate } from "react-router-dom";
|
|
|
import { useShallow } from 'zustand/react/shallow';
|
|
|
|
|
|
import { copy, isEmpty } from "@/utils/commons";
|
|
|
import { Conditional } from "@/components/Conditional";
|
|
|
import useConversationStore from "@/stores/ConversationStore";
|
|
|
import { useOrderStore, OrderLabelDefaultOptions, OrderStatusDefaultOptions } from "@/stores/OrderStore";
|
|
|
import useAuthStore from "@/stores/AuthStore";
|
|
|
import QuotesHistory from "./QuotesHistory";
|
|
|
import ConversationBind from "./../ConversationBind";
|
|
|
import ConversationsNewItem from "./../ConversationsNewItem";
|
|
|
import { useConversationNewItem } from "@/hooks/useConversation";
|
|
|
import EmailDetail from './../Components/EmailDetail';
|
|
|
import { postEditConversationItemColiAction } from "@/actions/ConversationActions";
|
|
|
|
|
|
const CustomerProfile = () => {
|
|
|
const { notification, message } = App.useApp();
|
|
|
const [loading, setLoading] = useState(false);
|
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
|
const [currentOrderNumber, setOrderNumber] = useState(false);
|
|
|
const [orderList, setOrderList] = useState([]);
|
|
|
const orderCommentRef = useRef(null);
|
|
|
|
|
|
const currentOrder = useConversationStore(useShallow(state => state.currentConversation?.coli_sn || ""));
|
|
|
const currentConversationID = useConversationStore(useShallow(state => state.currentConversation?.sn || ""));
|
|
|
const channels = useConversationStore(state => state.currentConversation?.channels);
|
|
|
const [updateCurrentConversation] = useConversationStore(state => [state.updateCurrentConversation]);
|
|
|
const [emailMsg, setEmailMsg, detailPopupOpen, setDetailOpen, openDetail] = useConversationStore(state => [state.emailMsg, state.setEmailMsg, state.detailPopupOpen, state.setDetailOpen, state.openDetail]);
|
|
|
const loginUser = useAuthStore(state => state.loginUser);
|
|
|
const [
|
|
|
orderDetail, customerDetail, lastQuotation, quotationList, fetchOrderDetail, setOrderPropValue, appendOrderComment, fetchOtherEmail, otherEmailList, fetchHistoryOrder
|
|
|
] = useOrderStore(s => [
|
|
|
s.orderDetail, s.customerDetail, s.lastQuotation, s.quotationList, s.fetchOrderDetail, s.setOrderPropValue, s.appendOrderComment, s.fetchOtherEmail, s.otherEmailList, s.fetchHistoryOrder
|
|
|
]);
|
|
|
const [resetOrderStore] = useOrderStore(state => [state.resetOrderStore])
|
|
|
|
|
|
const [chatOrder, setChatOrder] = useState(currentOrder);
|
|
|
|
|
|
const orderLabelOptions = copy(OrderLabelDefaultOptions);
|
|
|
orderLabelOptions.unshift({ value: 0, label: "未设置", disabled: true });
|
|
|
|
|
|
const orderStatusOptions = copy(OrderStatusDefaultOptions);
|
|
|
|
|
|
const getHistoryOrder = (email, whatsappid='') => {
|
|
|
return fetchHistoryOrder(loginUser.userId, email, whatsappid)
|
|
|
.then(orderList => {
|
|
|
const mapOrderList = orderList.map(o => {
|
|
|
return { value: o.coli_sn, label: o.coli_id }
|
|
|
})
|
|
|
setOrderList(mapOrderList)
|
|
|
if (!isEmpty(orderList)) {
|
|
|
setChatOrder(currentOrder)
|
|
|
}
|
|
|
})
|
|
|
}
|
|
|
|
|
|
useEffect(() => {
|
|
|
setChatOrder(currentOrder)
|
|
|
if (currentOrder) {
|
|
|
setLoading(true);
|
|
|
fetchOrderDetail(currentOrder)
|
|
|
.then(result => {
|
|
|
setOrderNumber(result.orderDetail.order_no)
|
|
|
setChatOrder(result.orderDetail.order_no)
|
|
|
const queryEmail = result.customerDetail.email || channels?.email || '';
|
|
|
const queryWA = result.customerDetail.whatsapp_phone_number || result.customerDetail.phone || channels?.whatsapp_phone_number || ''
|
|
|
getHistoryOrder(queryEmail, queryWA)
|
|
|
})
|
|
|
.finally(() => setLoading(false))
|
|
|
.catch(reason => {
|
|
|
notification.error({
|
|
|
message: "查询出错",
|
|
|
description: reason.message,
|
|
|
placement: "top",
|
|
|
duration: 60,
|
|
|
});
|
|
|
});
|
|
|
|
|
|
|
|
|
fetchOtherEmail(currentOrder)
|
|
|
.then(result => {
|
|
|
// console.info(result)
|
|
|
})
|
|
|
.finally(() => setLoading(false))
|
|
|
.catch(reason => {
|
|
|
notification.error({
|
|
|
message: "查询供应商邮件出错",
|
|
|
description: reason.message,
|
|
|
placement: "top",
|
|
|
duration: 60,
|
|
|
});
|
|
|
});
|
|
|
} else {
|
|
|
resetOrderStore();
|
|
|
}
|
|
|
return () => resetOrderStore()
|
|
|
}, [currentOrder]);
|
|
|
|
|
|
let regularText = "";
|
|
|
if (orderDetail.buytime > 0) regularText = "(R" + orderDetail.buytime + ")";
|
|
|
|
|
|
const { openOrderContactConversation } = useConversationNewItem();
|
|
|
const [newChatModalVisible, setNewChatModalVisible] = useState(false);
|
|
|
const [newChatFormValues, setNewChatFormValues] = useState({});
|
|
|
const handleNewChat = async values => {
|
|
|
const newContact = { wa_id: values.wa_id };
|
|
|
openOrderContactConversation(newContact.wa_id);
|
|
|
setNewChatModalVisible(false);
|
|
|
};
|
|
|
|
|
|
const handleEmailClick = useCallback((emailItem) => {
|
|
|
const emailMsg = {
|
|
|
conversationid: currentConversationID,
|
|
|
order_opi: orderDetail.opi_sn,
|
|
|
coli_sn: currentOrder,
|
|
|
id: emailItem.MAI_SN,
|
|
|
msgOrigin: {
|
|
|
from: '',
|
|
|
to: '',
|
|
|
id: emailItem.MAI_SN,
|
|
|
email: { mai_sn: emailItem.MAI_SN, subject: emailItem.MAI_Subject, id: emailItem.MAI_SN },
|
|
|
},
|
|
|
}
|
|
|
setEmailMsg(emailMsg);
|
|
|
openDetail();
|
|
|
}, [])
|
|
|
|
|
|
const handleOrderSwitch = async (coli_sn) => {
|
|
|
await postEditConversationItemColiAction({conversationid: currentConversationID, coli_sn });
|
|
|
setChatOrder(coli_sn);
|
|
|
updateCurrentConversation({ coli_sn });
|
|
|
};
|
|
|
|
|
|
if (currentOrder) {
|
|
|
return (
|
|
|
<div className="divide-x-0 divide-y divide-dashed divide-gray-300">
|
|
|
<Spin spinning={loading}>
|
|
|
<Card
|
|
|
className="p-2 "
|
|
|
bordered={false}
|
|
|
title={<Select
|
|
|
style={{
|
|
|
width: "100%",
|
|
|
}}
|
|
|
variant="borderless"
|
|
|
value={chatOrder}
|
|
|
options={orderList}
|
|
|
// onSelect={handleOrderSwitch}
|
|
|
onChange={handleOrderSwitch}
|
|
|
/>}
|
|
|
actions={[
|
|
|
<Select
|
|
|
key={"orderlabel"}
|
|
|
size="small"
|
|
|
style={{
|
|
|
width: "100%",
|
|
|
}}
|
|
|
variant="borderless"
|
|
|
onSelect={value => {
|
|
|
setOrderPropValue(currentOrder, "orderlabel", value)
|
|
|
.then(() => {
|
|
|
message.success("设置成功");
|
|
|
})
|
|
|
.catch(reason => {
|
|
|
notification.error({
|
|
|
message: "设置出错",
|
|
|
description: reason.message,
|
|
|
placement: "top",
|
|
|
duration: 60,
|
|
|
});
|
|
|
});
|
|
|
}}
|
|
|
value={orderDetail.tags}
|
|
|
options={orderLabelOptions}
|
|
|
/>,
|
|
|
<Select
|
|
|
key={"orderstatus"}
|
|
|
size="small"
|
|
|
style={{
|
|
|
width: "100%",
|
|
|
}}
|
|
|
variant="borderless"
|
|
|
onSelect={value => {
|
|
|
setOrderPropValue(currentOrder, "orderstatus", value)
|
|
|
.then(() => {
|
|
|
message.success("设置成功");
|
|
|
})
|
|
|
.catch(reason => {
|
|
|
notification.error({
|
|
|
message: "设置出错",
|
|
|
description: reason.message,
|
|
|
placement: "top",
|
|
|
duration: 60,
|
|
|
});
|
|
|
});
|
|
|
}}
|
|
|
value={orderDetail.states}
|
|
|
options={orderStatusOptions}
|
|
|
/>,
|
|
|
]}>
|
|
|
<Flex gap={10}>
|
|
|
<Flex vertical={true} justify="space-between">
|
|
|
<Typography.Text>
|
|
|
<FieldNumberOutlined className="pr-1" />
|
|
|
{orderDetail.order_no}
|
|
|
</Typography.Text>
|
|
|
<Typography.Text>
|
|
|
<UserOutlined className=" pr-1" />
|
|
|
{customerDetail.name + regularText}
|
|
|
</Typography.Text>
|
|
|
<Typography.Text>
|
|
|
<PhoneOutlined className=" pr-1" />
|
|
|
{customerDetail.phone}
|
|
|
</Typography.Text>
|
|
|
<Typography.Text>
|
|
|
<MailOutlined className=" pr-1" />
|
|
|
{customerDetail.email}
|
|
|
</Typography.Text>
|
|
|
<Typography.Text>
|
|
|
<WhatsAppOutlined className="pr-1" />
|
|
|
<Button
|
|
|
type="link"
|
|
|
size={"small"}
|
|
|
onClick={() => {
|
|
|
setNewChatModalVisible(true);
|
|
|
setNewChatFormValues((prev) => ({ ...prev, phone_number: customerDetail.whatsapp_phone_number, name: customerDetail.name, email: customerDetail.email, is_current_order: true }))
|
|
|
}}>
|
|
|
{customerDetail.whatsapp_phone_number}
|
|
|
</Button>
|
|
|
</Typography.Text>
|
|
|
<Typography.Text>
|
|
|
<span>特殊要求:</span>
|
|
|
{orderDetail.customer_request}
|
|
|
</Typography.Text>
|
|
|
<Typography.Text>
|
|
|
<span>外联备注:</span>
|
|
|
{orderDetail.wl_memo}
|
|
|
</Typography.Text>
|
|
|
</Flex>
|
|
|
</Flex>
|
|
|
</Card>
|
|
|
<Divider orientation="left">
|
|
|
<Typography.Text strong>最新报价</Typography.Text>
|
|
|
</Divider>
|
|
|
<Flex vertical={true} className="p-2 ">
|
|
|
<Conditional
|
|
|
condition={quotationList.length > 0}
|
|
|
whenFalse={<Empty description={<span>暂无报价</span>}></Empty>}
|
|
|
whenTrue={
|
|
|
<>
|
|
|
<p className="m-0 py-2 line-clamp-2 ">
|
|
|
<a target="_blank" href={lastQuotation.letterurl} rel="noreferrer">
|
|
|
<LinkOutlined />
|
|
|
{lastQuotation.lettertitle}
|
|
|
</a>
|
|
|
</p>
|
|
|
<Flex justify={"space-between"}>
|
|
|
<QuotesHistory dataSource={quotationList} />
|
|
|
</Flex>
|
|
|
</>
|
|
|
}
|
|
|
/>
|
|
|
</Flex>
|
|
|
|
|
|
<Divider orientation="left">
|
|
|
<Typography.Text strong>供应商邮件</Typography.Text>
|
|
|
</Divider>
|
|
|
|
|
|
<List
|
|
|
dataSource={otherEmailList}
|
|
|
pagination={
|
|
|
{
|
|
|
pageSize: 2,
|
|
|
showLessItems: true,
|
|
|
size: 'small'
|
|
|
}
|
|
|
}
|
|
|
renderItem={(email) => (
|
|
|
<List.Item
|
|
|
className='hover:bg-stone-50 cursor-pointer'
|
|
|
onClick={() => {
|
|
|
handleEmailClick(email)
|
|
|
}}>
|
|
|
<Flex
|
|
|
vertical
|
|
|
>
|
|
|
<div><Typography.Text ellipsis={{tooltip: email.SenderReceiver}} style={{width: 280}}><b>From: </b>{email.SenderReceiver}</Typography.Text></div>
|
|
|
<div><Typography.Text ellipsis={{tooltip: email.MAI_Subject}} style={{width: 280}}><b>Subject: </b>{email.MAI_Subject}</Typography.Text></div>
|
|
|
</Flex>
|
|
|
</List.Item>
|
|
|
)}
|
|
|
/>
|
|
|
<Divider orientation="left">
|
|
|
<Typography.Text strong>表单信息</Typography.Text>
|
|
|
</Divider>
|
|
|
<p className="p-2 overflow-auto m-0 break-words whitespace-pre-wrap" dangerouslySetInnerHTML={{ __html: orderDetail.order_detail }}></p>
|
|
|
<Modal
|
|
|
title="添加备注"
|
|
|
open={isModalOpen}
|
|
|
onOk={() => {
|
|
|
const orderCommnet = orderCommentRef.current.value;
|
|
|
if (isEmpty(orderCommnet)) {
|
|
|
message.warning("请输入备注后再提交。");
|
|
|
} else {
|
|
|
appendOrderComment(loginUser.userId, currentOrder, orderCommnet)
|
|
|
.then(() => {
|
|
|
message.success("添加成功");
|
|
|
setIsModalOpen(false);
|
|
|
})
|
|
|
.catch(reason => {
|
|
|
notification.error({
|
|
|
message: "添加出错",
|
|
|
description: reason.message,
|
|
|
placement: "top",
|
|
|
duration: 60,
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
orderCommentRef.current.value = "";
|
|
|
}}
|
|
|
onCancel={() => {
|
|
|
setIsModalOpen(false);
|
|
|
}}>
|
|
|
<textarea ref={orderCommentRef} className="w-full" rows={4}></textarea>
|
|
|
</Modal>
|
|
|
<Button
|
|
|
size={"small"}
|
|
|
onClick={() => {
|
|
|
setIsModalOpen(true);
|
|
|
}}>
|
|
|
添加备注
|
|
|
</Button>
|
|
|
</Spin>
|
|
|
<ConversationsNewItem initialValues={newChatFormValues} open={newChatModalVisible} onCreate={handleNewChat} onCancel={() => setNewChatModalVisible(false)} />
|
|
|
<EmailDetail open={detailPopupOpen} setOpen={setDetailOpen} emailMsg={emailMsg} key={`supplier-email-detail-1-${emailMsg?.id}`} />
|
|
|
|
|
|
</div>
|
|
|
);
|
|
|
} else {
|
|
|
return (
|
|
|
<Empty description={<span>暂无相关订单</span>}>
|
|
|
<ConversationBind currentConversationID={currentConversationID} userId={loginUser.userId} onBoundSuccess={coli_sn => updateCurrentConversation({ coli_sn })} />
|
|
|
</Empty>
|
|
|
);
|
|
|
}
|
|
|
};
|
|
|
|
|
|
export default CustomerProfile;
|