Bladeren bron

支持基于栅格系统的表单布局

tongshangming 2 jaren geleden
bovenliggende
commit
eb47992060

+ 1 - 1
package.json

@@ -1,6 +1,6 @@
 {
   "name": "fs-admin",
-  "version": "1.6.0",
+  "version": "1.7.0",
   "scripts": {
     "dev": "vite --host",
     "build": "run-p type-check build-only",

+ 1 - 0
src/components.d.ts

@@ -27,6 +27,7 @@ declare module '@vue/runtime-core' {
     ElDict: typeof import('./components/form/ElDict.vue')['default']
     ElEditor: typeof import('./components/form/ElEditor.vue')['default']
     ElEmployees: typeof import('./components/form/ElEmployees.vue')['default']
+    ElFormLayout: typeof import('./components/form/ElFormLayout.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']

+ 22 - 14
src/components/core/form/AdvancedForm.vue

@@ -7,6 +7,7 @@ interface Props {
 }
 const props = defineProps<Props>()
 
+const containerTypes = ['form-tabs', 'form-layout']
 const formData = computed(() => {
   if (props.formData.id) {
     return props.formData
@@ -14,19 +15,21 @@ const formData = computed(() => {
     const res = props.formData
     props.formConfig?.formItems.forEach(item => {
       item.group.forEach(element => {
-        if (element.type !== 'form-tabs') {
+        if (containerTypes.includes(element.type)) {
+          element.children?.forEach(tab => {
+            tab.children?.forEach(child => {
+              if (!child.notFormItem) {
+                res[child.name] =
+                  res[child.name] !== undefined && child.value !== undefined ? res[child.name] : child.value
+              }
+            })
+          })
+        } else {
           if (!element.notFormItem) {
             // 避免修改当前表单项value重置其他表单项的value
             res[element.name] =
               res[element.name] !== undefined && element.value !== undefined ? res[element.name] : element.value
           }
-        } else {
-          element.children?.forEach(tab => {
-            tab.children?.forEach(child => {
-              res[child.name] =
-                res[child.name] !== undefined && child.value !== undefined ? res[child.name] : child.value
-            })
-          })
         }
       })
     })
@@ -37,7 +40,7 @@ const formData = computed(() => {
 // 构造formTabs插槽
 props.formConfig.formItems.forEach(item => {
   item.group.forEach(child => {
-    if (child.type === 'form-tabs') {
+    if (containerTypes.includes(child.type)) {
       child.slots = []
       child.children?.forEach(tab => {
         tab.children?.forEach((child: any) => {
@@ -59,11 +62,12 @@ props.formConfig.formItems.forEach(item => {
   >
     <el-row :gutter="20">
       <el-col :span="sub.span || formConfig.span || 12" v-for="(sub, key) in item.group" :key="key">
-        <el-form-tabs
-          v-if="sub.type === 'form-tabs'"
+        <component
+          :is="'el-' + sub.type"
+          v-if="containerTypes.includes(sub.type)"
           v-model="sub.value"
           v-bind="sub.props"
-          :tabs="sub.children"
+          :children="sub.children"
           :formData="formData"
           :formConfig="formConfig"
           v-on="sub.events || {}"
@@ -71,7 +75,7 @@ props.formConfig.formItems.forEach(item => {
           <template #[slot.alias]="slotProps" v-for="slot in sub.slots" :key="slot.alias">
             <slot :name="slot.alias" v-bind="slotProps"></slot>
           </template>
-        </el-form-tabs>
+        </component>
         <template v-else>
           <el-form-item :label="sub.label" :rules="sub.rules" :prop="sub.name" v-show="!sub.hidden">
             <form-comp :item="sub" v-model="formData[sub.name]">
@@ -93,4 +97,8 @@ props.formConfig.formItems.forEach(item => {
   </el-card>
 </template>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+:deep(.el-select) {
+  width: 100%;
+}
+</style>

+ 22 - 13
src/components/core/form/BasicForm.vue

@@ -7,23 +7,27 @@ interface Props {
 }
 const props = defineProps<Props>()
 
+const containerTypes = ['form-tabs', 'form-layout']
 const formData = computed(() => {
   if (props.formData.id) {
     return props.formData
   } else {
     const res = props.formData
     props.formConfig?.formItems.forEach(item => {
-      if (item.type !== 'form-tabs') {
-        if (!item.notFormItem) {
-          // 避免修改当前表单项value重置其他表单项的value
-          res[item.name] = res[item.name] !== undefined && item.value !== undefined ? res[item.name] : item.value
-        }
-      } else {
+      if (containerTypes.includes(item.type)) {
         item.children?.forEach(tab => {
           tab.children?.forEach(child => {
-            res[child.name] = res[child.name] !== undefined && child.value !== undefined ? res[child.name] : child.value
+            if (!child.notFormItem) {
+              res[child.name] =
+                res[child.name] !== undefined && child.value !== undefined ? res[child.name] : child.value
+            }
           })
         })
+      } else {
+        if (!item.notFormItem) {
+          // 避免修改当前表单项value重置其他表单项的value
+          res[item.name] = res[item.name] !== undefined && item.value !== undefined ? res[item.name] : item.value
+        }
       }
     })
     return res
@@ -32,7 +36,7 @@ const formData = computed(() => {
 
 // 构造formTabs插槽
 props.formConfig.formItems.forEach(item => {
-  if (item.type === 'form-tabs') {
+  if (containerTypes.includes(item.type)) {
     item.slots = []
     item.children?.forEach(tab => {
       tab.children?.forEach((child: any) => {
@@ -46,11 +50,12 @@ props.formConfig.formItems.forEach(item => {
 <template>
   <el-row :gutter="20">
     <el-col :span="item.span || formConfig.span || 12" v-for="(item, index) in formConfig.formItems" :key="index">
-      <el-form-tabs
-        v-if="item.type === 'form-tabs'"
+      <component
+        :is="'el-' + item.type"
+        v-if="containerTypes.includes(item.type)"
         v-model="item.value"
         v-bind="item.props"
-        :tabs="item.children"
+        :children="item.children"
         :formData="formData"
         :formConfig="formConfig"
         v-on="item.events || {}"
@@ -58,7 +63,7 @@ props.formConfig.formItems.forEach(item => {
         <template #[slot.alias]="slotProps" v-for="slot in item.slots" :key="slot.alias">
           <slot :name="slot.alias" v-bind="slotProps"></slot>
         </template>
-      </el-form-tabs>
+      </component>
       <template v-else>
         <el-form-item :label="item.label" :rules="item.rules" :prop="item.name" v-show="!item.hidden">
           <form-comp :item="item" v-model="formData[item.name]">
@@ -72,4 +77,8 @@ props.formConfig.formItems.forEach(item => {
   </el-row>
 </template>
 
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+:deep(.el-select) {
+  width: 100%;
+}
+</style>

+ 14 - 21
src/components/core/form/FormComp.vue

@@ -80,30 +80,13 @@ const headers = reactive({
     v-on="item.events || {}"
   >
     <template #[slot.name]="slotProps" v-for="slot in item.slots" :key="slot.alias">
-      <slot :name="slot.alias" v-bind="slotProps"></slot>
+      <slot :name="slot.alias" v-bind="slotProps">
+        <el-icon v-if="item.props['list-type'] === 'picture-card'"><Plus /></el-icon>
+        <el-button type="primary" v-else>上传</el-button>
+      </slot>
     </template>
   </el-upload>
 
-  <el-select
-    v-else-if="item.type === 'select'"
-    v-model="modelValue"
-    v-bind="item.props"
-    :placeholder="item.placeholder || placeholder(item)"
-    v-on="item.events || {}"
-  >
-    <el-option
-      v-for="(option, index) in item.options"
-      :label="option.label"
-      :value="option.value"
-      :key="index"
-      v-bind="option.props"
-    >
-    </el-option>
-    <template #[slot.name]="slotProps" v-for="slot in item.slots" :key="slot.alias">
-      <slot :name="slot.alias" v-bind="slotProps"></slot>
-    </template>
-  </el-select>
-
   <component
     v-else
     :is="'el-' + item.type"
@@ -160,6 +143,16 @@ const headers = reactive({
         </el-checkbox>
       </template>
     </template>
+    <template v-if="item.type === 'select'">
+      <el-option
+        v-for="(option, index) in item.options"
+        :label="option.label"
+        :value="option.value"
+        :key="index"
+        v-bind="option.props"
+      >
+      </el-option>
+    </template>
     <template #[slot.name]="slotProps" v-for="slot in item.slots" :key="slot.alias">
       <slot :name="slot.alias" v-bind="slotProps"></slot>
     </template>

+ 1 - 5
src/components/core/form/ProForm.vue

@@ -86,8 +86,4 @@ defineExpose({
   </el-form>
 </template>
 
-<style lang="scss" scoped>
-:deep(.el-select) {
-  width: 100%;
-}
-</style>
+<style lang="scss" scoped></style>

+ 32 - 0
src/components/form/ElFormLayout.vue

@@ -0,0 +1,32 @@
+<script setup lang="ts">
+import type { BasicForm, BasicFormItem } from '@/types/form'
+
+interface Props {
+  children: Array<BasicFormItem>
+  formConfig: BasicForm
+  formData: any
+}
+defineProps<Props>()
+</script>
+
+<template>
+  <el-row :gutter="20">
+    <el-col v-bind="item.props" v-for="(item, index) in children" :key="index">
+      <el-form-item
+        v-for="child in item.children"
+        :label="child.label"
+        :rules="child.rules"
+        :prop="child.name"
+        v-show="!child.hidden"
+      >
+        <form-comp :item="child" v-model="formData[child.name]">
+          <template #[slot.alias]="slotProps" v-for="slot in child.slots" :key="slot.alias">
+            <slot :name="slot.alias" v-bind="slotProps"></slot>
+          </template>
+        </form-comp>
+      </el-form-item>
+    </el-col>
+  </el-row>
+</template>
+
+<style lang="scss" scoped></style>

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

@@ -3,7 +3,7 @@ import type { BasicForm, BasicFormItem } from '@/types/form'
 
 interface Props {
   modelValue: string
-  tabs: Array<{
+  children: Array<{
     label: string
     name: string
     children: Array<BasicFormItem>
@@ -22,7 +22,7 @@ const modelValue = computed({
 
 <template>
   <el-tabs v-model="modelValue" style="width: 100%">
-    <el-tab-pane :label="tab.label" :name="tab.name" v-for="tab in tabs" :key="tab.name">
+    <el-tab-pane :label="tab.label" :name="tab.name" v-for="tab in children" :key="tab.name">
       <el-row :gutter="20">
         <el-col :span="item.span || formConfig.span || 12" v-for="(item, index) in tab.children" :key="index">
           <el-form-item :label="item.label" :rules="item.rules" :prop="item.name" v-show="!item.hidden">

+ 2 - 4
src/views/form/Basic.vue

@@ -295,19 +295,17 @@ const handleInputConfirm = () => {
   <div class="h-full bg-white p-16px pt-50px flex justify-center overflow-auto">
     <div class="w-500px">
       <pro-form :formConfig="formConfig" :formData="formData" :create="create" :update="update" ref="proFormRef">
-        <template #prepend> testt </template>
         <template #prepend1> test1 </template>
-        <template #append> testt </template>
         <template #append1> test1 </template>
         <template #cDefault="{ node, data }">
           <span>{{ data.label }}</span>
           <span v-if="!node.isLeaf"> ({{ data.children.length }}) </span>
         </template>
         <template #file>
-          <el-button type="primary">上传</el-button>
+          <el-button type="primary">上传文件</el-button>
         </template>
         <template #password>
-          <el-input type="password" name="password" v-model="formData.password"></el-input>
+          <el-input type="password" name="password" v-model="formData.password" placeholder="请输入密码"></el-input>
           <el-text type="info">密码需包含大写字母、小写字母、数字</el-text>
         </template>
         <template #customDefault>