index.tsx 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489
  1. import Selector from "@/pages/launchSystemNew/launchManage/createAd/selector"
  2. import React, { useEffect, useState } from "react"
  3. import style from './index.less'
  4. import { Button, Col, Form, Input, message, Modal, Row, Select, Space, Table, Tag, Tooltip, Typography } from "antd";
  5. import { CloseCircleFilled } from "@ant-design/icons";
  6. import { getGroupListApi } from "@/services/launchAdq/subgroup";
  7. import { useAjax } from "@/Hook/useAjax";
  8. import { getAccountAssetsGroupListAllApi } from "@/services/adqV3/global";
  9. import { getUserAccountListApi } from "@/services/launchAdq/adAuthorize";
  10. import { arraysHaveSameValues, groupBy } from "@/utils/utils";
  11. import { DELIVERY_MODE_ENUM } from "../../const";
  12. import '../../index.less'
  13. const { Text } = Typography;
  14. interface Props {
  15. setAccountCreateLogs: React.Dispatch<React.SetStateAction<PULLIN.AccountCreateLogsProps[]>>
  16. accountCreateLogs: PULLIN.AccountCreateLogsProps[]
  17. setOwnerAccountId: React.Dispatch<React.SetStateAction<number | undefined>>
  18. ownerAccountId: number | undefined
  19. deliveryMode?: keyof typeof DELIVERY_MODE_ENUM
  20. mType?: string,
  21. putInType?: 'NOVEL' | 'GAME'
  22. onChange?: (value?: any[], isClear?: boolean) => void
  23. dynamicGroup?: any[]
  24. }
  25. /**
  26. * 选择账户
  27. * @returns
  28. */
  29. const SelectAccount: React.FC<Props> = ({ putInType, accountCreateLogs, setAccountCreateLogs, onChange, dynamicGroup, deliveryMode, mType }) => {
  30. /***********************************/
  31. const [form] = Form.useForm()
  32. const [visible, setVisible] = useState<boolean>(false)
  33. const [selectedRows, setSelectedRows] = useState<any[]>([])
  34. const [tipsVisible, setTipsVisible] = useState<boolean>(false)
  35. const [loading, setLoading] = useState<boolean>(false)
  36. const [queryForm, setQueryForm] = useState<{ accountIdList?: number[], adUnitTypeList?: string[], groupId?: number, remark?: string, sysGroupId?: number, pageNum: number, pageSize: number }>({ pageNum: 1, pageSize: 50 })
  37. const getGroupList = useAjax(() => getGroupListApi())
  38. const getAccountAssetsGroupListAll = useAjax((params) => getAccountAssetsGroupListAllApi(params))
  39. const getUserAccountList = useAjax((params) => getUserAccountListApi(params))
  40. /***********************************/
  41. const onFinish = (data: any) => {
  42. let oldQueryFrom = JSON.parse(JSON.stringify(queryForm))
  43. let params = { ...oldQueryFrom, ...data, pageNum: 1 }
  44. if (params?.accountIdList) {
  45. params.accountIdList = params?.accountIdList.split(/[,,\n\s]+/ig).filter((item: any) => item)
  46. } else {
  47. delete params?.accountIdList
  48. }
  49. setQueryForm(params)
  50. }
  51. // 判断选择的账号是否在同一个资产组,允许选择云端素材的关键
  52. const getauthMainAccountData = (accountCreateLogs: PULLIN.AccountCreateLogsProps[]): Promise<{ authMainAccountId?: number, isSelectRemote: boolean }> => {
  53. return new Promise((resolve) => {
  54. if (accountCreateLogs?.length) {
  55. setLoading(true)
  56. getUserAccountListApi({ adUnitTypeList: putInType === 'NOVEL' ? ['NOVEL', 'NOVEL_IAA', 'SKIT_IAA'] : ['GAME', 'GAME_IAA'], pageNum: 1, pageSize: 20000, accountIdList: accountCreateLogs.map(item => item.accountId) }).then(res => {
  57. setLoading(false)
  58. console.log('ppppp', res)
  59. if (res?.data?.records?.length) {
  60. const list = accountCreateLogs.map(item => item.accountId)
  61. const selectAccountList = res.data.records.filter((item: { accountId: any }) => list.includes(item.accountId))
  62. const groupAccount = groupBy(selectAccountList, (item) => item.groupId, true)
  63. const GrounpArray = Object.keys(groupAccount).map(function (group) {
  64. return groupAccount[group];
  65. })
  66. if (GrounpArray.length === 1 && !groupAccount['undefined']) {
  67. resolve({ authMainAccountId: GrounpArray?.[0]?.[0]?.authMainAccountId || GrounpArray?.[0]?.[0]?.accountId, isSelectRemote: true })
  68. } else if (GrounpArray.length === 2 && groupAccount?.['undefined']?.length === 1) {
  69. const undefinedAccount = groupAccount?.['undefined'][0].accountId
  70. let authMainAccountId: any
  71. Object.keys(groupAccount).forEach(key => {
  72. if (key !== 'undefined') {
  73. authMainAccountId = groupAccount[key][0].authMainAccountId
  74. }
  75. })
  76. if (undefinedAccount === authMainAccountId) {
  77. resolve({ authMainAccountId: authMainAccountId, isSelectRemote: true })
  78. } else {
  79. resolve({ authMainAccountId: -1, isSelectRemote: false })
  80. }
  81. } else if (groupAccount?.['undefined']?.length === 1 && groupAccount?.['undefined']?.[0]?.isGroupMainAccount) {
  82. resolve({ authMainAccountId: groupAccount?.['undefined']?.[0]?.accountId, isSelectRemote: true })
  83. } else {
  84. resolve({ authMainAccountId: -1, isSelectRemote: false })
  85. }
  86. }
  87. }).catch(() => {
  88. setVisible(false)
  89. resolve({ authMainAccountId: undefined, isSelectRemote: false })
  90. })
  91. } else {
  92. resolve({ authMainAccountId: undefined, isSelectRemote: false })
  93. }
  94. })
  95. }
  96. useEffect(() => {
  97. if (visible && accountCreateLogs?.length) {
  98. setSelectedRows(JSON.parse(JSON.stringify(accountCreateLogs)))
  99. }
  100. }, [accountCreateLogs, visible])
  101. useEffect(() => {
  102. if (putInType && visible) {
  103. getUserAccountList.run({ adUnitTypeList: putInType === 'NOVEL' ? ['NOVEL', 'NOVEL_IAA', 'SKIT_IAA'] : ['GAME', 'GAME_IAA'], ...queryForm })
  104. }
  105. }, [putInType, queryForm, visible])
  106. useEffect(() => {
  107. if (putInType) {
  108. // 获取账户组
  109. getGroupList.run()
  110. // 获取资产共享组
  111. getAccountAssetsGroupListAll.run({})
  112. }
  113. return () => {
  114. document.body.style.overflow = 'auto';
  115. }
  116. }, [putInType])
  117. const handleOk = (isClear: boolean) => {
  118. document.body.style.overflow = 'auto';
  119. onChange?.(selectedRows, isClear)
  120. setSelectedRows([])
  121. setVisible(false)
  122. setTipsVisible(false)
  123. }
  124. const handleCancel = () => {
  125. document.body.style.overflow = 'auto';
  126. setSelectedRows([])
  127. setVisible(false)
  128. }
  129. return <div className={style.selectAccount}>
  130. <div className={style.selectAccount_row} style={{ zIndex: visible ? 1000 : 1 }}>
  131. <Selector
  132. label={visible ? '选择账户' : '媒体账户'}
  133. style={visible ? { borderColor: '#1890ff' } : {}}
  134. titleStyle={visible ? { borderColor: '#1890ff', color: '#1890ff' } : {}}
  135. >
  136. <div
  137. className={style.selectAccount_select}
  138. onClick={() => {
  139. document.body.style.overflow = 'hidden';
  140. setVisible(true)
  141. }}
  142. >
  143. <div className={style.selectAccount_select_content}>
  144. {(visible && selectedRows.length > 0) ? <>
  145. <Tag
  146. closable
  147. color="#F5F5F5"
  148. key={selectedRows[0].accountId}
  149. className={style.content_tag}
  150. onClose={() => {
  151. setSelectedRows(selectedRows.slice(1))
  152. }}
  153. >{selectedRows[0].accountId}</Tag>
  154. {selectedRows?.length > 1 && <Tooltip
  155. color="#FFF"
  156. title={<span style={{ color: '#000' }}>
  157. {selectedRows?.filter((_, index) => index !== 0)?.map((item) => <Tag
  158. color="#F5F5F5"
  159. className={style.content_tag}
  160. key={item.accountId}
  161. closable
  162. onClose={() => {
  163. setSelectedRows(selectedRows?.filter(item1 => item1.accountId !== item.accountId))
  164. }}
  165. >{item.accountId}</Tag>)}</span>
  166. }
  167. >
  168. <Tag color="#F5F5F5" className={style.content_tag}>+{selectedRows.length - 1}</Tag>
  169. </Tooltip>}
  170. </> : (!visible && accountCreateLogs?.length > 0) ? <>
  171. <Tag
  172. closable
  173. color="#F5F5F5"
  174. className={style.content_tag}
  175. key={accountCreateLogs[0].accountId}
  176. onClose={() => {
  177. setAccountCreateLogs(accountCreateLogs.slice(1))
  178. }}
  179. >{accountCreateLogs[0].accountId}</Tag>
  180. {accountCreateLogs?.length > 1 && <Tooltip
  181. color="#FFF"
  182. title={<span style={{ color: '#000' }}>
  183. {accountCreateLogs?.filter((_, index) => index !== 0)?.map((item) => <Tag
  184. className={style.content_tag}
  185. color="#F5F5F5"
  186. key={item.accountId}
  187. closable
  188. onClose={() => {
  189. setAccountCreateLogs(accountCreateLogs?.filter(item1 => item1.accountId !== item.accountId))
  190. }}
  191. >{item.accountId}</Tag>)}</span>
  192. }
  193. >
  194. <Tag color="#F5F5F5" className={style.content_tag}>+{accountCreateLogs.length - 1}</Tag>
  195. </Tooltip>}
  196. </> : <Text type="secondary">请选择媒体账户</Text>}
  197. </div>
  198. {visible}
  199. {((visible && selectedRows.length > 0) || (!visible && accountCreateLogs?.length > 0)) && <a className={style.clear} onClick={(e) => {
  200. e.stopPropagation()
  201. if (visible) {
  202. setSelectedRows([])
  203. } else {
  204. setAccountCreateLogs([])
  205. }
  206. }}><CloseCircleFilled /></a>}
  207. </div>
  208. </Selector>
  209. {visible && <div className={style.selectAccount_list}>
  210. <div className={style.selectAccount_list_header}>
  211. <Form layout="inline" className='queryForm' name="basicSelectAcc" form={form} onFinish={onFinish}>
  212. <Row gutter={[0, 6]}>
  213. <Col><Form.Item name='accountIdList'>
  214. <Input.TextArea
  215. rows={1}
  216. autoSize={{ minRows: 1, maxRows: 1 }}
  217. placeholder="账户(多个,,空格换行)"
  218. style={{ width: 180 }}
  219. allowClear
  220. />
  221. </Form.Item></Col>
  222. <Col><Form.Item name='remark'>
  223. <Input
  224. placeholder="备注"
  225. style={{ width: 120 }}
  226. allowClear
  227. />
  228. </Form.Item></Col>
  229. <Col><Form.Item name='sysGroupId'>
  230. <Select
  231. mode="multiple"
  232. style={{ minWidth: 180 }}
  233. placeholder="快捷选择媒体账户组"
  234. maxTagCount={1}
  235. allowClear
  236. filterOption={(input: any, option: any) => {
  237. return option!.children?.toString().toLowerCase().includes(input.toLowerCase())
  238. }}
  239. >
  240. {getGroupList?.data && getGroupList?.data?.map((item: any) => <Select.Option value={item.groupId} key={item.groupId}>{item.groupName}</Select.Option>)}
  241. </Select>
  242. </Form.Item></Col>
  243. <Col><Form.Item name='groupId'>
  244. <Select
  245. allowClear
  246. showSearch
  247. placeholder="账户资产共享组"
  248. filterOption={(input: any, option: any) => {
  249. return option!.children?.toString().toLowerCase().includes(input.toLowerCase())
  250. }}
  251. style={{ width: 145 }}
  252. >
  253. {getAccountAssetsGroupListAll?.data?.map((item: { accountId: any; authMainAccountId: number; id: number; accountGroupName: string }) => <Select.Option value={item.id} key={item.id}>{item.accountGroupName}({item.authMainAccountId})</Select.Option>)}
  254. </Select>
  255. </Form.Item></Col>
  256. <Col>
  257. <Space>
  258. <Button type="primary" htmlType="submit">搜索</Button>
  259. {/* <Button onClick={() => form.resetFields()}>重置</Button> */}
  260. </Space>
  261. </Col>
  262. </Row>
  263. </Form>
  264. {/*
  265. */}
  266. </div>
  267. <div className={style.selectAccount_list_table}>
  268. <Table
  269. size={'small'}
  270. bordered
  271. dataSource={getUserAccountList?.data?.records}
  272. rowKey={'accountId'}
  273. scroll={{ y: 220 }}
  274. pagination={{
  275. pageSize: getUserAccountList?.data?.size || 50,
  276. current: getUserAccountList?.data?.current || 1,
  277. showTotal: total => `总共 ${total} 账户`,
  278. total: getUserAccountList?.data?.total,
  279. showSizeChanger: true,
  280. showLessItems: true,
  281. defaultCurrent: 1,
  282. defaultPageSize: 50,//默认初始的每页条数
  283. onChange: (page, pageSize) => {
  284. setQueryForm({ ...queryForm, pageNum: page, pageSize })
  285. }
  286. }}
  287. loading={getUserAccountList.loading || loading}
  288. columns={[
  289. {
  290. title: '账号',
  291. dataIndex: 'accountId',
  292. key: 'accountId',
  293. width: 80,
  294. align: 'center',
  295. render(value) {
  296. return <span style={{ fontSize: 12 }}>{value}</span>
  297. }
  298. },
  299. {
  300. title: '企业',
  301. dataIndex: 'corporationName',
  302. key: 'corporationName',
  303. width: 180,
  304. ellipsis: true,
  305. render(value) {
  306. return <span style={{ fontSize: 12 }}>{value}</span>
  307. }
  308. },
  309. {
  310. title: '企业标识',
  311. dataIndex: 'corporationLicence',
  312. key: 'corporationLicence',
  313. width: 150,
  314. ellipsis: true,
  315. render(value) {
  316. return <span style={{ fontSize: 12 }}>{value}</span>
  317. }
  318. },
  319. {
  320. title: '备注',
  321. dataIndex: 'remark',
  322. key: 'remark',
  323. ellipsis: true,
  324. render(value) {
  325. return <span style={{ fontSize: 12 }}>{value || '--'}</span>
  326. }
  327. },
  328. ]}
  329. rowSelection={{
  330. selectedRowKeys: selectedRows.map(item => item.accountId),
  331. onSelect: (record: { accountId: number }, selected: boolean) => {
  332. if (selected) {
  333. selectedRows.push({ ...record })
  334. setSelectedRows([...selectedRows])
  335. } else {
  336. let newSelectAccData = selectedRows.filter((item: { accountId: number }) => item.accountId !== record.accountId)
  337. setSelectedRows([...newSelectAccData])
  338. }
  339. },
  340. onSelectAll: (selected: boolean, selectedRowss: { accountId: number }[], changeRows: { accountId: number }[]) => {
  341. if (selected) {
  342. let newSelectAccData = [...selectedRows]
  343. changeRows.forEach((item: { accountId: number }) => {
  344. let index = newSelectAccData.findIndex((ite: { accountId: number }) => ite.accountId === item.accountId)
  345. if (index === -1) {
  346. let data: any = { ...item }
  347. newSelectAccData.push(data)
  348. }
  349. })
  350. setSelectedRows([...newSelectAccData])
  351. } else {
  352. let newSelectAccData = selectedRows.filter((item: { accountId: number }) => {
  353. let index = changeRows.findIndex((ite: { accountId: number }) => ite.accountId === item.accountId)
  354. if (index !== -1) {
  355. return false
  356. } else {
  357. return true
  358. }
  359. })
  360. setSelectedRows([...newSelectAccData])
  361. }
  362. }
  363. }}
  364. />
  365. </div>
  366. <div className={style.selectAccount_list_footer}>
  367. <Button className={style.resetCss} onClick={handleCancel}>取消</Button>
  368. <Button
  369. className={style.resetCss}
  370. type="primary"
  371. loading={loading}
  372. style={{ marginLeft: 8 }}
  373. onClick={() => {
  374. if (accountCreateLogs?.length && arraysHaveSameValues(accountCreateLogs.map(item => item.accountId), selectedRows.map(item => item.accountId))) {
  375. handleCancel()
  376. return
  377. }
  378. let authMainAccountId: any
  379. let isY = false
  380. // 1.判断是否有账户组素材 有的话 获取账户组ID
  381. if (dynamicGroup && dynamicGroup?.length > 0) {
  382. if (deliveryMode && mType) {
  383. if (dynamicGroup.some((item: any) => {
  384. if (deliveryMode === 'DELIVERY_MODE_CUSTOMIZE') {
  385. if (['short_video', 'video'].includes(mType) && (item?.video_id?.materialType || item?.short_video1?.materialType) === 1) {
  386. authMainAccountId = item?.video_id?.accountId || item?.short_video1?.accountId
  387. return true
  388. } else if (['image_list'].includes(mType) && item?.image_list?.some((list: any) => {
  389. if (list?.materialType === 1) {
  390. authMainAccountId = list?.accountId
  391. return true
  392. } else {
  393. return false
  394. }
  395. })) {
  396. return true
  397. } else if (['element_story'].includes(mType) && item?.element_story?.some((list: any) => {
  398. if (list?.materialType === 1) {
  399. authMainAccountId = list?.accountId
  400. return true
  401. } else {
  402. return false
  403. }
  404. })) {
  405. return true
  406. } else if (['image'].includes(mType) && item?.image_id?.materialType === 1) {
  407. authMainAccountId = item?.image_id?.accountId
  408. return true
  409. } else {
  410. return false
  411. }
  412. } else {
  413. if (item?.list?.some((list: any) => {
  414. if (Array.isArray(list) && list.some((l: any) => {
  415. if (l.materialType === 1) {
  416. authMainAccountId = l?.accountId
  417. return true
  418. } else {
  419. return false
  420. }
  421. })) {
  422. return true
  423. } else if (list.materialType === 1) {
  424. authMainAccountId = list?.accountId
  425. return true
  426. } else {
  427. return false
  428. }
  429. })) {
  430. return true
  431. } else {
  432. return false
  433. }
  434. }
  435. })) {
  436. isY = true
  437. }
  438. } else {
  439. message.error('请联系管理员')
  440. }
  441. }
  442. if (isY && authMainAccountId) {
  443. // 2.有的话判断 判断账户是否为一组
  444. getauthMainAccountData(selectedRows).then(authMainData => {
  445. console.log('authMainData---->', authMainData)
  446. if (authMainData.isSelectRemote && authMainData.authMainAccountId === authMainAccountId) {
  447. handleOk(false)
  448. } else {
  449. setTipsVisible(true)
  450. }
  451. })
  452. // 3.是的话 判断是以前那组吗
  453. } else {
  454. handleOk(false)
  455. }
  456. }}
  457. >确定</Button>
  458. </div>
  459. </div>}
  460. </div>
  461. {visible && <div className={style.selectAccount_mask}></div>}
  462. {tipsVisible && <Modal
  463. title={<strong>提示</strong>}
  464. open={tipsVisible}
  465. onCancel={() => {
  466. setTipsVisible(false)
  467. }}
  468. onOk={() => handleOk(true)}
  469. className="modalResetCss"
  470. okText="清空"
  471. cancelText="留下来修改账户"
  472. >选择的素材有账户组素材,但是与当前账户不匹配,是否使用当前账号清空素材?</Modal>}
  473. </div>
  474. }
  475. export default React.memo(SelectAccount)