123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517 |
- import DatePickePage from '@/components/DatePicker'
- import GroupWxTabs from '@/components/GroupWxTabs'
- import Tables from '@/components/Tables'
- import useEcharts from '@/Hook/useEcharts'
- import { FullscreenExitOutlined, FullscreenOutlined, SearchOutlined, SettingOutlined } from '@ant-design/icons'
- import { Button, Card, Col, Drawer, Input, InputNumber, Row, Select, Space, Tooltip, Transfer } from 'antd'
- import { RadioChangeEvent } from 'antd/lib/radio'
- import { Moment } from 'moment'
- import React, { useCallback, useEffect, useRef, useState } from 'react'
- import { useModel } from 'umi'
- import DailyReport from './components/DailyReport'
- import { dateColumns, weChatColumns } from './tableConfig'
- import style from './index.less'
- import { SelectValue } from 'antd/es/select'
- import HocError from '@/Hoc/HocError'
- import { quanpin } from '@/utils/fullScreen'
- import { TransferDirection } from 'antd/lib/transfer'
- import Sortable from 'sortablejs'
- const gutter = { xs: 24, sm: 24, md: 12, xl: 8 }
- function DataCenter() {
- const { state, getOverview, dispatch, getDaily, getChanne } = useModel('useData.useDataCenter')
- const { currentUser }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser }))
- const { state: userState } = useModel('useOperating.useUser')
- const { state: { groupActionWx } } = useModel('useOperating.useWxGroupList')
- const { selectdName, isFell } = userState
- const { state: { pitcher } } = useModel('useData.useTableData')
- const [total, setTotal] = useState<number>(0)
- const [size, setSize] = useState<'small' | 'middle' | 'large'>('small')
- const [page, setPage] = useState<number>(1)
- const [pageSize, setPageSize] = useState<number>(100)
- const [visible, setVisible] = useState<boolean>(false)
- const { LineData1, LineData2, LineData3, tableValue, date_range, channel, start, end, tableData, order_by, order } = state
- const [selectedKeys, setSelectedKeys] = useState<any[]>([])
- const [targetKeys, setTargetKeys] = useState<any[]>(localStorage?.getItem(`日期汇总`) ? JSON.parse(localStorage?.getItem(`日期汇总`) as string) : [])
- const [sortArr, setSortArr] = useState<any[]>([])
- const [fixedNum, setFixedNum] = useState<number | string>(localStorage.getItem(`日期汇总fixedNum`) || 1)
- const [newColumns, setNewColumns] = useState<any[]>([])
- const [moveArr, setMoveArr] = useState<any[]>([])
- const [statistical, setStatistical] = useState<any>({})
- const [tabKey, setTabKey] = useState<string>('1')
- const [showZj, setShowZj] = useState<boolean>(false)
- const [sortOrder, setSortOrder] = useState<{ columnKey: string, order: 'descend' | 'ascend' | undefined }>({ columnKey: '', order: undefined })
- const { Line } = useEcharts()
- const ref = useRef(null)
- //获取日报数据
- useEffect(() => {
- let obj: any = {}
- dispatch({ type: 'setState', params: { overview: obj } })
- let dataQuery: any = { user_id: currentUser.userId == 1 ? userState.selectdUserId : currentUser.userId }
- pitcher && (dataQuery['pitcher'] = pitcher)
- getOverview.run(dataQuery).then((res: any) => {
- let data = res?.data
- if (data?.length > 0) {
- Object.keys(data[0]).forEach((key: string) => {
- if (typeof data[0][key] === 'number') {
- obj[key] = parseFloat(data[0][key].toFixed(4))
- } else {
- obj[key] = data[0][key]
- }
- })
- }
- dispatch({ type: 'setState', params: { overview: obj } })
- })
- }, [pitcher, userState.selectdUserId, currentUser.userId])
- //获取tables表格数据
- useEffect(() => {
- tableSubmut({ current: 1, pageSize: 100 })
- }, [pitcher, tableValue, selectdName])
- /**图表日期选择 */
- const lineDayChange = useCallback((vlaue: '7' | '15') => {
- dispatch({ type: 'LineDay', params: { LineDay: vlaue } })
- console.log(vlaue)
- }, [])
- /**table切换事件 */
- const tableChange = useCallback((e: RadioChangeEvent) => {
- setTargetKeys([])//清空选中数组
- setMoveArr([])//清空移动数组
- setNewColumns([])//清空渲染列表
- dispatch({ type: 'setState', params: { tableData: [] } })//清空数据
- let value = e.target.value
- let name = value === '1' ? '日期汇总' : '公众号汇总'
- setFixedNum(localStorage.getItem(`${name}fixedNum`) || 1)
- setSort(value)//排序函数
- dispatch({ type: 'tableChange', params: { tableValue: value } })
- let newTargetKeys = localStorage?.getItem(`${name}`) ? JSON.parse(localStorage?.getItem(`${name}`) as string) : []
- setTargetKeys(newTargetKeys)//读取字段配置
- filterColumns(newTargetKeys, value)
- }, [fixedNum, targetKeys])
- /**table搜索事件 */
- const tableSubmut = useCallback((pagination?: { current?: number, pageSize?: number }, filters?: any, sortData?: { column: { dataIndex: string }, order?: "ascend" | "descend", columnKey: string }) => {
- let data = { page: pagination?.current || 1, page_size: pagination?.pageSize || 100 }
- pitcher && (data['pitcher'] = pitcher)
- setPageSize(pagination?.pageSize || 100)
- setPage(pagination?.current || 1)
- channel && (data['channel'] = channel)
- start && (data['start'] = start)
- end && (data['end'] = end)
- userState.selectdUserId && (data['user_id'] = currentUser.userId == 1 ? userState.selectdUserId : currentUser.userId)
- // date_range && (data['date_range'] = date_range);
- sortOrder?.order && (data['order'] = sortOrder?.order === 'ascend' ? 'asc' : 'desc');
- sortOrder?.columnKey && (data['order_by'] = sortOrder?.columnKey)
- sortData?.order && (data['order'] = sortData?.order === 'ascend' ? 'asc' : 'desc');
- sortData?.column?.dataIndex && (data['order_by'] = sortData?.column?.dataIndex)
- if (sortData) { // 返回排序
- setSortOrder({ columnKey: sortData.columnKey, order: sortData?.order })
- }
- let ajax = tableValue === '1' ? getDaily : getChanne
- ajax.run(data).then((res: any) => {
- let data: any = res?.data
- setStatistical(res?.total_data)
- if (tableValue === '1') {
- let LineData1 = [{ legendName: '消耗' }]
- let LineData2 = [{ legendName: '充值' }]
- let LineData3 = [{ legendName: 'ROI' }]
- let newData = data?.length > 0 ? (JSON.parse(JSON.stringify(data))).sort((a: { date: string }, b: { date: string }) => {
- return new Date(a.date).getTime() - new Date(b.date).getTime()
- }) : []
- newData?.map((item: { date: string, cost: number, first_roi: number, order_amount: number }) => {
- LineData1[0][item.date] = item.cost
- LineData2[0][item.date] = item.order_amount
- LineData3[0][item.date] = item.first_roi
- })
- dispatch({ type: 'setState', params: { LineData1, LineData2, LineData3 } })
- }
- dispatch({
- type: 'setState',
- params: {
- tableData: data || []
- }
- })
- setTotal(res?.total)
- })
- }, [channel, start, end, date_range, selectdName, sortOrder, tableValue, order_by, order, userState.selectdUserId, pitcher, currentUser.userId])
- /**tableDay事件 */
- const tableDayChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
- let value = e.target.value
- dispatch({ type: 'setState', params: { date_range: value, start: '', end: '' } })
- }, [])
- /**tableAppid事件 */
- const tableAppidChange = useCallback((value: SelectValue) => {
- dispatch({ type: 'tableAppid', params: { channel: value as string } })
- }, [])
- /**tableDate事件 */
- const tableDateChange = useCallback((arr: Moment[], formatString: string | string[]) => {
- dispatch({ type: 'setState', params: { start: (formatString as string[])[0], end: (formatString as string[])[1], date_range: '' } })
- }, [])
- /**table字段设置 */
- const handleChange = useCallback((nextTargetKeys: string[], direction: TransferDirection, moveKeys: string[]) => {
- setTargetKeys(nextTargetKeys)
- filterColumns(nextTargetKeys, tableValue as '1' | '2')
- }, [tableValue, fixedNum])
- const handleSelectChange = useCallback((sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
- setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys])
- }, [])
- const handleScroll = (direction: TransferDirection, e: React.SyntheticEvent<HTMLUListElement, Event>) => {
- // console.log('direction:', direction);
- // console.log('target:', e.target);
- };
- //获取排序列表
- const setSort = useCallback((tableValue?: any) => {
- let arr: any[] = []
- let columns = tableValue === '1' ? dateColumns : weChatColumns
- columns().map((item: any) => {
- if (typeof item.title === 'string') {
- arr.push({ title: item.title, value: item.dataIndex, key: item.dataIndex })
- }
- if (typeof item.title === 'object' && typeof item.title.props.children[0] === 'string') {
- arr.push({ title: item.title, value: item.dataIndex, key: item.dataIndex })
- }
- })
- setSortArr(arr)
- }, [])
- /**首次加载 */
- useEffect(() => {
- setSort('1')
- filterColumns(localStorage?.getItem(`日期汇总`) ? JSON.parse(localStorage?.getItem(`日期汇总`) as string) : [], '1')
- }, [])
- /** 计算新的渲染Columns*/
- const filterColumns = (targetKeys: any[], tableValue: '1' | '2') => {
- let arr: any[] = []
- if (targetKeys && targetKeys.length > 0) {
- let fixedNum: any = localStorage.getItem(`${tableValue === '1' ? '日期汇总fixedNum' : '公众号汇总fixedNum'}`) ? localStorage.getItem(`${tableValue === '1' ? '日期汇总fixedNum' : '公众号汇总fixedNum'}`) : 1
- let columns = tableValue === '1' ? dateColumns() : weChatColumns()
- targetKeys?.forEach((v: string, index: number) => {
- columns?.forEach((item: any) => {
- if (item.dataIndex === v) {
- if (index < fixedNum) {
- item.fixed = true
- } else {
- item.fixed = false
- }
- arr.push(item)
- }
- })
- })
- localStorage.setItem(`${tableValue === '1' ? '日期汇总' : '公众号汇总'}`, JSON.stringify(targetKeys))//保存至本地浏览器
- setNewColumns(arr)
- }
- }
- /**拖动排序 */
- useEffect(() => {
- if (visible) {
- let ul: any = document.getElementsByClassName('ant-transfer-list-content-show-remove')[0]
- if (ul) {
- new Sortable(ul, {
- animation: 150, onEnd: () => {
- let arr: any = []
- for (let item of ul?.children) {
- arr.push(item.title)
- }
- setMoveArr(arr)
- }
- })
- }
- }
- }, [visible])
- /**计算当前UL的顺序生成新的key表 */
- useEffect(() => {
- if (moveArr.length > 0) {
- let newTargetKeys: any[] = []
- moveArr?.forEach((t: string) => {
- sortArr?.forEach((arr: any) => {
- if (t === arr?.title) {
- newTargetKeys.push(arr?.key)
- }
- })
- })
- filterColumns(newTargetKeys, tableValue as '1' | '2')
- setTargetKeys(newTargetKeys)
- }
- }, [moveArr, sortArr, tableValue])
- const content = <Row gutter={[20, 20]} >
- {/**日报 */}
- <div className={style.gktitle}>
- <div> {(pitcher ? pitcher : currentUser.userId == 1 ? selectdName : currentUser.name) + ' -- ' + '概况'} </div>
- </div>
- <Col span={24} >
- {
- state.overview && JSON.stringify(state.overview) !== '{}' ?
- <DailyReport {...state.overview} /> : <DailyReport {...{}} />
- }
- </Col>
- {/**图表 */}
- <Col span={24}>
- <Row className={style.chart} gutter={[20, 20]} >
- <Col span={24} >
- <Card
- hoverable
- title={(pitcher ? pitcher : currentUser.userId == 1 ? selectdName : currentUser.name) + '--' + (tabKey === '1' ? `消耗图表` : tabKey === '2' ? '充值图表' : 'ROI图表')}
- headStyle={{ textAlign: 'center' }}
- tabList={[{ key: '1', tab: '消耗图表' }, { key: '2', tab: '充值图表' }, { key: '3', tab: 'ROI图表' }]}
- activeTabKey={tabKey}
- onTabChange={(key: string) => {
- setTabKey(key)
- }}
- loading={getDaily?.loading}
- >
- {
- tabKey === '1' && <Line
- style={{ width: '100%', height: 300, display: 'flex', justifyContent: 'center' }}
- data={LineData1}
- areaStyle
- color={'#607d8b'}
- markPoint={[
- { type: 'max', name: '最大值' },
- { type: 'min', name: '最小值' }
- ]}
- />
- }
- {
- tabKey === '2' && <Line
- style={{ width: '100%', height: 300, display: 'flex', justifyContent: 'center' }}
- data={LineData2}
- areaStyle
- color={'#009688'}
- markPoint={[
- { type: 'max', name: '最大值' },
- { type: 'min', name: '最小值' }
- ]}
- />
- }
- {
- tabKey === '3' && <Line
- style={{ width: '100%', height: 300, display: 'flex', justifyContent: 'center' }}
- data={LineData3}
- areaStyle
- color={'#00bcd4'}
- markPoint={[
- { type: 'max', name: '最大值' },
- { type: 'min', name: '最小值' }
- ]}
- />
- }
- </Card>
- </Col>
- </Row>
- </Col>
- {/**table */}
- <Col span={24} ref={ref} style={isFell ? { background: '#fff' } : {}}>
- <Card
- hoverable
- title={(pitcher ? pitcher : currentUser.userId == 1 ? selectdName : currentUser.name) + '--' + (tableValue === '1' ? '日期汇总数据' : '公众号汇总数据')}
- headStyle={{ textAlign: 'center' }}
- >
- <Row gutter={[0, 20]}>
- {/**头部搜索 */}
- <Col span={24}>
- <Row>
- <Col style={{ display: 'flex', justifyContent: 'space-between', width: '100%' }}>
- <Space>
- {
- tableValue === '2' && <Select
- style={{ width: 150 }}
- placeholder="输入搜索公众号"
- onChange={tableAppidChange}
- showArrow
- showSearch
- allowClear
- value={channel}
- >
- {
- groupActionWx?.map((list: any, eq: number) => {
- return <Select.Option key={list?.id} value={list?.nickName}>
- <img src={list?.headImg || localStorage?.bookImg} className={style.item_img} /> {list?.nickName}
- </Select.Option>
- })
- })
- </Select>
- }
- <DatePickePage model='RangePicker' DatePickerChange={tableDateChange} allowClear date={start ? [start, end] : ['', '']} />
- {/* <Input
- style={{ width: 120 }}
- onChange={tableDayChange}
- allowClear
- placeholder='过去N天'
- value={date_range}
- >
- </Input> */}
- <Button type='primary' onClick={() => tableSubmut()}><SearchOutlined />搜索</Button>
- </Space>
- <Space style={{ float: 'right' }}>
- {/* {<Button
- size='small'
- type='link'
- onClick={() => {
- setShowZj(!showZj)
- }}>
- {showZj ? '隐藏总计' : '展示总计'}
- </Button>} */}
- <Button
- size='small'
- type='text'
- onClick={() => {
- setVisible(true)
- }}>
- <SettingOutlined />
- </Button>
- <Button
- type='text'
- onClick={() => {
- if (ref?.current) {
- quanpin(ref?.current)
- }
- }}>
- {
- <Tooltip title={!isFell ? '全屏' : '退出全屏'}>{!isFell ? <FullscreenOutlined /> : <FullscreenExitOutlined />}</Tooltip>
- }
- </Button>
- <Drawer
- title="table字段设置"
- width={420}
- visible={visible}
- getContainer={ref?.current || false}
- onClose={() => {
- setVisible(false)
- }}
- >
- <div>
- <span>请输入固定列数值:</span>
- <InputNumber
- size="small"
- min={1}
- max={100000}
- onChange={(v) => {
- setFixedNum(v as number)
- localStorage.setItem(`${tableValue === '1' ? '日期汇总fixedNum' : '公众号汇总fixedNum'}`, `${v}`)
- filterColumns(targetKeys, tableValue as '1' | '2')
- }}
- value={fixedNum}
- style={{ marginBottom: 10 }}
- placeholder='请输入固定列数值'
- />
- </div>
- <Transfer
- dataSource={sortArr || []}
- titles={['不展示', '展示']}
- showSearch
- targetKeys={targetKeys || []}
- selectedKeys={selectedKeys || []}
- onChange={handleChange}
- onSelectChange={handleSelectChange}
- onScroll={handleScroll}
- render={(item: any) => item?.title}
- oneWay
- style={{ marginBottom: 16 }}
- listStyle={{
- height: 'calc(100vh - 100px)',
- }}
- />
- </Drawer>
- </Space>
- </Col>
- </Row>
- </Col>
- {/**表格 */}
- <Col span={24}>
- <div className={style[size]}>
- <Tables
- columns={newColumns?.length > 0 ? newColumns : dateColumns()}
- dataSource={[{ ...statistical, id: 1 }]}
- pagination={false}
- hideOnSinglePage
- bordered
- size='small'
- scroll={isFell ? { y: document.body.clientHeight - 300, x: 1000 } : { y: 600, x: 1000 }}
- className='total_table'
- />
- <Tables
- bordered
- columns={newColumns?.length > 0 ? newColumns : dateColumns({ sortOrder })}
- dataSource={showZj ? [{ ...statistical, id: 1 }] : tableData || []}
- pageSize={pageSize}
- current={showZj ? 1 : page}
- // rowClassName={(record: { color: string }) => style[record['color']]}
- loading={getDaily?.loading}
- size={size}
- defaultPageSize={100}
- total={showZj ? 1 : total}
- scroll={isFell ? { y: document.body.clientHeight - 280, x: 1000 } : { y: 600, x: 1000 }}
- onChange={tableSubmut}
- className='all_table'
- // summary={() => {
- // let arr: any[] = []
- // if (targetKeys.length > 0) {
- // arr = targetKeys
- // } else {
- // dateColumns().forEach((item: any) => {
- // arr.push(item.dataIndex)
- // })
- // }
- // if (arr.length > 0 && JSON.stringify(statistical) !== '{}') {
- // return <Table.Summary.Row >
- // {
- // arr.map((key: string, index: number) => {
- // let str: any = ''
- // if (typeof statistical[key] === 'string') {
- // str = statistical[key]
- // }
- // if (typeof statistical[key] === 'number' && ((key as string)?.includes('roi') || (key as string)?.includes('rate'))) {
- // if (key === 'first_roi' && statistical[key] <= 8) {
- // let a = statistical[key] ? parseFloat((statistical[key] * 100).toFixed(2)) : 0
- // str = <span style={{ color: a <= 8 ? 'green' : '' }}>{a + '%'}</span>
- // } else {
- // str = statistical[key] ? `${parseFloat((statistical[key] * 100).toFixed(2))}%` : '0%'
- // }
- // } else if(typeof statistical[key] === 'number'){
- // str = <Statistic value={statistical[key] || 0} />
- // }
- // return <Table.Summary.Cell
- // index={index}
- // key={key}
- // align='center'
- // >{str}</Table.Summary.Cell>
- // })
- // }
- // </Table.Summary.Row>
- // }
- // return null
- // }}
- />
- {/* {
- tableValue === '2' && <Tables
- bordered
- columns={newColumns?.length > 0 ? newColumns : weChatColumns()}
- onChange={tableSubmut}
- dataSource={tableData || []}
- pageSize={pageSize}
- current={page}
- // rowClassName={(record: { color: string }) => style[record['color']]}
- loading={getDaily?.loading || getChanne?.loading}
- size={size}
- defaultPageSize={30}
- total={total}
- scroll={isFell ? { y: document.body.clientHeight - 200, x: 1000 } : { y: 600, x: 1000 }}
- />
- } */}
- </div>
- </Col>
- </Row>
- </Card>
- </Col>
- </Row>
- return <>
- <GroupWxTabs height='calc(100vh - 180px)' isUserSelect isFadminQTab>
- {content}
- </GroupWxTabs>
- </>
- }
- export default HocError(DataCenter)
|