Browse Source

form-create: 封装通用选择器 hook

puhui999 10 months ago
parent
commit
b4d85b782e

+ 0 - 3
src/components/DictSelect/index.ts

@@ -1,3 +0,0 @@
-import DictSelect from './src/DictSelect.vue'
-
-export { DictSelect }

+ 0 - 46
src/components/DictSelect/src/DictSelect.vue

@@ -1,46 +0,0 @@
-<!-- 数据字典 Select 选择器 -->
-<template>
-  <el-select class="w-1/1" v-bind="attrs">
-    <template v-if="valueType === 'int'">
-      <el-option
-        v-for="(dict, index) in getIntDictOptions(dictType)"
-        :key="index"
-        :label="dict.label"
-        :value="dict.value"
-      />
-    </template>
-    <template v-if="valueType === 'str'">
-      <el-option
-        v-for="(dict, index) in getStrDictOptions(dictType)"
-        :key="index"
-        :label="dict.label"
-        :value="dict.value"
-      />
-    </template>
-    <template v-if="valueType === 'bool'">
-      <el-option
-        v-for="(dict, index) in getBoolDictOptions(dictType)"
-        :key="index"
-        :label="dict.label"
-        :value="dict.value"
-      />
-    </template>
-  </el-select>
-</template>
-
-<script lang="ts" setup>
-import { getBoolDictOptions, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
-
-// 接受父组件参数
-interface Props {
-  dictType: string // 字典类型
-  valueType: string // 字典值类型
-}
-
-withDefaults(defineProps<Props>(), {
-  dictType: '',
-  valueType: 'str'
-})
-const attrs = useAttrs()
-defineOptions({ name: 'DictSelect' })
-</script>

+ 93 - 10
src/components/FormCreate/src/components/useCurrencySelect.tsx

@@ -1,25 +1,41 @@
 import request from '@/config/axios'
 import { isEmpty } from '@/utils/is'
 import { CurrencySelectProps } from '@/components/FormCreate/src/type'
+import { getBoolDictOptions, getIntDictOptions, getStrDictOptions } from '@/utils/dict'
 
 export const useCurrencySelect = (option: CurrencySelectProps) => {
   return defineComponent({
     name: option.name,
     props: {
-      // 字典类型
+      // 选项标签
       labelField: {
         type: String,
-        default: () => option.labelField ?? ''
+        default: () => option.labelField ?? 'label'
       },
-      // 字典值类型
+      // 选项的值
       valueField: {
         type: String,
-        default: () => option.valueField ?? ''
+        default: () => option.valueField ?? 'value'
       },
       // api 接口
       restful: {
         type: String,
         default: () => option.restful ?? ''
+      },
+      // 字典类型
+      dictType: {
+        type: String,
+        default: ''
+      },
+      // 字典值类型 'str' | 'int' | 'bool'
+      dictValueType: {
+        type: String,
+        default: 'str'
+      },
+      // 选择器类型,下拉框 select、多选框 checkbox、单选框 radio
+      selectType: {
+        type: String,
+        default: 'select'
       }
     },
     setup(props) {
@@ -27,6 +43,12 @@ export const useCurrencySelect = (option: CurrencySelectProps) => {
       const options = ref<any[]>([]) // 下拉数据
       const getOptions = async () => {
         options.value = []
+        // 字典选择器
+        if (option.isDict) {
+          options.value = getDictOptions()
+          return
+        }
+        // 接口选择器
         if (isEmpty(props.restful)) {
           return
         }
@@ -41,17 +63,78 @@ export const useCurrencySelect = (option: CurrencySelectProps) => {
         }
         console.log(`接口[${props.restful}] 返回结果不是一个数组`)
       }
-
+      // 获得字典配置
+      const getDictOptions = () => {
+        switch (props.dictValueType) {
+          case 'str':
+            return getStrDictOptions(props.dictType)
+          case 'int':
+            return getIntDictOptions(props.dictType)
+          case 'bool':
+            return getBoolDictOptions(props.dictType)
+          default:
+            return []
+        }
+      }
       onMounted(async () => {
         await getOptions()
       })
+      const buildSelect = () => {
+        return (
+          <>
+            <el-select class="w-1/1" {...attrs}>
+              {options.value.map((item, index) => (
+                <el-option key={index} label={item.label} value={item.value} />
+              ))}
+            </el-select>
+          </>
+        )
+      }
+      const buildCheckbox = () => {
+        if (isEmpty(options.value)) {
+          options.value = [
+            { label: '选项1', value: '选项1' },
+            { label: '选项2', value: '选项2' }
+          ]
+        }
+        return (
+          <>
+            <el-checkbox-group class="w-1/1" {...attrs}>
+              {options.value.map((item, index) => (
+                <el-checkbox key={index} label={item.label} value={item.value} />
+              ))}
+            </el-checkbox-group>
+          </>
+        )
+      }
+      const buildRadio = () => {
+        if (isEmpty(options.value)) {
+          options.value = [
+            { label: '选项1', value: '选项1' },
+            { label: '选项2', value: '选项2' }
+          ]
+        }
+        return (
+          <>
+            <el-radio-group class="w-1/1" {...attrs}>
+              {options.value.map((item, index) => (
+                <el-radio key={index} value={item.value}>
+                  {item.label}
+                </el-radio>
+              ))}
+            </el-radio-group>
+          </>
+        )
+      }
       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>
+          {props.selectType === 'select'
+            ? buildSelect()
+            : props.selectType === 'radio'
+              ? buildRadio()
+              : props.selectType === 'checkbox'
+                ? buildCheckbox()
+                : buildSelect()}
         </>
       )
     }

+ 11 - 0
src/components/FormCreate/src/config/selectRule.ts

@@ -1,4 +1,15 @@
 const selectRule = [
+  {
+    type: 'select',
+    field: 'selectType',
+    title: '选择器类型',
+    value: 'select',
+    options: [
+      { label: '下拉框', value: 'select' },
+      { label: '单选框', value: 'radio' },
+      { label: '多选框', value: 'checkbox' }
+    ]
+  },
   { type: 'switch', field: 'multiple', title: '是否多选' },
   {
     type: 'switch',

+ 1 - 1
src/components/FormCreate/src/config/useDictSelectRule.ts

@@ -46,7 +46,7 @@ export const useDictSelectRule = () => {
         },
         {
           type: 'select',
-          field: 'valueType',
+          field: 'dictValueType',
           title: '字典值类型',
           value: 'str',
           options: [

+ 3 - 2
src/components/FormCreate/src/type/index.ts

@@ -35,9 +35,10 @@ export interface DragRule {
 // 通用下拉组件 Props 类型
 export interface CurrencySelectProps {
   name: string // 组件名称
-  labelField?: string // 字典类型
-  valueField?: string // 字典值类型
+  labelField?: string // 选项标签
+  valueField?: string // 选项的值
   restful?: string // api 接口
+  isDict?: boolean // 是否字典选择器
 }
 
 // 选择组件规则配置类型

+ 2 - 0
src/components/FormCreate/src/useFormCreateDesigner.ts

@@ -67,6 +67,8 @@ export const useFormCreateDesigner = async (designer: Ref) => {
     designer.value?.removeMenuItem('fc-editor')
     // 移除自带的下拉选择器组件,使用 currencySelectRule 替代
     designer.value?.removeMenuItem('select')
+    designer.value?.removeMenuItem('radio')
+    designer.value?.removeMenuItem('checkbox')
     const components = [
       editorRule,
       uploadFileRule,

+ 4 - 1
src/plugins/formCreate/index.ts

@@ -19,7 +19,6 @@ import formCreate from '@form-create/element-ui'
 import install from '@form-create/element-ui/auto-import'
 //======================= 自定义组件 =======================
 import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
-import { DictSelect } from '@/components/DictSelect'
 import { useCurrencySelect } from '@/components/FormCreate'
 import { Editor } from '@/components/Editor'
 
@@ -38,6 +37,10 @@ const DeptSelect = useCurrencySelect({
 const RestfulSelect = useCurrencySelect({
   name: 'RestfulSelect'
 })
+const DictSelect = useCurrencySelect({
+  name: 'DictSelect',
+  isDict: true
+})
 const components = [
   ElAside,
   ElPopconfirm,