这边记录我们公司后端做的导出接口和前端是如何对接的
这边的技术栈是:
1: react
2: fetch
第一步:简单封装--导出界面
import { DrawerForm } from '@ant-design/pro-components';
import { CloseOutlined } from '@ant-design/icons';
import { Col, Input, Row, Select, DatePicker, message, InputNumber, Card, Button } from 'antd'
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
import { DEPT_NAMESPACE } from "@/actions/dept";
import { getCurrentUser } from "@/utils/authority";
import { getDictBiz } from "@/utils/utils";
import { DICT_BIZ_NAMESPACE } from "@/actions/dictbiz";
import { clubSetMealSave, clubSetMealUpdate } from "@/services/club";
import { list } from '@/services/menu';import style from './common.less';const { TextArea } = Input;function NewExp(props) {//show 是根据需要是否展示下方的弹窗//hang 是根据返回结果关闭弹窗//changeHange 是根据需要把参数返回出去//title 是弹窗的标题//Component 是触发弹窗的关键const { title, Component, changeHange, hang, show } = props// 时间const [startDate, setStartDate] = useState(null)const [startDate1, setStartDate1] = useState(null)const [flag, setflag] = useState(false)const submit = async () => {// 判断时间if (!show) {if (startDate != null || startDate1 != null) {// 时间比较大小if (startDate1 < startDate) {return message.error('结束时间不能小于开始时间')}let data = {d1: startDate,d2: startDate1,}changeHange(data)if (hang() == 1) {setflag(false)setStartDate(null)setStartDate1(null)}}} else {changeHange()if (hang() == 1) {setflag(false)setStartDate(null)setStartDate1(null)}}// if (res?.success) {// message.success('保存成功')// setflag(false)// changeupadte()// }}const onChange = (date, dateString) => {setStartDate(dateString)};const onChange1 = (date, dateString) => {setStartDate1(dateString)};return (<>{!show ?<><DrawerFormclassName={style.common}submitter={{resetButtonProps: { type: 'dashed' },submitButtonProps: { style: { display: 'none' } },resetButtonRender: (_, dom) => null,// <Button key="submit" type="primary" onClick={() => { submit() }}>保存</Button>render: (props, defaultDoms) => {return [<Button key="clean" onClick={() => { setflag(false) }}>取消</Button>,<Button key="close" type="primary" onClick={() => { submit('pass') }}>下载</Button>,]}}} drawerProps={{closeIcon: null,destroyOnClose: true,extra: <CloseOutlined onClick={() => setflag(false)} />}}visible={flag}onVisibleChange={(e) => {setflag(e)}}width={440}onFinish={() => submit()}title={<span style={{color: '#1F1F1F',fontSize: '18px',fontWeight: 600,height: '22px',lineHeight: '22px'}}>{title}</span>}trigger={Component}><div style={{ ...style0 }}><div style={{ ...style1 }}>导出开始时间</div><DatePicker placeholder='请选择开始时间' style={{ ...style2 }} onChange={onChange} /></div><div style={{ ...style0, margin: '20px 0' }}><div style={{ ...style1, }}>导出结束结束</div><DatePicker placeholder='请选择结束时间' style={{ ...style2 }} onChange={onChange1} /></div></DrawerForm></>:<><ButtononClick={() => { submit('pass') }}type="primary">导出</Button></>}</>)
}
const style0 = {display: 'flex',justifyContent: 'space-between',alignItems: 'center',
}
const style1 = {width: '22%'
}
const style2 = {width: '76%'
}
const mapStateToProps = (state) => {return {};
};export default connect(mapStateToProps)(NewExp)
第二步:封装请求导出js-----utils
import { stringify } from 'qs';//引入qs库export async function download(url, params) {// /api/blade-cust/custhubAppointment/export-customerconst urls = `/api/${url}?${stringify(params)}`;const response = await fetch(urls, {method: 'GET',headers: {'Authorization': ``,'Blade-Auth': `Bearer ${getAccessToken()}` //请求token,'Content-Type': 'application/json' //JSON形式----有时候也是具体什么时候用看需求 //responseType:"blob",,}});if (!response.ok) {throw new Error(`HTTP error! status: ${response.status}`);}const blob = await response.blob();const contentDisposition = response.headers.get('content-disposition');const filename = contentDisposition ? contentDisposition.split('filename=')[1].replace(/"/g, '') : 'exported_data.csv';const urlBlob = window.URL.createObjectURL(blob);const a = document.createElement('a');if (a) {
//创建了一个a 直接下载 a.href = urlBlob;a.download = filename;document.body.appendChild(a);a.click();a.remove();window.URL.revokeObjectURL(urlBlob);return true //这边是给我返回成功的状态}}
第三步:导入封好的js---使用
import { download } from '@/utils/utils'const hang = () => {return 1}const changeHange = async (e) => {try {
//这个都是 参数---接口需要const startTime = e.d1;const endTime = e.d2;const type = userRole;const bigType = defaultvalue;const params1 = {startTime,endTime,type,bigType};let d = await download('blade-cust/custhubCustomer/export-customer', params1)if (d) {message.success('导出成功,请保存')hang()}} catch (error) {console.error('Export failed:', error);}}//导出显示组件<NewExps title={'导出'}hang={hang}Component={<Button type="primary">导出</Button>}changeHange={changeHange}></NewExps>
上方是不用打开新的页面---直接可以点击下载的
这个是打开新界面---代码奉献上---弹窗一个 直接会弹出对应的下载框
import { Upload, Switch, Button, Card, Col, Input, message, Modal, Row, Tree } from 'antd';Modal.confirm({title: '用户导出确认',content: '是否导出用户数据?',okText: '确定',okType: 'danger',cancelText: '取消',onOk() {const account = params.account || '';const realName = params.realName || '';window.open(`/api/blade-system/user/export-user?Blade-Auth=bearer ${getAccessToken()}&account=${account}&realName=${realName}`);},onCancel() {},});