diff --git a/src/lib/msgUtils.js b/src/lib/msgUtils.js index dcd2b7e..c9710dc 100644 --- a/src/lib/msgUtils.js +++ b/src/lib/msgUtils.js @@ -175,7 +175,6 @@ export const whatsappMsgTypeMapped = { type: 'text', data: (msg) => { const templateDataMapped = msg.template?.components ? msg.template.components.reduce((r, v) => ({...r, [v.type]: v}), {}) : null; - console.log(msg.template.name, templateDataMapped); return { id: msg.wamid, text: templateDataMapped?.body?.parameters?.[0]?.text || '', title: msg.template.name } }, }, @@ -226,6 +225,7 @@ export const parseRenderMessageList = (messages, conversationid = null) => { /** * WhatsApp Templates params + * @deprecated */ export const whatsappTemplatesParamMapped = { /** @deprecated */ diff --git a/src/views/Conversations/Components/InputTemplate.jsx b/src/views/Conversations/Components/InputTemplate.jsx index 32bf216..80955b1 100644 --- a/src/views/Conversations/Components/InputTemplate.jsx +++ b/src/views/Conversations/Components/InputTemplate.jsx @@ -1,23 +1,40 @@ import { useState } from 'react'; -import { Popover, Flex, Button, List } from 'antd'; +import { App, Popover, Flex, Button, List, Input } from 'antd'; import { MessageOutlined, SendOutlined } from '@ant-design/icons'; import { useAuthContext } from '@/stores/AuthContext'; import { useConversationState } from '@/stores/ConversationContext'; -import { cloneDeep, getNestedValue, objectMapper } from '@/utils/utils'; +import { cloneDeep, flush, getNestedValue, objectMapper } from '@/utils/utils'; import { v4 as uuid } from 'uuid'; -import { whatsappTemplatesParamMapped, replaceTemplateString } from '@/lib/msgUtils'; +import { replaceTemplateString } from '@/lib/msgUtils'; +const splitTemplate = (template) => { + const placeholders = template.match(/{{(.*?)}}/g) || []; + const keys = placeholders.map((placeholder) => placeholder.slice(2, -2)); + const arr = template.split(/{{(.*?)}}/).filter(Boolean); + const obj = arr.reduce((prev, curr, index) => { + if (keys.includes(curr)) { + prev.push({ key: curr }); + } else { + prev.push(curr); + } + return prev; + }, []); + return obj; +}; const InputTemplate = ({ disabled = false, invokeSendMessage }) => { + const { notification } = App.useApp() const { loginUser } = useAuthContext(); const { currentConversation, templates } = useConversationState(); + // 用于替换变量: customer, agent + const valueMapped = { ...cloneDeep(currentConversation), ...objectMapper(loginUser, { username: [{ key: 'agent_name' }, { key: 'your_name' }] }) }; const [openTemplates, setOpenTemplates] = useState(false); const handleOpenChange = (newOpen) => { setOpenTemplates(newOpen); }; const handleSendTemplate = (fromTemplate) => { - // 替换变量: customer, agent - const _conversation = { ...cloneDeep(currentConversation), ...objectMapper(loginUser, { username: { key: 'agent_name' } }) }; + const mergeInput = {...cloneDeep(valueMapped), ...activeInput[fromTemplate.name]}; + let valid = true; const msgObj = { type: 'whatsappTemplate', to: currentConversation.whatsapp_phone_number, @@ -30,10 +47,11 @@ const InputTemplate = ({ disabled = false, invokeSendMessage }) => { name: fromTemplate.name, language: { code: fromTemplate.language }, components: fromTemplate.components_origin.map((citem) => { - const params = whatsappTemplatesParamMapped[fromTemplate.name].map((v) => ({ type: 'text', text: getNestedValue(_conversation, v) || '' })); + const keys = (citem?.text || '').match(/{{(.*?)}}/g).map((key) => key.replace(/{{|}}/g, '')); + const params = keys.map((v) => ({ type: 'text', text: getNestedValue(mergeInput, [v]) })); const paramText = params.map((p) => p.text); const fillTemplate = paramText.length ? replaceTemplateString(citem?.text || '', paramText) : citem?.text || ''; - + valid = keys.length !== flush(paramText).length ? false : valid; return { type: citem.type.toLowerCase(), parameters: params, @@ -43,10 +61,49 @@ const InputTemplate = ({ disabled = false, invokeSendMessage }) => { }, template_origin: fromTemplate, }; + if (valid !== true) { + notification.warning({ + message: '提示', + description: '信息未填写完整, 请补充填写', + placement: 'top', + duration: 3, + }) + return false; + } invokeSendMessage(msgObj); setOpenTemplates(false); }; + const [activeInput, setActiveInput] = useState({}); + const onInput = (tempItem, key, val, initObj) => { + setActiveInput((prev) => { + return { ...prev, [tempItem.name]: { ...initObj, ...prev[tempItem.name], [key]: val } }; + }); + }; + + const renderForm = (tempItem) => { + const templateText = tempItem.components.body?.[0]?.text || ''; + const tempArr = splitTemplate(templateText); + const keys = templateText.match(/{{(.*?)}}/g).map((key) => key.replace(/{{|}}/g, '')); + const paramsVal = keys.reduce((r, k) => ({ ...r, [k]: getNestedValue(valueMapped, [k]) }), {}); + + return tempArr.map((ele) => + typeof ele === 'string' ? ( + + {ele} + + ) : ( + onInput(tempItem, ele.key, e.target.value, paramsVal)} + className='w-auto max-w-24' + size={'small'} + title={ele.key} + placeholder={paramsVal[ele.key] || ele.key} + /> + ) + ); + }; return ( <> { renderItem={(item, index) => ( <>{item.components.header?.[0]?.text || item.name}> @@ -67,7 +124,14 @@ const InputTemplate = ({ disabled = false, invokeSendMessage }) => { } - description={item.components.body?.[0]?.text} + description={ + <> + + {renderForm(item)} + {item.components?.footer?.[0] ? {item.components.footer[0].text || ''} : null} + + > + } /> )}