定时任务,按需开启下载

思路

1、下载列表定时请求数据,首次加载组件,例如登录,开启定时任务请求
2、当任务已下载执行完成后,清除定时任务
3、当触发导出表格任务时,再次开启定时任务

也就是在任务下载中的时候,才去执行请求调用,其他情况下避免了不必要的请求

在这里插入图片描述

关键代码

isOpenFetchFileList//是否开启定时任务

useEffect(() => {
        if (isOpenFetchFileList) {
            if (!timer) {
                console.log('开启定时任务');
                const t = setInterval(() => {
                    dispatch({
                        type: 'downloadTasks/fetchFileList',
                    });
                }, 5000);
                dispatch({
                    type: 'downloadTasks/overrideStateProps',
                    payload: {
                        timer: t,
                    },
                });
            }
        } else if (timer) {
            console.log('关闭定时任务---');
            clearInterval(timer);
            dispatch({
                type: 'downloadTasks/overrideStateProps',
                payload: {
                    timer: null,
                    isOpenFetchFileList: false,
                },
            });
        }
    }, [isOpenFetchFileList, timer, dispatch]);

model

import { message } from 'antd';
import DownloadTasksApi from '@/services/DownloadTasks.js';
import moment from 'moment';
import qs from 'qs';
import { downloadFile } from '@/utils/utils';

const namespace = 'downloadTasks';
// const selectState = state => state[namespace];

const SUCCESS = DownloadTasksApi.SUCCESS; // 完成
const DOWNLOADIND = DownloadTasksApi.DOWNLOADIND; // 下载中
export default {
    namespace,
    state: {
        isOpenFetchFileList: true,
        timer: null,
        fetchFileList: [],
        isSomeDownloading: false,
        downloadLoading: false,
    },
    reducers: {
        overrideStateProps(state, { payload }) {
            return {
                ...state,
                ...payload,
            };
        },
        updateStateProps(state, { payload }) {
            const { name, value } = payload;
            return {
                ...state,
                ...{ [name]: { ...state[name], ...value } },
            };
        },
    },
    effects: {
        /**
         * 触发任务下载
         * @param {*} listParams 参数列表
         * @param {*} url 请求地址
         */
        *triggerFileExport({ payload }, { put, call }) {
            const { listParams, url } = payload;
            yield put({
                type: 'overrideStateProps',
                payload: {
                    downloadLoading: true,
                },
            });
            const response = yield call(DownloadTasksApi.triggerFileExport, { listParams, url });
            switch (response.XCmdrCode) {
                case 0:
                    message.info('下载中,请进入下载任务列表查看下载进度');
                    yield put({
                        type: 'overrideStateProps',
                        payload: {
                            isOpenFetchFileList: true,
                        },
                    });

                    yield put({
                        type: 'fetchFileList',
                    });
                    break;
                case 342:
                    message.warn(`${response?.XCmdrMessage || '当前已有下载任务,请稍后再点击'}`);
                    break;
                default:
                    break;
            }
            yield put({
                type: 'overrideStateProps',
                payload: {
                    downloadLoading: false,
                },
            });
        },
        *fetchFileList({ payload }, { put, call, select }) {
            const { token } = yield select(store => store.user);
            const handleDownload = item => {
                const { task_id, type, created_at } = item;
                const params = {
                    type,
                    task_id,
                };
                const downloadExcelUrl = `https://admin-api.zhgcloud.com/export-task/export-excel?${qs.stringify(
                    params,
                )}&token=${token}`;
                downloadFile(
                    downloadExcelUrl,
                    `${DownloadTasksApi?.DOWNLOADTASKS[type]?.name || ''}${created_at ||
                        moment().format('YYYY-MM-DD')}.xls`,
                );
            };
            const response = yield call(DownloadTasksApi.getExportTaskTxportTaskList);
            const list = response?.XCmdrResult || [];
            const changeList = list?.map(item => {
                const { is_frontend_export, status } = item;
                if (status === SUCCESS) {
                    if (is_frontend_export === 0) {
                        handleDownload(item);
                    }
                }
                return { ...item };
            });
            const isSomeDownloading = changeList?.some(item => item?.status === DOWNLOADIND);

            switch (response.XCmdrCode) {
                case 0:
                    if (!isSomeDownloading) {
                        yield put({
                            type: 'overrideStateProps',
                            payload: {
                                isOpenFetchFileList: false,
                                isSomeDownloading: false,
                            },
                        });
                    }
                    yield put({
                        type: 'overrideStateProps',
                        payload: {
                            fetchFileList: changeList,
                            isSomeDownloading,
                        },
                    });

                    break;
                default:
                    yield put({
                        type: 'overrideStateProps',
                        payload: {
                            isOpenFetchFileList: false,
                        },
                    });
                    break;
            }
        },
        /**
         * 重新触发任务下载
         */
        *handleReExport({ payload }, { put, call }) {
            const { task_id, type, params } = payload;
            const response = yield call(DownloadTasksApi.handleReDownload, { task_id, type, params });
            switch (response.XCmdrCode) {
                case 0:
                    yield put({
                        type: 'overrideStateProps',
                        payload: {
                            isOpenFetchFileList: true,
                        },
                    });

                    yield put({
                        type: 'fetchFileList',
                    });
                    break;
                case 342:
                    message.warn(`${response?.XCmdrMessage || '当前已有下载任务,请稍后再点击'}`);
                    break;
                default:
                    break;
            }
        },
    },
};

下载组件

import { Dropdown, List } from 'antd';
import React, { useMemo, useEffect } from 'react';
import InfiniteScroll from 'react-infinite-scroller';
import moment from 'moment';
import { useSelector, useDispatch } from 'umi';
import qs from 'qs';
import DownloadTasks from '@/services/DownloadTasks';
import useToken from '@/hooks/useToken';
import download_task_green from '@/assets/download_task_green.png';
import download_task_grey from '@/assets/download_task_grey.png';
import download_task_red from '@/assets/download_task_red.png';
import download_task_yellow from '@/assets/download_task_yellow.png';
import no_pass_ic from '@/assets/no_pass_ic.png';
import styles from './FileDownloadList.less';

const ListItem = List.Item;
const SUCCESS = DownloadTasks.SUCCESS; // 完成
const DOWNLOADIND = DownloadTasks.DOWNLOADIND; // 下载中
const FAILED = DownloadTasks.FAILED; // 下载失败
const getType = type => {
    return DownloadTasks?.DOWNLOADTASKS[type]?.name || '';
};
export default () => {
    const token = useToken();
    const dispatch = useDispatch();
    const { isOpenFetchFileList, timer, fetchFileList, isSomeDownloading } = useSelector(state => state.downloadTasks);
    useEffect(() => {
        if (isOpenFetchFileList) {
            if (!timer) {
                console.log('开启定时任务');
                const t = setInterval(() => {
                    dispatch({
                        type: 'downloadTasks/fetchFileList',
                    });
                }, 5000);
                dispatch({
                    type: 'downloadTasks/overrideStateProps',
                    payload: {
                        timer: t,
                    },
                });
            }
        } else if (timer) {
            console.log('关闭定时任务---');
            clearInterval(timer);
            dispatch({
                type: 'downloadTasks/overrideStateProps',
                payload: {
                    timer: null,
                    isOpenFetchFileList: false,
                },
            });
        }
    }, [isOpenFetchFileList, timer, dispatch]);
    const getDowloadSatus = item => {
        const { rows, completed_rows, status } = item;
        switch (status) {
            case DOWNLOADIND:
                return (
                    <div className={styles.list_item_download_ing}>
                        <img src={download_task_yellow} alt="" style={{ marginLeft: 2 }} />
                        <span style={{ marginLeft: 2, color: 'rgb(253, 173, 77)' }}>下载中</span>
                    </div>
                );
            case SUCCESS:
                return (
                    <div className={styles.list_item_download_ok}>
                        <img src={download_task_green} alt="" />
                        <span style={{ marginLeft: 2, color: 'rgb(13, 207, 151)' }}>完成</span>
                    </div>
                );
            case FAILED:
                return (
                    <div className={styles.list_item_download_failed}>
                        <img src={no_pass_ic} alt="" style={{ marginLeft: 2 }} />
                        <span style={{ marginLeft: 3, color: 'rgb(251, 92, 124)' }}>失败</span>
                    </div>
                );
            default:
                if (rows === completed_rows) {
                    return (
                        <div className={styles.list_item_download_ok}>
                            <img src={download_task_green} alt="" />
                            <span style={{ marginLeft: 2, color: 'rgb(13, 207, 151)' }}>完成</span>
                        </div>
                    );
                } else {
                    return (
                        <div className={styles.list_item_download_ing}>
                            <img src={download_task_yellow} alt="" style={{ marginLeft: 2 }} />
                            <span style={{ marginLeft: 2, color: 'rgb(253, 173, 77)' }}>下载中</span>
                        </div>
                    );
                }
        }
    };

    const fliesList = useMemo(() => {
        const handleDownload = item => {
            const { task_id, type, created_at } = item;
            const params = {
                type,
                task_id,
            };
            const downloadExcelUrl = `https://admin-api.zhgcloud.com/export-task/export-excel?${qs.stringify(
                params,
            )}&token=${token}`;
            downloadFile(downloadExcelUrl, `${getType(type)}${created_at || moment().format('YYYY-MM-DD')}.xls`);
        };
        // 重新下载
        const handleReDownload = item => {
            const { task_id, type, params } = item;
            const fetParams = {
                task_id,
                params,
                type,
            };
            DownloadTasks.handleReDownload(fetParams).then(res => {
                if (res.XCmdrCode === 0) {
                    //
                }
            });
        };
        const handleDowloadButton = item => {
            const { status } = item;
            switch (status) {
                case SUCCESS:
                    return (
                        <span className="curp txt-primary" onClick={() => handleDownload(item)}>
                            下载
                        </span>
                    );
                case FAILED:
                    return (
                        <span
                            className="curp txt-primary"
                            style={{ marginLeft: 2 }}
                            onClick={() => handleReDownload(item)}
                        >
                            重新下载
                        </span>
                    );
                default:
                    return null;
            }
        };

        const fliesDiv = (
            <>
                <div className={styles.fliesListContainer}>
                    <div className={styles.flies_list_title}>
                        <div className={styles.flies_list_title_lable}>下载任务列表</div>
                        {/* <div className={styles.flies_list_close} onClick={handleClose}>x</div> */}
                    </div>
                    <div className={styles.infiniteScroll_container}>
                        <InfiniteScroll>
                            <List
                                dataSource={fetchFileList}
                                renderItem={item => (
                                    <ListItem key={item?.task_id} style={{ alignItems: 'self-start' }}>
                                        <div className={styles.list_item_wrap}>
                                            <div className={styles.list_item_type}>{getType(item.type)}</div>
                                            <div className={styles.list_item_time}>{item.created_at}</div>
                                            <div
                                                style={{
                                                    display: 'flex',
                                                    justifyContent: 'space-between',
                                                }}
                                            >
                                                {getDowloadSatus(item)}

                                                <div style={{ minWidth: '50px', textAlignLast: 'right' }}>
                                                    {handleDowloadButton(item)}
                                                </div>
                                            </div>
                                        </div>
                                    </ListItem>
                                )}
                            />
                        </InfiniteScroll>
                    </div>
                </div>
            </>
        );

        return fliesDiv;
    }, [fetchFileList, token]);
    return (
        <div style={{ display: 'inline-block' }}>
            <Dropdown overlay={fliesList} trigger={['click']}>
                <img
                    src={isSomeDownloading ? download_task_red : download_task_grey}
                    className={styles.download_task_icon}
                    alt=""
                />
            </Dropdown>
        </div>
    );
};


下载按钮组件

导出按钮可以使用防抖处理,这里选用loading

防抖处理

lodash工具库/

import React, { useMemo, useState } from 'react';
import { Button } from 'antd';
import { useDispatch, useSelector } from 'react-redux';
import Authorized from '@/utils/Authorized';
import DownloadTasks from '@/services/DownloadTasks';
import debounce from 'lodash/debounce';

export default ({ authority, listParams = {}, type = '', name = '导出表格', isDisabled = false }) => {
    const dispatch = useDispatch();
    const { downloadLoading } = useSelector(state => state.downloadTasks);
    const [exportAbled, setExportAbled] = useState(false);
    const exportButton = useMemo(() => {
        const handleEexport = () => {
            const url = DownloadTasks?.DOWNLOADTASKS[type]?.url;
            dispatch({
                type: `${DownloadTasks.EXPORTTASKMODEL}`,
                payload: { listParams, url },
            });
            if (isDisabled) {
                setExportAbled(true);
                setTimeout(() => {
                    setExportAbled(false);
                }, 2000);
            }
        };
        return (
            <Authorized authority={[authority]} noMatch={null}>
                <Button
                    disabled={exportAbled}
                    onClick={debounce(handleEexport, 1000, { leading: true })}
                    style={{ marginLeft: 10 }}
                    loading={downloadLoading}
                >
                    {name}
                </Button>
            </Authorized>
        );
    }, [authority, dispatch, exportAbled, listParams, type, name, isDisabled, downloadLoading]);
    return exportButton;
};

loading处理
import React, { useMemo, useState } from 'react';
import { Button } from 'antd';
import { useDispatch, useSelector } from 'react-redux';
import Authorized from '@/utils/Authorized';
import DownloadTasks from '@/services/DownloadTasks';

export default ({ authority, listParams = {}, type = '', name = '导出表格', isDisabled = false }) => {
    const dispatch = useDispatch();
    const { downloadLoading } = useSelector(state => state.downloadTasks);
    const [exportAbled, setExportAbled] = useState(false);
    const exportButton = useMemo(() => {
        const handleEexport = () => {
            const url = DownloadTasks?.DOWNLOADTASKS[type]?.url;
            dispatch({
                type: `${DownloadTasks.EXPORTTASKMODEL}`,
                payload: { listParams, url },
            });
            if (isDisabled) {
                setExportAbled(true);
                setTimeout(() => {
                    setExportAbled(false);
                }, 2000);
            }
        };
        return (
            <Authorized authority={[authority]} noMatch={null}>
                <Button
                    disabled={exportAbled}
                    onClick={handleEexport}
                    style={{ marginLeft: 10 }}
                    loading={downloadLoading}
                >
                    {name}
                </Button>
            </Authorized>
        );
    }, [authority, dispatch, exportAbled, listParams, type, name, isDisabled, downloadLoading]);
    return exportButton;
};


下载组件使用

                <DownloadTaskExport
                    authority="admin_contract_management_export"
                    type="admin_contracts"
                    listParams={listParams}
                    name="导出表格"
                />

serve

import request from '@/utils/request';
import { apiHostMap } from './apiHostMap';
import Model from './Model';

export default class DownloadTasks extends Model {
    static EXPORTTASKMODEL = 'downloadTasks/triggerFileExport';

    // model
    static SUCCESS = 'success';

    // 完成
    static DOWNLOADIND = 'downloading';

    // 下载中
    static FAILED = 'failed'; // 下载失败

    static DOWNLOADTASKS = {
        client: {
            name: '客户档案',
            type: 'client',
            url: 'client/export-task?type=client',
        },
        client_high_sea: {
            name: '客户公海',
            type: ' client_high_sea',
            url: 'client/high-sea-export-task',
        },
        admin_contracts: {
            name: '销售合同',
            type: 'admin_contracts',
            url: 'admin_contracts/export-task?type=admin_contracts',
        },
    };

    // 获取下载任务列表
    static getExportTaskTxportTaskList(params) {
        return request(`${apiHostMap.HOST}/export-task/export-task-list`, {
            params,
        });
    }

    // 任务列表导出
    static exportTaskListDownload(params) {
        return request(`${apiHostMap.HOST}/export-task/export-excel`, { params });
    }

    // 触发任务下载
    static triggerFileExport(params) {
        const { listParams, url } = params;
        return request(`${apiHostMap.HOST}/${url}`, { params: listParams });
    }

    // 重新触发任务下载
    static handleReDownload(item) {
        const { task_id, type, params } = item;
        return request(`${apiHostMap.HOST}/export-task/reload-export-task?task_id=${task_id}&&type=${type}&&${params}`);
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值