这边记录我们公司后端做的导出接口和前端是如何对接的
这边的技术栈是:
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 ?
<>
<DrawerForm
className={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>
</>
:
<>
<Button
onClick={() => { 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-customer
const 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() {},
});