feat: 🎉 导入导出

用户管理加入导入导出
This commit is contained in:
猿小天
2023-05-13 00:36:16 +08:00
parent ad59bc68aa
commit 2c22ecbac5
6 changed files with 210 additions and 8 deletions

View File

@@ -0,0 +1,146 @@
<template>
<div style="display: inline-block">
<el-button size="default" type="success" @click="handleImport()">
<slot>导入</slot>
</el-button>
<el-dialog :title="props.upload.title" v-model="uploadShow" width="400px" append-to-body>
<div v-loading="loading">
<el-upload
ref="uploadRef"
:limit="1"
accept=".xlsx, .xls"
:headers="props.upload.headers"
:action="props.upload.url"
:disabled="isUploading"
:on-progress="handleFileUploadProgress"
:on-success="handleFileSuccess"
:auto-upload="false"
drag
>
<i class="el-icon-upload"/>
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<template #tip>
<div class="el-upload__tip" style="color:red">提示仅允许导入xlsxlsx格式文件</div>
</template>
</el-upload>
<div>
<el-button type="warning" style="font-size:14px;margin-top: 20px" @click="importTemplate">下载导入模板</el-button>
<el-button type="warning" style="font-size:14px;margin-top: 20px" @click="updateTemplate">批量更新模板</el-button>
</div>
</div>
<template #footer>
<div class="dialog-footer">
<el-button type="primary" :disabled="loading" @click="submitFileForm"> </el-button>
<el-button :disabled="loading" @click="uploadShow = false"> </el-button>
</div>
</template>
</el-dialog>
</div>
</template>
<script lang="ts" setup name="importExcel">
import { request, downloadFile } from '/@/utils/service';
import {inject,ref} from "vue";
import { getBaseURL } from '/@/utils/baseUrl';
import { Session } from '/@/utils/storage';
import { ElMessageBox } from 'element-plus'
import type { Action } from 'element-plus'
const refreshView = inject('refreshView')
let props = defineProps({
upload: {
type: Object,
default () {
return {
// 是否显示弹出层
open: true,
// 弹出层标题
title: '',
// 是否禁用上传
isUploading: false,
// 是否更新已经存在的用户数据
updateSupport: 0,
// 设置上传的请求头部
headers: { Authorization: 'JWT ' + Session.get('token') },
// 上传的地址
url: getBaseURL() + 'api/system/file/'
}
}
},
api: { // 导入接口地址
type: String,
default () {
return undefined
}
}
})
let loading = ref(false)
const uploadRef = ref()
const uploadShow = ref(false)
const isUploading = ref(false)
/** 导入按钮操作 */
const handleImport = function () {
uploadShow.value = true
}
/** 下载模板操作 */
const importTemplate=function () {
downloadFile({
url: props.api + 'import_data/',
params: {},
method: 'get'
})
}
/***
* 批量更新模板
*/
const updateTemplate=function () {
downloadFile({
url: props.api + 'update_template/',
params: {},
method: 'get'
})
}
// 文件上传中处理
const handleFileUploadProgress=function (event:any, file:any, fileList:any) {
isUploading.value = true
}
// 文件上传成功处理
const handleFileSuccess=function (response:any, file:any, fileList:any) {
isUploading.value = false
loading.value = true
uploadRef.value.clearFiles()
// 是否更新已经存在的用户数据
return request({
url: props.api + 'import_data/',
method: 'post',
data: {
url: response.data.url
}
}).then((response:any) => {
loading.value = false
ElMessageBox.alert('导入成功', '导入完成', {
confirmButtonText: 'OK',
callback: (action: Action) => {
refreshView()
},
})
}).catch(()=>{
loading.value = false
})
}
// 提交上传文件
const submitFileForm=function () {
uploadRef.value.submit()
}
</script>
<style scoped>
</style>

View File

@@ -90,6 +90,9 @@ function createService() {
return dataAxios;
}
return dataAxios;
case 4000:
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
return Promise.reject(dataAxios.msg);
default:
// 不是正确的 code
errorCreate(`${dataAxios.msg}: ${response.config.url}`);
@@ -187,3 +190,34 @@ export const request = createRequestFunction(service);
// 用于模拟网络请求的实例和请求方法
export const serviceForMock = createService();
export const requestForMock = createRequestFunction(serviceForMock);
/**
* 下载文件
* @param url
* @param params
* @param method
* @param filename
*/
export const downloadFile = function ({url,params,method,filename = '文件导出'}:any) {
request({
url: url,
method: method,
params: params,
responseType: 'blob'
// headers: {Accept: 'application/vnd.openxmlformats-officedocument'}
}).then((res:any) => {
const xlsxName = window.decodeURI(res.headers['content-disposition'].split('=')[1])
const fileName = xlsxName || `${filename}.xlsx`
if (res) {
const blob = new Blob([res.data], { type: 'charset=utf-8' })
const elink = document.createElement('a')
elink.download = fileName
elink.style.display = 'none'
elink.href = URL.createObjectURL(blob)
document.body.appendChild(elink)
elink.click()
URL.revokeObjectURL(elink.href) // 释放URL 对象0
document.body.removeChild(elink)
}
})
}

View File

@@ -1,4 +1,4 @@
import { request } from '/@/utils/service';
import { request,downloadFile } from '/@/utils/service';
import { PageQuery, AddReq, DelReq, EditReq, InfoReq } from '@fast-crud/fast-crud';
export const apiPrefix = '/api/system/user/';
@@ -48,3 +48,11 @@ export function DelObj(id: DelReq) {
data: { id },
});
}
export function exportData(params:any){
return downloadFile({
url: apiPrefix + 'export_data/',
params: params,
method: 'get'
})
}

View File

@@ -20,6 +20,10 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
return await api.AddObj(form);
};
const exportRequest = async (query: UserPageQuery) => {
return await api.exportData(query)
}
//权限判定
const hasPermissions:any = inject('$hasPermissions');
@@ -41,6 +45,13 @@ export const createCrudOptions = function ({ crudExpose }: CreateCrudOptionsProp
add: {
show: hasPermissions('user:Create')
// show:true
},
export:{
text:"导出",//按钮文字
title:"导出",//鼠标停留显示的信息
click(){
return exportRequest(crudExpose.getSearchFormData())
}
}
}
},

View File

@@ -30,10 +30,15 @@
</el-col>
<el-col xs="24" :sm="16" :md="18" :lg="20" :xl="20" class="p-1">
<el-card :body-style="{ height: '100%' }">
<fs-crud ref="crudRef" v-bind="crudBinding"></fs-crud>
<fs-crud ref="crudRef" v-bind="crudBinding">
<template #actionbar-right>
<importExcel api="api/system/user/" >导入 </importExcel>
</template>
</fs-crud>
</el-card>
</el-col>
</el-row>
</fs-page>
</template>
@@ -42,11 +47,9 @@ import { useExpose, useCrud } from '@fast-crud/fast-crud';
import { createCrudOptions } from './crud';
import * as api from './api';
import { ElTree } from 'element-plus';
import { ref, onMounted, watch, toRaw, defineAsyncComponent } from 'vue';
import { ref, onMounted, watch, toRaw } from 'vue';
import XEUtils from 'xe-utils';
import { errorMessage, successMessage } from '../../../utils/message';
import { GetDept } from './api';
import { dictionary } from '/@/utils/dictionary';
import importExcel from '/@/components/importExcel/index.vue'
interface Tree {
id: number;