index.tsx 44 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  1. import { inject, observer } from 'mobx-react';
  2. import React, { useCallback, useEffect, useState } from 'react';
  3. import style from './index.less'
  4. import { App, Button, Card, Empty, Flex, Form, Input, Popconfirm, Select, Space, Spin, Table, Tabs } from 'antd';
  5. import MassSending from './components/massSending';
  6. import { useAjax } from '@/Hook/useAjax';
  7. import { welcomeMsgJobTypeApi } from '@/pages/weComTask/API/weMaterial/weMaterial';
  8. import SelectCorpUser from '../../corpUserManage/selectCorpUser';
  9. import { SearchOutlined, PlusOutlined, RedoOutlined, SaveOutlined, CheckOutlined } from '@ant-design/icons';
  10. import { getGroupData, getUserInDataData, restoreGroupData, restoreUserInheritData } from './const';
  11. import { friendsColumns, highMassSendingColumns, massSendingColumns, userInheritColumns, welcomeColumns } from './tableConfig';
  12. import SubmitModal from './submitModal';
  13. import { addTaskApi, getCreateDetailsApi, updateTaskApi } from '@/pages/weComTask/API/businessPlan/create';
  14. import { useNavigate } from 'react-router-dom';
  15. import SelectExternalAccount from '@/pages/weComTask/components/selectExternalAccount';
  16. import Welcome from './components/welcome';
  17. import UserInherit from './components/userInherit';
  18. import { toJS } from 'mobx';
  19. import SelectCwTag from '@/pages/weComTask/components/selectCwTag';
  20. import SelectCorpUserGroup from '../../corpUserManage/selectCorpUserGroup';
  21. import { getBindMpListApi } from '@/pages/weComTask/API/corpUserAssign';
  22. export const DispatchTaskCreate = React.createContext<TASK_CREATE.DispatchTaskCreate | null>(null);
  23. /**
  24. * 任务创建
  25. * @param props
  26. * @returns
  27. */
  28. const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookListProps[], bookPlatForm: TASK_CREATE.BookPlatFormProps[] } } }> = ({ weComTaskStore }) => {
  29. /***********************************************/
  30. const navigate = useNavigate();
  31. const { bookList, bookPlatForm } = toJS(weComTaskStore.data)
  32. const [settings, setSettings] = useState<TASK_CREATE.SettingsProps>();
  33. const [projectId, setProjectId] = useState<number>()
  34. const [isEditSc, setIsEditSc] = useState<boolean>(false) // 是否编辑素材
  35. const { message, modal } = App.useApp()
  36. const [msgJobTypeList, setMsgJobTypeList] = useState<{ value: string, label: string }[]>([])
  37. const [previewData, setPreviewData] = useState<TASK_CREATE.previewDataProps>({})
  38. const [previewDataOld, setPreviewDataOld] = useState<TASK_CREATE.previewDataProps>({})
  39. const [subVisible, setSubVisible] = useState<boolean>(false) // 选择设置名称弹窗控制
  40. const [eaVisible, setEaVisible] = useState<boolean>(false)
  41. const [qwVisible, setQwVisible] = useState<boolean>(false)
  42. const [mpList, setMplist] = useState<{ label: string, value: number }[]>([])
  43. const [previewContent, setPreviewContent] = useState<{ groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] }>({})
  44. const welcomeMsgJobType = useAjax(() => welcomeMsgJobTypeApi())//获取欢迎语类型
  45. const addTask = useAjax((params) => addTaskApi(params))
  46. const updateTask = useAjax((params) => updateTaskApi(params))
  47. const getCreateDetails = useAjax((params) => getCreateDetailsApi(params))
  48. const getBindMpList = useAjax(() => getBindMpListApi())
  49. /***********************************************/
  50. console.log('settings--->', settings, previewContent)
  51. useEffect(() => {
  52. const project = sessionStorage.getItem('OFFICIALTASKID')
  53. if (project) {
  54. const { id, isCopy, isEditSc } = JSON.parse(project)
  55. setIsEditSc(isEditSc)
  56. if (!isCopy) {
  57. setProjectId(id)
  58. }
  59. getCreateDetails.run(id).then(res => {
  60. sessionStorage.removeItem('OFFICIALTASKID')
  61. if (res?.data) {
  62. const { corpUsers, bizType, platform, templateProductId, welcomeMsgTemplateDTO, groupSendTaskAddDTO, externalUserTransferTasksDTO } = res.data
  63. let newSettings: TASK_CREATE.SettingsProps = {
  64. bizType,
  65. platform: Number(platform) as any,
  66. templateProductId,
  67. corpUserGroups: corpUsers.map(item => {
  68. return {
  69. corpUsers: item.corpUserList.map(({ corpUserId, name, corpId, mpAccountId, mpAccountInfo, id }) => {
  70. return { id: id || (corpId + '_' + corpUserId), corpUserId, name, corpName: item.corpName, corpId, mpAccountId, mpAccountName: mpAccountInfo?.name }
  71. })
  72. }
  73. }),
  74. welcomeMsgTemplateDTO
  75. }
  76. if (groupSendTaskAddDTO && Object.keys(groupSendTaskAddDTO).length > 0) {
  77. const data = restoreGroupData(groupSendTaskAddDTO)
  78. newSettings = { ...newSettings, ...data }
  79. }
  80. if (externalUserTransferTasksDTO && Object.keys(externalUserTransferTasksDTO)?.length > 0) {
  81. const data = restoreUserInheritData(externalUserTransferTasksDTO)
  82. newSettings.userInherit = data
  83. }
  84. setSettings(newSettings)
  85. // 历史数据回填
  86. const welcomeMsgContent: any[] = []
  87. const groupMsgContent: any[] = []
  88. corpUsers.forEach((c, c_index) => {
  89. if (c?.welcomeMsgContent?.length > 0) {
  90. welcomeMsgContent[c_index] = c?.welcomeMsgContent?.map(item => ({
  91. linkUrl: item?.linkUrl,
  92. miniprogramAppid: item?.miniprogramAppid,
  93. miniprogramPage: item?.miniprogramPage
  94. }))
  95. }
  96. if (c?.groupMsgContent?.length > 0) {
  97. groupMsgContent[c_index] = c?.groupMsgContent?.map(item => {
  98. return item?.map(i2 => i2?.map(item => ({
  99. linkUrl: item?.linkUrl,
  100. miniprogramAppid: item?.miniprogramAppid,
  101. miniprogramPage: item?.miniprogramPage
  102. })))
  103. })
  104. }
  105. })
  106. const newPreviewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] } = {
  107. welcomeMsgContent,
  108. groupMsgContent
  109. }
  110. setPreviewContent(newPreviewContent)
  111. }
  112. })
  113. } else {
  114. const task = localStorage.getItem('TASK_CORP_CREATE')
  115. if (task) {
  116. setSettings(JSON.parse(task).settings)
  117. }
  118. }
  119. }, [])
  120. useEffect(() => {
  121. welcomeMsgJobType.run().then(res => {
  122. if (res?.data) {
  123. setMsgJobTypeList(Object.keys(res.data).map(key => ({ value: key, label: res.data[key] })))
  124. }
  125. })
  126. getBindMpList.run().then(res => {
  127. setMplist(res?.data?.map((item: any) => ({ label: item.name, value: item.id })))
  128. })
  129. }, [])
  130. // 预览
  131. const preview = () => {
  132. const newPreviewData: TASK_CREATE.previewDataProps = {}
  133. if (!settings?.corpUserGroups || settings?.corpUserGroups?.length === 0) {
  134. message.error('请先选择客服号')
  135. return
  136. }
  137. if (!settings?.bizType) {
  138. message.error('请选择业务类型')
  139. return
  140. }
  141. if (!settings?.platform) {
  142. message.error('请选择书城')
  143. return
  144. }
  145. // 欢迎语
  146. if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
  147. const welcome = []
  148. if (!settings?.corpUserGroups?.every((item, i) => {
  149. return settings?.welcomeMsgTemplateDTO?.mediaContentList?.every((mediaItem, index, row) => {
  150. const linkData = []
  151. const miniProgramData = []
  152. const contentReactNode = mediaItem.map(item => {
  153. switch (item.mediaType) {
  154. case 'link':
  155. linkData.push(item)
  156. return `<span style="color: red">链接</span>`
  157. case 'miniprogram':
  158. miniProgramData.push(item)
  159. return `<span style="color: red">小程序</span>`
  160. case 'file':
  161. return `<span>文件</span>`
  162. case 'video':
  163. return `<span>视频</span>`
  164. case 'image':
  165. return `<span>图片</span>`
  166. case 'text':
  167. return `<span>文本</span>`
  168. default:
  169. return `<span style="color: red">请联系管理员</span>`
  170. }
  171. })
  172. welcome.push({
  173. ...settings?.welcomeMsgTemplateDTO,
  174. sendData: mediaItem,
  175. contentReactNode,
  176. corpUsergroupIndex: i,
  177. corpUserGroupName: `客服组${i + 1}`,
  178. corpUserList: item.corpUsers,
  179. linkData,
  180. miniProgramData,
  181. contentIndex: index + 1,
  182. bizType: settings?.bizType,
  183. channel: settings?.channel,
  184. platform: settings?.platform,
  185. templateProductId: settings?.templateProductId,
  186. id: i * row.length + (index + 1),
  187. rowSpan: index === 0 ? row.length : 0,
  188. mpAccountId: item.corpUsers?.[0]?.mpAccountId,
  189. mpAccountName: item.corpUsers?.[0]?.mpAccountName,
  190. corpUserStrList: item.corpUsers?.map(item => item.corpId + '_' + item.corpUserId)
  191. })
  192. return true
  193. })
  194. })) {
  195. return
  196. }
  197. console.log('welcome--->', welcome)
  198. newPreviewData.welcome = welcome
  199. }
  200. // 群发
  201. if ((settings?.massSendingContent && Object.keys(settings?.massSendingContent).length) && (settings?.massSendingStrategy && Object.keys(settings?.massSendingStrategy).length)) {
  202. const massSendingData = getGroupData(settings)
  203. const massSending = []
  204. if (!settings?.corpUserGroups?.every((item, i) => {
  205. let strategyIndex = 0
  206. return massSendingData.every((dataItem, li, row) => {
  207. const mediaItem = JSON.parse(JSON.stringify(dataItem?.content?.attachmentList || []))
  208. if (dataItem?.content?.text?.content) {
  209. mediaItem.push({
  210. msgType: 'TASK_CONTENT_TEXT',
  211. textContent: dataItem?.content?.text?.content
  212. })
  213. }
  214. const linkData = []
  215. const miniProgramData = []
  216. const contentReactNode = mediaItem.map(item => {
  217. switch (item.msgType) {
  218. case 'TASK_CONTENT_LINK':
  219. linkData.push(item)
  220. return `<span style="color: red">链接</span>`
  221. case 'TASK_STATUS_MINIPROGRAM':
  222. miniProgramData.push(item)
  223. return `<span style="color: red">小程序</span>`
  224. case 'TASK_STATUS_FILE':
  225. return `<span>文件</span>`
  226. case 'TASK_STATUS_VIDEO':
  227. return `<span>视频</span>`
  228. case 'TASK_CONTENT_IMAGE':
  229. return `<span>图片</span>`
  230. case 'TASK_CONTENT_TEXT':
  231. return `<span>文本</span>`
  232. default:
  233. return `<span style="color: red">请联系管理员</span>`
  234. }
  235. })
  236. massSending.push({
  237. ...dataItem,
  238. contentReactNode,
  239. corpUsergroupIndex: i,
  240. corpUserGroupName: `客服组${i + 1}`,
  241. corpUserList: item.corpUsers,
  242. bizType: settings?.bizType,
  243. channel: settings?.channel,
  244. platform: settings?.platform,
  245. templateProductId: settings?.templateProductId,
  246. id: i * row.length + (li + 1),
  247. linkData,
  248. miniProgramData,
  249. userRowSpan: li % row.length === 0 ? row.length : 0,
  250. strategyRowSpan: strategyIndex !== dataItem.strategyIndex ? dataItem.strategyDataCount : 0,
  251. mpAccountId: item.corpUsers?.[0]?.mpAccountId,
  252. mpAccountName: item.corpUsers?.[0]?.mpAccountName,
  253. corpUserStrList: item.corpUsers?.map(item => item.corpId + '_' + item.corpUserId)
  254. })
  255. strategyIndex = dataItem.strategyIndex
  256. return true
  257. })
  258. })) {
  259. return
  260. }
  261. console.log('massSending---->', massSending)
  262. newPreviewData.massSending = massSending
  263. }
  264. // 是否有客户继承配置
  265. if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
  266. const userInData = getUserInDataData(settings?.userInherit?.schedulingStrategyDTO, settings?.userInherit?.taskName)
  267. const userInherit = []
  268. // 数据内容
  269. if (!settings?.corpUserGroups?.every((item, i) => {
  270. return userInData.every((dataItem, ii, row) => {
  271. userInherit.push({
  272. ...dataItem,
  273. taskName: dataItem?.taskName,
  274. corpUsergroupIndex: i,
  275. corpUserGroupName: `客服组${i + 1}`,
  276. corpUserList: item.corpUsers,
  277. bizType: settings?.bizType,
  278. channel: settings?.channel,
  279. platform: settings?.platform,
  280. templateProductId: settings?.templateProductId,
  281. userRowSpan: ii === 0 ? row.length : 0,
  282. id: i * row.length + (ii + 1)
  283. })
  284. return true
  285. })
  286. })) {
  287. return
  288. }
  289. console.log('userInherit-->', userInherit)
  290. newPreviewData.userInherit = userInherit
  291. }
  292. if (newPreviewData && Object.keys(newPreviewData).length) {
  293. setPreviewData(newPreviewData)
  294. setPreviewDataOld(newPreviewData)
  295. } else {
  296. message.error('请填写至少填写一项内容')
  297. }
  298. }
  299. // 设置任务名称
  300. const setTaskName = () => {
  301. console.log('---------->', previewContent)
  302. // 欢迎语
  303. if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
  304. if (settings?.welcomeMsgTemplateDTO?.mediaContentList?.some(item => item?.some(i => i?.mediaType === 'link' || i?.mediaType === 'miniprogram')) && !(previewContent?.welcomeMsgContent?.length > 0)) {
  305. message.error('请先上传欢迎语Excel内容')
  306. return
  307. }
  308. if (!settings?.corpUserGroups?.every((_, i) => {
  309. return settings?.welcomeMsgTemplateDTO?.mediaContentList?.every((mediaItem, index) => {
  310. const welcomeMsgContent = previewContent.welcomeMsgContent?.[i]?.[index]
  311. if (mediaItem?.some(media => media?.mediaType === 'link' ? !welcomeMsgContent?.linkUrl : media?.mediaType === 'miniprogram' ? (!welcomeMsgContent?.miniprogramAppid || !welcomeMsgContent?.miniprogramPage) : false)) {
  312. message.error('欢迎语内容配置错误,请检查')
  313. return false
  314. }
  315. return true
  316. })
  317. })) {
  318. return
  319. }
  320. }
  321. // 群发任务
  322. if ((settings?.massSendingContent && Object.keys(settings?.massSendingContent).length) && (settings?.massSendingStrategy && Object.keys(settings?.massSendingStrategy).length)) {
  323. if (settings?.massSendingContent?.massSendingContentDTO?.some(item => item?.sendContentDto?.some(si => si?.contentDTO?.some(i => i?.attachmentList?.some(a => ['TASK_CONTENT_LINK', 'TASK_STATUS_MINIPROGRAM'].includes(a?.msgType))))) && !(previewContent?.groupMsgContent?.length > 0)) {
  324. message.error('需要配置小程序、链接,请认真填写')
  325. return
  326. }
  327. const massSendingData = getGroupData(settings)
  328. if (!settings?.corpUserGroups?.every((_, i) => {
  329. return massSendingData.every((dataItem) => {
  330. const groupMsgContent = previewContent?.groupMsgContent?.[i]?.[dataItem.strategyIndex - 1]?.[dataItem.sendDataIndex - 1]?.[dataItem.contentIndex - 1]
  331. if (dataItem?.content?.attachmentList?.length && dataItem?.content?.attachmentList?.some(item => (item?.msgType === 'TASK_CONTENT_LINK' ? !groupMsgContent?.linkUrl : item?.msgType === 'TASK_STATUS_MINIPROGRAM' ? (!groupMsgContent?.miniprogramAppid || !groupMsgContent?.miniprogramPage) : false))) {
  332. message.error('群发内容配置错误,请检查')
  333. return false
  334. }
  335. return true
  336. })
  337. })) {
  338. return
  339. }
  340. }
  341. // 客户继承
  342. if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
  343. const userInData = getUserInDataData(settings?.userInherit?.schedulingStrategyDTO, settings?.userInherit?.taskName)
  344. if (!settings?.corpUserGroups?.every((item, i) => {
  345. return userInData.every((dataItem) => {
  346. const externalUser = previewContent.externalUserTransferContent?.[i]?.[dataItem.strategyIndex - 1]?.[dataItem.inheritIndex - 1]
  347. if (!externalUser || !externalUser?.corpUserName || !externalUser?.corpUserId) {
  348. message.error('配置错误,' + JSON.stringify(dataItem) + ',' + JSON.stringify(item.externalUserTransferContent))
  349. return false
  350. }
  351. return true
  352. })
  353. })) {
  354. return
  355. }
  356. }
  357. setSubVisible(true)
  358. }
  359. const onSubmit = (values: any) => {
  360. const { bizType, platform, templateProductId, corpUserGroups, welcomeMsgTemplateDTO, massSendingContent, massSendingStrategy, userInherit } = settings
  361. const params = {
  362. ...values,
  363. bizType,
  364. platform,
  365. templateProductId,
  366. corpUsers: corpUserGroups?.map((item, index) => {
  367. const params: { [x: string]: any } = {
  368. corpId: item.corpUsers[0].corpId,
  369. corpUserIds: item.corpUsers.map(item => item.corpUserId)
  370. }
  371. // 欢迎语
  372. if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
  373. params.welcomeMsgContent = previewContent?.welcomeMsgContent?.[index] || undefined
  374. }
  375. // 群发
  376. if (massSendingStrategy && Object.keys(massSendingStrategy).length > 0) {
  377. params.groupMsgContent = previewContent?.groupMsgContent?.[index] || undefined
  378. }
  379. // 继承
  380. if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
  381. params.takeoverUserIds = previewContent?.externalUserTransferContent?.[index] || undefined
  382. }
  383. return params
  384. })
  385. }
  386. // 欢迎语
  387. if (welcomeMsgTemplateDTO && Object.keys(welcomeMsgTemplateDTO).length) {
  388. params.welcomeMsgTemplateDTO = welcomeMsgTemplateDTO
  389. }
  390. // 群发
  391. if (massSendingStrategy && Object.keys(massSendingStrategy).length) {
  392. params.groupSendTaskAddDTO = {
  393. groupSendName: massSendingStrategy.groupSendName,
  394. strategyList: massSendingStrategy?.strategySettings?.map((settingsItem, settingsIndex) => {
  395. const {
  396. // 发送对象
  397. sendData,
  398. // 策略
  399. ...strategy
  400. } = settingsItem
  401. return {
  402. ...strategy,
  403. taskDetail: sendData.map((sendItem, sendIndex) => {
  404. // 发送内容
  405. const { contentDTO, sendMode } = massSendingContent.massSendingContentDTO[settingsIndex]['sendContentDto'][sendIndex]
  406. const detail: { [x: string]: any } = {
  407. sendMode,
  408. contentDTO,
  409. externalUserFilterName: sendItem?.externalUserFilterName
  410. }
  411. if (sendItem.externalUserType === 'specify') {
  412. detail.externalUserFilter = {
  413. configName: sendItem.externalUserFilter.configName,
  414. ...sendItem.externalUserFilter.configContent
  415. }
  416. }
  417. return detail
  418. })
  419. }
  420. })
  421. }
  422. }
  423. // 客户继承
  424. if (userInherit && Object.keys(userInherit).length) {
  425. params.externalUserTransferTasksDTO = {
  426. taskName: userInherit.taskName,
  427. schedulingStrategyDTO: userInherit.schedulingStrategyDTO.map(strategyItem => {
  428. const {
  429. inheritDto,
  430. ...strategy
  431. } = strategyItem
  432. return {
  433. ...strategy,
  434. transferStrategyContentDTOS: inheritDto.map(inheritItem => {
  435. const inherit: { [x: string]: any } = {
  436. transferSuccessMsg: inheritItem.transferSuccessMsg
  437. }
  438. if (inheritItem.transferType === 'specify') {
  439. inherit.externalUserFilter = {
  440. configName: inheritItem.transferUserDto.configName,
  441. ...inheritItem.transferUserDto.configContent
  442. }
  443. }
  444. return inherit
  445. })
  446. }
  447. })
  448. }
  449. }
  450. console.log('11111111111111', values)
  451. if (projectId) {
  452. params.projectId = projectId
  453. updateTask.run(params).then(res => {
  454. console.log(res)
  455. if (res?.data) {
  456. message.success('修改提交成功')
  457. setProjectId(undefined)
  458. sessionStorage.setItem('CAMPCORP', values?.projectName)
  459. navigate('/weComTask/businessPlan/taskList')
  460. }
  461. })
  462. } else {
  463. addTask.run(params).then(res => {
  464. console.log(res)
  465. if (res?.data) {
  466. modal.success({
  467. content: '任务提交成功',
  468. styles: { body: { fontWeight: 700 } },
  469. okText: '跳转任务列表',
  470. closable: true,
  471. onOk: () => {
  472. sessionStorage.setItem('CAMPCORP', values?.projectName)
  473. navigate('/weComTask/businessPlan/taskList')
  474. },
  475. onCancel: () => {
  476. setSubVisible(false)
  477. }
  478. })
  479. }
  480. })
  481. }
  482. }
  483. // 重置表格
  484. const onPreviewReset = () => {
  485. setPreviewData({})
  486. setPreviewDataOld({})
  487. if (!isEditSc) {
  488. setPreviewContent({})
  489. }
  490. }
  491. const severBd = () => {
  492. localStorage.setItem('TASK_CORP_CREATE', JSON.stringify({ settings }))
  493. message.success('存储成功')
  494. }
  495. const setContent = useCallback((data: TASK_CREATE.SetContentProps) => {
  496. const { msg, index, type } = data
  497. const newPreviewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] } = JSON.parse(JSON.stringify(previewContent))
  498. switch (type) {
  499. case 'welcome':
  500. newPreviewContent.welcomeMsgContent = newPreviewContent?.welcomeMsgContent || []
  501. if (!newPreviewContent.welcomeMsgContent?.[index[0]]) newPreviewContent.welcomeMsgContent[index[0]] = [];
  502. if (!newPreviewContent.welcomeMsgContent[index[0]][index[1]]) newPreviewContent.welcomeMsgContent[index[0]][index[1]] = {};
  503. newPreviewContent.welcomeMsgContent[index[0]][index[1]] = { ...newPreviewContent.welcomeMsgContent[index[0]][index[1]], ...msg }
  504. break
  505. case 'massSending':
  506. newPreviewContent.groupMsgContent = newPreviewContent?.groupMsgContent || []
  507. if (!newPreviewContent.groupMsgContent?.[index[0]]) newPreviewContent.groupMsgContent[index[0]] = [];
  508. if (!newPreviewContent.groupMsgContent[index[0]][index[1]]) newPreviewContent.groupMsgContent[index[0]][index[1]] = [];
  509. if (!newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]]) newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]] = [];
  510. if (!newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]]) newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]] = {};
  511. newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]] = { ...newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]], ...msg }
  512. break
  513. case 'userInherit':
  514. newPreviewContent.externalUserTransferContent = newPreviewContent?.externalUserTransferContent || []
  515. if (!newPreviewContent.externalUserTransferContent?.[index[0]]) newPreviewContent.externalUserTransferContent[index[0]] = [];
  516. if (!newPreviewContent.externalUserTransferContent[index[0]][index[1]]) newPreviewContent.externalUserTransferContent[index[0]][index[1]] = [];
  517. if (!newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]]) newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]] = {};
  518. newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]] = { ...newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]], ...msg }
  519. break
  520. }
  521. setPreviewContent(newPreviewContent)
  522. }, [previewContent])
  523. const tableSearch = useCallback((values) => {
  524. console.log(values)
  525. if (values?.mpAccountIds?.length > 0 || values?.corpUserIds?.length > 0) {
  526. const newPreviewData: TASK_CREATE.previewDataProps = {}
  527. const corpUserStrList = values?.corpUserIds?.map(item => item.corpId + '_' + item.corpUserId)
  528. if (previewDataOld?.welcome) {
  529. newPreviewData.welcome = previewDataOld.welcome.filter(item => (
  530. (values?.mpAccountIds?.length > 0 ? values.mpAccountIds.includes(item.mpAccountId) : true)
  531. &&
  532. (corpUserStrList?.length > 0 ? item.corpUserStrList.some(str => corpUserStrList.includes(str)) : true)
  533. )).map(item => ({ ...item, rowSpan: 1 }))
  534. }
  535. if (previewDataOld?.massSending) {
  536. newPreviewData.massSending = previewDataOld.massSending.filter(item => (
  537. (values?.mpAccountIds?.length > 0 ? values.mpAccountIds.includes(item.mpAccountId) : true)
  538. &&
  539. (corpUserStrList?.length > 0 ? item.corpUserStrList.some(str => corpUserStrList.includes(str)) : true)
  540. )).map(item => ({ ...item, userRowSpan: 1, strategyRowSpan: 1, sendDataRowSpan: 1 }))
  541. }
  542. setPreviewData(newPreviewData)
  543. } else {
  544. setPreviewData(previewDataOld)
  545. }
  546. }, [previewDataOld, previewData])
  547. return <div className={style.create}>
  548. <Spin spinning={getCreateDetails.loading}>
  549. <Card title={<strong>{projectId ? getCreateDetails?.data?.data?.projectName + '任务编辑' : ''}配置区</strong>} className={`${style.card} ${style.config}`}>
  550. <Space wrap>
  551. <Space.Compact>
  552. <Button>客服组</Button>
  553. <SelectCorpUserGroup
  554. disabled={isEditSc}
  555. value={settings?.corpUserGroups}
  556. onChange={(corpUserGroups) => {
  557. console.log(corpUserGroups)
  558. setSettings({
  559. ...settings, corpUserGroups: corpUserGroups.map(item => {
  560. return {
  561. ...item, corpUsers: item.corpUsers.map((item: any) => {
  562. const { corpUserId, name, corpName, corpId, mpAccountId, mpAccountInfo, id } = item
  563. return { corpUserId, name, corpName, corpId, mpAccountId, mpAccountName: mpAccountInfo?.name || item?.mpAccountName, id }
  564. })
  565. }
  566. })
  567. })
  568. onPreviewReset()
  569. }}
  570. />
  571. </Space.Compact>
  572. <Space.Compact>
  573. <Button>业务类型</Button>
  574. <Select
  575. showSearch
  576. style={{ width: 120 }}
  577. allowClear
  578. placeholder="请选择类型"
  579. filterOption={(input, option) =>
  580. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  581. }
  582. value={settings?.bizType}
  583. onChange={(e) => {
  584. setSettings({ ...settings, bizType: e })
  585. onPreviewReset()
  586. }}
  587. options={msgJobTypeList.filter(item => item.value === 'novel')}
  588. />
  589. </Space.Compact>
  590. {settings?.bizType === 'novel' ? <>
  591. <Space.Compact>
  592. <Button>书城</Button>
  593. <Select
  594. showSearch
  595. allowClear
  596. placeholder="请选择书城"
  597. style={{ width: 120 }}
  598. filterOption={(input, option) =>
  599. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  600. }
  601. value={settings?.platform}
  602. onChange={(e) => {
  603. setSettings({ ...settings, platform: e, templateProductId: undefined })
  604. onPreviewReset()
  605. }}
  606. options={bookPlatForm.map(item => ({ value: item.id, label: item.platformName }))}
  607. />
  608. </Space.Compact>
  609. <Space.Compact>
  610. <Button>适用产品</Button>
  611. <Select
  612. showSearch
  613. style={{ width: 150 }}
  614. allowClear
  615. placeholder="请选择模板适用产品"
  616. filterOption={(input, option) =>
  617. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  618. }
  619. value={settings?.templateProductId}
  620. onChange={(e) => {
  621. setSettings({ ...settings, templateProductId: e })
  622. onPreviewReset()
  623. }}
  624. options={bookList.filter(item => settings?.platform ? item.platformId === settings?.platform : true).map(item => ({ value: item.id, label: item.bookName }))}
  625. />
  626. </Space.Compact>
  627. </> : settings?.bizType === 'game' ? <Space.Compact>
  628. <Button>游戏渠道</Button>
  629. <Input
  630. style={{ width: 200 }}
  631. allowClear
  632. placeholder="请输入游戏渠道"
  633. value={settings.channel}
  634. onChange={(e) => {
  635. setSettings({ ...settings, channel: e.target.value })
  636. onPreviewReset()
  637. }}
  638. />
  639. </Space.Compact> : undefined}
  640. {(settings?.highMassSendingStrategy && Object.keys(settings?.highMassSendingStrategy).length > 0) && <Button
  641. onClick={() => setEaVisible(true)}
  642. type={settings?.corpUsers?.every(item => item?.externalUserList?.length) ? 'primary' : 'default'}
  643. >
  644. {settings?.corpUsers?.every(item => item?.externalUserList?.length) ? <>
  645. 重选高级群发外部客户
  646. <CheckOutlined style={{ marginLeft: 5 }} />
  647. </> : '高级群发外部客户选择'}
  648. </Button>}
  649. {(settings?.friendsStrategy && Object.keys(settings?.friendsStrategy).length > 0 && settings?.corpUsers?.length > 0) && <Button
  650. onClick={() => {
  651. setQwVisible(true)
  652. }}
  653. type={settings?.corpUsers?.some(item => item?.friendsTagContent?.length) ? 'primary' : 'default'}
  654. >
  655. {settings?.corpUsers?.some(item => item?.friendsTagContent?.length) ? <>
  656. 重选企业标签
  657. <CheckOutlined style={settings?.corpUsers?.every(item => item?.friendsTagContent?.length) ? { marginLeft: 5 } : { marginLeft: 5, color: 'red' }} />
  658. </> : '选择企业标签'}
  659. </Button>}
  660. </Space>
  661. <div className={style.settingsBody}>
  662. <div className={style.settingsBody_content}>
  663. <DispatchTaskCreate.Provider
  664. value={{
  665. settings, setSettings,
  666. bookPlatForm,
  667. bookList,
  668. msgJobTypeList,
  669. onPreviewReset,
  670. isEditSc
  671. }}>
  672. <div className={style.settingsBody_content_right}>
  673. {/* 欢迎语 */}
  674. <Welcome />
  675. {/* 群发设置 */}
  676. <MassSending />
  677. {/* 高级群发 */}
  678. {/* <HighMassSending /> */}
  679. {/* 朋友圈 */}
  680. {/* <Friends /> */}
  681. {/* 客户继承 */}
  682. <UserInherit />
  683. </div>
  684. </DispatchTaskCreate.Provider>
  685. </div>
  686. </div>
  687. <Space className={style.bts} wrap>
  688. <Button icon={<SaveOutlined />} onClick={severBd}>存为预设</Button>
  689. <Popconfirm
  690. title="确定清空?"
  691. onConfirm={() => {
  692. setSettings(undefined)
  693. setPreviewData({})
  694. setPreviewDataOld({})
  695. localStorage.removeItem('TASK_CORP_CREATE')
  696. }}
  697. >
  698. <Button icon={<RedoOutlined />} danger>清空配置/预设</Button>
  699. </Popconfirm>
  700. <Button type='primary' onClick={preview}><SearchOutlined />预览任务/配置内容</Button>
  701. </Space>
  702. </Card>
  703. </Spin>
  704. <Card className={style.card} style={{ marginTop: 10, marginBottom: 10 }}>
  705. {Object.keys(previewData).length > 0 ? <div style={{ minHeight: 300 }}>
  706. <Form
  707. layout={'inline'}
  708. onFinish={tableSearch}
  709. >
  710. <Form.Item label={<strong>公众号</strong>} name="mpAccountIds">
  711. <Select
  712. showSearch
  713. style={{ minWidth: 160 }}
  714. maxTagCount={1}
  715. placeholder="公众号"
  716. filterOption={(input, option) =>
  717. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  718. }
  719. allowClear
  720. mode='multiple'
  721. options={mpList}
  722. />
  723. </Form.Item>
  724. <Space.Compact>
  725. <Button>客服组</Button>
  726. <Form.Item name="corpUserIds">
  727. <SelectCorpUser placeholder="请选择客服号" />
  728. </Form.Item>
  729. </Space.Compact>
  730. <Form.Item>
  731. <Space>
  732. <Button htmlType="reset">重置</Button>
  733. <Button type="primary" htmlType='submit'>搜索</Button>
  734. </Space>
  735. </Form.Item>
  736. </Form>
  737. <Tabs
  738. defaultActiveKey="1"
  739. items={Object.keys(previewData).map(key => ({
  740. key: key,
  741. label: { 'userInherit': '客户继承', 'massSending': '客户群发', 'welcome': '欢迎语', 'highMassSending': '高级群发', 'friends': '朋友圈' }[key],
  742. children: key === 'userInherit' ? <>
  743. <Table
  744. dataSource={previewData[key]}
  745. columns={userInheritColumns(setContent)}
  746. rowKey={'id'}
  747. bordered={true}
  748. scroll={{ y: 550 }}
  749. pagination={false}
  750. />
  751. </> : key === 'massSending' ? <>
  752. <Table
  753. dataSource={previewData[key]}
  754. columns={massSendingColumns(setContent, bookPlatForm, bookList, previewContent, bookPlatForm.find(item => item.id === Number(settings?.platform)).platformKey)}
  755. rowKey={'id'}
  756. bordered={true}
  757. scroll={{ y: 550 }}
  758. pagination={false}
  759. />
  760. </> : key === 'welcome' ? <>
  761. <Table
  762. dataSource={previewData[key]}
  763. columns={welcomeColumns(bookPlatForm, bookList, setContent, previewContent, bookPlatForm.find(item => item.id === Number(settings?.platform)).platformKey)}
  764. rowKey={'id'}
  765. bordered={true}
  766. scroll={{ y: 550 }}
  767. pagination={false}
  768. />
  769. </> : key === 'highMassSending' ? <>
  770. <Table
  771. dataSource={previewData[key]}
  772. columns={highMassSendingColumns()}
  773. rowKey={'id'}
  774. bordered={true}
  775. scroll={{ y: 550 }}
  776. pagination={false}
  777. />
  778. </> : key === 'friends' ? <>
  779. <Table
  780. dataSource={previewData[key]}
  781. columns={friendsColumns()}
  782. rowKey={'id'}
  783. bordered={true}
  784. scroll={{ y: 550 }}
  785. pagination={false}
  786. />
  787. </> : undefined
  788. }))}
  789. tabBarExtraContent={<Space size={10}>
  790. {/* <Text strong>欢迎语:{previewData?.welcome?.length || 0},群发:{previewData?.massSending?.length || 0},客户继承:{previewData?.userInherit?.length || 0}</Text> */}
  791. <Button type='primary' icon={<PlusOutlined />} onClick={() => {
  792. setTaskName()
  793. }}>提交</Button>
  794. </Space>}
  795. />
  796. </div> : <div style={{ minHeight: 400, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
  797. <Empty description="请先完成模块配置后,再预览" />
  798. </div>}
  799. </Card>
  800. {/* 提交配置 */}
  801. {subVisible && <SubmitModal
  802. visible={subVisible}
  803. loading={addTask.loading || updateTask.loading}
  804. projectName={projectId ? getCreateDetails?.data?.data?.projectName : undefined}
  805. onChange={(values) => {
  806. onSubmit(values)
  807. }}
  808. onClose={() => {
  809. setSubVisible(false)
  810. }}
  811. />}
  812. {/* 选择外部客户 */}
  813. {eaVisible && <SelectExternalAccount
  814. corpUsers={settings?.corpUsers || []}
  815. visible={eaVisible}
  816. onClose={() => {
  817. setEaVisible(false)
  818. }}
  819. onChange={(value) => {
  820. setEaVisible(false)
  821. setSettings({
  822. ...settings,
  823. corpUsers: value
  824. })
  825. }}
  826. />}
  827. {qwVisible && <SelectCwTag
  828. corpUsers={settings?.corpUsers || []}
  829. visible={qwVisible}
  830. onClose={() => {
  831. setQwVisible(false)
  832. }}
  833. onChange={(value) => {
  834. setQwVisible(false)
  835. setSettings({
  836. ...settings,
  837. corpUsers: value
  838. })
  839. }}
  840. />}
  841. </div>
  842. };
  843. export default inject('store')(observer((props: any) => Create(props.store)))