在项目中,我需要使用表单设计器form-create-designer设计带有选择用户的弹窗组件,而设计器内置的组件不能满足需求,因此要创建自定义组件。form-create 支持在表单内部生成任何 vue 组件。
1.开发选择用户的组件 SelectUser.vue
<!--用户选择组件-->
<template>
<div>
<el-row :gutter="10">
<el-col :span="20">
<el-input v-model="selectUserNames"/>
</el-col>
<el-col :span="4">
<el-button type="primary" @click="selectUser">选择</el-button>
</el-col>
</el-row>
<el-input v-model="selectUserIds" style="display: none"/>
<el-dialog title="选择用户" v-model="dialogVisible" width="50%">
<el-row :gutter="10">
<el-col :span="8">
<el-tree-select v-model="value" :data="orgData" filterable :props="orgProps" show-checkbox/>
</el-col>
<el-col :span="8">
<el-input v-model="userName" placeholder="账号"/>
</el-col>
<el-col :span="8">
<el-button type="primary" @click="search">查询</el-button>
</el-col>
</el-row>
<el-table v-loading="loading" :data="tableData" ref="tableRef" stripe style="width: 100%;height: 350px"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55"/>
<el-table-column prop="username" label="用户账号" width="140"/>
<el-table-column prop="realname" label="用户姓名" width="140"/>
<el-table-column prop="sex_dictText" label="性别" width="80"/>
<el-table-column prop="orgCodeTxt" label="部门"/>
</el-table>
<Pagination v-if="pagination.total" :pageSize="pagination.pageSize" :pageNo="pagination.pageNo"
:total="pagination.total" @pageChange="pageChange" @sizeChange="sizeChange"/>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="updateSelect">
确定
</el-button>
</span>
</template>
</el-dialog>
</div>
</template>
<script lang="ts">
import {defineComponent, reactive, ref, watch} from 'vue'
import {defHttp} from "/@/utils/http/axios";
import Pagination from "./Pagination.vue";
import {ElTable} from 'element-plus'
export default defineComponent({
name: "SelectUser",
components: {
Pagination, ElTable
},
props: {
modelValue: {
type: String,
},
},
emits: ['update:modelValue'],
setup(props, {emit}) {
const tableRef = ref<InstanceType<typeof ElTable>>()
const selectUserIds = ref<any>()
const multipleSelection = ref([])
//初始化赋值
selectUserIds.value = props.modelValue
const userName = ref<any>()
const value = ref<any>()
const orgData = ref<any>([])
const orgProps = ref<any>({
label: 'title'
})
const pagination = reactive({
pageNo: 1,
pageSize: 10,
total: null
})
const dialogVisible = ref<boolean>(false)
const loading = ref<boolean>(false)
const tableData = ref<any>([])
const selectUsers = ref<any>([])
const selectUserNames = ref<any>()
async function list(pageNo, pageSize) {
loading.value = true
if (pageNo) pagination.pageNo = pageNo;
if (pageSize) pagination.pageSize = pageSize;
let params = {
username: userName.value,
departId: value.value,
pageNo: pagination.pageNo,
pageSize: pagination.pageSize
}
const data = await defHttp.get({url: "/sys/user/queryUserComponentData", params});
tableData.value = data.records
pagination.total = data.total
loading.value = false
}
function search() {
list(1, 10);
}
//切换当前页时触发
function pageChange(page) {
list(page, 10);
}
//每页展示条数切换时触发
function sizeChange(value) {
list(1, value);
}
/**
* 组织结构树查询
*/
async function initDeptData() {
const data = await defHttp.get({url: "/sys/sysDepart/queryTreeList"});
orgData.value = data
}
watch(
() => props.modelValue,
(val: string, prevVal: string) => {
selectUserIds.value = val
if (!selectUserNames.value) {
listRealnameData(val)
}
},
{
immediate: true,
}
);
/**
* 根据用户名查询真实姓名
*/
async function listRealnameData(value) {
if (!value) {
return
}
let params = {
userNames: value
}
const data = await defHttp.get({url: "/sys/user/listRealname", params});
selectUserNames.value = data
}
/**
* 选择用户
*/
async function selectUser() {
dialogVisible.value = true
if (orgData.value.length == 0) {
initDeptData();
}
await list(1, 10)
let checkUsers = [];
if (selectUserIds.value) {
selectUserIds.value.split(",").forEach((item) => {
let list = tableData.value.filter(val => val.username == item);
if (list && list.length > 0) {
checkUsers.push(list[0])
}
})
}
if (checkUsers && checkUsers.length > 0) {
checkUsers.forEach(row => {
tableRef.value!.toggleRowSelection(row, true)
})
}
}
const handleSelectionChange = (val) => {
multipleSelection.value = val
}
/**
* 确认选择
*/
function updateSelect() {
let selectUserIds = []
let selectUsers = []
if (multipleSelection.value.length > 0) {
multipleSelection.value.forEach((item) => {
selectUserIds.push(item.username)
selectUsers.push(item.realname)
})
}
selectUserNames.value = selectUsers.join(",")
emit('update:modelValue', selectUserIds.join(","));
dialogVisible.value = false
}
return {
tableRef,
multipleSelection,
userName,
value,
orgData,
orgProps,
pagination,
dialogVisible,
loading,
tableData,
selectUserIds,
selectUsers,
search,
pageChange,
sizeChange,
initDeptData,
selectUser,
handleSelectionChange,
updateSelect,
selectUserNames
}
}
});
</script>
<style lang="less" scoped>
</style>
参考: 生成自定义组件 | form-create
2.注册组件
全局注册:在main.ts中引入自定义组件,
app.component('selectUser', SelectUser) 注册组件。
3.form-create-designer自定义组件
(1)定义组件的拖拽规则
创建文件SelectUser.ts,内容如下:
import uniqueId from '@form-create/utils/lib/unique';
import {localeProps, makeRequiredRule} from './index';
const label = '用户组件';
const name = 'selectUser';
export const selectuser = {
//拖拽组件的图标
icon: 'icon-add',
//拖拽组件的名称
label,
//拖拽组件的 key
name,
//拖拽组件的生成规则
rule() {
//如果在 props 方法中需要修改 rule 的属性,需要提前在 rule 上定义对应的属性
return {
//生成组件的名称
type: name,
//field 自定不能重复,所以这里每次都会生成一个新的
field: uniqueId(),
title: label,
info: '',
$required: false,
props: {},
};
},
//拖拽组件配置项(props)的生成规则
props(_, {t}) {
return localeProps(t, name + '.props', [
makeRequiredRule(),
])
}
};
注意:name = 'selectUser',name的值为注册的组件名称。
rule的规则配置请参考:自定义组件 | form-create-designer
(2)将自定义拖拽规则插入到表单设计器form-create-designer
左侧表单
<template>
<fc-designer ref="designerRef"/>
</template>
<script lang="ts" setup>
import {ref} from 'vue';
import {selectuser} from "./custom/SelectUser";
const designerRef = ref()
//插入组件规则
designerRef.value.addComponent(selectuser);
//插入拖拽按钮到`系统组件`分类下
designerRef.value.addMenu({
title: '系统组件',
name: 'system',
list: [
{
icon: selectuser.icon,
name: selectuser.name,
label: selectuser.label
}]
});
</script>
4.表单设计器form-create-designer
效果图
预览效果图:
5.表单创建器form-create生成的表单效果图