index.tsx 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. import { useAjax } from "@/Hook/useAjax"
  2. import { getCrowdPackApi, sysCrowdPackApi } from "@/services/launchAdq/createAd"
  3. import { Button, Checkbox, Input, message, Modal, Space, Switch, Tooltip } from "antd"
  4. import React, { useEffect, useState } from "react"
  5. import style from '../goodsModal/index.less'
  6. import columns from "../crowdPackModal/tableConfig"
  7. import { CheckOutlined, QuestionCircleOutlined, SyncOutlined } from "@ant-design/icons"
  8. import Tables from "@/components/Tables"
  9. /**
  10. * 自动扩量设置
  11. * @returns
  12. */
  13. interface Props {
  14. visible?: boolean,
  15. onClose?: () => void,
  16. onChange?: (data: any, expandData: { expandEnabled: boolean, expandTargeting: string[] }) => void,
  17. data: any,
  18. sysTargeting: any,
  19. expandData?: { expandEnabled: boolean, expandTargeting: string[] }
  20. }
  21. const ExpandModal: React.FC<Props> = (props) => {
  22. /******************************/
  23. const { visible, onClose, data: data1, onChange, sysTargeting, expandData } = props
  24. const [data, setData] = useState<any>(data1)
  25. const [tableData, setTableData] = useState<any[]>([])//table数据
  26. const [selectAdz, setSelectAdz] = useState<number>(1) // 选择账户
  27. const [name, setName] = useState<string>('')
  28. const [disabledList, setDisabledList] = useState<boolean[]>([true, true, true, true])
  29. const [queryForm, setQueryForm] = useState<{ expandEnabled: boolean, expandTargeting: string[] }>(expandData || { expandEnabled: false, expandTargeting: [] })
  30. const getCrowdPack = useAjax((params) => getCrowdPackApi(params))
  31. const sysCrowdPack = useAjax((params) => sysCrowdPackApi(params))
  32. /******************************/
  33. useEffect(() => {
  34. if (sysTargeting && sysTargeting?.targeting) {
  35. let newDisabledList: boolean[] = [true, true, true, true]
  36. Object.keys(sysTargeting?.targeting)?.forEach((item: any) => {
  37. switch (item) {
  38. case 'geoLocation': // 地域
  39. if (sysTargeting?.targeting[item]?.regions && sysTargeting?.targeting[item]?.regions?.length > 0) {
  40. newDisabledList[0] = false
  41. }
  42. break
  43. case 'age':
  44. newDisabledList[1] = false
  45. break
  46. case 'gender':
  47. newDisabledList[2] = false
  48. break
  49. case 'education':
  50. newDisabledList[3] = false
  51. break
  52. }
  53. })
  54. setDisabledList(newDisabledList)
  55. }
  56. }, [sysTargeting])
  57. useEffect(() => {
  58. // customAudienceList?: any, excludedCustomAudienceList?: any
  59. if (data?.length > 0) {
  60. getList([data[selectAdz - 1].adAccountId])
  61. } else {
  62. setTableData([])
  63. }
  64. }, [selectAdz])
  65. // 同步种子人群
  66. const synGoodsList = () => {
  67. sysCrowdPack.run(data?.map((item: { adAccountId: number }) => item?.adAccountId)).then(res => {
  68. getList([data[selectAdz - 1].adAccountId])
  69. })
  70. }
  71. // 获取人群包列表
  72. const getList = (accountIds: number[]) => {
  73. getCrowdPack.run({ accountIds, source: 'ADVERTISER_OWN_DATA' }).then(res => {
  74. if (res && Object.keys(res)?.indexOf(accountIds[0].toString()) !== -1) {
  75. setTableData(res[accountIds[0]]?.map((item: { audienceId: string }) => ({ ...item, id: item.audienceId })))
  76. } else {
  77. setTableData([])
  78. }
  79. })
  80. }
  81. const handleOk = () => {
  82. onChange && onChange(data, queryForm)
  83. }
  84. /** 表格选折 */
  85. const onChangeTable = (selectedRowKeys: React.Key[], selectedRows: any[]) => {
  86. if (selectedRows?.length > 10) {
  87. message.error('扩量种子人群最多选择10个')
  88. return
  89. }
  90. let newData = JSON.parse(JSON.stringify(data))
  91. newData[selectAdz - 1]['coldStartAudienceList'] = selectedRows
  92. setData([...newData])
  93. }
  94. /** 设置选中广告主 */
  95. const handleSelectAdz = (value: number, item: any) => {
  96. if (value === selectAdz) {
  97. return
  98. }
  99. setSelectAdz(value)
  100. }
  101. /** 一键设置 */
  102. const setOnekey = () => {
  103. let expandNames: string[] = data[selectAdz - 1]['coldStartAudienceList']?.map((item: { name: string }) => item.name)
  104. let newData = JSON.parse(JSON.stringify(data))
  105. const hide = message.loading(`正在设置...`, 0, () => {
  106. message.success('设置成功');
  107. });
  108. getCrowdPack.run({ accountIds: newData?.filter((item: { adAccountId: number }) => item.adAccountId !== data[selectAdz - 1].adAccountId)?.map((item: { adAccountId: number }) => item?.adAccountId), source: 'ADVERTISER_OWN_DATA' }).then(res => {
  109. if (res && typeof res === 'object') {
  110. Object.keys(res).forEach((key: string) => {
  111. let values = expandNames.map(name => {
  112. let value = res[key]?.find((item: { name: string }) => item.name === name)
  113. if (value) {
  114. return { ...value, id: value.audienceId }
  115. }
  116. return undefined
  117. }).filter(item => item)
  118. if (values.length > 0) {
  119. newData = newData.map((item: { adAccountId: string }) => {
  120. if (item.adAccountId === key) {
  121. return { ...item, coldStartAudienceList: values }
  122. }
  123. return item
  124. })
  125. }
  126. })
  127. setData(newData)
  128. }
  129. message.success('设置完成');
  130. hide()
  131. })
  132. }
  133. return <Modal
  134. title={<Space>
  135. <span>自动扩量</span>
  136. <Button size="small" onClick={() => { synGoodsList() }} type="link" loading={sysCrowdPack.loading}>同步扩量种子人群</Button>
  137. </Space>}
  138. visible={visible}
  139. onCancel={() => { onClose && onClose() }}
  140. onOk={handleOk}
  141. width={1100}
  142. className={style.SelectPackage}
  143. bodyStyle={{ padding: '0 10px 0 10px' }}
  144. >
  145. <div className={style.topContent} style={{ paddingBottom: queryForm.expandEnabled ? 4 : 20 }}>
  146. <Space direction='vertical'>
  147. <Space>
  148. <strong className={style.title}>自动扩量:</strong>
  149. <Switch onChange={(e) => {
  150. setQueryForm({ ...queryForm, expandEnabled: e, expandTargeting: [] });
  151. if (!e) {
  152. let newData = JSON.parse(JSON.stringify(data))
  153. newData = newData?.map((item: { coldStartAudienceList: any }) => {
  154. return { ...item, coldStartAudienceList: [] }
  155. })
  156. setData([...newData])
  157. }
  158. }} checked={queryForm.expandEnabled} checkedChildren="开启" unCheckedChildren="关闭" />
  159. </Space>
  160. {queryForm.expandEnabled && <>
  161. <Space>
  162. <strong className={style.title}>不可突破定向:</strong>
  163. <Checkbox.Group style={{ width: '100%' }} onChange={(e) => { setQueryForm({ ...queryForm, expandTargeting: e as string[] }) }} value={queryForm.expandTargeting} >
  164. <Checkbox value="geo_location" disabled={disabledList[0]}>地域</Checkbox>
  165. <Checkbox value="age" disabled={disabledList[1]}>年龄</Checkbox>
  166. <Checkbox value="gender" disabled={disabledList[2]}>性别</Checkbox>
  167. <Checkbox value="education" disabled={disabledList[3]}>学历</Checkbox>
  168. </Checkbox.Group>
  169. </Space>
  170. <Space>
  171. <strong className={style.title}>扩量种子人群(选填):</strong>
  172. </Space>
  173. </>}
  174. </Space>
  175. </div>
  176. {queryForm.expandEnabled && <div className={style.content} style={{ borderTop: '1px solid #f0f0f0' }}>
  177. <div className={style.left}>
  178. <h4 className={style.title}>媒体账户</h4>
  179. {data?.map((item: { adAccountId: number, id: number }, index: number) => (
  180. <div key={index} onClick={() => { handleSelectAdz(index + 1, item) }} className={`${style.accItem} ${selectAdz === index + 1 && style.select} `}>
  181. {item?.adAccountId}
  182. {data[index]['coldStartAudienceList']?.length > 0 && <CheckOutlined style={{ color: '#1890ff' }} />}
  183. </div>
  184. ))}
  185. </div>
  186. <div className={style.right}>
  187. <Space style={{ marginBottom: 10 }}>
  188. <Input placeholder="请输入用户群名称" allowClear value={name} onChange={(e) => setName(e.target.value)} />
  189. <Button icon={<SyncOutlined />} type='link' loading={getCrowdPack?.loading} onClick={() => { getList([data[selectAdz - 1].adAccountId]) }}></Button>
  190. {data?.length > 1 && <Button disabled={!data[selectAdz - 1]['coldStartAudienceList']?.length} onClick={setOnekey} type="link" loading={getCrowdPack.loading}>
  191. <Space>
  192. <span>一键设置</span>
  193. <Tooltip color="#FFF" overlayInnerStyle={{ color: '#000' }} title="设置其它账号有相同名称的种子人群为那个账号的种子人群(注意需要用户群名称相同,否则不设置)">
  194. <QuestionCircleOutlined />
  195. </Tooltip>
  196. </Space>
  197. </Button>}
  198. </Space>
  199. <Tables
  200. columns={columns()}
  201. dataSource={tableData?.filter((item: { name: string }) => name ? item.name.indexOf(name) !== -1 : true)}
  202. size="small"
  203. loading={getCrowdPack?.loading}
  204. scroll={{ y: 300 }}
  205. bordered
  206. defaultPageSize={100}
  207. rowSelection={{
  208. type: 'checkbox',
  209. selectedRowKeys: data[selectAdz - 1]['coldStartAudienceList']?.map((item: any) => item?.id?.toString()),
  210. onChange: onChangeTable,
  211. getCheckboxProps: (record: any) => ({
  212. id: record.id,
  213. })
  214. }}
  215. />
  216. </div>
  217. </div>}
  218. </Modal>
  219. }
  220. export default React.memo(ExpandModal)