Forráskód Böngészése

新增分组组件、步骤条组件

tongshangming 2 éve
szülő
commit
254c7e5282

+ 2 - 2
src/components.d.ts

@@ -28,7 +28,9 @@ declare module '@vue/runtime-core' {
     ElEditor: typeof import('./components/form/ElEditor.vue')['default']
     ElEmployees: typeof import('./components/form/ElEmployees.vue')['default']
     ElFormCard: typeof import('./components/form/ElFormCard.vue')['default']
+    ElFormGroup: typeof import('./components/form/ElFormGroup.vue')['default']
     ElFormLayout: typeof import('./components/form/ElFormLayout.vue')['default']
+    ElFormSteps: typeof import('./components/form/ElFormSteps.vue')['default']
     ElFormTabs: typeof import('./components/form/ElFormTabs.vue')['default']
     ElImageUpload: typeof import('./components/form/ElImageUpload.vue')['default']
     EmployeesRoleDialog: typeof import('./components/workflow/dialog/employeesRoleDialog.vue')['default']
@@ -44,7 +46,6 @@ declare module '@vue/runtime-core' {
     GlobalSetting: typeof import('./components/core/GlobalSetting.vue')['default']
     GlobalSubMenu: typeof import('./components/core/GlobalSubMenu.vue')['default']
     GlobalTabs: typeof import('./components/core/GlobalTabs.vue')['default']
-    ImageUpload: typeof import('./components/ImageUpload.vue')['default']
     NodeWrap: typeof import('./components/workflow/nodeWrap.vue')['default']
     OrgLayout: typeof import('./components/org/OrgLayout.vue')['default']
     OrgList: typeof import('./components/org/OrgList.vue')['default']
@@ -57,7 +58,6 @@ declare module '@vue/runtime-core' {
     SelectBox: typeof import('./components/workflow/selectBox.vue')['default']
     SelectResult: typeof import('./components/workflow/selectResult.vue')['default']
     SelIcon: typeof import('./components/SelIcon.vue')['default']
-    SlotTmpl: typeof import('./components/core/form/SlotTmpl.vue')['default']
     SvgIcon: typeof import('./components/SvgIcon.vue')['default']
     WorkflowEdit: typeof import('./components/workflow/WorkflowEdit.vue')['default']
   }

+ 8 - 7
src/components/core/form/BasicForm.vue

@@ -28,6 +28,7 @@ const formData = computed(() => {
     return res
   }
 })
+console.log(formData.value)
 
 // 构造表单容器插槽
 buildContainerSlots(props.formConfig.formItems)
@@ -35,7 +36,12 @@ buildContainerSlots(props.formConfig.formItems)
 
 <template>
   <el-row :gutter="20">
-    <el-col :span="item.span || formConfig.span || 12" v-for="(item, index) in formConfig.formItems" :key="index">
+    <el-col
+      :span="item.span || formConfig.span || 12"
+      v-for="(item, index) in formConfig.formItems"
+      :key="index"
+      v-show="!item.hidden"
+    >
       <component
         :is="'el-' + item.type"
         v-if="containerTypes.includes(item.type)"
@@ -51,12 +57,7 @@ buildContainerSlots(props.formConfig.formItems)
         </template>
       </component>
       <template v-else>
-        <el-form-item
-          :label="item.notFormItem ? '' : item.label"
-          :rules="item.rules"
-          :prop="item.name"
-          v-show="!item.hidden"
-        >
+        <el-form-item :label="item.notFormItem ? '' : item.label" :rules="item.rules" :prop="item.name">
           <form-comp :item="item" v-model="formData[item.name]">
             <template #[slot.alias]="slotProps" v-for="slot in item.slots" :key="slot.alias">
               <slot :name="slot.alias" v-bind="slotProps"></slot>

+ 7 - 7
src/components/form/ElFormCard.vue

@@ -18,7 +18,12 @@ const cardSlot = props.formItem.slots?.find(slot => slot.name === 'header')
       <slot :name="cardSlot.alias" v-bind="slotProps"></slot>
     </template>
     <el-row :gutter="20">
-      <el-col :span="item.span || formConfig.span || 12" v-for="(item, index) in formItem.children" :key="index">
+      <el-col
+        :span="item.span || formConfig.span || 12"
+        v-for="(item, index) in formItem.children"
+        :key="index"
+        v-show="!item.hidden"
+      >
         <component
           :is="'el-' + item.type"
           v-if="containerTypes.includes(item.type)"
@@ -34,12 +39,7 @@ const cardSlot = props.formItem.slots?.find(slot => slot.name === 'header')
           </template>
         </component>
         <template v-else>
-          <el-form-item
-            :label="item.notFormItem ? '' : item.label"
-            :rules="item.rules"
-            :prop="item.name"
-            v-show="!item.hidden"
-          >
+          <el-form-item :label="item.notFormItem ? '' : item.label" :rules="item.rules" :prop="item.name">
             <form-comp :item="item" v-model="formData[item.name]">
               <template #[slot.alias]="slotProps" v-for="slot in item.slots" :key="slot.alias">
                 <slot :name="slot.alias" v-bind="slotProps"></slot>

+ 21 - 0
src/components/form/ElFormGroup.vue

@@ -0,0 +1,21 @@
+<script setup lang="ts">
+import type { BasicForm, BasicFormItem } from '@/types/form'
+
+interface Props {
+  formItem: BasicFormItem
+  formConfig: BasicForm
+  formData: any
+}
+const props = defineProps<Props>()
+
+const config = {
+  ...props.formConfig,
+  formItems: props.formItem.children
+}
+</script>
+
+<template>
+  <basic-form :formConfig="config" :formData="formData"></basic-form>
+</template>
+
+<style lang="scss" scoped></style>

+ 7 - 1
src/components/form/ElFormLayout.vue

@@ -12,7 +12,13 @@ defineProps<Props>()
 
 <template>
   <el-row :gutter="20">
-    <el-col :span="item.span" v-bind="item.props" v-for="(item, index) in formItem.children" :key="index">
+    <el-col
+      :span="item.span"
+      v-bind="item.props"
+      v-for="(item, index) in formItem.children"
+      :key="index"
+      v-show="!item.hidden"
+    >
       <component
         :is="'el-' + item.type"
         v-if="containerTypes.includes(item.type)"

+ 57 - 0
src/components/form/ElFormSteps.vue

@@ -0,0 +1,57 @@
+<script setup lang="ts">
+import type { StepProps } from 'element-plus'
+import type { BasicForm, BasicFormItem } from '@/types/form'
+
+interface Props {
+  formItem: BasicFormItem
+  formConfig: BasicForm
+  formData: any
+  showSubmitBtn: boolean
+}
+const props = withDefaults(defineProps<Props>(), {
+  active: 0,
+  showSubmitBtn: true
+})
+const emits = defineEmits(['submit', 'next'])
+
+const stepsProps = props.formItem.props as {
+  active: number
+  steps: Array<StepProps>
+}
+
+const handleNext = () => {
+  stepsProps.active < stepsProps.steps?.length - 1 && stepsProps.active++
+  emits('next', props.formData)
+}
+const handleSubmit = () => {
+  emits('submit', props.formData)
+}
+</script>
+
+<template>
+  <el-steps class="mb-4" v-bind="stepsProps">
+    <el-step v-for="item in stepsProps?.steps" v-bind="item"></el-step>
+  </el-steps>
+  <template v-for="(item, index) in formItem.children">
+    <component
+      :is="'el-' + item.type"
+      :formItem="item"
+      :formData="formData"
+      v-if="stepsProps.active === index"
+    ></component>
+  </template>
+  <div class="text-center">
+    <el-button
+      type="primary"
+      @click="handleSubmit"
+      v-if="showSubmitBtn && stepsProps.active === stepsProps.steps?.length - 1"
+    >
+      提交
+    </el-button>
+    <el-button type="primary" @click="handleNext" v-if="stepsProps.active < stepsProps.steps?.length - 1">
+      下一步
+    </el-button>
+  </div>
+</template>
+
+<style lang="scss" scoped></style>

+ 7 - 7
src/components/form/ElFormTabs.vue

@@ -25,7 +25,12 @@ const modelValue = computed({
       </template>
 
       <el-row :gutter="20">
-        <el-col :span="item.span || formConfig.span || 12" v-for="(item, index) in tab.children" :key="index">
+        <el-col
+          :span="item.span || formConfig.span || 12"
+          v-for="(item, index) in tab.children"
+          :key="index"
+          v-show="!item.hidden"
+        >
           <component
             :is="'el-' + item.type"
             v-if="containerTypes.includes(item.type)"
@@ -41,12 +46,7 @@ const modelValue = computed({
             </template>
           </component>
           <template v-else>
-            <el-form-item
-              :label="item.notFormItem ? '' : item.label"
-              :rules="item.rules"
-              :prop="item.name"
-              v-show="!item.hidden"
-            >
+            <el-form-item :label="item.notFormItem ? '' : item.label" :rules="item.rules" :prop="item.name">
               <form-comp :item="item" v-model="formData[item.name]">
                 <template #[slot.alias]="slotProps" v-for="slot in item.slots" :key="slot.alias">
                   <slot :name="slot.alias" v-bind="slotProps"></slot>

+ 8 - 0
src/router/asyncRouter.ts

@@ -220,6 +220,14 @@ const asyncRouter: RouteRecordRaw[] = [
         meta: {
           title: 'tab表单'
         }
+      },
+      {
+        path: '/form/step',
+        name: 'formStep',
+        component: () => import('@/views/form/Step.vue'),
+        meta: {
+          title: '步骤表单'
+        }
       }
     ]
   },

+ 12 - 2
src/utils/constants.ts

@@ -82,5 +82,15 @@ export const themeNavList = [
 
 export const ACCESS_TOKEN = 'access_token'
 
-export const containerTypes = ['form-tabs', 'form-layout', 'form-card']
-export const notFormItem = ['form-tabs', 'tab-pane', 'form-layout', 'row', 'col', 'form-card', 'divider']
+export const containerTypes = ['form-tabs', 'form-layout', 'form-card', 'form-group', 'form-steps']
+export const notFormItem = [
+  'form-tabs',
+  'tab-pane',
+  'form-layout',
+  'row',
+  'col',
+  'form-card',
+  'divider',
+  'form-group',
+  'form-steps'
+]

+ 1 - 0
src/views/form/Advanced.vue

@@ -184,6 +184,7 @@ const formConfig = reactive<BasicForm>({
           label: '用户名',
           value: '',
           name: 'name5',
+          hidden: true,
           type: 'input'
         },
         {

+ 15 - 6
src/views/form/Basic.vue

@@ -1,9 +1,11 @@
 <script lang="ts" setup>
 import type { BasicForm } from '@/types/form'
 import { ElInput } from 'element-plus'
+import useValidator from '@/hooks/useValidator'
 
-const formData = reactive<any>({})
+const validator = useValidator()
 
+const formData = reactive<any>({})
 const formConfig = reactive<BasicForm>({
   span: 24,
   props: {
@@ -32,18 +34,25 @@ const formConfig = reactive<BasicForm>({
     },
     {
       label: '区域',
-      value: '',
+      value: [],
       name: 'area',
-      type: 'area'
+      type: 'area',
+      props: {
+        props: {
+          value: 'id'
+        }
+      }
     },
     {
       label: '手机号',
       value: '',
       name: 'phone',
       type: 'input',
-      props: {
-        maxlength: 11
-      }
+      rules: [
+        {
+          validator: validator.mobile
+        }
+      ]
     },
     {
       label: '开关',

+ 144 - 0
src/views/form/Step.vue

@@ -0,0 +1,144 @@
+<script lang="ts" setup>
+import type { BasicForm } from '@/types/form'
+import useValidator from '@/hooks/useValidator'
+
+const validator = useValidator()
+
+const proFormRef = ref<any>()
+const handleSave = () => {
+  proFormRef.value.submit()
+}
+
+const formData = reactive<any>({})
+const formConfig = reactive<BasicForm>({
+  formItems: [
+    {
+      label: '',
+      value: '',
+      name: '',
+      type: 'form-steps',
+      span: 24,
+      props: {
+        steps: [
+          {
+            title: 'step 1'
+          },
+          {
+            title: 'step 2'
+          },
+          {
+            title: 'step 3'
+          }
+        ],
+        active: 0,
+        simple: true,
+        showSubmitBtn: false
+      },
+      events: {
+        submit: handleSave
+      },
+      children: [
+        {
+          label: '',
+          value: '',
+          name: '',
+          type: 'form-group',
+          span: 24,
+          children: [
+            {
+              label: '付款账户',
+              value: '',
+              name: 'pay',
+              type: 'input'
+            },
+            {
+              label: '收款账户',
+              value: '',
+              name: 'account',
+              type: 'input'
+            },
+            {
+              label: '收款人姓名',
+              value: '',
+              name: 'name',
+              type: 'input'
+            },
+            {
+              label: '收款金额',
+              value: '',
+              name: 'sum',
+              type: 'input'
+            }
+          ]
+        },
+        {
+          label: '',
+          value: '',
+          name: '',
+          type: 'form-group',
+          children: [
+            {
+              label: '区域1',
+              value: '',
+              name: 'area1',
+              type: 'area'
+            },
+            {
+              label: '手机号',
+              value: '',
+              name: 'phone1',
+              type: 'input',
+              rules: [
+                {
+                  validator: validator.mobile
+                }
+              ]
+            }
+          ]
+        },
+        {
+          label: '',
+          value: '',
+          name: '',
+          type: 'form-group',
+          children: [
+            {
+              label: '',
+              value: '',
+              name: '',
+              notFormItem: true,
+              type: 'result',
+              span: 24,
+              props: {
+                icon: 'success',
+                title: '操作成功',
+                class: 'w-full text-center'
+              }
+            }
+          ]
+        }
+      ]
+    }
+  ]
+})
+
+const create = (data: any) => {
+  console.log(data)
+}
+const update = (data: any) => {
+  console.log(data)
+}
+</script>
+
+<template>
+  <div class="h-full bg-white p-16px pt-50px flex justify-center overflow-auto">
+    <div class="w-800px">
+      <pro-form :formConfig="formConfig" :formData="formData" :create="create" :update="update" ref="proFormRef">
+        <template #prepend1> test1 </template>
+        <template #append1> test1 </template>
+      </pro-form>
+    </div>
+  </div>
+</template>
+
+<style lang="scss" scoped></style>