From ce748496c6dee9305e9344cd6d5d6e036f813a0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B6=85=E5=87=A1?= <2508779859@qq.com> Date: Sun, 20 Apr 2025 23:24:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20:recycle:=20pageModal=E7=BB=84?= =?UTF-8?q?=E4=BB=B6=EF=BC=8C=E4=BB=A3=E7=A0=81=E9=87=8D=E6=9E=84=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E4=BD=BF=E7=94=A8=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/CURD/PageContent.vue | 67 +--- src/components/CURD/PageModal.vue | 479 ++++++++++--------------- src/components/CURD/types.ts | 26 +- src/components/CURD/usePage.ts | 16 +- src/views/demo/curd/config/content.ts | 4 +- src/views/demo/curd/config/content2.ts | 15 +- src/views/demo/curd/config/edit.ts | 17 +- src/views/demo/curd/config/edit2.ts | 105 ++++++ src/views/demo/curd/index.vue | 106 +++--- 9 files changed, 407 insertions(+), 428 deletions(-) create mode 100644 src/views/demo/curd/config/edit2.ts diff --git a/src/components/CURD/PageContent.vue b/src/components/CURD/PageContent.vue index 526342c3..fd461292 100644 --- a/src/components/CURD/PageContent.vue +++ b/src/components/CURD/PageContent.vue @@ -160,7 +160,7 @@ v-hasPerm="btn.perm ?? '*:*:*'" v-bind="btn.attrs" @click=" - handleOperat({ + handleOperate({ name: btn.name, row: scope.row, column: scope.column, @@ -331,7 +331,7 @@ import { } from "element-plus"; import ExcelJS from "exceljs"; import { reactive, ref, computed } from "vue"; -import type { IContentConfig, IObject, IOperatData } from "./types"; +import type { IContentConfig, IObject, IOperateData } from "./types"; import type { IToolsButton } from "./types"; // 定义接收的属性 @@ -343,55 +343,10 @@ const emit = defineEmits<{ searchClick: []; toolbarClick: [name: string]; editClick: [row: IObject]; - operatClick: [data: IOperatData]; filterChange: [data: IObject]; + operateClick: [data: IOperateData]; }>(); -// 按钮文本映射 -const BUTTONS_TEXT: Record = { - add: "新增", - delete: "删除", - import: "导入", - export: "导出", - refresh: "刷新", - filter: "筛选列", - search: "搜索", - imports: "批量导入", - exports: "批量导出", - view: "查看", - edit: "编辑", -}; - -// 按钮权限映射 -const AUTH_MAP: Record = { - add: "add", - delete: "delete", - import: "import", - export: "export", - refresh: "*:*:*", - filter: "*:*:*", - search: "search", - imports: "imports", - exports: "exports", - view: "view", - edit: "edit", -}; - -// 按钮图标映射 -const BUTTONS_ICON: Record = { - add: "plus", - delete: "delete", - import: "upload", - export: "download", - refresh: "refresh", - filter: "operation", - search: "search", - imports: "upload", - exports: "download", - view: "view", - edit: "edit", -}; - // 表格工具栏按钮配置 const config = computed(() => props.contentConfig); const buttonConfig = reactive>({ @@ -821,18 +776,8 @@ function handleToolbar(name: string) { } // 操作列 -function handleOperat(data: IOperatData) { - switch (data.name) { - case "edit": - emit("editClick", data.row); - break; - case "delete": - handleDelete(data.row[pk]); - break; - default: - emit("operatClick", data); - break; - } +function handleOperate(data: IOperateData) { + emit("operateClick", data); } // 属性修改 @@ -953,7 +898,7 @@ function saveXlsx(fileData: any, fileName: string) { } // 暴露的属性和方法 -defineExpose({ fetchPageData, exportPageData, getFilterParams, getSelectionData }); +defineExpose({ fetchPageData, exportPageData, getFilterParams, getSelectionData, handleRefresh }); + diff --git a/src/components/CURD/types.ts b/src/components/CURD/types.ts index 5db9295d..a9da104a 100644 --- a/src/components/CURD/types.ts +++ b/src/components/CURD/types.ts @@ -15,7 +15,7 @@ export type IObject = Record; type DataComponent = "date-picker" | "time-picker" | "time-select" | "custom-tag" | "input-tag"; type InputComponent = "input" | "select" | "input-number" | "cascader" | "tree-select"; -type OtherComponent = "text" | "radio" | "checkbox" | "switch" | "custom"; +type OtherComponent = "text" | "radio" | "checkbox" | "switch" | "icon-select" | "custom"; export type ISearchComponent = DataComponent | InputComponent; export type IComponentType = DataComponent | InputComponent | OtherComponent; @@ -26,14 +26,12 @@ export type IToolsButton = { name: string; // 按钮名称 text?: string; // 按钮文本 perm?: Array | string; // 权限标识(可以是完整权限字符串如'sys:user:add'或操作权限如'add') - icon?: string; // 按钮图标 - type?: string; // 按钮类型 attrs?: Partial & { style?: CSSProperties }; // 按钮属性 render?: (row: IObject) => boolean; // 条件渲染 }; export type IToolsDefault = ToolbarLeft | ToolbarRight | ToolbarTable | IToolsButton; -export interface IOperatData { +export interface IOperateData { name: string; row: IObject; column: IObject; @@ -184,9 +182,11 @@ export interface IContentConfig { export interface IModalConfig { // 权限前缀(如sys:user,用于组成权限标识),不提供则不进行权限校验 permPrefix?: string; + // 标签冒号(默认:false) + colon?: boolean; // 主键名(主要用于编辑数据,默认为id) pk?: string; - // 组件类型 + // 组件类型(默认:dialog) component?: "dialog" | "drawer"; // dialog组件属性 dialog?: Partial>; @@ -195,7 +195,7 @@ export interface IModalConfig { // form组件属性 form?: IForm; // 表单项 - formItems: IFormItems; + formItems: IFormItems; // 提交之前处理 beforeSubmit?: (data: T) => void; // 提交的网络请求函数(需返回promise) @@ -205,9 +205,9 @@ export interface IModalConfig { export type IForm = Partial>; // 表单项 -export type IFormItems = Array<{ +export type IFormItems = Array<{ // 组件类型(如input,select,radio,custom等,默认input) - type?: IComponentType; + type: IComponentType; // 组件属性 attrs?: IObject; // 组件可选项(适用于select,radio,checkbox组件) @@ -222,7 +222,7 @@ export type IFormItems = Array<{ // 标签文本 label: string; // 标签提示 - tips?: string; + tips?: string | IObject; // 键名 prop: string; // 验证规则 @@ -233,12 +233,8 @@ export type IFormItems = Array<{ hidden?: boolean; // layout组件Col属性 col?: Partial; - // 监听函数 - watch?: (newValue: any, oldValue: any, data: T, items: IObject[]) => void; - // 计算属性函数 - computed?: (data: T) => any; - // 监听收集函数 - watchEffect?: (data: T) => void; + // 组件事件 + events?: Record void>; // 初始化数据函数扩展 initFn?: (item: IObject) => void; }>; diff --git a/src/components/CURD/usePage.ts b/src/components/CURD/usePage.ts index d0fa0090..b5f6c557 100644 --- a/src/components/CURD/usePage.ts +++ b/src/components/CURD/usePage.ts @@ -23,9 +23,18 @@ function usePage() { addModalRef.value?.setModalVisible(); } // 编辑 - function handleEditClick(row: IObject) { - //显示编辑表单 根据数据进行填充 - editModalRef.value?.setModalVisible(row); + async function handleEditClick(row: IObject, callback?: (result?: IObject) => IObject) { + editModalRef.value?.setModalVisible(); + editModalRef.value?.handleDisabled(false); + let from = await (callback?.(row) ?? Promise.resolve(row)); + editModalRef.value?.setFormData(from ? from : row); + } + // 编辑 + async function handleViewClick(row: IObject, callback?: (result?: IObject) => IObject) { + editModalRef.value?.setModalVisible(); + editModalRef.value?.handleDisabled(true); + let from = await (callback?.(row) ?? Promise.resolve(row)); + editModalRef.value?.setFormData(from ? from : row); } // 表单提交 function handleSubmitClick() { @@ -58,6 +67,7 @@ function usePage() { handleResetClick, handleAddClick, handleEditClick, + handleViewClick, handleSubmitClick, handleExportClick, handleSearchClick, diff --git a/src/views/demo/curd/config/content.ts b/src/views/demo/curd/config/content.ts index 680a38bb..020b1fd1 100644 --- a/src/views/demo/curd/config/content.ts +++ b/src/views/demo/curd/config/content.ts @@ -112,12 +112,12 @@ const contentConfig: IContentConfig = { { name: "detail", text: "详情", - attrs: { icon: "Document" }, + attrs: { icon: "Document", type: "primary" }, }, { name: "reset_pwd", text: "重置密码", - perm: "password:reset", + // perm: "password-reset", attrs: { icon: "refresh-left", // color: "#626AEF", // 使用 text 属性,颜色不生效 diff --git a/src/views/demo/curd/config/content2.ts b/src/views/demo/curd/config/content2.ts index ad1b5478..11a82169 100644 --- a/src/views/demo/curd/config/content2.ts +++ b/src/views/demo/curd/config/content2.ts @@ -5,6 +5,7 @@ const contentConfig: IContentConfig = { table: { showOverflowTooltip: true, }, + pagePosition: "right", toolbar: [], indexAction: function (params) { // 模拟发起网络请求获取列表数据 @@ -14,7 +15,7 @@ const contentConfig: IContentConfig = { list: [ { id: 1, - username: "tom", + username: "root", avatar: "https://foruda.gitee.com/images/1723603502796844527/03cdca2a_716974.gif", percent: 99, price: 10, @@ -115,14 +116,16 @@ const contentConfig: IContentConfig = { width: 220, templet: "tool", operat: [ + "view", + "edit", { - name: "reset_pwd", - text: "重置密码", - perm: "password:reset", - attrs: { icon: "refresh-left", type: "primary" }, + name: "delete", + text: "展示删除", + perm: "delete", + attrs: { icon: "delete", type: "danger" }, render(row) { // 根据条件,显示或隐藏 - return row.id === 1; + return row.id !== 1; }, }, ], diff --git a/src/views/demo/curd/config/edit.ts b/src/views/demo/curd/config/edit.ts index 358f940b..1581d6a0 100644 --- a/src/views/demo/curd/config/edit.ts +++ b/src/views/demo/curd/config/edit.ts @@ -2,6 +2,8 @@ import UserAPI, { type UserForm } from "@/api/system/user.api"; import type { IModalConfig } from "@/components/CURD/types"; import { DeviceEnum } from "@/enums/settings/device.enum"; import { useAppStore } from "@/store"; +import DeptAPI from "@/api/system/dept.api"; +import RoleAPI from "@/api/system/role.api"; const modalConfig: IModalConfig = { permPrefix: "sys:user", @@ -11,12 +13,12 @@ const modalConfig: IModalConfig = { size: useAppStore().device === DeviceEnum.MOBILE ? "80%" : 500, }, pk: "id", + beforeSubmit(data) { + console.log("beforeSubmit", data); + }, formAction: function (data) { return UserAPI.update(data.id as string, data); }, - beforeSubmit(data) { - console.log("提交之前处理", data); - }, formItems: [ { label: "用户名", @@ -49,12 +51,17 @@ const modalConfig: IModalConfig = { "check-strictly": true, "render-after-expand": false, }, + async initFn(formItem) { + // 注意:如果initFn函数不是箭头函数,this会指向此配置项对象,那么也就可以用this来替代形参formItem + formItem.attrs.data = await DeptAPI.getOptions(); + }, }, { type: "custom", label: "性别", prop: "gender", initialValue: 1, + attrs: { style: { width: "100%" } }, }, { label: "角色", @@ -67,6 +74,9 @@ const modalConfig: IModalConfig = { }, options: [], initialValue: [], + async initFn(formItem) { + formItem.options = await RoleAPI.getOptions(); + }, }, { type: "input", @@ -105,6 +115,7 @@ const modalConfig: IModalConfig = { prop: "status", type: "switch", attrs: { + inlinePrompt: true, activeText: "正常", inactiveText: "禁用", activeValue: 1, diff --git a/src/views/demo/curd/config/edit2.ts b/src/views/demo/curd/config/edit2.ts new file mode 100644 index 00000000..d69ee6f2 --- /dev/null +++ b/src/views/demo/curd/config/edit2.ts @@ -0,0 +1,105 @@ +import type { IModalConfig } from "@/components/CURD/types"; +import { DeviceEnum } from "@/enums/settings/device.enum"; +import { useAppStore } from "@/store"; + +const modalConfig: IModalConfig = { + permPrefix: "sys:user", + component: "drawer", + colon: true, + pk: "id", + drawer: { + title: "修改用户", + size: useAppStore().device === DeviceEnum.MOBILE ? "80%" : 500, + }, + form: { labelPosition: "right", labelWidth: "auto" }, + beforeSubmit(data) { + console.log("beforeSubmit", data); + }, + formAction: function (data) { + // return UserAPI.update(data.id as string, data); + // 模拟发起网络请求修改字段 + ElMessage.success(JSON.stringify(data)); + return Promise.resolve(null); + }, + formItems: [ + { + tips: { effect: "light", placement: "top", content: "自定义文字提示" }, + type: "input", + label: "文本", + prop: "username", + attrs: { placeholder: "请输入", clearable: true }, + }, + { + type: "input-number", + label: "百分比", + prop: "percent", + attrs: { placeholder: "请输入", controls: false }, + slotName: "suffix", + }, + { + type: "input-number", + label: "货币符", + prop: "price", + attrs: { placeholder: "请输入", controls: false }, + slotName: "prefix", + }, + { + type: "input", + label: "链接", + prop: "url", + attrs: { placeholder: "请输入", clearable: true }, + }, + { + type: "icon-select", + label: "链接", + prop: "icon", + }, + { + type: "custom", + label: "列表值", + prop: "gender", + slotName: "gender", + attrs: { style: { width: "100%" } }, + }, + { + type: "select", + label: "自定义", + prop: "status", + attrs: { placeholder: "全部", clearable: true }, + options: [ + { label: "启用", value: 1 }, + { label: "禁用", value: 0 }, + ], + }, + { + type: "switch", + label: "Switch", + prop: "status2", + attrs: { + inlinePrompt: true, + activeValue: 1, + inactiveValue: 0, + activeText: "启用", + inactiveText: "禁用", + }, + }, + { + type: "input-number", + label: "输入框", + prop: "sort", + attrs: { placeholder: "请输入", controls: false }, + }, + { + type: "date-picker", + label: "日期格式化", + prop: "createTime", + attrs: { + type: "datetime", + format: "YYYY/MM/DD hh:mm:ss", + "value-format": "x", + }, + }, + ], +}; + +export default reactive(modalConfig); diff --git a/src/views/demo/curd/index.vue b/src/views/demo/curd/index.vue index 40eef43f..0ceeb080 100644 --- a/src/views/demo/curd/index.vue +++ b/src/views/demo/curd/index.vue @@ -26,11 +26,10 @@ ref="contentRef" :content-config="contentConfig" @add-click="handleAddClick" - @edit-click="handleEditClick" @export-click="handleExportClick" @search-click="handleSearchClick" @toolbar-click="handleToolbarClick" - @operat-click="handleOperatClick" + @operate-click="handleOperateClick" @filter-change="handleFilterChange" >