Compare commits

...

2 Commits

Author SHA1 Message Date
Lei OT 31b854efab 1 7 months ago
Lei OT ade510a701 feat: 打开供应商邮件 7 months ago

@ -13,18 +13,22 @@
"@dckj/react-better-modal": "^0.1.2", "@dckj/react-better-modal": "^0.1.2",
"@lexical/react": "^0.20.0", "@lexical/react": "^0.20.0",
"@vonage/client-sdk": "^1.7.2", "@vonage/client-sdk": "^1.7.2",
"@yoopta/email-builder": "^4.9.2",
"antd": "^5.22.2", "antd": "^5.22.2",
"dayjs": "^1.11.13", "dayjs": "^1.11.13",
"dingtalk-jsapi": "^3.0.41", "dingtalk-jsapi": "^3.0.41",
"emoji-picker-react": "^4.12.0", "emoji-picker-react": "^4.12.0",
"lexical": "^0.20.0", "lexical": "^0.20.0",
"react": "^18.3.1", "react": "^18.3.1",
"react-chat-elements": "^12.0.17",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-router-dom": "^6.28.0", "react-router-dom": "^6.28.0",
"zustand": "^4.5.5",
"react-chat-elements": "^12.0.17",
"rxjs": "^7.8.1", "rxjs": "^7.8.1",
"uuid": "^9.0.1" "slate": "^0.110.2",
"slate-dom": "^0.111.0",
"slate-react": "^0.111.0",
"uuid": "^9.0.1",
"zustand": "^4.5.5"
}, },
"devDependencies": { "devDependencies": {
"@types/react": "^18.3.12", "@types/react": "^18.3.12",

@ -53,6 +53,7 @@ const initialConversationState = {
totalNotify: 0, totalNotify: 0,
msgListLoading: false, msgListLoading: false,
detailPopupOpen: false,
}; };
const globalNotifySlice = (set) => ({ const globalNotifySlice = (set) => ({
@ -467,6 +468,18 @@ const messageSlice = (set, get) => ({
}, },
}); });
/**
* Email
*/
const emailSlice = (set, get) => ({
emailMsg: {},
setEmailMsg: (emailMsg) => set({ emailMsg }),
detailPopupOpen: false,
setDetailOpen: (v) => set({ detailPopupOpen: v }),
openDetail: () => set(() => ({ detailPopupOpen: true })),
closeDetail: () => set(() => ({ detailPopupOpen: false })),
})
export const useConversationStore = create( export const useConversationStore = create(
devtools((set, get) => ({ devtools((set, get) => ({
...initialConversationState, ...initialConversationState,
@ -479,6 +492,7 @@ export const useConversationStore = create(
...tagsSlice(set, get), ...tagsSlice(set, get),
...filterSlice(set, get), ...filterSlice(set, get),
...globalNotifySlice(set, get), ...globalNotifySlice(set, get),
...emailSlice(set, get),
// state actions // state actions
addError: (error) => set((state) => ({ errors: [...state.errors, error] })), addError: (error) => set((state) => ({ errors: [...state.errors, error] })),

@ -18,6 +18,9 @@ const TagColorStyle = (tag) => {
} }
} }
/**
* @property {*} emailMsg - 邮件数据. { msgOrigin: { from, to, id, email: { subject, mai_sn, } } }
*/
const EmailDetail = ({ open, setOpen, emailMsg, ...props }) => { const EmailDetail = ({ open, setOpen, emailMsg, ...props }) => {
// console.log('emailDetail', emailMsg); // console.log('emailDetail', emailMsg);

@ -0,0 +1,83 @@
import { useEffect, useState, useMemo } from 'react'
import EmailBuilder, {
createYooptaEmailEditor,
// type EmailTemplateOptions,
} from '@yoopta/email-builder'
const templateOptions = {
head: {
styles: [
{
id: 'font',
content: `body { font-family: Verdana, sans-serif; }`,
},
],
meta: [
{ content: 'width=device-width', name: 'viewport' },
{ charset: 'UTF-8' },
{ content: 'IE=edge', httpEquiv: 'X-UA-Compatible' },
{ content: 'telephone=no,address=no,email=no,date=no,url=no', name: 'format-detection' },
{ content: 'light', name: 'color-scheme' },
],
},
body: {
attrs: {
style: {
backgroundColor: '#fafafa',
width: '900px',
margin: '0 auto',
},
},
},
container: {
attrs: {
style: {
width: 800,
margin: '0 auto',
},
},
},
}
function EmailBuilderC() {
const editor = useMemo(() => createYooptaEmailEditor({ template: templateOptions }), [])
const [value, setValue] = useState({})
const uploadImageToServer = async () => {}
const uploadVideoToServer = async () => {}
const uploadPosterToServer = async () => {}
const uploadFileToServer = async () => {}
// media upload handlers
const mediaUploaders = {
image: {
upload: async (file) => {
const url = await uploadImageToServer(file)
return url
},
},
video: {
upload: async (file) => {
const url = await uploadVideoToServer(file)
return url
},
uploadPoster: async (file) => {
const url = await uploadPosterToServer(file)
return url
},
},
file: {
upload: async (file) => {
const url = await uploadFileToServer(file)
return url
},
},
}
return (
<div className='h-96'>
<EmailBuilder view='editor' className='h-96' editor={editor} value={value} onChange={setValue} media={mediaUploaders} header={null} autoFocus={true} placeholder='Write your email here...' />
</div>
)
}
export default EmailBuilderC

@ -17,6 +17,7 @@ import { sentMsgTypeMapped, } from '@/channel/bubbleMsgUtils';
import { useEmailDetail } from '@/hooks/useEmail'; import { useEmailDetail } from '@/hooks/useEmail';
import useSnippetStore from '@/stores/SnippetStore' import useSnippetStore from '@/stores/SnippetStore'
import { useOrderStore } from '@/stores/OrderStore' import { useOrderStore } from '@/stores/OrderStore'
import EmailBuilderC from './Editor/EmailBuilder';
// //
// .application, .exe, .app // .application, .exe, .app
@ -513,7 +514,8 @@ const EmailEditorPopup = ({ open, setOpen, fromEmail, fromUser, fromOrder, toEma
<Input /> <Input />
</Form.Item> </Form.Item>
</Form> </Form>
<LexicalEditor {...{ isRichText }} onChange={handleEditorChange} defaultValue={initialContent} /> {/* <LexicalEditor {...{ isRichText }} onChange={handleEditorChange} defaultValue={initialContent} /> */}
<EmailBuilderC />
</DnDModal> </DnDModal>
</ConfigProvider> </ConfigProvider>

@ -12,6 +12,7 @@ import QuotesHistory from "./QuotesHistory";
import ConversationBind from "./../ConversationBind"; import ConversationBind from "./../ConversationBind";
import ConversationsNewItem from "./../ConversationsNewItem"; import ConversationsNewItem from "./../ConversationsNewItem";
import { useConversationNewItem } from "@/hooks/useConversation"; import { useConversationNewItem } from "@/hooks/useConversation";
import EmailDetail from './../Components/EmailDetail';
const CustomerProfile = () => { const CustomerProfile = () => {
const { notification, message } = App.useApp(); const { notification, message } = App.useApp();
@ -22,6 +23,7 @@ const CustomerProfile = () => {
const currentOrder = useConversationStore(state => state.currentConversation?.coli_sn || ""); const currentOrder = useConversationStore(state => state.currentConversation?.coli_sn || "");
const currentConversationID = useConversationStore(state => state.currentConversation?.sn || ""); const currentConversationID = useConversationStore(state => state.currentConversation?.sn || "");
const [updateCurrentConversation] = useConversationStore(state => [state.updateCurrentConversation]); const [updateCurrentConversation] = useConversationStore(state => [state.updateCurrentConversation]);
const [emailDetail, setEmailMsg, detailPopupOpen, setDetailOpen, openDetail] = useConversationStore(state => [state.emailDetail, state.setEmailMsg, state.detailPopupOpen, state.setDetailOpen, state.openDetail]);
const loginUser = useAuthStore(state => state.loginUser); const loginUser = useAuthStore(state => state.loginUser);
const [ const [
orderDetail, customerDetail, lastQuotation, quotationList, fetchOrderDetail, setOrderPropValue, appendOrderComment, fetchOtherEmail, otherEmailList orderDetail, customerDetail, lastQuotation, quotationList, fetchOrderDetail, setOrderPropValue, appendOrderComment, fetchOtherEmail, otherEmailList
@ -83,6 +85,12 @@ const CustomerProfile = () => {
const renderOtherEmailList = () => { const renderOtherEmailList = () => {
}
const handleEmailClick = (emailItem) => {
const emailMsg = { msgOrigin: { from: '', to: '', id: emailItem.MAI_SN, email: { mai_sn: emailItem.MAI_SN, subject: emailItem.MAI_Subject, id: emailItem.MAI_SN } } }
setEmailMsg(emailMsg);
openDetail();
} }
if (currentOrder) { if (currentOrder) {
@ -223,6 +231,7 @@ const CustomerProfile = () => {
className='hover:bg-stone-50' className='hover:bg-stone-50'
onClick={() => { onClick={() => {
console.info('email...') console.info('email...')
handleEmailClick(email)
}}> }}>
<Flex <Flex
vertical vertical
@ -275,6 +284,8 @@ const CustomerProfile = () => {
</Button> </Button>
</Spin> </Spin>
<ConversationsNewItem initialValues={newChatFormValues} open={newChatModalVisible} onCreate={handleNewChat} onCancel={() => setNewChatModalVisible(false)} /> <ConversationsNewItem initialValues={newChatFormValues} open={newChatModalVisible} onCreate={handleNewChat} onCancel={() => setNewChatModalVisible(false)} />
<EmailDetail open={detailPopupOpen} setOpen={setDetailOpen} emailMsg={emailDetail} key={`email-detail-1-${emailDetail.id}`} />
</div> </div>
); );
} else { } else {

Loading…
Cancel
Save