feat: ✨ pageModal组件,添加二级弹窗与使用案例
This commit is contained in:
@@ -503,19 +503,24 @@ function handleDelete(id?: number | string) {
|
|||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
type: "warning",
|
type: "warning",
|
||||||
}).then(function () {
|
})
|
||||||
|
.then(function () {
|
||||||
if (props.contentConfig.deleteAction) {
|
if (props.contentConfig.deleteAction) {
|
||||||
props.contentConfig.deleteAction(ids).then(() => {
|
props.contentConfig
|
||||||
|
.deleteAction(ids)
|
||||||
|
.then(() => {
|
||||||
ElMessage.success("删除成功");
|
ElMessage.success("删除成功");
|
||||||
removeIds.value = [];
|
removeIds.value = [];
|
||||||
//清空选中项
|
//清空选中项
|
||||||
tableRef.value?.clearSelection();
|
tableRef.value?.clearSelection();
|
||||||
handleRefresh(true);
|
handleRefresh(true);
|
||||||
});
|
})
|
||||||
|
.catch(() => {});
|
||||||
} else {
|
} else {
|
||||||
ElMessage.error("未配置deleteAction");
|
ElMessage.error("未配置deleteAction");
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 导出表单
|
// 导出表单
|
||||||
@@ -777,7 +782,14 @@ function handleToolbar(name: string) {
|
|||||||
|
|
||||||
// 操作列
|
// 操作列
|
||||||
function handleOperate(data: IOperateData) {
|
function handleOperate(data: IOperateData) {
|
||||||
|
switch (data.name) {
|
||||||
|
case "delete":
|
||||||
|
props.contentConfig?.deleteAction && handleDelete(data.row[pk]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
emit("operateClick", data);
|
emit("operateClick", data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 属性修改
|
// 属性修改
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
<!-- drawer -->
|
<!-- drawer -->
|
||||||
<template v-if="modalConfig.component === 'drawer'">
|
<template v-if="modalConfig.component === 'drawer'">
|
||||||
<el-drawer
|
<el-drawer
|
||||||
@@ -30,7 +31,6 @@
|
|||||||
:prop="item.prop"
|
:prop="item.prop"
|
||||||
:form-data="formData"
|
:form-data="formData"
|
||||||
:attrs="item.attrs"
|
:attrs="item.attrs"
|
||||||
style="width: 100%"
|
|
||||||
></slot>
|
></slot>
|
||||||
</template>
|
</template>
|
||||||
<component
|
<component
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
<template v-else>
|
<template v-else>
|
||||||
<el-dialog
|
<el-dialog
|
||||||
v-model="modalVisible"
|
v-model="modalVisible"
|
||||||
v-bind="{ destroyOnClose: true, appendToBody: true, ...modalConfig.dialog }"
|
v-bind="{ destroyOnClose: true, ...modalConfig.dialog }"
|
||||||
@close="handleClose"
|
@close="handleClose"
|
||||||
>
|
>
|
||||||
<!-- 表单 -->
|
<!-- 表单 -->
|
||||||
@@ -79,9 +79,9 @@
|
|||||||
<el-form-item :label="item.label" :prop="item.prop">
|
<el-form-item :label="item.label" :prop="item.prop">
|
||||||
<!-- Label -->
|
<!-- Label -->
|
||||||
<template #label>
|
<template #label>
|
||||||
<span class="flex-y-center">
|
<span>
|
||||||
{{ item?.label || "" }}
|
{{ item?.label || "" }}
|
||||||
<el-tooltip v-if="item?.tips">
|
<el-tooltip v-if="item?.tips" v-bind="getTooltipProps(item.tips)">
|
||||||
<QuestionFilled class="w-4 h-4 mx-1" />
|
<QuestionFilled class="w-4 h-4 mx-1" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span v-if="modalConfig.colon" class="ml-0.5">:</span>
|
<span v-if="modalConfig.colon" class="ml-0.5">:</span>
|
||||||
@@ -109,9 +109,11 @@
|
|||||||
v-for="opt in item.options"
|
v-for="opt in item.options"
|
||||||
:label="opt.label"
|
:label="opt.label"
|
||||||
:value="opt.value"
|
:value="opt.value"
|
||||||
>
|
></component>
|
||||||
<slot v-if="item.slotName" :name="item.slotName"></slot>
|
</template>
|
||||||
</component>
|
|
||||||
|
<template v-if="item?.slotName && $slots[item.slotName]" #[item.slotName]>
|
||||||
|
<slot :name="item.slotName" />
|
||||||
</template>
|
</template>
|
||||||
</component>
|
</component>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
@@ -126,22 +128,24 @@
|
|||||||
</template>
|
</template>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useThrottleFn } from "@vueuse/core";
|
import { useThrottleFn } from "@vueuse/core";
|
||||||
import type { FormInstance, FormRules } from "element-plus";
|
import type { FormInstance, FormRules } from "element-plus";
|
||||||
import type { IModalConfig, IObject } from "./types";
|
import type { IComponentType, IModalConfig, IObject } from "./types";
|
||||||
import InputTag from "@/components/InputTag/index.vue";
|
import InputTag from "@/components/InputTag/index.vue";
|
||||||
import IconSelect from "@/components/IconSelect/index.vue";
|
import IconSelect from "@/components/IconSelect/index.vue";
|
||||||
|
|
||||||
|
defineSlots<{ [key: string]: (_args: any) => any }>();
|
||||||
// 定义接收的属性
|
// 定义接收的属性
|
||||||
const props = defineProps<{ modalConfig: IModalConfig }>();
|
const props = defineProps<{ modalConfig: IModalConfig }>();
|
||||||
// 自定义事件
|
// 自定义事件
|
||||||
const emit = defineEmits<{ submitClick: [] }>();
|
const emit = defineEmits<{ submitClick: []; customSubmit: [queryParams: IObject] }>();
|
||||||
// 组件映射表
|
// 组件映射表
|
||||||
/* eslint-disable */
|
/* eslint-disable */
|
||||||
const componentMap = new Map([
|
const componentMap = new Map<IComponentType, any>([
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
["input", markRaw(ElInput)], // @ts-ignore
|
["input", markRaw(ElInput)], // @ts-ignore
|
||||||
["select", markRaw(ElSelect)], // @ts-ignore
|
["select", markRaw(ElSelect)], // @ts-ignore
|
||||||
@@ -160,7 +164,7 @@ const componentMap = new Map([
|
|||||||
["icon-select", markRaw(IconSelect)], // @ts-ignore"
|
["icon-select", markRaw(IconSelect)], // @ts-ignore"
|
||||||
["custom", ""],
|
["custom", ""],
|
||||||
]);
|
]);
|
||||||
const childrenMap = new Map([
|
const childrenMap = new Map<IComponentType, any>([
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
["select", markRaw(ElOption)], // @ts-ignore
|
["select", markRaw(ElOption)], // @ts-ignore
|
||||||
["radio", markRaw(ElRadio)], // @ts-ignore"
|
["radio", markRaw(ElRadio)], // @ts-ignore"
|
||||||
@@ -168,13 +172,13 @@ const childrenMap = new Map([
|
|||||||
]);
|
]);
|
||||||
/* eslint-enable */
|
/* eslint-enable */
|
||||||
|
|
||||||
const pk = props.modalConfig.pk ?? "id";
|
const pk = props.modalConfig.pk ?? "id"; // 主键名,用于表单数据处理
|
||||||
const modalVisible = ref(false);
|
const modalVisible = ref(false); // 弹窗显示状态
|
||||||
const formRef = ref<FormInstance>();
|
const formRef = ref<FormInstance>(); // 表单实例
|
||||||
const formItems = reactive(props.modalConfig.formItems ?? []);
|
const formItems = reactive(props.modalConfig.formItems ?? []); // 表单配置项
|
||||||
const formData = reactive<IObject>({});
|
const formData = reactive<IObject>({}); // 表单数据
|
||||||
const formRules: FormRules = {};
|
const formRules: FormRules = {}; // 表单验证规则
|
||||||
const formDisable = ref(false);
|
const formDisable = ref(false); // 表单禁用状态
|
||||||
|
|
||||||
// 获取tooltip提示框属性
|
// 获取tooltip提示框属性
|
||||||
const getTooltipProps = (tips: string | IObject) => {
|
const getTooltipProps = (tips: string | IObject) => {
|
||||||
@@ -204,17 +208,16 @@ const handleSubmit = useThrottleFn(() => {
|
|||||||
props.modalConfig.beforeSubmit(formData);
|
props.modalConfig.beforeSubmit(formData);
|
||||||
}
|
}
|
||||||
if (!props.modalConfig?.formAction) {
|
if (!props.modalConfig?.formAction) {
|
||||||
ElMessage.error("未配置exportAction");
|
emit("customSubmit", formData);
|
||||||
|
handleClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
props.modalConfig.formAction(formData).then(() => {
|
props.modalConfig.formAction(formData).then(() => {
|
||||||
let msg = "操作成功";
|
|
||||||
if (props.modalConfig.component === "drawer") {
|
if (props.modalConfig.component === "drawer") {
|
||||||
msg = `${props.modalConfig.drawer?.title}成功`;
|
ElMessage.success(`${props.modalConfig.drawer?.title}成功`);
|
||||||
} else {
|
} else {
|
||||||
msg = `${props.modalConfig.dialog?.title}成功`;
|
ElMessage.success(`${props.modalConfig.dialog?.title}成功`);
|
||||||
}
|
}
|
||||||
ElMessage.success(msg);
|
|
||||||
emit("submitClick");
|
emit("submitClick");
|
||||||
handleClose();
|
handleClose();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ export type PageFormInstance = InstanceType<typeof PageForm>;
|
|||||||
|
|
||||||
export type IObject = Record<string, any>;
|
export type IObject = Record<string, any>;
|
||||||
|
|
||||||
type DataComponent = "date-picker" | "time-picker" | "time-select" | "custom-tag" | "input-tag";
|
type DateComponent = "date-picker" | "time-picker" | "time-select" | "custom-tag" | "input-tag";
|
||||||
type InputComponent = "input" | "select" | "input-number" | "cascader" | "tree-select";
|
type InputComponent = "input" | "select" | "input-number" | "cascader" | "tree-select";
|
||||||
type OtherComponent = "text" | "radio" | "checkbox" | "switch" | "icon-select" | "custom";
|
type OtherComponent = "text" | "radio" | "checkbox" | "switch" | "icon-select" | "custom";
|
||||||
export type ISearchComponent = DataComponent | InputComponent;
|
export type ISearchComponent = DateComponent | InputComponent;
|
||||||
export type IComponentType = DataComponent | InputComponent | OtherComponent;
|
export type IComponentType = DateComponent | InputComponent | OtherComponent;
|
||||||
|
|
||||||
type ToolbarLeft = "add" | "delete" | "import" | "export";
|
type ToolbarLeft = "add" | "delete" | "import" | "export";
|
||||||
type ToolbarRight = "refresh" | "filter" | "imports" | "exports" | "search";
|
type ToolbarRight = "refresh" | "filter" | "imports" | "exports" | "search";
|
||||||
@@ -44,26 +44,7 @@ export interface ISearchConfig {
|
|||||||
// 标签冒号(默认:false)
|
// 标签冒号(默认:false)
|
||||||
colon?: boolean;
|
colon?: boolean;
|
||||||
// 表单项(默认:[])
|
// 表单项(默认:[])
|
||||||
formItems?: Array<{
|
formItems?: IFormItems;
|
||||||
// 组件类型(如input,select等)
|
|
||||||
type?: ISearchComponent;
|
|
||||||
// 标签文本
|
|
||||||
label?: string;
|
|
||||||
// 标签提示
|
|
||||||
tips?: string | IObject;
|
|
||||||
// 键名
|
|
||||||
prop: string;
|
|
||||||
// 组件属性(input-tag组件支持join,btnText,size属性)
|
|
||||||
attrs?: IObject;
|
|
||||||
// 初始值
|
|
||||||
initialValue?: any;
|
|
||||||
// 可选项(适用于select组件)
|
|
||||||
options?: Array<{ label: string; value: any }>;
|
|
||||||
// 组件事件
|
|
||||||
events?: Record<string, (...args: any) => void>;
|
|
||||||
// 初始化数据函数扩展
|
|
||||||
initFn?: (formItem: IObject) => void;
|
|
||||||
}>;
|
|
||||||
// 是否开启展开和收缩(默认:true)
|
// 是否开启展开和收缩(默认:true)
|
||||||
isExpandable?: boolean;
|
isExpandable?: boolean;
|
||||||
// 默认展示的表单项数量(默认:3)
|
// 默认展示的表单项数量(默认:3)
|
||||||
@@ -199,36 +180,36 @@ export interface IModalConfig<T = any> {
|
|||||||
// 提交之前处理
|
// 提交之前处理
|
||||||
beforeSubmit?: (data: T) => void;
|
beforeSubmit?: (data: T) => void;
|
||||||
// 提交的网络请求函数(需返回promise)
|
// 提交的网络请求函数(需返回promise)
|
||||||
formAction: (data: T) => Promise<any>;
|
formAction?: (data: T) => Promise<any>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type IForm = Partial<Omit<FormProps, "model" | "rules">>;
|
export type IForm = Partial<Omit<FormProps, "model" | "rules">>;
|
||||||
|
|
||||||
// 表单项
|
// 表单项
|
||||||
export type IFormItems = Array<{
|
export type IFormItems = Array<{
|
||||||
// 组件类型(如input,select,radio,custom等,默认input)
|
// 组件类型(如input,select,radio,custom等)
|
||||||
type: IComponentType;
|
type: IComponentType;
|
||||||
|
// 标签提示
|
||||||
|
tips?: string | IObject;
|
||||||
|
// 标签文本
|
||||||
|
label: string;
|
||||||
|
// 键名
|
||||||
|
prop: string;
|
||||||
// 组件属性
|
// 组件属性
|
||||||
attrs?: IObject;
|
attrs?: IObject;
|
||||||
// 组件可选项(适用于select,radio,checkbox组件)
|
// 组件可选项(只适用于select,radio,checkbox组件)
|
||||||
options?: Array<{
|
options?: Array<{
|
||||||
label: string;
|
label: string;
|
||||||
value: any;
|
value: any;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
[key: string]: any;
|
[key: string]: any;
|
||||||
}>;
|
}>;
|
||||||
// 插槽名(适用于组件类型为custom)
|
|
||||||
slotName?: string;
|
|
||||||
// 标签文本
|
|
||||||
label: string;
|
|
||||||
// 标签提示
|
|
||||||
tips?: string | IObject;
|
|
||||||
// 键名
|
|
||||||
prop: string;
|
|
||||||
// 验证规则
|
// 验证规则
|
||||||
rules?: FormItemRule[];
|
rules?: FormItemRule[];
|
||||||
// 初始值
|
// 初始值
|
||||||
initialValue?: any;
|
initialValue?: any;
|
||||||
|
// 插槽名(适用于自定义组件,设置类型为custom)
|
||||||
|
slotName?: string;
|
||||||
// 是否隐藏
|
// 是否隐藏
|
||||||
hidden?: boolean;
|
hidden?: boolean;
|
||||||
// layout组件Col属性
|
// layout组件Col属性
|
||||||
|
|||||||
@@ -18,24 +18,51 @@ function usePage() {
|
|||||||
contentRef.value?.fetchPageData({ ...queryParams, ...filterParams }, true);
|
contentRef.value?.fetchPageData({ ...queryParams, ...filterParams }, true);
|
||||||
}
|
}
|
||||||
// 新增
|
// 新增
|
||||||
function handleAddClick() {
|
function handleAddClick(RefImpl?: Ref<PageContentInstance>) {
|
||||||
//显示添加表单
|
if (RefImpl) {
|
||||||
|
RefImpl?.value.setModalVisible();
|
||||||
|
RefImpl?.value.handleDisabled(false);
|
||||||
|
} else {
|
||||||
addModalRef.value?.setModalVisible();
|
addModalRef.value?.setModalVisible();
|
||||||
|
addModalRef.value?.handleDisabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// 编辑
|
// 编辑
|
||||||
async function handleEditClick(row: IObject, callback?: (result?: IObject) => IObject) {
|
async function handleEditClick(
|
||||||
|
row: IObject,
|
||||||
|
callback?: (result?: IObject) => IObject,
|
||||||
|
RefImpl?: Ref<PageContentInstance>
|
||||||
|
) {
|
||||||
|
if (RefImpl) {
|
||||||
|
RefImpl.value?.setModalVisible();
|
||||||
|
RefImpl.value?.handleDisabled(false);
|
||||||
|
let from = await (callback?.(row) ?? Promise.resolve(row));
|
||||||
|
RefImpl.value?.setFormData(from ? from : row);
|
||||||
|
} else {
|
||||||
editModalRef.value?.setModalVisible();
|
editModalRef.value?.setModalVisible();
|
||||||
editModalRef.value?.handleDisabled(false);
|
editModalRef.value?.handleDisabled(false);
|
||||||
let from = await (callback?.(row) ?? Promise.resolve(row));
|
let from = await (callback?.(row) ?? Promise.resolve(row));
|
||||||
editModalRef.value?.setFormData(from ? from : row);
|
editModalRef.value?.setFormData(from ? from : row);
|
||||||
}
|
}
|
||||||
// 编辑
|
}
|
||||||
async function handleViewClick(row: IObject, callback?: (result?: IObject) => IObject) {
|
// 查看
|
||||||
|
async function handleViewClick(
|
||||||
|
row: IObject,
|
||||||
|
callback?: (result?: IObject) => IObject,
|
||||||
|
RefImpl?: Ref<PageContentInstance>
|
||||||
|
) {
|
||||||
|
if (RefImpl) {
|
||||||
|
RefImpl.value?.setModalVisible();
|
||||||
|
RefImpl.value?.handleDisabled(true);
|
||||||
|
let from = await (callback?.(row) ?? Promise.resolve(row));
|
||||||
|
RefImpl.value?.setFormData(from ? from : row);
|
||||||
|
} else {
|
||||||
editModalRef.value?.setModalVisible();
|
editModalRef.value?.setModalVisible();
|
||||||
editModalRef.value?.handleDisabled(true);
|
editModalRef.value?.handleDisabled(true);
|
||||||
let from = await (callback?.(row) ?? Promise.resolve(row));
|
let from = await (callback?.(row) ?? Promise.resolve(row));
|
||||||
editModalRef.value?.setFormData(from ? from : row);
|
editModalRef.value?.setFormData(from ? from : row);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// 表单提交
|
// 表单提交
|
||||||
function handleSubmitClick() {
|
function handleSubmitClick() {
|
||||||
//根据检索条件刷新列表数据
|
//根据检索条件刷新列表数据
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
import UserAPI, { type UserForm } from "@/api/system/user.api";
|
import UserAPI, { type UserForm } from "@/api/system/user.api";
|
||||||
import type { IModalConfig } from "@/components/CURD/types";
|
import type { IModalConfig } from "@/components/CURD/types";
|
||||||
|
import DeptAPI from "@/api/system/dept.api";
|
||||||
|
import RoleAPI from "@/api/system/role.api";
|
||||||
|
|
||||||
const modalConfig: IModalConfig<UserForm> = {
|
const modalConfig: IModalConfig<UserForm> = {
|
||||||
permPrefix: "sys:user",
|
permPrefix: "sys:user",
|
||||||
@@ -45,7 +47,7 @@ const modalConfig: IModalConfig<UserForm> = {
|
|||||||
{
|
{
|
||||||
label: "所属部门",
|
label: "所属部门",
|
||||||
prop: "deptId",
|
prop: "deptId",
|
||||||
rules: [{ required: true, message: "所属部门不能为空", trigger: "blur" }],
|
rules: [{ required: true, message: "所属部门不能为空", trigger: "change" }],
|
||||||
type: "tree-select",
|
type: "tree-select",
|
||||||
attrs: {
|
attrs: {
|
||||||
placeholder: "请选择所属部门",
|
placeholder: "请选择所属部门",
|
||||||
@@ -54,17 +56,22 @@ const modalConfig: IModalConfig<UserForm> = {
|
|||||||
"check-strictly": true,
|
"check-strictly": true,
|
||||||
"render-after-expand": false,
|
"render-after-expand": false,
|
||||||
},
|
},
|
||||||
|
async initFn(formItem) {
|
||||||
|
// 注意:如果initFn函数不是箭头函数,this会指向此配置项对象,那么也就可以用this来替代形参formItem
|
||||||
|
formItem.attrs.data = await DeptAPI.getOptions();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "custom",
|
type: "custom",
|
||||||
label: "性别",
|
label: "性别",
|
||||||
prop: "gender",
|
prop: "gender",
|
||||||
initialValue: 1,
|
initialValue: 1,
|
||||||
|
attrs: { style: { width: "100%" } },
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "角色",
|
label: "角色",
|
||||||
prop: "roleIds",
|
prop: "roleIds",
|
||||||
rules: [{ required: true, message: "用户角色不能为空", trigger: "blur" }],
|
rules: [{ required: true, message: "用户角色不能为空", trigger: "change" }],
|
||||||
type: "select",
|
type: "select",
|
||||||
attrs: {
|
attrs: {
|
||||||
placeholder: "请选择",
|
placeholder: "请选择",
|
||||||
@@ -72,6 +79,9 @@ const modalConfig: IModalConfig<UserForm> = {
|
|||||||
},
|
},
|
||||||
options: [],
|
options: [],
|
||||||
initialValue: [],
|
initialValue: [],
|
||||||
|
async initFn(formItem) {
|
||||||
|
formItem.options = await RoleAPI.getOptions();
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: "input",
|
type: "input",
|
||||||
@@ -115,6 +125,12 @@ const modalConfig: IModalConfig<UserForm> = {
|
|||||||
],
|
],
|
||||||
initialValue: 1,
|
initialValue: 1,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: "custom",
|
||||||
|
label: "二级弹窗",
|
||||||
|
prop: "openModal",
|
||||||
|
slotName: "openModal",
|
||||||
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
59
src/views/demo/curd/config/add2.ts
Normal file
59
src/views/demo/curd/config/add2.ts
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import { type UserForm } from "@/api/system/user.api";
|
||||||
|
import type { IModalConfig } from "@/components/CURD/types";
|
||||||
|
import DeptAPI from "@/api/system/dept.api";
|
||||||
|
|
||||||
|
const modalConfig: IModalConfig<UserForm> = {
|
||||||
|
colon: true,
|
||||||
|
dialog: {
|
||||||
|
title: "二级弹窗",
|
||||||
|
width: 500,
|
||||||
|
draggable: true,
|
||||||
|
},
|
||||||
|
form: {
|
||||||
|
labelWidth: "auto",
|
||||||
|
labelPosition: "top",
|
||||||
|
},
|
||||||
|
formItems: [
|
||||||
|
{
|
||||||
|
label: "用户名",
|
||||||
|
prop: "username",
|
||||||
|
rules: [{ required: true, message: "用户名不能为空", trigger: "blur" }],
|
||||||
|
type: "input",
|
||||||
|
attrs: { placeholder: "请输入" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "用户昵称",
|
||||||
|
prop: "nickname",
|
||||||
|
rules: [{ required: true, message: "用户昵称不能为空", trigger: "blur" }],
|
||||||
|
type: "input",
|
||||||
|
attrs: { placeholder: "请输入" },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "所属部门",
|
||||||
|
prop: "deptId",
|
||||||
|
rules: [{ required: true, message: "所属部门不能为空", trigger: "change" }],
|
||||||
|
type: "tree-select",
|
||||||
|
attrs: {
|
||||||
|
placeholder: "请选择",
|
||||||
|
data: [],
|
||||||
|
filterable: true,
|
||||||
|
"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%" } },
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// 如果有异步数据会修改配置的,推荐用reactive包裹,而纯静态配置的可以直接导出
|
||||||
|
export default reactive(modalConfig);
|
||||||
@@ -57,7 +57,17 @@
|
|||||||
@submit-click="handleSubmitClick"
|
@submit-click="handleSubmitClick"
|
||||||
>
|
>
|
||||||
<template #gender="scope">
|
<template #gender="scope">
|
||||||
<Dict v-model="scope.formData[scope.prop]" code="gender" />
|
<Dict v-model="scope.formData[scope.prop]" code="gender" v-bind="scope.attrs" />
|
||||||
|
</template>
|
||||||
|
<template #openModal>
|
||||||
|
<el-button type="primary" @click="openSecondModal">打开二级弹窗</el-button>
|
||||||
|
</template>
|
||||||
|
</page-modal>
|
||||||
|
|
||||||
|
<!-- 二级弹窗 -->
|
||||||
|
<page-modal ref="addModalRef2" :modal-config="addModalConfig2" @custom-click="secondSubmit">
|
||||||
|
<template #gender="scope">
|
||||||
|
<Dict v-model="scope.formData[scope.prop]" code="gender" v-bind="scope.attrs" />
|
||||||
</template>
|
</template>
|
||||||
</page-modal>
|
</page-modal>
|
||||||
|
|
||||||
@@ -104,9 +114,10 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import UserAPI from "@/api/system/user.api";
|
import UserAPI from "@/api/system/user.api";
|
||||||
import type { IObject, IOperateData } from "@/components/CURD/types";
|
import type { IObject, IOperateData, PageContentInstance } from "@/components/CURD/types";
|
||||||
import usePage from "@/components/CURD/usePage";
|
import usePage from "@/components/CURD/usePage";
|
||||||
import addModalConfig from "./config/add";
|
import addModalConfig from "./config/add";
|
||||||
|
import addModalConfig2 from "./config/add2";
|
||||||
import contentConfig from "./config/content";
|
import contentConfig from "./config/content";
|
||||||
import contentConfig2 from "./config/content2";
|
import contentConfig2 from "./config/content2";
|
||||||
import editModalConfig from "./config/edit";
|
import editModalConfig from "./config/edit";
|
||||||
@@ -121,7 +132,7 @@ const {
|
|||||||
editModalRef,
|
editModalRef,
|
||||||
handleQueryClick,
|
handleQueryClick,
|
||||||
handleResetClick,
|
handleResetClick,
|
||||||
// handleAddClick,
|
handleAddClick,
|
||||||
handleEditClick,
|
handleEditClick,
|
||||||
handleViewClick,
|
handleViewClick,
|
||||||
handleSubmitClick,
|
handleSubmitClick,
|
||||||
@@ -130,12 +141,8 @@ const {
|
|||||||
handleFilterChange,
|
handleFilterChange,
|
||||||
} = usePage();
|
} = usePage();
|
||||||
|
|
||||||
// 新增
|
const addModalRef2 = ref();
|
||||||
async function handleAddClick() {
|
|
||||||
addModalRef.value?.setModalVisible();
|
|
||||||
// 加载下拉数据源,建议在初始化配置项 initFn 中加载,避免多次请求
|
|
||||||
// addModalConfig.formItems[2]!.attrs!.data = await DeptAPI.getOptions();
|
|
||||||
}
|
|
||||||
// 其他工具栏
|
// 其他工具栏
|
||||||
function handleToolbarClick(name: string) {
|
function handleToolbarClick(name: string) {
|
||||||
console.log(name);
|
console.log(name);
|
||||||
@@ -162,7 +169,8 @@ const handleOperateClick = (data: IObject) => {
|
|||||||
ElMessageBox.prompt("请输入用户「" + data.row.username + "」的新密码", "重置密码", {
|
ElMessageBox.prompt("请输入用户「" + data.row.username + "」的新密码", "重置密码", {
|
||||||
confirmButtonText: "确定",
|
confirmButtonText: "确定",
|
||||||
cancelButtonText: "取消",
|
cancelButtonText: "取消",
|
||||||
}).then(({ value }) => {
|
})
|
||||||
|
.then(({ value }) => {
|
||||||
if (!value || value.length < 6) {
|
if (!value || value.length < 6) {
|
||||||
ElMessage.warning("密码至少需要6位字符,请重新输入");
|
ElMessage.warning("密码至少需要6位字符,请重新输入");
|
||||||
return false;
|
return false;
|
||||||
@@ -170,18 +178,6 @@ const handleOperateClick = (data: IObject) => {
|
|||||||
UserAPI.resetPassword(data.row.id, value).then(() => {
|
UserAPI.resetPassword(data.row.id, value).then(() => {
|
||||||
ElMessage.success("密码重置成功,新密码是:" + value);
|
ElMessage.success("密码重置成功,新密码是:" + value);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
} else if (data.name === "delete") {
|
|
||||||
ElMessageBox.confirm("确认删除?", "警告", {
|
|
||||||
confirmButtonText: "确定",
|
|
||||||
cancelButtonText: "取消",
|
|
||||||
type: "warning",
|
|
||||||
})
|
|
||||||
.then(function () {
|
|
||||||
UserAPI.deleteByIds(data.row.id).then(() => {
|
|
||||||
ElMessage.success("删除成功");
|
|
||||||
contentRef.value?.handleRefresh(true); // 刷新列表
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
}
|
}
|
||||||
@@ -198,6 +194,14 @@ const handleOperateClick2 = (data: IOperateData) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 打开二级弹窗
|
||||||
|
const openSecondModal = () => {
|
||||||
|
handleAddClick(addModalRef2 as Ref<PageContentInstance>);
|
||||||
|
};
|
||||||
|
const secondSubmit = () => {
|
||||||
|
ElMessage.success("二级弹窗提交成功");
|
||||||
|
};
|
||||||
|
|
||||||
// 切换示例
|
// 切换示例
|
||||||
const isA = ref(true);
|
const isA = ref(true);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
Reference in New Issue
Block a user