From 1e0dee0a6e1664b243ed6ebb941f48c8fdccd47d Mon Sep 17 00:00:00 2001 From: cshaptx4869 <994774638@qq.com> Date: Sat, 27 Apr 2024 20:22:23 +0800 Subject: [PATCH 1/2] =?UTF-8?q?refactor:=20:recycle:=20=E6=8A=BD=E7=A6=BBC?= =?UTF-8?q?URD=E7=9A=84=E4=BD=BF=E7=94=A8=E9=83=A8=E5=88=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E4=B8=BAHooks=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- mock/user.mock.ts | 12 +++++ src/components/PageContent/index.vue | 45 ++++++++++++++--- src/hooks/usePage.ts | 58 ++++++++++++++++++++++ src/views/demo/curd/config/content.ts | 5 ++ src/views/demo/curd/index.vue | 70 +++++++++++---------------- 5 files changed, 140 insertions(+), 50 deletions(-) create mode 100644 src/hooks/usePage.ts diff --git a/mock/user.mock.ts b/mock/user.mock.ts index fc84c2be..7c7b0608 100644 --- a/mock/user.mock.ts +++ b/mock/user.mock.ts @@ -144,6 +144,18 @@ export default defineMock([ }; }, }, + + // 导出Excel + { + url: "users/_export", + method: ["GET"], + headers: { + "Content-Disposition": + "attachment; filename=%E7%94%A8%E6%88%B7%E5%88%97%E8%A1%A8.xlsx", + "Content-Type": + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + }, + }, ]); // 用户映射表数据 diff --git a/src/components/PageContent/index.vue b/src/components/PageContent/index.vue index 663aa4e8..634b48e7 100644 --- a/src/components/PageContent/index.vue +++ b/src/components/PageContent/index.vue @@ -185,7 +185,7 @@ import Pagination from "@/components/Pagination/index.vue"; import type { TableProps } from "element-plus"; // 对象类型 -type IObject = Record; +export type IObject = Record; // 定义接收的属性 export interface IOperatData { name: string; @@ -201,7 +201,9 @@ export interface IContentConfig { // 列表的网络请求函数(需返回promise) indexAction: (data: IObject) => Promise; // 删除的网络请求函数(需返回promise) - deleteAction: (id: string) => Promise; + deleteAction?: (id: string) => Promise; + // 导出的网络请求函数(需返回promise) + exportAction?: (queryParams: IObject) => Promise; // 主键名(默认为id) pk?: string; // 表格工具栏(默认支持refresh,add,delete,export,也可自定义) @@ -232,7 +234,7 @@ const emit = defineEmits<{ operatClick: [data: IOperatData]; }>(); // 暴露的属性和方法 -defineExpose({ fetchPageData }); +defineExpose({ fetchPageData, exportPageData }); // 主键 const pk = props.contentConfig.pk ?? "id"; @@ -294,10 +296,14 @@ function handleDelete(id?: number | string) { cancelButtonText: "取消", type: "warning", }).then(function () { - props.contentConfig.deleteAction(ids).then(() => { - ElMessage.success("删除成功"); - handleRefresh(); - }); + if (props.contentConfig.deleteAction) { + props.contentConfig.deleteAction(ids).then(() => { + ElMessage.success("删除成功"); + handleRefresh(); + }); + } else { + ElMessage.error("未配置deleteAction"); + } }); } // 分页 @@ -338,6 +344,31 @@ function handleOperat(data: IOperatData) { break; } } +// 导出Excel +function exportPageData(queryParams: IObject = {}) { + if (props.contentConfig.exportAction) { + props.contentConfig.exportAction(queryParams).then((response) => { + const fileData = response.data; + const fileName = decodeURI( + response.headers["content-disposition"].split(";")[1].split("=")[1] + ); + const fileType = + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"; + + const blob = new Blob([fileData], { type: fileType }); + const downloadUrl = window.URL.createObjectURL(blob); + const downloadLink = document.createElement("a"); + downloadLink.href = downloadUrl; + downloadLink.download = fileName; + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + window.URL.revokeObjectURL(downloadUrl); + }); + } else { + ElMessage.error("未配置exportAction"); + } +} diff --git a/src/hooks/usePage.ts b/src/hooks/usePage.ts new file mode 100644 index 00000000..a20fc4c6 --- /dev/null +++ b/src/hooks/usePage.ts @@ -0,0 +1,58 @@ +import { ref } from "vue"; +import type PageSearch from "@/components/PageSearch/index.vue"; +import type PageContent from "@/components/PageContent/index.vue"; +import type PageModal from "@/components/PageModal/index.vue"; +import type { IOperatData, IObject } from "@/components/PageContent/index.vue"; +export type { IOperatData, IObject }; + +function usePage() { + const searchRef = ref>(); + const contentRef = ref>(); + const addModalRef = ref>(); + const editModalRef = ref>(); + + // 搜索 + function handleQueryClick(queryParams: IObject) { + contentRef.value?.fetchPageData(queryParams, true); + } + // 重置 + function handleResetClick() { + contentRef.value?.fetchPageData({}, true); + } + // 新增 + function handleAddClick() { + //显示添加表单 + addModalRef.value?.setModalVisible(); + } + // 编辑 + function handleEditClick(row: IObject) { + //显示编辑表单 根据数据进行填充 + editModalRef.value?.setModalVisible(row); + } + // 表单提交 + function handleSubmitClick() { + //刷新列表数据 + contentRef.value?.fetchPageData({}, true); + } + // 导出 + function handleExportClick() { + // 根据检索条件导出数据 + const queryParams = searchRef.value?.getQueryParams(); + contentRef.value?.exportPageData(queryParams); + } + + return { + searchRef, + contentRef, + addModalRef, + editModalRef, + handleQueryClick, + handleResetClick, + handleAddClick, + handleEditClick, + handleSubmitClick, + handleExportClick, + }; +} + +export default usePage; diff --git a/src/views/demo/curd/config/content.ts b/src/views/demo/curd/config/content.ts index 1ee989ab..a4470f91 100644 --- a/src/views/demo/curd/config/content.ts +++ b/src/views/demo/curd/config/content.ts @@ -1,4 +1,5 @@ import type { IContentConfig } from "@/components/PageContent/index.vue"; +import { exportUser } from "@/api/user"; const contentConfig: IContentConfig = { pageName: "sys:user", @@ -60,6 +61,10 @@ const contentConfig: IContentConfig = { }); }); }, + exportAction: function (queryParams) { + // 导出Excel文件 + return exportUser(queryParams as any); + }, pk: "id", toolbar: [ "refresh", diff --git a/src/views/demo/curd/index.vue b/src/views/demo/curd/index.vue index 6c7197a9..9709a2ed 100644 --- a/src/views/demo/curd/index.vue +++ b/src/views/demo/curd/index.vue @@ -19,9 +19,9 @@ @operat-click="handleOperatClick" > @@ -46,43 +46,25 @@ import searchConfig from "./config/search"; import contentConfig from "./config/content"; import addModalConfig from "./config/add"; import editModalConfig from "./config/edit"; -import type PageSearch from "@/components/PageSearch/index.vue"; -import type PageContent from "@/components/PageContent/index.vue"; -import type { IOperatData } from "@/components/PageContent/index.vue"; -import type PageModal from "@/components/PageModal/index.vue"; +import usePage from "@/hooks/usePage"; +import type { IOperatData, IObject } from "@/hooks/usePage"; -const searchRef = ref>(); -const contentRef = ref>(); -const addModalRef = ref>(); - -// 搜索 -function handleQueryClick(queryParams: any) { - contentRef.value?.fetchPageData(queryParams, true); -} -// 重置 -function handleResetClick() { - contentRef.value?.fetchPageData({}, true); -} -// 新增 -function handleAddClick() { - //显示添加表单 - addModalRef.value?.setModalVisible(); -} -// 导出 -function handleExportClick() { - console.log("export"); - // 可以根据检索条件去导出数据 - console.log(searchRef.value?.getQueryParams()); -} -// 其他工具栏 -function handleToolbarClick(name: string) { - console.log(name); -} +const { + searchRef, + contentRef, + addModalRef, + editModalRef, + handleQueryClick, + handleResetClick, + handleAddClick, + // handleEditClick, + handleSubmitClick, + handleExportClick, +} = usePage(); // 编辑 -const editModalRef = ref>(); -function handleEditClick(row: any) { - //显示编辑表单 根据id获取的数据进行填充 - const idMap: Record = { +function handleEditClick(row: IObject) { + // 模拟根据id获取数据进行填充 + const idMap: IObject = { 2: { id: 2, username: "admin", @@ -112,6 +94,13 @@ function handleEditClick(row: any) { }; editModalRef.value?.setModalVisible(idMap[row.id]); } +// 其他工具栏 +function handleToolbarClick(name: string) { + console.log(name); + if (name === "upload") { + ElMessage.success("点击了导入按钮"); + } +} // 其他操作列 function handleOperatClick(data: IOperatData) { console.log(data); @@ -134,9 +123,4 @@ function handleOperatClick(data: IOperatData) { }); } } -// 表单提交 -function handleSubmitClick() { - //刷新列表数据 - contentRef.value?.fetchPageData({}, true); -} From afea9a08b97a9b1bf44cb4e4e1feac67425b0521 Mon Sep 17 00:00:00 2001 From: cshaptx4869 <994774638@qq.com> Date: Sat, 27 Apr 2024 20:31:24 +0800 Subject: [PATCH 2/2] =?UTF-8?q?refactor:=20:recycle:=20=E4=BF=AE=E6=94=B9C?= =?UTF-8?q?URD=E5=AF=BC=E5=85=A5=E6=9D=83=E9=99=90=E7=82=B9=E6=A0=87?= =?UTF-8?q?=E8=AF=86=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/demo/curd/config/content.ts | 4 ++-- src/views/demo/curd/index.vue | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/views/demo/curd/config/content.ts b/src/views/demo/curd/config/content.ts index a4470f91..7cd9c6a0 100644 --- a/src/views/demo/curd/config/content.ts +++ b/src/views/demo/curd/config/content.ts @@ -72,10 +72,10 @@ const contentConfig: IContentConfig = { "delete", "export", { - name: "upload", + name: "import", icon: "upload", text: "导入", - auth: "upload", + auth: "import", }, ], cols: [ diff --git a/src/views/demo/curd/index.vue b/src/views/demo/curd/index.vue index 9709a2ed..595e5696 100644 --- a/src/views/demo/curd/index.vue +++ b/src/views/demo/curd/index.vue @@ -97,7 +97,7 @@ function handleEditClick(row: IObject) { // 其他工具栏 function handleToolbarClick(name: string) { console.log(name); - if (name === "upload") { + if (name === "import") { ElMessage.success("点击了导入按钮"); } }