使用 tsx 封装 form-create 通用选择组件

This commit is contained in:
puhui999 2024-04-30 14:15:44 +08:00
parent 21483448b9
commit 1f1ac1f246
11 changed files with 217 additions and 65 deletions

View File

@ -1,4 +1,4 @@
import { useFormCreateDesigner } from './src/useFormCreateDesigner'
import CurrencySelect from './src/CurrencySelect/index.vue'
import { useCurrencySelect } from './src/components/useCurrencySelect'
export { useFormCreateDesigner, CurrencySelect }
export { useFormCreateDesigner, useCurrencySelect }

View File

@ -1,53 +0,0 @@
<template>
<el-select class="w-1/1" v-bind="attrs">
<el-option
v-for="(item, index) in options"
:key="index"
:label="item.label"
:value="item.value"
/>
</el-select>
</template>
<script lang="ts" setup>
import request from '@/config/axios'
import { isEmpty } from '@/utils/is'
defineOptions({ name: 'CurrencySelect' })
//
interface Props {
labelField?: string //
valueField?: string //
restful?: string // api
}
const props = withDefaults(defineProps<Props>(), {
labelField: 'nickname',
valueField: 'id',
restful: '/system/user/simple-list'
})
const attrs = useAttrs()
const options = ref<any[]>([]) //
const getOptions = async () => {
options.value = []
if (isEmpty(props.restful)) {
return
}
// TODO GET 使
const data = await request.get({ url: props.restful })
if (Array.isArray(data)) {
options.value = data.map((item: any) => ({
label: item[props.labelField],
value: item[props.valueField]
}))
return
}
console.log(`接口[${props.restful}] 返回结果不是一个数组`)
}
onMounted(() => {
getOptions()
})
</script>

View File

@ -0,0 +1,59 @@
import request from '@/config/axios'
import { isEmpty } from '@/utils/is'
import { CurrencySelectProps } from '@/components/FormCreate/src/type'
export const useCurrencySelect = (option: CurrencySelectProps) => {
return defineComponent({
name: option.name,
props: {
// 字典类型
labelField: {
type: String,
default: () => option.labelField ?? ''
},
// 字典值类型
valueField: {
type: String,
default: () => option.valueField ?? ''
},
// api 接口
restful: {
type: String,
default: () => option.restful ?? ''
}
},
setup(props) {
const attrs = useAttrs()
const options = ref<any[]>([]) // 下拉数据
const getOptions = async () => {
options.value = []
if (isEmpty(props.restful)) {
return
}
// TODO 只支持 GET 查询,复杂下拉构建条件请使用业务表单
const data = await request.get({ url: props.restful })
if (Array.isArray(data)) {
options.value = data.map((item: any) => ({
label: item[props.labelField],
value: item[props.valueField]
}))
return
}
console.log(`接口[${props.restful}] 返回结果不是一个数组`)
}
onMounted(async () => {
await getOptions()
})
return () => (
<>
<el-select className="w-1/1" {...attrs}>
{options.value.map((item, index) => (
<el-option key={index} label={item.label} value={item.value} />
))}
</el-select>
</>
)
}
})
}

View File

@ -4,6 +4,8 @@ import { useUploadImgsRule } from './useUploadImgsRule'
import { useDictSelectRule } from './useDictSelectRule'
import { useCurrencySelectRule } from './useCurrencySelectRule'
import { useEditorRule } from './useEditorRule'
import { useUserSelectRule } from './useUserSelectRule'
import { useDeptSelectRule } from './useDeptSelectRule'
export {
useUploadFileRule,
@ -11,5 +13,7 @@ export {
useUploadImgsRule,
useDictSelectRule,
useCurrencySelectRule,
useEditorRule
useEditorRule,
useUserSelectRule,
useDeptSelectRule
}

View File

@ -1,8 +1,9 @@
import { generateUUID } from '@/utils'
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
import selectRule from '@/components/FormCreate/src/config/selectRule'
import { DragRule } from '@/components/FormCreate/src/type'
export const useCurrencySelectRule = () => {
export const useCurrencySelectRule = (): DragRule => {
const label = '通用选择器'
const name = 'CurrencySelect'
return {

View File

@ -0,0 +1,26 @@
import { generateUUID } from '@/utils'
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
import selectRule from '@/components/FormCreate/src/config/selectRule'
import { DragRule } from '@/components/FormCreate/src/type'
export const useDeptSelectRule = (): DragRule => {
const label = '部门选择器'
const name = 'DeptSelect'
return {
icon: 'icon-select',
label,
name,
rule() {
return {
type: name,
field: generateUUID(),
title: label,
info: '',
$required: false
}
},
props(_, { t }) {
return localeProps(t, name + '.props', [makeRequiredRule(), ...selectRule])
}
}
}

View File

@ -0,0 +1,26 @@
import { generateUUID } from '@/utils'
import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
import selectRule from '@/components/FormCreate/src/config/selectRule'
import { DragRule } from '@/components/FormCreate/src/type'
export const useUserSelectRule = (): DragRule => {
const label = '用户选择器'
const name = 'UserSelect'
return {
icon: 'icon-select',
label,
name,
rule() {
return {
type: name,
field: generateUUID(),
title: label,
info: '',
$required: false
}
},
props(_, { t }) {
return localeProps(t, name + '.props', [makeRequiredRule(), ...selectRule])
}
}
}

View File

@ -0,0 +1,41 @@
import { Rule } from '@form-create/element-ui' //左侧拖拽按钮
//左侧拖拽按钮
export interface MenuItem {
label: string
name: string
icon: string
}
//左侧拖拽按钮分类
export interface Menu {
title: string
name: string
list: MenuItem[]
}
export interface MenuList extends Array<Menu> {}
//拖拽组件的规则
export interface DragRule {
icon: string
name: string
label: string
children?: string
inside?: true
drag?: true | String
dragBtn?: false
mask?: false
rule(): Rule
props(v: any, v1: any): Rule[]
}
// 通用下拉组件 Props 类型
export interface CurrencySelectProps {
name: string // 组件名称
labelField?: string // 字典类型
valueField?: string // 字典值类型
restful?: string // api 接口
}

View File

@ -1,12 +1,15 @@
import {
useCurrencySelectRule,
useDeptSelectRule,
useDictSelectRule,
useEditorRule,
useUploadFileRule,
useUploadImgRule,
useUploadImgsRule
useUploadImgsRule,
useUserSelectRule
} from './config'
import { Ref } from 'vue'
import { Menu } from '@/components/FormCreate/src/type'
/**
* hook
@ -26,7 +29,10 @@ export const useFormCreateDesigner = (designer: Ref) => {
const dictSelectRule = useDictSelectRule()
const currencySelectRule = useCurrencySelectRule()
onMounted(() => {
/**
*
*/
const buildFormComponents = () => {
// 移除自带的上传组件规则,使用 uploadFileRule、uploadImgRule、uploadImgsRule 替代
designer.value?.removeMenuItem('upload')
// 移除自带的富文本组件规则,使用 editorRule 替代
@ -51,5 +57,35 @@ export const useFormCreateDesigner = (designer: Ref) => {
label: component.label
})
})
}
const userSelectRule = useUserSelectRule()
const deptSelectRule = useDeptSelectRule()
/**
*
*/
const buildSystemMenu = () => {
const components = [userSelectRule, deptSelectRule]
const menu: Menu = {
name: 'system',
title: '系统字段',
list: components.map((component) => {
// 插入组件规则
designer.value?.addComponent(component)
// 插入拖拽按钮到 `system` 分类下
return {
icon: component.icon,
name: component.name,
label: component.label
}
})
}
designer.value?.addMenu(menu)
}
onMounted(async () => {
await nextTick()
buildFormComponents()
buildSystemMenu()
})
}

View File

@ -20,9 +20,22 @@ import install from '@form-create/element-ui/auto-import'
//======================= 自定义组件 =======================
import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
import { DictSelect } from '@/components/DictSelect'
import { CurrencySelect } from '@/components/FormCreate'
import { useCurrencySelect } from '@/components/FormCreate'
import { Editor } from '@/components/Editor'
const UserSelect = useCurrencySelect({
name: 'UserSelect',
labelField: 'nickname',
valueField: 'id',
restful: '/system/user/simple-list'
})
const DeptSelect = useCurrencySelect({
name: 'DeptSelect',
labelField: 'name',
valueField: 'id',
restful: '/system/dept/simple-list'
})
const components = [
ElAside,
ElPopconfirm,
@ -40,7 +53,8 @@ const components = [
UploadImgs,
UploadFile,
DictSelect,
CurrencySelect,
UserSelect,
DeptSelect,
Editor
]

View File

@ -8,11 +8,9 @@
<el-button size="small" type="danger" @click="showTemplate">生成组件</el-button>
</div>
</el-col>
<!-- 表单设计器 -->
<el-col>
<FcDesigner ref="designer" height="780px" />
</el-col>
</el-row>
<!-- 表单设计器 -->
<FcDesigner ref="designer" height="780px" />
</ContentWrap>
<!-- 弹窗表单预览 -->