updateAd.tsx 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. import { Checkbox, DatePicker, Form, Input, message, Modal, notification, Radio, Select, Space, TimePicker, Tooltip } from "antd"
  2. import React, { useEffect, useState } from "react"
  3. import TimeInSelect from "../../components/timeInSelect"
  4. import moment from "moment"
  5. import { getTimeSeriesList } from "./const";
  6. import { editAdqAdgroupsDataApi } from "@/services/launchAdq/adq";
  7. import { useAjax } from "@/Hook/useAjax";
  8. import { BidStrategyEnum, GoalRoasEnum } from "@/services/launchAdq/enum";
  9. import { QuestionCircleOutlined } from "@ant-design/icons";
  10. import { RangePickerProps } from "antd/lib/date-picker";
  11. const { RangePicker } = DatePicker;
  12. let DatePickers: any = DatePicker
  13. interface Props {
  14. title: string,
  15. visible?: boolean,
  16. onChange?: () => void,
  17. onClose?: () => void,
  18. selectedRows: any[]
  19. }
  20. /**
  21. * 修改广告
  22. * @returns
  23. */
  24. const UpdateAd: React.FC<Props> = ({ title = '修改广告', visible, onChange, onClose, selectedRows }) => {
  25. /***************************/
  26. const [form] = Form.useForm();
  27. let dateType = Form.useWatch('dateType', form)
  28. let field = Form.useWatch('field', form)
  29. const [state, setState] = useState<any>({ isShowTime: [] })
  30. const [isBidSType, setIsBidSType] = useState<boolean>(true)
  31. const [timeSeriesType, setTimeSeriesType] = useState<'allDayLong' | 'timeInterValS'>('allDayLong')
  32. const editAdqAdgroupsData = useAjax((params) => editAdqAdgroupsDataApi(params))
  33. /***************************/
  34. useEffect(() => {
  35. setIsBidSType(selectedRows.every((item: { smartBidType: string }) => item.smartBidType === 'SMART_BID_TYPE_CUSTOM'))
  36. }, [selectedRows])
  37. const handleOk = () => {
  38. form.validateFields().then(values => {
  39. console.log(values);
  40. let newValues = JSON.parse(JSON.stringify(values))
  41. let field = newValues.field
  42. let adgroupsUpdateDatetimeDTO = {} // 排期
  43. let adgroupsUpdateBidAmountDTO = {} // 出价
  44. let deepConversionSpec = {} // ROI
  45. let data = {}
  46. if (timeSeriesType === 'allDayLong') {
  47. newValues.timeSeries = getTimeSeriesList()
  48. }
  49. if (title === '批量修改深度优化') {
  50. deepConversionSpec['deepConversionType'] = newValues.deepConversionType
  51. deepConversionSpec['deepConversionWorthSpec'] = {
  52. expectedRoi: newValues.deepBidAmount,
  53. goal: newValues.goal
  54. }
  55. } else {
  56. field?.forEach((key: string) => {
  57. switch (key) {
  58. case 'dateType':
  59. if (newValues.dateType === '2') {
  60. adgroupsUpdateDatetimeDTO['beginDate'] = moment(newValues.date).format('YYYY-MM-DD')
  61. adgroupsUpdateDatetimeDTO['endDate'] = ''
  62. } else {
  63. adgroupsUpdateDatetimeDTO['beginDate'] = moment(newValues.date[0]).format('YYYY-MM-DD')
  64. adgroupsUpdateDatetimeDTO['endDate'] = moment(newValues.date[1]).format('YYYY-MM-DD')
  65. }
  66. break
  67. case 'timeType':
  68. // if (timeSeriesType === 'timeInterValS') {
  69. // if (newValues.firstDayBeginTime && moment(newValues.firstDayBeginTime).format('HH:mm:ss') !== '00:00:00') {
  70. // message.error('1111')
  71. // return
  72. // }
  73. // }
  74. if (newValues.timeSeries) {
  75. adgroupsUpdateDatetimeDTO['timeSeries'] = newValues.timeSeries.join('')
  76. }
  77. if (newValues.firstDayBeginTime) {
  78. adgroupsUpdateDatetimeDTO['firstDayBeginTime'] = moment(newValues.firstDayBeginTime).format('HH:mm:ss')
  79. }
  80. break
  81. case 'bidSType':
  82. adgroupsUpdateBidAmountDTO['bidStrategy'] = newValues.bidStrategy
  83. adgroupsUpdateBidAmountDTO['bidAmount'] = newValues.bidAmount * 100
  84. break
  85. case 'adgroupName':
  86. data['adgroupName'] = newValues.adgroupName
  87. break
  88. }
  89. })
  90. }
  91. editAdqAdgroupsData.run({ adgroupIds: selectedRows.map((item: { adgroupId: number }) => item.adgroupId), adgroupsUpdateDatetimeDTO, adgroupsUpdateBidAmountDTO, deepConversionSpec, ...data }).then(res => {
  92. if (res) {
  93. message.success(`修改操作完成.结果请在操作记录查询!`)//成功: ${res.success},失败: ${res.fail}
  94. if (res?.fail) {
  95. notification.error({
  96. message: `修改失败`,
  97. description: `成功: ${res.success},修改失败${res.fail}条,失败的请到任务列表查看`,
  98. duration: 0
  99. });
  100. }
  101. onChange?.()
  102. }
  103. })
  104. })
  105. }
  106. /** 禁止选择以前时间 */
  107. const disabledDate: RangePickerProps['disabledDate'] = current => {
  108. // Can not select days before today and today
  109. return current && current < moment().startOf('day');
  110. };
  111. return <Modal
  112. title={title}
  113. visible={visible}
  114. onOk={handleOk}
  115. width={800}
  116. onCancel={() => onClose && onClose()}
  117. confirmLoading={editAdqAdgroupsData.loading}
  118. >
  119. <Form
  120. form={form}
  121. labelCol={{ span: 4 }}
  122. className='ad_form_style'
  123. colon={false}
  124. initialValues={{
  125. dateType: '2',
  126. date: moment().startOf('day'),
  127. timeSeries: getTimeSeriesList(),
  128. firstDayBeginTime: moment('2023-02-24 00:00:00'),
  129. bidStrategy: 'BID_STRATEGY_TARGET_COST',
  130. bidAmount: 1000,
  131. optimizationMode: 'DEEP_CONVERSION_TARGET',
  132. deepConversionType: 'DEEP_CONVERSION_WORTH',
  133. goal: 'GOAL_1DAY_PURCHASE_ROAS'
  134. }}
  135. >
  136. {title === '批量修改' ? <>
  137. <Form.Item label={<strong>选择修改字段</strong>} name='field' rules={[{ required: true, message: '选择修改字段' }]}>
  138. <Checkbox.Group>
  139. <Checkbox value="dateType">投放日期</Checkbox>
  140. <Checkbox value="timeType">投放时段</Checkbox>
  141. <Checkbox value="bidSType" disabled={!isBidSType}>
  142. <Space size={5}>
  143. 出价
  144. {!isBidSType && <Tooltip title="选择的广告包含自动出价类型,不支持修改出价">
  145. <QuestionCircleOutlined />
  146. </Tooltip>}
  147. </Space>
  148. </Checkbox>
  149. <Checkbox value="adgroupName">广告名称</Checkbox>
  150. </Checkbox.Group>
  151. </Form.Item>
  152. {field?.includes('dateType') && <>
  153. <Form.Item label={<strong>投放日期</strong>} name='dateType'>
  154. <Radio.Group onChange={(e) => {
  155. if (e.target.value === "1") {
  156. form.setFieldsValue({ date: [moment().startOf('day'), moment().startOf('day').add(1, 'M')] })
  157. }
  158. if (e.target.value === "2") {
  159. form.setFieldsValue({ date: moment().startOf('day') })
  160. }
  161. }}>
  162. <Radio.Button value="1">选择开始与结束日期</Radio.Button>
  163. <Radio.Button value="2">长期投放</Radio.Button>
  164. </Radio.Group>
  165. </Form.Item>
  166. {/* 投放日期的不同展示不同的日期选择 */}
  167. {dateType === '1' ? <Form.Item name='date' rules={[{ required: true, message: '请选择日期' }]}>
  168. <RangePicker style={{ marginLeft: 125 }} disabledDate={disabledDate}></RangePicker>
  169. </Form.Item> : <Form.Item name='date' style={{ marginLeft: 125 }} rules={[{ required: true, message: '请选择日期' }]}>
  170. <DatePickers disabledDate={disabledDate} />
  171. </Form.Item>}
  172. </>}
  173. {field?.includes('timeType') && <>
  174. <Form.Item label={<strong>投放时段</strong>} style={{ marginBottom: 0 }}>
  175. <Space direction='vertical' style={{ width: '100%' }}>
  176. <Radio.Group
  177. name='timeSeriesType'
  178. value={timeSeriesType}
  179. onChange={(value) => {
  180. setTimeSeriesType(value.target.value)
  181. if (value.target.value === 'timeInterValS') {
  182. setState({ isShowTime: ['1'] })
  183. }
  184. }}>
  185. <Radio.Button value={'allDayLong'}>全天投放</Radio.Button>
  186. <Radio.Button value={'timeInterValS'}>指定多个时段</Radio.Button>
  187. </Radio.Group>
  188. {timeSeriesType === 'timeInterValS' && <Form.Item name='timeSeries' noStyle rules={[{ required: true, message: '请选择时段' }]}>
  189. <TimeInSelect />
  190. </Form.Item>}
  191. </Space>
  192. </Form.Item>
  193. <Form.Item label={<strong></strong>}>
  194. <Space>
  195. <Checkbox.Group options={[{ label: '指定首日开始投放时间', value: '1' }]} disabled={timeSeriesType === 'timeInterValS'} value={state.isShowTime} onChange={(checkedValue) => { setState({ ...state, isShowTime: checkedValue }) }} />
  196. {state?.isShowTime?.length > 0 && <Form.Item name='firstDayBeginTime' noStyle rules={[{ required: true, message: '请选择时间' }]}>
  197. <TimePicker />
  198. </Form.Item>}
  199. </Space>
  200. </Form.Item>
  201. </>}
  202. {field?.includes('bidSType') && <>
  203. <Form.Item label={<strong>出价策略</strong>} name='bidStrategy' rules={[{ required: true, message: '请选择出价策略' }]}>
  204. <Radio.Group>
  205. {Object.keys(BidStrategyEnum).map(key => {
  206. return <Radio.Button value={key} key={key} disabled={key === 'BID_STRATEGY_PRIORITY_CAP_COST'}>{BidStrategyEnum[key]}</Radio.Button>
  207. })}
  208. </Radio.Group>
  209. </Form.Item>
  210. <Form.Item label={<strong>出价</strong>} name='bidAmount' rules={[{ required: true, message: '请输入价格' }]}>
  211. <Input placeholder={`输入价格 元`} style={{ width: 300 }} />
  212. </Form.Item>
  213. </>}
  214. {field?.includes('adgroupName') && <>
  215. <Form.Item label={<strong>广告名称</strong>} name='adgroupName' rules={[{ required: true, message: '请输入广告名称' }]}>
  216. <Input placeholder={`请输入广告名称`} style={{ width: 300 }} />
  217. </Form.Item>
  218. </>}
  219. </> : <>
  220. <Form.Item label={<strong>深度优化方式</strong>} name='optimizationMode' rules={[{ required: true, message: '请选择深度优化方式' }]}>
  221. <Radio.Group disabled>
  222. <Radio.Button value="DEEP_CONVERSION_TARGET">深度目标优化</Radio.Button>
  223. </Radio.Group>
  224. </Form.Item>
  225. <Form.Item label={<strong>深度优化类型</strong>} name='deepConversionType' rules={[{ required: true, message: '请选择深度优化类型' }]}>
  226. <Radio.Group disabled onChange={() => {
  227. form.setFieldsValue({
  228. goal: undefined,
  229. deepBidAmount: undefined
  230. })
  231. }}>
  232. <Radio.Button value="DEEP_CONVERSION_WORTH">优化 ROI</Radio.Button>
  233. </Radio.Group>
  234. </Form.Item>
  235. <Form.Item label={<strong>深度优化目标</strong>} name='goal' rules={[{ required: true, message: '请选择深度优化目标' }]}>
  236. <Select style={{ width: 380 }} placeholder='请选择'>
  237. {Object.keys(GoalRoasEnum).filter(key => ['GOAL_1DAY_PURCHASE_ROAS']?.includes(key)).map(key => <Select.Option value={key} key={key}>{GoalRoasEnum[key]}</Select.Option>)}
  238. </Select>
  239. </Form.Item>
  240. <Form.Item label={<strong>期望ROI</strong>} name='deepBidAmount' rules={[{ required: true, message: '请输入期望ROI' }]}>
  241. <Input style={{ width: 380 }} placeholder={`期望ROI目标范围0.001~1000,输入0.05,表示ROI目标为5%`} />
  242. </Form.Item>
  243. </>}
  244. </Form>
  245. </Modal>
  246. }
  247. export default React.memo(UpdateAd)