index.tsx 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. import { Button, Card, DatePicker, Input, message, Select, Space, Tabs } from 'antd'
  2. import { SelectValue } from 'antd/es/select'
  3. import moment from 'moment'
  4. import React, { useCallback, useEffect, useReducer, useState } from 'react'
  5. import AddTitle from './components/addTitle'
  6. import Tables from '@/components/Tables'
  7. import columns from './tableConfig'
  8. import { useModel } from 'umi'
  9. const { Option } = Select
  10. const { Search } = Input
  11. const { TabPane } = Tabs
  12. import BatchAddLabel from '@/components/BatchAddLabel'
  13. import style from './index.less'
  14. interface State {
  15. pageNum: number,
  16. pageSize: number,
  17. beginDate: string | undefined, // 上传时间
  18. endDate: string | undefined, // 结束时间
  19. labelIds: SelectValue, // 标签
  20. novels: string | undefined, //书籍
  21. sortRule: string | undefined, // 类型排序
  22. upOrder: boolean, // 升序降序
  23. type: number | undefined, // 素材类型
  24. isCollect: boolean, // 获取类型
  25. dataType: string, // 数据类型
  26. content: string, // 关键字
  27. }
  28. interface Action {
  29. type: 'init' | 'begainDate' | 'content' | 'endDate' | 'labelIds' | 'dataType' | 'novels' | 'sortRule' | 'upOrder' | 'type' | 'isCollect' | 'pageNum' | 'pageSize',
  30. params?: any
  31. }
  32. function reducer(state: State, action: Action) {
  33. let { type, params } = action
  34. switch (type) {
  35. case 'begainDate':
  36. return { ...state, beginDate: params.beginDate }
  37. case 'endDate':
  38. return { ...state, endDate: params.endDate }
  39. case 'labelIds':
  40. return { ...state, labelIds: params.labelIds }
  41. case 'novels':
  42. return { ...state, novels: params.novels }
  43. case 'sortRule':
  44. return { ...state, sortRule: params.sortRule }
  45. case 'upOrder':
  46. return { ...state, upOrder: params.upOrder }
  47. case 'type':
  48. return { ...state, type: params.type }
  49. case 'isCollect':
  50. return { ...state, isCollect: params.isCollect }
  51. case 'dataType':
  52. return { ...state, dataType: params.dataType }
  53. case 'pageNum':
  54. return { ...state, pageNum: params.pageNum }
  55. case 'pageSize':
  56. return { ...state, pageSize: params.pageSize }
  57. case 'content':
  58. return { ...state, content: params.content }
  59. case 'init':
  60. return { ...initState }
  61. default:
  62. return { ...state }
  63. }
  64. }
  65. const initState = {
  66. pageNum: 1,
  67. pageSize: 20,
  68. beginDate: undefined,
  69. endDate: undefined,
  70. labelIds: [],
  71. novels: undefined,
  72. sortRule: 'consume_amount',
  73. upOrder: false,
  74. type: 1,
  75. isCollect: false,
  76. dataType: 'all',
  77. content: ''
  78. }
  79. /**广告标题*/
  80. function AdTitle() {
  81. const [state, dispatch] = useReducer(reducer, initState)
  82. const { beginDate, endDate, labelIds, dataType, sortRule, upOrder, type, isCollect } = state
  83. const [visible, setVisible] = useState<boolean>(false)
  84. const { dataList, getLabels, datacollects, setTagContent } = useModel('useLaunch.useMaterial')
  85. const [checkboxIds, setCheckboxIds] = useState<any>([]) // 勾选ID
  86. const [editData, setEditData] = useState<any>({})
  87. const [batchVisible, setBatchVisible] = useState<boolean>(false) // 批量添加标签弹窗控制
  88. useEffect(() => {
  89. getLabels.run({ pageNum: 1, pageSize: 200 })
  90. }, [])
  91. useEffect(() => {
  92. dataList.run({ ...state, labelIds, name: 'contentList' })
  93. }, [state])
  94. /**分页 */
  95. const pageChange = useCallback((page: string | number, pageSize?: string | number) => {
  96. dispatch({ type: 'pageNum', params: { pageNum: page } })
  97. dispatch({ type: 'pageSize', params: { pageSize: pageSize } })
  98. }, [])
  99. /** 收藏 */
  100. const collectsHandle = useCallback(({ id, isCollects }: { id: number, isCollects: boolean }) => {
  101. let collectsType: number = type === 1 ? 4 : 5
  102. datacollects.run({ type: collectsType, contentIds: id.toString(), name: 'contentCollect', collect: isCollects }).then(res => {
  103. dataList.refresh()
  104. })
  105. }, [dataList])
  106. /** 修改 */
  107. const editHandle = useCallback(({ item }: { item: any }) => {
  108. setEditData(item)
  109. setVisible(true)
  110. }, [])
  111. // 批量添加标签
  112. const batchEdit = useCallback(() => {
  113. setBatchVisible(true)
  114. }, [batchVisible])
  115. // 批量添加标签确定
  116. const batchEditOK = useCallback((value: string[]) => {
  117. setTagContent.run({mediaIds: checkboxIds?.map((item: {id: number}) => item?.id).toString(), labelIds: value.toString()}).then(() => {
  118. dataList.refresh()
  119. setBatchVisible(false)
  120. // setCheckboxIds([])
  121. })
  122. }, [batchVisible, checkboxIds, dataList])
  123. return <Card className={style.adOrigin} title={
  124. <>
  125. <div className={style.headerItem}>
  126. <div>
  127. <Space>
  128. <DatePicker style={{ width: 120 }} value={beginDate ? moment(beginDate) : null} onChange={(e: moment.Moment | null) => { dispatch({ type: 'begainDate', params: { beginDate: e ? moment(e).format('YYYY-MM-DD') : null } }) }} placeholder='消耗开始时间' />
  129. <DatePicker style={{ width: 120 }} value={endDate ? moment(endDate) : null} onChange={(e: moment.Moment | null) => { dispatch({ type: 'endDate', params: { endDate: e ? moment(e).format('YYYY-MM-DD') : null } }) }} placeholder='消耗结束时间' />
  130. <Select style={{ width: 160 }} maxTagCount='responsive' value={labelIds} onChange={(value: SelectValue) => { dispatch({ type: 'labelIds', params: { labelIds: value } }) }} placeholder="选择标签" allowClear mode="multiple">
  131. {getLabels?.data?.records.map((item: any) => (<Option value={item?.id} key={item?.id}>{item?.label}</Option>))}
  132. </Select>
  133. <Search style={{ width: 150 }} placeholder="请输入小说" onSearch={(e) => { dispatch({ type: 'novels', params: { novels: e } }) }} allowClear />
  134. <Select style={{ width: 150 }} value={sortRule} onChange={(value: SelectValue) => { dispatch({ type: 'sortRule', params: { sortRule: value } }) }} placeholder="选择排序类型" allowClear>
  135. <Option value="view_times">浏览次数</Option>
  136. <Option value="consume_amount">消耗金额</Option>
  137. <Option value="click_rate">点击率</Option>
  138. </Select>
  139. <Select style={{ width: 70 }} value={upOrder ? '1' : '2'} onChange={(value: SelectValue) => { dispatch({ type: 'upOrder', params: { upOrder: value === '1' ? true : false } }) }} >
  140. <Option value="1">升序</Option>
  141. <Option value="2">降序</Option>
  142. </Select>
  143. <Select style={{ width: 100 }} value={isCollect ? 'true' : 'false'} onChange={(value: SelectValue) => { dispatch({ type: 'isCollect', params: { isCollect: value === 'true' ? true : false } }) }}>
  144. <Option value="false">全部</Option>
  145. <Option value="true">我的收藏</Option>
  146. </Select>
  147. <Select style={{ width: 70 }} value={type} onChange={(value: SelectValue) => { dispatch({ type: 'type', params: { type: value } }) }} placeholder="请选择素材类型">
  148. <Option value={1}>标题</Option>
  149. <Option value={2}>文案</Option>
  150. </Select>
  151. <Search style={{ width: 160 }} placeholder="请输入关键字" onSearch={(e) => { dispatch({ type: 'content', params: { content: e } }) }} allowClear />
  152. </Space>
  153. </div>
  154. <div>
  155. <Space>
  156. <Button type="primary" disabled={checkboxIds?.length > 1 ? false : true} onClick={batchEdit}>批量添加标签</Button>
  157. </Space>
  158. </div>
  159. </div>
  160. </>
  161. }>
  162. {visible && <AddTitle visible={visible} hideModal={() => { setVisible(false); }} editData={editData} ajax={dataList} dataType={dataType}></AddTitle>}
  163. {/* 批量添加标签 */}
  164. {batchVisible && <BatchAddLabel show={batchVisible} onClose={()=>{setBatchVisible(false)}} onChange={batchEditOK} ajax={setTagContent}/>}
  165. <Tabs onChange={(e) => { dispatch({ type: 'dataType', params: { dataType: e } }) }} type="card" size='small' className={style.tabs} activeKey={dataType}>
  166. <TabPane tab="公司云共享" key="all" />
  167. <TabPane tab="个人云共享" key="personal" />
  168. </Tabs>
  169. <Tables
  170. columns={columns(collectsHandle, editHandle)}
  171. dataSource={dataList?.data?.records.map((item: any) => ({...item, id: Number(item?.id)}))}
  172. total={dataList?.data?.total}
  173. pageChange={pageChange}
  174. sizeChange={pageChange}
  175. size="small"
  176. bordered
  177. loading={dataList?.loading}
  178. scroll={{ x: 2000 }}
  179. rowSelection={{
  180. selectedRowKeys: checkboxIds?.map((item: any) => item?.id?.toString()),
  181. getCheckboxProps: (record: any) => ({
  182. disabled: checkboxIds?.find((item1: any) => item1?.id === record?.id) ? false : checkboxIds.length >= 20 ? true : false
  183. }),
  184. onSelect: (record: any, selected: any, selectedRows: any, nativeEvent: any) => {
  185. setCheckboxIds([...selectedRows])
  186. },
  187. onSelectAll: (selected: any, selectedRows: any, changeRows: any) => {
  188. if (selectedRows.length > 20) {
  189. message.error('最多选择20个')
  190. selectedRows = selectedRows.splice(0, 20)
  191. }
  192. setCheckboxIds([...selectedRows])
  193. }
  194. }}
  195. />
  196. </Card>
  197. }
  198. export default AdTitle