mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 10:57:13 +08:00 
			
		
		
		
	新增:新增系统管理/部门管理/导出功能(引入 Easy Excel 依赖用于导出 Excel,详情可见 README 介绍。另请注意:测试导出功能时,前端需要关闭 mockjs,否则 responseType 会被 mockjs 设置为 '',导致导出的文件无法打开)
This commit is contained in:
		| @@ -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) => { | ||||
|   | ||||
| @@ -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', | ||||
|   }); | ||||
| } | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   /** | ||||
|    * 过滤部门树 | ||||
|    * | ||||
|   | ||||
| @@ -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) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user