新增:新增系统管理/部门管理/导出功能(引入 Easy Excel 依赖用于导出 Excel,详情可见 README 介绍。另请注意:测试导出功能时,前端需要关闭 mockjs,否则 responseType 会被 mockjs 设置为 '',导致导出的文件无法打开)

This commit is contained in:
2023-02-06 23:02:23 +08:00
parent 4bde837649
commit ceba8e9e53
30 changed files with 536 additions and 82 deletions

View File

@@ -1,9 +1,9 @@
import axios from 'axios';
import qs from 'query-string';
import { DeptParams } from '@/api/system/dept';
import { DeptParam } from '@/api/system/dept';
import { TreeNodeData } from '@arco-design/web-vue';
export default function listDeptTree(params: DeptParams) {
export default function listDeptTree(params: DeptParam) {
return axios.get<TreeNodeData[]>('/common/tree/dept', {
params,
paramsSerializer: (obj) => {

View File

@@ -17,12 +17,12 @@ export interface DeptRecord {
children?: Array<DeptRecord>,
}
export interface DeptParams {
export interface DeptParam {
deptName?: string;
status?: number;
}
export function listDept(params: DeptParams) {
export function listDept(params: DeptParam) {
return axios.get<DeptRecord[]>(`${BASE_URL}/all`, {
params,
paramsSerializer: (obj) => {
@@ -45,4 +45,14 @@ export function updateDept(req: DeptRecord) {
export function deleteDept(ids: number | Array<number>) {
return axios.delete(`${BASE_URL}/${ids}`);
}
export function exportDept(params: DeptParam) {
return axios.get(`${BASE_URL}/export`, {
params,
paramsSerializer: (obj) => {
return qs.stringify(obj);
},
responseType: 'blob',
});
}

View File

@@ -36,11 +36,17 @@ export interface HttpResponse<T = unknown> {
// response interceptors
axios.interceptors.response.use((response: AxiosResponse<HttpResponse>) => {
// 二进制数据则直接返回
if(response.request.responseType === 'blob' || response.request.responseType === 'arraybuffer'){
return response;
}
// 操作成功则直接返回
const res = response.data;
if (res.success) {
return res;
}
// 操作失败,弹出错误提示
Message.error({
content: res.msg,
duration: 3000

View File

@@ -51,12 +51,12 @@
<a-button type="primary" status="danger" :disabled="multiple" :title="multiple ? '请选择要删除的数据' : ''" @click="handleBatchDelete">
<template #icon><icon-delete /></template>删除
</a-button>
<a-button :loading="exportLoading" type="primary" status="warning" @click="handleExport">
<template #icon><icon-download /></template>导出
</a-button>
</a-space>
</a-col>
<a-col :span="12" style="display: flex; align-items: center; justify-content: end">
<a-button type="primary" status="warning" disabled title="尚未开放">
<template #icon><icon-download /></template>导出
</a-button>
</a-col>
</a-row>
</div>
@@ -239,12 +239,13 @@
import { SelectOptionData, TreeNodeData } from '@arco-design/web-vue';
import {
DeptRecord,
DeptParams,
DeptParam,
listDept,
getDept,
createDept,
updateDept,
deleteDept,
exportDept,
} from '@/api/system/dept';
import listDeptTree from '@/api/common';
@@ -267,6 +268,7 @@
const multiple = ref(true);
const loading = ref(false);
const detailLoading = ref(false);
const exportLoading = ref(false);
const visible = ref(false);
const detailVisible = ref(false);
const statusOptions = ref<SelectOptionData[]>([
@@ -296,7 +298,7 @@
*
* @param params 查询参数
*/
const getList = (params: DeptParams = { ...queryParams.value }) => {
const getList = (params: DeptParam = { ...queryParams.value }) => {
loading.value = true;
listDept(params).then((res) => {
deptList.value = res.data;
@@ -309,29 +311,6 @@
};
getList();
/**
* 确定
*/
const handleOk = () => {
proxy.$refs.formRef.validate((valid: any) => {
if (!valid) {
if (form.value.deptId !== undefined) {
updateDept(form.value).then((res) => {
handleCancel();
getList();
proxy.$message.success(res.msg);
});
} else {
createDept(form.value).then((res) => {
handleCancel();
getList();
proxy.$message.success(res.msg);
});
}
}
});
};
/**
* 打开新增对话框
*/
@@ -384,6 +363,29 @@
proxy.$refs.formRef.resetFields();
};
/**
* 确定
*/
const handleOk = () => {
proxy.$refs.formRef.validate((valid: any) => {
if (!valid) {
if (form.value.deptId !== undefined) {
updateDept(form.value).then((res) => {
handleCancel();
getList();
proxy.$message.success(res.msg);
});
} else {
createDept(form.value).then((res) => {
handleCancel();
getList();
proxy.$message.success(res.msg);
});
}
}
});
};
/**
* 查看详情
*
@@ -407,20 +409,6 @@
detailVisible.value = false;
};
/**
* 修改状态
*
* @param record 记录信息
*/
const handleChangeStatus = (record: DeptRecord) => {
const tip = record.status === 1 ? '启用' : '禁用';
updateDept(record).then((res) => {
proxy.$message.success(`${tip}成功`);
}).catch(() => {
record.status = (record.status === 1) ? 2 : 1;
});
};
/**
* 批量删除
*/
@@ -463,6 +451,52 @@
multiple.value = !rowKeys.length;
};
/**
* 导出
*/
const handleExport = () => {
if (exportLoading.value) return;
exportLoading.value = true;
exportDept({ ...queryParams.value }).then(async(res) => {
const blob = new Blob([res.data], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'});
const contentDisposition = res.headers['content-disposition']
const pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
const result = pattern.exec(contentDisposition) || '';
// 对名字进行解码
const fileName = window.decodeURI(result[1])
// 创建下载的链接
const downloadElement = document.createElement('a');
const href = window.URL.createObjectURL(blob);
downloadElement.style.display = 'none';
downloadElement.href = href;
// 下载后文件名
downloadElement.download = fileName;
document.body.appendChild(downloadElement);
// 点击下载
downloadElement.click();
// 下载完成,移除元素
document.body.removeChild(downloadElement);
// 释放掉 blob 对象
window.URL.revokeObjectURL(href);
}).finally(() => {
exportLoading.value = false;
});
};
/**
* 修改状态
*
* @param record 记录信息
*/
const handleChangeStatus = (record: DeptRecord) => {
const tip = record.status === 1 ? '启用' : '禁用';
updateDept(record).then((res) => {
proxy.$message.success(`${tip}成功`);
}).catch(() => {
record.status = (record.status === 1) ? 2 : 1;
});
};
/**
* 过滤部门树
*

View File

@@ -148,7 +148,7 @@
captchaLoading.value = false;
captchaDisable.value = true;
captchaBtnNameKey.value = `${t('userCenter.securitySettings.updateEmail.form.reSendCaptcha')}(${captchaTime.value -= 1}s)`;
captchaTimer.value = window.setInterval(function() {
captchaTimer.value = window.setInterval(() => {
captchaTime.value -= 1;
captchaBtnNameKey.value = `${t('userCenter.securitySettings.updateEmail.form.reSendCaptcha')}(${captchaTime.value}s)`;
if (captchaTime.value < 0) {