MiniProgramPage.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import { useAjax } from "@/Hook/useAjax"
  2. import { CheckOutlined, CloseOutlined, QuestionCircleOutlined, SyncOutlined } from "@ant-design/icons"
  3. import { Button, Input, message, Modal, Select, Space, Table, Tooltip, Typography } from "antd"
  4. import React, { useEffect, useState } from "react"
  5. import style from '../GoodsModal/index.less'
  6. import columns from "./tableConfig"
  7. import { getWechatAppletApi } from "@/services/adqV3/global"
  8. import New1Radio from "../New1Radio"
  9. import { getErpUserAll } from "@/services/launchAdq/adq"
  10. const { Title, Text } = Typography;
  11. /**
  12. * 获取微信小程序
  13. * @returns
  14. */
  15. interface Props {
  16. visible?: boolean,
  17. onClose?: () => void,
  18. onChange?: (value: { data: PULLIN.AccountCreateLogsProps[], landingPageType: 0 | 1 }) => void,
  19. adgroups: any
  20. dynamic: any
  21. data: PULLIN.AccountCreateLogsProps[]
  22. }
  23. const MiniProgramPage: React.FC<Props> = (props) => {
  24. /*************************/
  25. const { visible, onClose, data: data1, onChange, dynamic } = props
  26. const { creativeTemplateId, deliveryMode, creativeComponents: { mainJumpInfo }, landingPageType } = dynamic
  27. const [selectAdz, setSelectAdz] = useState<number>(1) // 选择广告主
  28. const [data, setData] = useState<PULLIN.AccountCreateLogsProps[]>(data1 || [])
  29. const userId = localStorage.getItem('userId')
  30. const [queryForm, setQueryForm] = useState<{ appletName?: string, appletIdList?: string[], createBy?: number, pageSize: number, pageNum: number }>({ pageNum: 1, pageSize: 20, createBy: userId ? Number(userId) : undefined })
  31. const [pageAllocationType, setPageAllocationType] = useState<0 | 1>(landingPageType || 0)
  32. const listAjax = useAjax((params) => getWechatAppletApi(params))
  33. const allOfMember = useAjax(() => getErpUserAll())
  34. /*************************/
  35. useEffect(() => {
  36. allOfMember.run()
  37. }, [])
  38. useEffect(() => {
  39. getList()
  40. }, [queryForm])
  41. // 获取落地页列表
  42. const getList = () => {
  43. listAjax.run(queryForm)
  44. }
  45. const handleOk = () => {
  46. if (deliveryMode === "DELIVERY_MODE_COMPONENT" && !data?.every(item => item.pageList?.length === mainJumpInfo?.length)) {
  47. message.error(`当前落地页数量不足,跳转类型选择了${mainJumpInfo.length}组,落地页应当选择${mainJumpInfo.length}组`)
  48. return
  49. }
  50. if (data?.every(item => item.pageList)) {
  51. onChange && onChange({ data, landingPageType: pageAllocationType })
  52. } else {
  53. message.error('还有账号未选择落地页!')
  54. }
  55. }
  56. /** 设置选中广告主 */
  57. const handleSelectAdz = (value: number, item: any) => {
  58. if (value === selectAdz) {
  59. return
  60. }
  61. setSelectAdz(value)
  62. }
  63. /** 一键设置 */
  64. const setOnekey = () => {
  65. const hide = message.loading(`正在设置...`, 0, () => {
  66. message.success('设置成功');
  67. });
  68. let newData: PULLIN.AccountCreateLogsProps[] = JSON.parse(JSON.stringify(data))
  69. let pageList = data[selectAdz - 1]['pageList']
  70. newData = newData.map(item => {
  71. if (item.accountId !== data[selectAdz - 1].accountId) {
  72. return { ...item, pageList: pageList }
  73. }
  74. return item
  75. })
  76. setData(newData)
  77. message.success('设置完成');
  78. hide()
  79. }
  80. return <Modal
  81. title={<Space>
  82. <strong>选择微信小程序</strong>
  83. {data?.length > 1 && <Button style={{ padding: 0, margin: 0 }} disabled={!data[selectAdz - 1]['pageList']?.length} onClick={setOnekey} type="link" loading={listAjax.loading}>
  84. <Space>
  85. <span style={{ fontSize: 12 }}>一键设置</span>
  86. <Tooltip color="#FFF" overlayInnerStyle={{ color: '#000' }} title="设置其它账号有相同名称的落地页为那个账号的落地页(需要落地页名称相同,否则不设置,注意只会根据当前条件去搜索,比如选择了被授权落地页,只会去被授权落地页里找对应落地页)">
  87. <QuestionCircleOutlined />
  88. </Tooltip>
  89. </Space>
  90. </Button>}
  91. <Button
  92. type="link"
  93. danger
  94. disabled={!data?.some(item => item.pageList?.length)}
  95. onClick={() => {
  96. setData(data => data.map(item => ({ ...item, pageList: [] })))
  97. }}
  98. >全部清空</Button>
  99. </Space>}
  100. open={visible}
  101. onCancel={() => { onClose && onClose() }}
  102. onOk={handleOk}
  103. width={1100}
  104. className={`${style.SelectPackage} modalResetCss`}
  105. bodyStyle={{ padding: '0 10px 0 10px' }}
  106. >
  107. {[910].includes(creativeTemplateId) && <div className={style.pageType}>
  108. <Space size={12}>
  109. <strong>落地页分配规则</strong>
  110. <New1Radio
  111. data={[{ label: '全部相同', value: 0 }, { label: '平均分配', value: 1 }]}
  112. value={pageAllocationType}
  113. onChange={(e) => {
  114. setPageAllocationType(e)
  115. }}
  116. />
  117. </Space>
  118. </div>}
  119. <div className={style.content}>
  120. <div className={style.left}>
  121. <h4 className={style.title}>媒体账户</h4>
  122. <div className={style.accountIdList}>
  123. {data?.map((item, index) => (
  124. <div key={index} onClick={() => { handleSelectAdz(index + 1, item) }} className={`${style.accItem} ${selectAdz === index + 1 && style.select} `}>
  125. {item?.accountId}
  126. {data[index].pageList?.length > 0 && <CheckOutlined style={{ color: '#1890ff' }} />}
  127. </div>
  128. ))}
  129. </div>
  130. </div>
  131. <div className={style.right}>
  132. <Space style={{ marginBottom: 10 }}>
  133. <Select
  134. showSearch
  135. placeholder="请选择创建人"
  136. onChange={(e) => setQueryForm({ ...queryForm, createBy: e, pageNum: 1 })}
  137. filterOption={(input, option) =>
  138. (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
  139. }
  140. value={queryForm?.createBy}
  141. allowClear
  142. style={{ width: 120 }}
  143. loading={allOfMember.loading}
  144. options={allOfMember?.data?.map((item: { userId: any; nickname: string }) => ({
  145. value: item.userId,
  146. label: item.nickname
  147. }))}
  148. />
  149. <Input style={{ width: 160 }} placeholder="请输入小程序名称" value={queryForm?.appletName} allowClear onChange={(e) => setQueryForm({ ...queryForm, appletName: e.target.value, pageNum: 1 })} />
  150. <Input.TextArea
  151. style={{ width: 250 }}
  152. placeholder="请输入小程序原始ID(多个逗号隔开)"
  153. allowClear
  154. rows={1}
  155. onChange={(e) => {
  156. let value = e.target.value
  157. let arr: string[] = []
  158. if (value) {
  159. value = value.replace(/[,,\s]/g, ',')
  160. arr = value.split(',').filter((a: string) => a)
  161. }
  162. setQueryForm({ ...queryForm, appletIdList: arr, pageNum: 1 })
  163. }}
  164. />
  165. <Button style={{ padding: 0, margin: 0 }} icon={<SyncOutlined />} type='link' loading={listAjax?.loading} onClick={() => { listAjax?.refresh() }}><span style={{ fontSize: 12 }}>刷新</span></Button>
  166. </Space>
  167. <Table
  168. columns={columns(3)}
  169. dataSource={listAjax.data?.records?.map((item: { appletName: any; id: any }) => ({ ...item, pageName: item.appletName, pageId: item.id }))}
  170. size="small"
  171. loading={listAjax?.loading}
  172. scroll={{ y: 400 }}
  173. bordered
  174. rowKey={'id'}
  175. pagination={{
  176. defaultPageSize: 20,
  177. current: listAjax.data?.current || 1,
  178. pageSize: listAjax.data?.size || 10,
  179. total: listAjax.data?.total || 0
  180. }}
  181. onChange={(pagination) => {
  182. const { current, pageSize } = pagination
  183. setQueryForm({ ...queryForm, pageNum: current || 1, pageSize: pageSize || 10 })
  184. }}
  185. rowSelection={{
  186. type: ([910].includes(creativeTemplateId) || deliveryMode === "DELIVERY_MODE_COMPONENT") ? 'checkbox' : 'radio',
  187. getCheckboxProps: (record) => {
  188. // 组件化创意
  189. if (deliveryMode === "DELIVERY_MODE_COMPONENT") {
  190. if (data[selectAdz - 1]?.pageList?.length >= mainJumpInfo?.length) {
  191. return {
  192. disabled: data[selectAdz - 1]?.pageList?.some((item: any) => item?.id === record?.id) ? false : true
  193. }
  194. } else {
  195. return {
  196. disabled: false
  197. }
  198. }
  199. }
  200. return {
  201. disabled: false
  202. }
  203. },
  204. selectedRowKeys: data[selectAdz - 1]?.pageList?.map((item: any) => item?.id),
  205. hideSelectAll: deliveryMode === "DELIVERY_MODE_COMPONENT",
  206. onSelect: (record: any, selected: boolean) => {
  207. let newData = JSON.parse(JSON.stringify(data))
  208. if (([910].includes(creativeTemplateId) || deliveryMode === "DELIVERY_MODE_COMPONENT")) {
  209. let selectedRows = newData?.[selectAdz - 1]?.['pageList'] || []
  210. if (selected) {
  211. selectedRows.push({ ...record })
  212. newData[selectAdz - 1]['pageList'] = selectedRows
  213. } else {
  214. newData[selectAdz - 1]['pageList'] = selectedRows.filter((item: { id: number }) => item.id !== record.id)
  215. }
  216. } else {
  217. newData[selectAdz - 1]['pageList'] = [record]
  218. }
  219. setData([...newData])
  220. },
  221. onSelectAll: (selected: boolean, _: any[], changeRows: { id: number }[]) => {
  222. let newData = JSON.parse(JSON.stringify(data))
  223. let selectedRows = newData?.[selectAdz - 1]?.['pageList'] || []
  224. if (selected) {
  225. let newSelectAccData = [...selectedRows]
  226. changeRows.forEach((item: { id: number }) => {
  227. let index = newSelectAccData.findIndex((ite: { id: number }) => ite.id === item.id)
  228. if (index === -1) {
  229. let data: any = { ...item }
  230. newSelectAccData.push(data)
  231. }
  232. })
  233. newData[selectAdz - 1]['pageList'] = newSelectAccData
  234. } else {
  235. newData[selectAdz - 1]['pageList'] = selectedRows.filter((item: { id: number }) => {
  236. let index = changeRows.findIndex((ite: { id: number }) => ite.id === item.id)
  237. if (index !== -1) {
  238. return false
  239. } else {
  240. return true
  241. }
  242. })
  243. }
  244. setData([...newData])
  245. }
  246. }}
  247. />
  248. </div>
  249. <div className={style.center}>
  250. <Title level={5}>已选:{data[selectAdz - 1]?.pageList?.length || 0}</Title>
  251. <div className={style.select_content} style={{ height: 416 }}>
  252. {data[selectAdz - 1]?.pageList?.map((item: any) => <div key={item.id}>
  253. <Text ellipsis={{ tooltip: true }} className={style.marketingAssetName}>{item.appletName}</Text>
  254. <CloseOutlined className={style.close} onClick={() => {
  255. let newData: PULLIN.AccountCreateLogsProps[] = JSON.parse(JSON.stringify(data))
  256. newData[selectAdz - 1].pageList = newData[selectAdz - 1]?.pageList?.filter((i: any) => i?.id !== item.id)
  257. setData(newData)
  258. }} />
  259. </div>)}
  260. </div>
  261. </div>
  262. </div>
  263. </Modal>
  264. }
  265. export default React.memo(MiniProgramPage)