modal.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. import React, { useCallback, useEffect } from 'react'
  2. import { Modal, Form, Input, Divider, Select, Radio, DatePicker, Switch, Checkbox } from 'antd'
  3. import { SiteSetEnum, BidModeEnum, OptimizationGoalEnum, BidStrategyEnum, PromotedObjectType, EducationEnum } from '@/services/launchAdq/enum'
  4. import { ModalConfig } from '.'
  5. import moment from 'moment';
  6. import { useAjax } from '@/Hook/useAjax';
  7. import { getSceneTagsList } from '@/services/launchAdq/global';
  8. const { RangePicker }: { RangePicker: any } = DatePicker;
  9. let DatePickers: any = DatePicker
  10. interface Props {
  11. title?: string,
  12. visible: boolean,
  13. PupFn: (arg: ModalConfig) => void,
  14. callback: (params: any) => void,
  15. confirmLoading: boolean
  16. }
  17. /**广告模板*/
  18. function AdModal(props: Props) {
  19. let { visible, title, confirmLoading, PupFn, callback } = props
  20. const sceneTagsList = useAjax((params) => getSceneTagsList(params))
  21. const [form] = Form.useForm();
  22. let dateType = Form.useWatch('dateType', form)
  23. let bidMode = Form.useWatch('bidMode', form)
  24. let smartBidType = Form.useWatch('smartBidType', form)
  25. let autoAcquisitionEnabled = Form.useWatch('autoAcquisitionEnabled', form)
  26. let siteSet = Form.useWatch('siteSet', form)
  27. let wechatPositionType = Form.useWatch('wechatPositionType', form)
  28. let wechatSceneType = Form.useWatch('wechatSceneType', form)
  29. // 确定事件
  30. const handleOk = useCallback(() => {
  31. form.validateFields().then(values => {
  32. let newValues = JSON.parse(JSON.stringify(values))
  33. newValues.sceneSpec = {}
  34. if (newValues.dateType === '2') {
  35. newValues['beginDate'] = moment(newValues.date).format('YYYY-MM-DD')
  36. } else {
  37. newValues['beginDate'] = moment(newValues.date[0]).format('YYYY-MM-DD')
  38. newValues['endDate'] = moment(newValues.date[1]).format('YYYY-MM-DD')
  39. }
  40. if (newValues.wechatPositionType === '1') {
  41. newValues.sceneSpec = { ...newValues.sceneSpec, wechatPosition: newValues.wechatPosition }
  42. }
  43. if (newValues.wechatSceneType === '1') {
  44. newValues.sceneSpec = { ...newValues.sceneSpec, wechatScene: {
  45. officialAccountMediaCategory:newValues.officialAccountMediaCategory,
  46. miniProgramAndMiniGame:newValues.miniProgramAndMiniGame,
  47. payScene:newValues.payScene
  48. } }
  49. }
  50. if (newValues.sceneSpec.wechatPosition?.length === 0) {
  51. delete newValues.sceneSpec.wechatPosition
  52. }
  53. // if(newValues.sceneSpec.wechatScene)
  54. if (!newValues.sceneSpec.wechatPosition && !newValues.sceneSpec.wechatScene) {
  55. delete newValues.sceneSpec
  56. }
  57. delete newValues.officialAccountMediaCategory
  58. delete newValues.miniProgramAndMiniGame
  59. delete newValues.payScene
  60. delete newValues.wechatPositionType
  61. delete newValues.wechatPosition
  62. delete newValues.wechatScene
  63. delete newValues['dateType']
  64. delete newValues['date']
  65. newValues['timeSeries'] = Array(336).fill(1).join('')
  66. callback(newValues)
  67. })
  68. // PupFn({ visible: false })
  69. }, [form])
  70. // 场景定向
  71. useEffect(() => {
  72. sceneTagsList.run({ typeList: ['WECHAT_POSITION', 'OFFICIAL_ACCOUNT_MEDIA_CATEGORY', 'MINI_PROGRAM_AND_MINI_GAME', 'PAY_SCENE'] })
  73. }, [])
  74. console.log()
  75. return <Modal
  76. visible={visible}
  77. title={title + '广告'}
  78. onCancel={() => { PupFn({ visible: false }) }}
  79. onOk={handleOk}
  80. width={900}
  81. confirmLoading={confirmLoading}
  82. >
  83. <Form
  84. form={form}
  85. labelCol={{ span: 5 }}
  86. initialValues={
  87. {
  88. bidMode: 'BID_MODE_OCPM',
  89. dateType: '2',
  90. bidStrategy: 'BID_STRATEGY_AVERAGE_COST',
  91. timeSeries: '1',
  92. smartBidType: 'SMART_BID_TYPE_CUSTOM',
  93. autoAcquisitionEnabled: false,
  94. wechatSceneType: '0',
  95. wechatPositionType: '0'
  96. }
  97. }
  98. >
  99. {/* ============================================================基本信息============================================================= */}
  100. <Divider orientation='center'>基本信息</Divider>
  101. <Form.Item label={<strong>广告名称</strong>} name='adgroupName' rules={[{ required: true, message: '请输入广告名称!' }]}>
  102. <Input placeholder='广告名称' style={{ width: 300 }} />
  103. </Form.Item>
  104. <Form.Item label={<strong>推广目标类型</strong>} name='promotedObjectType' rules={[{ required: true, message: '请选择推广告推广目标类型!' }]}>
  105. <Select style={{ width: 300 }} showSearch filterOption={(input, option) =>
  106. (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
  107. } allowClear>
  108. {
  109. Object.keys(PromotedObjectType).map(key => {
  110. return <Select.Option value={key} key={key}>{PromotedObjectType[key]}</Select.Option>
  111. })
  112. }
  113. </Select>
  114. </Form.Item>
  115. <Form.Item label={<strong>广告版位</strong>} name='siteSet' rules={[{ required: true, message: '请输入选择广告版位!' }]}>
  116. <Select mode='multiple' style={{ width: 300 }} allowClear>
  117. {
  118. Object.keys(SiteSetEnum).map(key => {
  119. return <Select.Option value={key} key={key}>{SiteSetEnum[key]}</Select.Option>
  120. })
  121. }
  122. </Select>
  123. </Form.Item>
  124. {
  125. siteSet?.some((s: string) => s === 'SITE_SET_WECHAT') && <>
  126. <Form.Item label={<strong>微信公众号与小程序定投</strong>} name='wechatPositionType' style={wechatPositionType === '1' ? { marginBottom: 5 } : {}}>
  127. <Radio.Group >
  128. <Radio.Button value="0">不限</Radio.Button>
  129. <Radio.Button value="1">自定义</Radio.Button>
  130. </Radio.Group>
  131. </Form.Item>
  132. {wechatPositionType === '1' && <Form.Item style={{ marginLeft: 177 }} name='wechatPosition'>
  133. <Checkbox.Group options={sceneTagsList?.data?.WECHAT_POSITION?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} />
  134. </Form.Item>}
  135. <Form.Item label={<strong>微信公众号与小程序场景</strong>} name='wechatSceneType' style={wechatSceneType === '1' ? { marginBottom: 5 } : {}} >
  136. <Radio.Group >
  137. <Radio.Button value="0">不限</Radio.Button>
  138. <Radio.Button value="1">自定义</Radio.Button>
  139. </Radio.Group>
  140. </Form.Item>
  141. {wechatSceneType === '1' && <>
  142. <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>公众号媒体类型</strong></p>
  143. <Form.Item style={{ marginLeft: 177 }} name='officialAccountMediaCategory'>
  144. <Checkbox.Group options={sceneTagsList?.data?.OFFICIAL_ACCOUNT_MEDIA_CATEGORY?.filter((i: { description: string; }) => i.description !== '不限')?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} />
  145. </Form.Item>
  146. <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>小程序小游戏流量类型</strong></p>
  147. <Form.Item style={{ marginLeft: 177 }} name='miniProgramAndMiniGame'>
  148. <Checkbox.Group options={sceneTagsList?.data?.MINI_PROGRAM_AND_MINI_GAME?.filter((i: { description: string; }) => i.description !== '不限')?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} />
  149. </Form.Item>
  150. <p style={{ marginBottom: 5, marginLeft: 177 }}><strong style={{ marginRight: 20 }}>订单详情页消费场景</strong></p>
  151. <Form.Item style={{ marginLeft: 177 }} name='payScene'>
  152. <Checkbox.Group options={sceneTagsList?.data?.PAY_SCENE?.filter((i: { description: string; }) => i.description !== '不限')?.map((item: { description: any; id: any; }) => ({ label: item.description, value: item.id }))} />
  153. </Form.Item>
  154. </>}
  155. </>
  156. }
  157. {/* ============================================================排期与出价============================================================= */}
  158. <Divider orientation='center'>排期与出价</Divider>
  159. <Form.Item label={<strong>投放日期</strong>} name='dateType'>
  160. <Radio.Group >
  161. <Radio.Button value="1">选择开始与结束日期</Radio.Button>
  162. <Radio.Button value="2">长期投放</Radio.Button>
  163. </Radio.Group>
  164. </Form.Item>
  165. {/* 投放日期的不同展示不同的日期选择 */}
  166. {
  167. dateType === '1' ? <Form.Item name='date' rules={[{ required: true, message: '请选择日期' }]}>
  168. <RangePicker style={{ marginLeft: 177 }}></RangePicker>
  169. </Form.Item> : <Form.Item name='date' style={{ marginLeft: 177 }} rules={[{ required: true, message: '请选择日期' }]}>
  170. <DatePickers />
  171. </Form.Item>
  172. }
  173. <Form.Item label={<strong>投放时段</strong>}>
  174. <Radio.Group name='timeSeries' defaultValue='1'>
  175. <Radio.Button value={'1'}>全天投放</Radio.Button>
  176. </Radio.Group>
  177. </Form.Item>
  178. <Form.Item label={<strong>出价方式</strong>} name='bidMode'>
  179. <Radio.Group >
  180. {
  181. Object.keys(BidModeEnum).map(key => {
  182. return <Radio.Button value={key} key={key} disabled={!key.includes('CPM')}>{BidModeEnum[key]}</Radio.Button>
  183. })
  184. }
  185. </Radio.Group>
  186. </Form.Item>
  187. {/* 出价方式为OCPM才展示 */}
  188. {
  189. bidMode === 'BID_MODE_OCPM' && <>
  190. <Form.Item label={<strong>优化目标</strong>} name='optimizationGoal' rules={[{ required: true, message: '请选择优化目标' }]}>
  191. <Select style={{ width: 300 }} showSearch filterOption={(input, option) =>
  192. (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
  193. } allowClear>
  194. {
  195. Object.keys(OptimizationGoalEnum).map(key => {
  196. return <Select.Option value={key} key={key}>{OptimizationGoalEnum[key]}</Select.Option>
  197. })
  198. }
  199. </Select>
  200. </Form.Item>
  201. <Form.Item label={<strong>出价类型</strong>} name='smartBidType'>
  202. <Radio.Group >
  203. <Radio.Button value="SMART_BID_TYPE_CUSTOM">手动出价</Radio.Button>
  204. <Radio.Button value="SMART_BID_TYPE_SYSTEMATIC">自动出价</Radio.Button>
  205. </Radio.Group>
  206. </Form.Item>
  207. <Form.Item label={<strong>出价策略</strong>} name='bidStrategy'>
  208. <Radio.Group >
  209. {
  210. Object.keys(BidStrategyEnum).map(key => {
  211. return <Radio.Button value={key} key={key} disabled={smartBidType === 'SMART_BID_TYPE_SYSTEMATIC' && key === 'BID_STRATEGY_PRIORITY_CAP_COST'}> {BidStrategyEnum[key]}</Radio.Button>
  212. })
  213. }
  214. </Radio.Group>
  215. </Form.Item>
  216. </>
  217. }
  218. {/* 出价类型为手动出价才展示 */}
  219. {
  220. smartBidType !== 'SMART_BID_TYPE_SYSTEMATIC' && <>
  221. <Form.Item label={<strong>出价</strong>} name='bidAmount' rules={[{ required: true, message: '请输入价格' }]}>
  222. <Input placeholder='输入价格 元/千次曝光' style={{ width: 300 }} />
  223. </Form.Item>
  224. {/* 当版位选择大于1时才出现 */}
  225. {/* {siteSet?.length > 1 &&<Form.Item label={<strong>分版位出价</strong>} name='bidAdjustment'>
  226. <Switch checkedChildren="开启" unCheckedChildren="关闭" />
  227. </Form.Item>} */}
  228. <Form.Item label={<strong>一键起量</strong>} name='autoAcquisitionEnabled' valuePropName="checked">
  229. <Switch checkedChildren="开启" unCheckedChildren="关闭" />
  230. </Form.Item>
  231. {/* 一键起量开启时才出现 */}
  232. {autoAcquisitionEnabled && <Form.Item label={<strong>起量预算</strong>} name='autoAcquisitionBudget' rules={[{ required: true, message: '请输入起量预算' }]}>
  233. <Input placeholder='起量预算' style={{ width: 300 }} />
  234. </Form.Item>}
  235. </>
  236. }
  237. <Form.Item label={<strong>广告日预算</strong>} name='dailyBudget'>
  238. <Input placeholder='不填默认为不限' style={{ width: 300 }} />
  239. </Form.Item>
  240. </Form>
  241. </Modal >
  242. }
  243. export default AdModal