mirror of
https://github.com/continew-org/continew-admin-ui.git
synced 2025-09-09 20:57:17 +08:00
refactor: 优化导出下载功能
This commit is contained in:
@@ -12,3 +12,11 @@ export function listLog(query: System.LogQuery) {
|
|||||||
export function getLog(id: string) {
|
export function getLog(id: string) {
|
||||||
return http.get<System.LogDetailResp>(`${BASE_URL}/${id}`)
|
return http.get<System.LogDetailResp>(`${BASE_URL}/${id}`)
|
||||||
}
|
}
|
||||||
|
/** @desc 导出日志列表 */
|
||||||
|
export function exportLog(query: System.LogQuery) {
|
||||||
|
return http.download<any>(`${BASE_URL}/export/login`, query)
|
||||||
|
}
|
||||||
|
/**@desc 导出操作日志 */
|
||||||
|
export function exportOperateLog(query: System.LogQuery) {
|
||||||
|
return http.download<any>(`${BASE_URL}/export/operation`, query)
|
||||||
|
}
|
@@ -7,3 +7,4 @@ export * from './modules/useForm'
|
|||||||
export * from './modules/useDevice'
|
export * from './modules/useDevice'
|
||||||
export * from './modules/useBreakpoint'
|
export * from './modules/useBreakpoint'
|
||||||
export * from './modules/useBreakpointIndex'
|
export * from './modules/useBreakpointIndex'
|
||||||
|
export * from './modules/useDownload'
|
||||||
|
55
src/hooks/modules/useDownload.ts
Normal file
55
src/hooks/modules/useDownload.ts
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import { Message, Notification } from '@arco-design/web-vue'
|
||||||
|
/**
|
||||||
|
* @description 接收数据流生成 blob,创建链接,下载文件
|
||||||
|
* @param {Function} api 导出表格的api方法 (必传)
|
||||||
|
* @param {String} tempName 导出的文件名 (必传)
|
||||||
|
* @param {Object} params 导出的参数 (默认{})
|
||||||
|
* @param {Boolean} isNotify 是否有导出消息提示 (默认为 true)
|
||||||
|
* @param {String} fileType 导出的文件格式 (默认为.xlsx)
|
||||||
|
* */
|
||||||
|
interface NavigatorWithMsSaveOrOpenBlob extends Navigator {
|
||||||
|
msSaveOrOpenBlob(blob: Blob, fileName: string): void
|
||||||
|
}
|
||||||
|
export const useDownload = async (
|
||||||
|
api: (param: any) => Promise<any>,
|
||||||
|
tempName: string = '',
|
||||||
|
params: any = {},
|
||||||
|
isNotify = true,
|
||||||
|
fileType = '.xlsx'
|
||||||
|
) => {
|
||||||
|
try {
|
||||||
|
const res = await api(params)
|
||||||
|
if (res.headers['content-disposition']) {
|
||||||
|
tempName = decodeURI(res.headers['content-disposition'].split(';')[1].split('=')[1]);
|
||||||
|
} else {
|
||||||
|
tempName = tempName ? tempName : new Date().getTime() + fileType
|
||||||
|
}
|
||||||
|
if (isNotify && !res?.code) {
|
||||||
|
Notification.warning({
|
||||||
|
title: '温馨提示',
|
||||||
|
content: '如果数据庞大会导致下载缓慢哦,请您耐心等待!'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (res.status !== 200 || res.data === null || !(res.data instanceof Blob)) {
|
||||||
|
Message.error('导出失败,请稍后再试!')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const blob = new Blob([res.data])
|
||||||
|
// 兼容 edge 不支持 createObjectURL 方法
|
||||||
|
if ('msSaveOrOpenBlob' in (navigator as unknown as NavigatorWithMsSaveOrOpenBlob)) {
|
||||||
|
; (window.navigator as unknown as NavigatorWithMsSaveOrOpenBlob).msSaveOrOpenBlob(blob, tempName + fileType)
|
||||||
|
}
|
||||||
|
const blobUrl = window.URL.createObjectURL(blob)
|
||||||
|
const exportFile = document.createElement('a')
|
||||||
|
exportFile.style.display = 'none'
|
||||||
|
exportFile.download = tempName
|
||||||
|
exportFile.href = blobUrl
|
||||||
|
document.body.appendChild(exportFile)
|
||||||
|
exportFile.click()
|
||||||
|
// 去除下载对 url 的影响
|
||||||
|
document.body.removeChild(exportFile)
|
||||||
|
window.URL.revokeObjectURL(blobUrl)
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
}
|
@@ -61,7 +61,9 @@ http.interceptors.response.use(
|
|||||||
(response: AxiosResponse) => {
|
(response: AxiosResponse) => {
|
||||||
const { data } = response
|
const { data } = response
|
||||||
const { success, code, msg } = data
|
const { success, code, msg } = data
|
||||||
|
if(response.request.responseType==='blob'){
|
||||||
|
return response
|
||||||
|
}
|
||||||
// 成功
|
// 成功
|
||||||
if (success) {
|
if (success) {
|
||||||
NProgress.done()
|
NProgress.done()
|
||||||
@@ -122,6 +124,7 @@ const requestNative = <T = unknown>(config: AxiosRequestConfig): Promise<AxiosRe
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
http
|
http
|
||||||
.request<T>(config)
|
.request<T>(config)
|
||||||
|
.then((res: AxiosResponse) => resolve(res))
|
||||||
.catch((err: { msg: string }) => reject(err))
|
.catch((err: { msg: string }) => reject(err))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -173,5 +176,13 @@ const del = <T = any>(url: string, params?: object, config?: AxiosRequestConfig)
|
|||||||
...config
|
...config
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
const download = <T = any>(url: string, params?: object, config?: AxiosRequestConfig): Promise<AxiosResponse> => {
|
||||||
export default { get, post, put, patch, del, request, requestNative }
|
return requestNative({
|
||||||
|
method: 'get',
|
||||||
|
url,
|
||||||
|
responseType: 'blob',
|
||||||
|
params,
|
||||||
|
...config
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export default { get, post, put, patch, del, request, requestNative,download }
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #custom-right>
|
<template #custom-right>
|
||||||
<a-tooltip content="导出">
|
<a-tooltip content="导出">
|
||||||
<a-button>
|
<a-button @click="onExportFile">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-download />
|
<icon-download />
|
||||||
</template>
|
</template>
|
||||||
@@ -45,13 +45,12 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { listLog } from '@/apis'
|
import { listLog,exportLog } from '@/apis'
|
||||||
import type { TableInstance } from '@arco-design/web-vue'
|
import type { TableInstance } from '@arco-design/web-vue'
|
||||||
import DateRangePicker from '@/components/DateRangePicker/index.vue'
|
import DateRangePicker from '@/components/DateRangePicker/index.vue'
|
||||||
import { useTable } from '@/hooks'
|
import { useTable } from '@/hooks'
|
||||||
|
import {useDownload} from '@/hooks'
|
||||||
defineOptions({ name: 'LoginLog' })
|
defineOptions({ name: 'LoginLog' })
|
||||||
|
|
||||||
const filterChange = (values,record)=>{
|
const filterChange = (values,record)=>{
|
||||||
try {
|
try {
|
||||||
const slotName = columns[values.split('_').pop()].slotName as string
|
const slotName = columns[values.split('_').pop()].slotName as string
|
||||||
@@ -96,7 +95,10 @@ const columns: TableInstance['columns'] = [
|
|||||||
{ title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
|
{ title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
|
||||||
{ title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
|
{ title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
|
||||||
]
|
]
|
||||||
|
//导出登录日志
|
||||||
|
const onExportFile = ()=>{
|
||||||
|
useDownload(exportLog,'',queryForm)
|
||||||
|
}
|
||||||
const queryForm = reactive({
|
const queryForm = reactive({
|
||||||
module: '登录',
|
module: '登录',
|
||||||
ip: undefined,
|
ip: undefined,
|
||||||
|
@@ -22,7 +22,7 @@
|
|||||||
<a-button @click="reset">重置</a-button>
|
<a-button @click="reset">重置</a-button>
|
||||||
</template>
|
</template>
|
||||||
<template #custom-right>
|
<template #custom-right>
|
||||||
<a-tooltip content="导出">
|
<a-tooltip content="导出" @click="onExportFile">
|
||||||
<a-button>
|
<a-button>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<icon-download />
|
<icon-download />
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { listLog, type LogResp } from '@/apis'
|
import { listLog, type LogResp,exportOperateLog } from '@/apis'
|
||||||
import type { TableInstance } from '@arco-design/web-vue'
|
import type { TableInstance } from '@arco-design/web-vue'
|
||||||
import DateRangePicker from '@/components/DateRangePicker/index.vue'
|
import DateRangePicker from '@/components/DateRangePicker/index.vue'
|
||||||
import OperationLogDetailDrawer from './OperationLogDetailDrawer.vue'
|
import OperationLogDetailDrawer from './OperationLogDetailDrawer.vue'
|
||||||
import { useTable } from '@/hooks'
|
import { useDownload, useTable } from '@/hooks'
|
||||||
|
|
||||||
defineOptions({ name: 'OperationLog' })
|
defineOptions({ name: 'OperationLog' })
|
||||||
const filterChange = (values,record)=>{
|
const filterChange = (values,record)=>{
|
||||||
@@ -109,7 +109,10 @@ const columns: TableInstance['columns'] = [
|
|||||||
{ title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
|
{ title: '浏览器', dataIndex: 'browser', ellipsis: true, tooltip: true },
|
||||||
{ title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
|
{ title: '终端系统', dataIndex: 'os', ellipsis: true, tooltip: true }
|
||||||
]
|
]
|
||||||
|
//导出操作日志
|
||||||
|
const onExportFile = ()=>{
|
||||||
|
useDownload(exportOperateLog,'',queryForm)
|
||||||
|
}
|
||||||
const queryForm = reactive({
|
const queryForm = reactive({
|
||||||
description: undefined,
|
description: undefined,
|
||||||
ip: undefined,
|
ip: undefined,
|
||||||
|
Reference in New Issue
Block a user