index.tsx 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570
  1. import React, { useCallback, useEffect, useState } from 'react';
  2. import style from '../../businessPlan/create/index.less'
  3. import { App, Button, Card, Empty, Form, Input, Popconfirm, Select, Space, Spin, Table } from 'antd';
  4. import { welcomeMsgJobTypeApi } from '@/pages/weComTask/API/weMaterial/weMaterial';
  5. import { useAjax } from '@/Hook/useAjax';
  6. import { inject, observer } from 'mobx-react';
  7. import { toJS } from 'mobx';
  8. import Strategy from './components/strategy';
  9. import GroupUser from './components/groupUser';
  10. import { SaveOutlined, RedoOutlined, SearchOutlined, PlusOutlined } from '@ant-design/icons';
  11. import { getCorpUserChatAllListApi } from '@/pages/weComTask/API/groupLeaderManage';
  12. import SelectCorpUserChatUser from '../../groupLeaderManage/selectCorpUserChatUser';
  13. import { PreviewColumns } from './tableConfig';
  14. import SelectCorpUser from '../../corpUserManage/selectCorpUser';
  15. import { getBindMpListApi } from '@/pages/weComTask/API/corpUserAssign';
  16. import { getCorpAllListApi } from '@/API/global';
  17. import { removeEmptyValues } from '@/utils/utils';
  18. import SubmitModal from '../../businessPlan/create/submitModal';
  19. import { addPullGroupTaskApi, getCreateDetailsApi, updateGroupTaskApi } from '@/pages/weComTask/API/groupChat';
  20. import { useNavigate } from 'react-router-dom';
  21. import { getPullGroupData } from './const';
  22. import SelectGroupLeader from '../../groupLeaderManage/selectGroupLeader';
  23. export const DispatchGroupChatCreate = React.createContext<GROUP_CHAT_CREATE.DispatchGroupChatCreate | null>(null);
  24. /**
  25. * 群聊任务创建组件
  26. * @returns
  27. */
  28. const GroupChatCreate: 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 { message, modal } = App.useApp()
  33. const [settings, setSettings] = useState<GROUP_CHAT_CREATE.SettingsProps>();
  34. const [msgJobTypeList, setMsgJobTypeList] = useState<{ value: string, label: string }[]>([])
  35. const [previewData, setPreviewData] = useState<any[]>([])
  36. const [previewDataOld, setPreviewDataOld] = useState<any[]>([])
  37. const [mpList, setMplist] = useState<{ label: string, value: string }[]>([])
  38. const [subVisible, setSubVisible] = useState<boolean>(false) // 选择设置名称弹窗控制
  39. const [projectId, setProjectId] = useState<number>()
  40. const welcomeMsgJobType = useAjax(() => welcomeMsgJobTypeApi())//获取业务类型
  41. const getBindMpList = useAjax(() => getBindMpListApi())
  42. const getCorpAllList = useAjax((params) => getCorpAllListApi(params))
  43. const addPullGroupTask = useAjax((params) => addPullGroupTaskApi(params))
  44. const updateGroupTask = useAjax((params) => updateGroupTaskApi(params))
  45. const getCreateDetails = useAjax((params) => getCreateDetailsApi(params))
  46. /***********************************************/
  47. console.log('settings--->', settings)
  48. useEffect(() => {
  49. const project = sessionStorage.getItem('PG_OFFICIALTASKID')
  50. if (project) {
  51. const { id, isCopy } = JSON.parse(project)
  52. if (!isCopy) {
  53. setProjectId(id)
  54. }
  55. getCreateDetails.run(id).then(res => {
  56. sessionStorage.removeItem('PG_OFFICIALTASKID')
  57. if (res?.data) {
  58. const { bizType, platform, templateProductId, corpUsers, corpChatUserList, corpRobots, strategyList } = res.data
  59. const data = getPullGroupData(strategyList || [])
  60. console.log('data-->', data)
  61. let newSettings: GROUP_CHAT_CREATE.SettingsProps = {
  62. bizType,
  63. platform: Number(platform) as any,
  64. templateProductId,
  65. corpUserChat: corpChatUserList.map(item => {
  66. return {
  67. label: `${item.name}(${item.corpName})`,
  68. value: item.id,
  69. name: item.name,
  70. corpName: item.corpName,
  71. corpId: item.corpId,
  72. corpUserId: item.corpUserId
  73. }
  74. }),
  75. corpUsers: corpUsers?.map(item => {
  76. return {
  77. name: item.corpUserName,
  78. corpUserId: item.corpUserId,
  79. corpName: item.corpName,
  80. corpId: item.corpId
  81. }
  82. }),
  83. robotCorpUsers: corpRobots?.map(item => {
  84. return {
  85. name: item.corpUserName,
  86. corpUserId: item.corpUserId,
  87. corpName: item.corpName,
  88. corpId: item.corpId
  89. }
  90. }),
  91. strategyDTO: {
  92. ...data
  93. }
  94. }
  95. console.log('------------->', newSettings)
  96. setSettings(newSettings)
  97. }
  98. })
  99. } else {
  100. const task = localStorage.getItem('TASK_GROUP_CHAT_CREATE')
  101. if (task) {
  102. setSettings(JSON.parse(task).settings)
  103. }
  104. }
  105. }, [])
  106. useEffect(() => {
  107. welcomeMsgJobType.run().then(res => {
  108. if (res?.data) {
  109. setMsgJobTypeList(Object.keys(res.data).map(key => ({ value: key, label: res.data[key] })))
  110. }
  111. })
  112. getBindMpList.run().then(res => {
  113. setMplist(res?.data?.map((item: any) => ({ label: item.name, value: item.id + '' })))
  114. })
  115. getCorpAllList.run({})
  116. }, [])
  117. const severBd = () => {
  118. localStorage.setItem('TASK_GROUP_CHAT_CREATE', JSON.stringify({ settings }))
  119. message.success('存储成功')
  120. }
  121. const preview = () => {
  122. const { corpUserChat, corpUsers, robotCorpUsers, bizType, platform, templateProductId } = settings
  123. if (!corpUserChat || corpUserChat?.length === 0) {
  124. message.error('请先选择群主号')
  125. return
  126. }
  127. if (!corpUsers || corpUsers?.length === 0) {
  128. message.error('请先选择客服号')
  129. return
  130. }
  131. // if (!robotCorpUsers || robotCorpUsers?.length === 0) {
  132. // message.error('请先选择机器人号')
  133. // return
  134. // }
  135. if (!bizType) {
  136. message.error('请选择业务类型')
  137. return
  138. }
  139. if (!platform) {
  140. message.error('请选择书城')
  141. return
  142. }
  143. if (!(settings?.strategyDTO && Object.keys(settings?.strategyDTO).length > 0)) {
  144. message.error('请先设置策略')
  145. return
  146. }
  147. if (!settings?.strategyDTO?.strategyList?.every(item => item?.groupObjectList?.length > 0)) {
  148. message.error('请先设置群配置')
  149. return
  150. }
  151. const dto = settings.strategyDTO.strategyList.reduce((pre, cur, strategyIndex) => {
  152. const { groupObjectList, ...its } = cur
  153. groupObjectList.forEach((item, index) => {
  154. pre.push({
  155. ...item,
  156. ...its,
  157. strategyIndex,
  158. goIndex: index,
  159. taskName: settings.strategyDTO.taskName
  160. })
  161. })
  162. return pre
  163. }, [])
  164. let id = 1
  165. const list = corpUsers.reduce((pre, corpUser) => {
  166. return pre.concat(dto.map(item => {
  167. return {
  168. ...item,
  169. corpUser,
  170. corpUserChat,
  171. robotCorpUsers,
  172. bizType,
  173. platform,
  174. templateProductId,
  175. id: id++
  176. }
  177. }))
  178. }, [])
  179. console.log('==================>', list)
  180. setPreviewData(list)
  181. setPreviewDataOld(list)
  182. }
  183. // 重置表格
  184. const onPreviewReset = () => {
  185. setPreviewData([])
  186. setPreviewDataOld([])
  187. }
  188. const tableSearch = useCallback((values) => {
  189. console.log(values)
  190. const obj = removeEmptyValues(values)
  191. if (Object.keys(obj).length) {
  192. const newPreviewData = previewDataOld.filter(item => {
  193. const weChatAppid = item?.weChatAppid?.split('_')?.[1]
  194. return (obj?.mpAccountIds?.length > 0 ? obj.mpAccountIds.includes(weChatAppid) : true) &&
  195. (obj?.corpId ? item?.corpUser?.corpId === obj?.corpId : true) &&
  196. (obj?.corpUserIds?.length > 0 ? obj?.corpUserIds?.map(item => item.corpUserId)?.includes(item?.corpUser?.corpUserId) : true) &&
  197. (obj?.groupCorpId ? item?.corpUserChat?.map(item => item.corpId)?.includes(obj?.groupCorpId) : true) &&
  198. (obj?.robotCorpId ? item?.robotCorpUsers?.[0]?.corpId === obj?.robotCorpId : true) &&
  199. (obj?.groupObjectName ? item?.groupObjectName?.includes(obj?.groupObjectName) : true)
  200. })
  201. setPreviewData(newPreviewData)
  202. } else {
  203. setPreviewData(previewDataOld)
  204. }
  205. }, [previewDataOld, previewData])
  206. const onSubmit = (values: any) => {
  207. const { bizType, platform, templateProductId, corpUsers, corpUserChat, robotCorpUsers, strategyDTO } = settings
  208. console.log('--->', values)
  209. const params: { [x: string]: any } = {
  210. taskName: values.projectName,
  211. bizType,
  212. platform,
  213. templateProductId,
  214. corpChatUserIds: corpUserChat.map(item => item.value),
  215. corpRobots: robotCorpUsers?.map(item => ({
  216. corpId: item.corpId,
  217. corpUserId: item.corpUserId,
  218. corpUserName: item.name,
  219. corpName: item.corpName
  220. })),
  221. corpUsers: corpUsers.map(item => ({
  222. corpId: item.corpId,
  223. corpUserId: item.corpUserId,
  224. corpUserName: item.name,
  225. corpName: item.corpName
  226. })),
  227. strategyList: strategyDTO.strategyList.map(({ groupObjectList, ...item }) => {
  228. return {
  229. ...item,
  230. taskDetail: groupObjectList.map(go => {
  231. const { externalUserType, externalUserFilter, groupObjectName, tagDTO, weChatAppid, ...itgo } = go
  232. const detail = {
  233. ...itgo,
  234. groupName: groupObjectName,
  235. msgTagDTO: tagDTO
  236. }
  237. if (externalUserType === 'specify') {
  238. detail.externalUserFilter = {
  239. configName: externalUserFilter.configName,
  240. ...externalUserFilter.configContent
  241. }
  242. }
  243. if (weChatAppid) {
  244. detail.mpAccountId = weChatAppid.split('_')[1]
  245. }
  246. return detail
  247. })
  248. }
  249. })
  250. }
  251. console.log('提交参数--->', params)
  252. if (projectId) {
  253. params.projectId = projectId
  254. updateGroupTask.run(params).then(res => {
  255. console.log(res)
  256. if (res?.data) {
  257. message.success('修改提交成功')
  258. setProjectId(undefined)
  259. sessionStorage.setItem('CAMPCORP_PG', values?.projectName)
  260. navigate('/weComTask/groupChat/taskList')
  261. }
  262. })
  263. } else {
  264. addPullGroupTask.run(params).then(res => {
  265. console.log(res)
  266. if (res?.data) {
  267. modal.success({
  268. content: '任务提交成功',
  269. styles: { body: { fontWeight: 700 } },
  270. okText: '跳转任务列表',
  271. closable: true,
  272. onOk: () => {
  273. sessionStorage.setItem('CAMPCORP_PG', values?.projectName)
  274. navigate('/weComTask/groupChat/taskList')
  275. },
  276. onCancel: () => {
  277. setSubVisible(false)
  278. }
  279. })
  280. }
  281. })
  282. }
  283. }
  284. return <div className={style.create}>
  285. <Spin spinning={getCreateDetails.loading}>
  286. <Card title={<strong>{projectId ? getCreateDetails?.data?.data?.taskName + '任务编辑' : ''}配置区</strong>} className={`${style.card} ${style.config}`}>
  287. <Space wrap>
  288. <Space.Compact>
  289. <Button>群主号</Button>
  290. <SelectGroupLeader
  291. value={settings?.corpUserChat}
  292. onChange={(corpUserChat) => {
  293. setSettings({ ...settings, corpUserChat: corpUserChat, corpUsers: undefined, robotCorpUsers: undefined })
  294. onPreviewReset()
  295. }}
  296. />
  297. </Space.Compact>
  298. {settings?.corpUserChat?.length > 0 && <>
  299. <Space.Compact>
  300. <Button>客服号</Button>
  301. <SelectCorpUserChatUser
  302. placeholder="请选择客服号"
  303. bindType={1}
  304. corpUserChatIds={settings?.corpUserChat?.map(item => item.value)}
  305. value={settings?.corpUsers}
  306. onChange={(value) => {
  307. setSettings({
  308. ...settings,
  309. corpUsers: value,
  310. })
  311. onPreviewReset()
  312. }}
  313. />
  314. </Space.Compact>
  315. <Space.Compact>
  316. <Button>机器人号</Button>
  317. <SelectCorpUserChatUser
  318. placeholder="请选择机器人号"
  319. bindType={2}
  320. corpUserChatIds={settings?.corpUserChat?.map(item => item.value)}
  321. value={settings?.robotCorpUsers}
  322. onChange={(value) => {
  323. setSettings({
  324. ...settings,
  325. robotCorpUsers: value,
  326. })
  327. onPreviewReset()
  328. }}
  329. />
  330. </Space.Compact>
  331. </>}
  332. <Space.Compact>
  333. <Button>业务类型</Button>
  334. <Select
  335. showSearch
  336. style={{ width: 120 }}
  337. allowClear
  338. placeholder="请选择类型"
  339. filterOption={(input, option) =>
  340. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  341. }
  342. value={settings?.bizType}
  343. onChange={(e) => {
  344. setSettings({ ...settings, bizType: e })
  345. onPreviewReset()
  346. }}
  347. options={msgJobTypeList.filter(item => item.value === 'novel')}
  348. />
  349. </Space.Compact>
  350. {settings?.bizType === 'novel' ? <>
  351. <Space.Compact>
  352. <Button>书城</Button>
  353. <Select
  354. showSearch
  355. allowClear
  356. placeholder="请选择书城"
  357. style={{ width: 120 }}
  358. filterOption={(input, option) =>
  359. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  360. }
  361. value={settings?.platform}
  362. onChange={(e) => {
  363. setSettings({ ...settings, platform: e })
  364. onPreviewReset()
  365. }}
  366. options={bookPlatForm.map(item => ({ value: item.id, label: item.platformName }))}
  367. />
  368. </Space.Compact>
  369. <Space.Compact>
  370. <Button>适用产品</Button>
  371. <Select
  372. showSearch
  373. style={{ width: 150 }}
  374. allowClear
  375. placeholder="请选择模板适用产品"
  376. filterOption={(input, option) =>
  377. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  378. }
  379. value={settings?.templateProductId}
  380. onChange={(e) => {
  381. setSettings({ ...settings, templateProductId: e })
  382. onPreviewReset()
  383. }}
  384. options={bookList.map(item => ({ value: item.id, label: item.bookName }))}
  385. />
  386. </Space.Compact>
  387. </> : settings?.bizType === 'game' ? <Space.Compact>
  388. <Button>游戏渠道</Button>
  389. <Input
  390. style={{ width: 200 }}
  391. allowClear
  392. placeholder="请输入游戏渠道"
  393. value={settings.channel}
  394. onChange={(e) => {
  395. setSettings({ ...settings, channel: e.target.value })
  396. onPreviewReset()
  397. }}
  398. />
  399. </Space.Compact> : undefined}
  400. </Space>
  401. <div className={style.settingsBody}>
  402. <div className={style.settingsBody_content}>
  403. <DispatchGroupChatCreate.Provider
  404. value={{
  405. settings, setSettings,
  406. onPreviewReset,
  407. bookPlatForm, bookList
  408. }}
  409. >
  410. {/* 策略配置 */}
  411. <Strategy />
  412. {/* 进群对象 */}
  413. <GroupUser />
  414. </DispatchGroupChatCreate.Provider>
  415. </div>
  416. </div>
  417. <Space className={style.bts} wrap>
  418. <Button icon={<SaveOutlined />} onClick={severBd}>存为预设</Button>
  419. <Popconfirm
  420. title="确定清空?"
  421. onConfirm={() => {
  422. setSettings(undefined)
  423. onPreviewReset()
  424. localStorage.removeItem('TASK_GROUP_CHAT_CREATE')
  425. }}
  426. >
  427. <Button icon={<RedoOutlined />} danger>清空配置/预设</Button>
  428. </Popconfirm>
  429. <Button type='primary' onClick={preview}><SearchOutlined />预览任务/配置内容</Button>
  430. </Space>
  431. </Card>
  432. </Spin>
  433. <Card
  434. className={style.card}
  435. style={{ marginTop: 10, marginBottom: 10 }}
  436. extra={previewDataOld?.length > 0 ? <Button type='primary' icon={<PlusOutlined />} onClick={() => {
  437. setSubVisible(true)
  438. }}>提交</Button> : undefined}
  439. >
  440. {previewDataOld?.length > 0 ? <div style={{ minHeight: 300 }}>
  441. <Form
  442. layout={'inline'}
  443. onFinish={tableSearch}
  444. >
  445. <Form.Item label={<strong>公众号</strong>} style={{ marginBottom: 10 }} name="mpAccountIds">
  446. <Select
  447. showSearch
  448. style={{ minWidth: 160 }}
  449. maxTagCount={1}
  450. placeholder="公众号"
  451. filterOption={(input, option) =>
  452. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  453. }
  454. allowClear
  455. mode='multiple'
  456. options={mpList}
  457. />
  458. </Form.Item>
  459. <Form.Item label={<strong>客服号主体</strong>} style={{ marginBottom: 10 }} name="corpId">
  460. <Select
  461. showSearch
  462. style={{ minWidth: 110 }}
  463. maxTagCount={1}
  464. placeholder="请选择主体"
  465. filterOption={(input, option) =>
  466. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  467. }
  468. allowClear
  469. options={getCorpAllList?.data?.data?.map((item: any) => ({ label: item.corpName, value: item.corpId }))}
  470. />
  471. </Form.Item>
  472. <Space.Compact>
  473. <Button>客服号</Button>
  474. <Form.Item name="corpUserIds" style={{ marginBottom: 10 }}>
  475. <SelectCorpUser placeholder="请选择客服号" />
  476. </Form.Item>
  477. </Space.Compact>
  478. <Form.Item label={<strong>群主号主体</strong>} style={{ marginBottom: 10 }} name="groupCorpId">
  479. <Select
  480. showSearch
  481. style={{ minWidth: 110 }}
  482. maxTagCount={1}
  483. placeholder="请选择主体"
  484. filterOption={(input, option) =>
  485. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  486. }
  487. allowClear
  488. options={getCorpAllList?.data?.data?.map((item: any) => ({ label: item.corpName, value: item.corpId }))}
  489. />
  490. </Form.Item>
  491. <Form.Item label={<strong>机器人号主体</strong>} style={{ marginBottom: 10 }} name="robotCorpId">
  492. <Select
  493. showSearch
  494. style={{ minWidth: 110 }}
  495. maxTagCount={1}
  496. placeholder="请选择主体"
  497. filterOption={(input, option) =>
  498. ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
  499. }
  500. allowClear
  501. options={getCorpAllList?.data?.data?.map((item: any) => ({ label: item.corpName, value: item.corpId }))}
  502. />
  503. </Form.Item>
  504. <Form.Item label={<strong>群配置名称</strong>} style={{ marginBottom: 10 }} name="groupObjectName">
  505. <Input placeholder="请输入群配置名称" allowClear />
  506. </Form.Item>
  507. <Form.Item style={{ marginBottom: 10 }}>
  508. <Space>
  509. <Button htmlType="reset">重置</Button>
  510. <Button type="primary" htmlType='submit'>搜索</Button>
  511. </Space>
  512. </Form.Item>
  513. </Form>
  514. <Table
  515. dataSource={previewData}
  516. columns={PreviewColumns(bookPlatForm, bookList)}
  517. rowKey={'id'}
  518. bordered={true}
  519. scroll={{ y: 550 }}
  520. pagination={{
  521. showTotal(total, range) {
  522. return `共 ${total} 条记录 第 ${range[0]}-${range[1]} 条`
  523. },
  524. }}
  525. />
  526. </div> : <div style={{ minHeight: 400, display: 'flex', justifyContent: 'center', alignItems: 'center' }}>
  527. <Empty description="请先完成模块配置后,再预览" />
  528. </div>}
  529. </Card>
  530. {/* 提交配置 */}
  531. {subVisible && <SubmitModal
  532. visible={subVisible}
  533. loading={addPullGroupTask.loading}
  534. projectName={projectId ? getCreateDetails?.data?.data?.taskName : undefined}
  535. onChange={(values) => {
  536. onSubmit(values)
  537. }}
  538. onClose={() => {
  539. setSubVisible(false)
  540. }}
  541. />}
  542. </div>
  543. };
  544. export default inject('store')(observer((props: any) => GroupChatCreate(props.store)))