瀏覽代碼

使用项目组件对 form-create-designer 进行增强

puhui999 1 年之前
父節點
當前提交
bc004b3b27

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

@@ -1,3 +1,4 @@
-import MyFormCreate from './src/MyFormCreate.vue'
+import MyFormCreateDesigner from './src/MyFormCreateDesigner.vue'
+import { useFormCreateDesigner } from './src/useFormCreateDesigner'
 
-export { MyFormCreate }
+export { MyFormCreateDesigner, useFormCreateDesigner }

+ 0 - 54
src/components/FormCreate/src/MyFormCreate.vue

@@ -1,54 +0,0 @@
-<template>
-  <form-create v-bind="attrs">
-    <!-- 保障 form-create 的原始插槽 -->
-    <template v-for="(_, name) in slots" #[name]="slotData">
-      <slot :name="name" v-bind="slotData || {}"></slot>
-    </template>
-    <!--  使用项目重新封装的文件上传组件实现文件上载  -->
-    <template #type-upload="scope">
-      <!--      {{ logC(scope) }}-->
-      <template v-if="scope.prop.props.uploadType === 'file'">
-        <!-- TODO puhui999: 考虑是否使用属性透传直接把整个 scope.prop.props 传递给组件 -->
-        <UploadFile
-          :disabled="scope.prop.props.disabled"
-          :limit="scope.prop.props.limit"
-          :modelValue="scope.model.value || scope.prop.value"
-          @update:modelValue="(val) => setValue(scope, val)"
-        />
-      </template>
-      <template v-if="scope.prop.props.uploadType === 'image' && scope.prop.props.limit === 1">
-        <UploadImg
-          :disabled="scope.prop.props.disabled"
-          :modelValue="scope.model.value || scope.prop.value"
-          @update:modelValue="(val) => setValue(scope, val)"
-        />
-      </template>
-      <template v-if="scope.prop.props.uploadType === 'image' && scope.prop.props.limit > 1">
-        <UploadImgs
-          :disabled="scope.prop.props.disabled"
-          :limit="scope.prop.props.limit"
-          :modelValue="scope.model.value || scope.prop.value"
-          @update:modelValue="(val) => setValue(scope, val)"
-        />
-      </template>
-    </template>
-  </form-create>
-</template>
-
-<script lang="ts" setup>
-defineOptions({ name: 'MyFormCreate' })
-const attrs = useAttrs()
-const slots = useSlots()
-
-// 测试使用,查看组件 scope 值
-// const logC = (s) => {
-//   console.log(s)
-// }
-
-// 设置表单值
-const setValue = (scope: any, value: any) => {
-  const obj = {}
-  obj[scope.prop.field] = value
-  scope.api.setValue(obj)
-}
-</script>

+ 33 - 0
src/components/FormCreate/src/MyFormCreateDesigner.vue

@@ -0,0 +1,33 @@
+<!-- TODO puhui999: 没啥问题的话准备移除 -->
+<template>
+  <FcDesigner ref="designer" height="780px" />
+</template>
+
+<script lang="ts" setup>
+import { useUploadFileRule, useUploadImgRule, useUploadImgsRule } from './config'
+
+defineOptions({ name: 'MyFormCreateDesigner' })
+
+const designer = ref() // 表单设计器
+const uploadFileRule = useUploadFileRule()
+const uploadImgRule = useUploadImgRule()
+const uploadImgsRule = useUploadImgsRule()
+
+onMounted(() => {
+  // 移除自带的上传组件规则
+  designer.value?.removeMenuItem('upload')
+  const components = [uploadFileRule, uploadImgRule, uploadImgsRule]
+  components.forEach((component) => {
+    //插入组件规则
+    designer.value?.addComponent(component)
+    //插入拖拽按钮到`main`分类下
+    designer.value?.appendMenuItem('main', {
+      icon: component.icon,
+      name: component.name,
+      label: component.label
+    })
+  })
+})
+</script>
+
+<style lang="scss" scoped></style>

+ 5 - 0
src/components/FormCreate/src/config/index.ts

@@ -0,0 +1,5 @@
+import { useUploadFileRule } from './useUploadFileRule'
+import { useUploadImgRule } from './useUploadImgRule'
+import { useUploadImgsRule } from './useUploadImgsRule'
+
+export { useUploadFileRule, useUploadImgRule, useUploadImgsRule }

+ 80 - 0
src/components/FormCreate/src/config/useUploadFileRule.ts

@@ -0,0 +1,80 @@
+import { generateUUID } from '@/utils'
+import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
+
+export const useUploadFileRule = () => {
+  const label = '文件上传'
+  const name = 'UploadFile'
+  return {
+    icon: 'icon-upload',
+    label,
+    name,
+    rule() {
+      return {
+        type: name,
+        field: generateUUID(),
+        title: label,
+        info: '',
+        $required: false
+      }
+    },
+    props(_, { t }) {
+      return localeProps(t, name + '.props', [
+        makeRequiredRule(),
+        {
+          type: 'select',
+          field: 'fileType',
+          title: '文件类型',
+          value: ['doc', 'xls', 'ppt', 'txt', 'pdf'],
+          options: [
+            { label: 'doc', value: 'doc' },
+            { label: 'xls', value: 'xls' },
+            { label: 'ppt', value: 'ppt' },
+            { label: 'txt', value: 'txt' },
+            { label: 'pdf', value: 'pdf' }
+          ],
+          props: {
+            multiple: true
+          }
+        },
+        {
+          type: 'switch',
+          field: 'autoUpload',
+          title: '是否在选取文件后立即进行上传',
+          value: true
+        },
+        {
+          type: 'switch',
+          field: 'drag',
+          title: '拖拽上传',
+          value: false
+        },
+        {
+          type: 'switch',
+          field: 'isShowTip',
+          title: '是否显示提示',
+          value: true
+        },
+        {
+          type: 'inputNumber',
+          field: 'fileSize',
+          title: '大小限制(MB)',
+          value: 5,
+          props: { min: 0 }
+        },
+        {
+          type: 'inputNumber',
+          field: 'limit',
+          title: '数量限制',
+          value: 5,
+          props: { min: 0 }
+        },
+        {
+          type: 'switch',
+          field: 'disabled',
+          title: '是否禁用',
+          value: false
+        }
+      ])
+    }
+  }
+}

+ 89 - 0
src/components/FormCreate/src/config/useUploadImgRule.ts

@@ -0,0 +1,89 @@
+import { generateUUID } from '@/utils'
+import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
+
+export const useUploadImgRule = () => {
+  const label = '单图上传'
+  const name = 'UploadImg'
+  return {
+    icon: 'icon-upload',
+    label,
+    name,
+    rule() {
+      return {
+        type: name,
+        field: generateUUID(),
+        title: label,
+        info: '',
+        $required: false
+      }
+    },
+    props(_, { t }) {
+      return localeProps(t, name + '.props', [
+        makeRequiredRule(),
+        {
+          type: 'switch',
+          field: 'drag',
+          title: '拖拽上传',
+          value: false
+        },
+        {
+          type: 'select',
+          field: 'fileType',
+          title: '图片类型限制',
+          value: ['image/jpeg', 'image/png', 'image/gif'],
+          options: [
+            { label: 'image/apng', value: 'image/apng' },
+            { label: 'image/bmp', value: 'image/bmp' },
+            { label: 'image/gif', value: 'image/gif' },
+            { label: 'image/jpeg', value: 'image/jpeg' },
+            { label: 'image/pjpeg', value: 'image/pjpeg' },
+            { label: 'image/svg+xml', value: 'image/svg+xml' },
+            { label: 'image/tiff', value: 'image/tiff' },
+            { label: 'image/webp', value: 'image/webp' },
+            { label: 'image/x-icon', value: 'image/x-icon' }
+          ],
+          props: {
+            multiple: true
+          }
+        },
+        {
+          type: 'inputNumber',
+          field: 'fileSize',
+          title: '大小限制(MB)',
+          value: 5,
+          props: { min: 0 }
+        },
+        {
+          type: 'input',
+          field: 'height',
+          title: '组件高度',
+          value: '150px'
+        },
+        {
+          type: 'input',
+          field: 'width',
+          title: '组件宽度',
+          value: '150px'
+        },
+        {
+          type: 'input',
+          field: 'borderradius',
+          title: '组件边框圆角',
+          value: '8px'
+        },
+        {
+          type: 'switch',
+          field: 'disabled',
+          title: '是否显示删除按钮',
+          value: true
+        },
+        {
+          type: 'switch',
+          field: 'showBtnText',
+          title: '是否显示按钮文字',
+          value: true
+        }
+      ])
+    }
+  }
+}

+ 84 - 0
src/components/FormCreate/src/config/useUploadImgsRule.ts

@@ -0,0 +1,84 @@
+import { generateUUID } from '@/utils'
+import { localeProps, makeRequiredRule } from '@/components/FormCreate/src/utils'
+
+export const useUploadImgsRule = () => {
+  const label = '多图上传'
+  const name = 'UploadImgs'
+  return {
+    icon: 'icon-upload',
+    label,
+    name,
+    rule() {
+      return {
+        type: name,
+        field: generateUUID(),
+        title: label,
+        info: '',
+        $required: false
+      }
+    },
+    props(_, { t }) {
+      return localeProps(t, name + '.props', [
+        makeRequiredRule(),
+        {
+          type: 'switch',
+          field: 'drag',
+          title: '拖拽上传',
+          value: false
+        },
+        {
+          type: 'select',
+          field: 'fileType',
+          title: '图片类型限制',
+          value: ['image/jpeg', 'image/png', 'image/gif'],
+          options: [
+            { label: 'image/apng', value: 'image/apng' },
+            { label: 'image/bmp', value: 'image/bmp' },
+            { label: 'image/gif', value: 'image/gif' },
+            { label: 'image/jpeg', value: 'image/jpeg' },
+            { label: 'image/pjpeg', value: 'image/pjpeg' },
+            { label: 'image/svg+xml', value: 'image/svg+xml' },
+            { label: 'image/tiff', value: 'image/tiff' },
+            { label: 'image/webp', value: 'image/webp' },
+            { label: 'image/x-icon', value: 'image/x-icon' }
+          ],
+          props: {
+            multiple: true
+          }
+        },
+        {
+          type: 'inputNumber',
+          field: 'fileSize',
+          title: '大小限制(MB)',
+          value: 5,
+          props: { min: 0 }
+        },
+        {
+          type: 'inputNumber',
+          field: 'limit',
+          title: '数量限制',
+          value: 5,
+          props: { min: 0 }
+        },
+        {
+          type: 'input',
+          field: 'height',
+          title: '组件高度',
+          value: '150px'
+        },
+        {
+          type: 'input',
+          field: 'width',
+          title: '组件宽度',
+          value: '150px'
+        },
+        {
+          type: 'input',
+          field: 'borderradius',
+          title: '组件边框圆角',
+          value: '8px'
+        }
+      ])
+    }
+  }
+}

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

@@ -0,0 +1,31 @@
+import { useUploadFileRule, useUploadImgRule, useUploadImgsRule } from './config'
+import { Ref } from 'vue'
+
+/**
+ * 表单设计器增强 hook
+ * 新增
+ * - 文件上传
+ * - 单图上传
+ * - 多图上传
+ */
+export const useFormCreateDesigner = (designer: Ref) => {
+  const uploadFileRule = useUploadFileRule()
+  const uploadImgRule = useUploadImgRule()
+  const uploadImgsRule = useUploadImgsRule()
+
+  onMounted(() => {
+    // 移除自带的上传组件规则
+    designer.value?.removeMenuItem('upload')
+    const components = [uploadFileRule, uploadImgRule, uploadImgsRule]
+    components.forEach((component) => {
+      //插入组件规则
+      designer.value?.addComponent(component)
+      //插入拖拽按钮到`main`分类下
+      designer.value?.appendMenuItem('main', {
+        icon: component.icon,
+        name: component.name,
+        label: component.label
+      })
+    })
+  })
+}

+ 19 - 0
src/components/FormCreate/src/utils/index.ts

@@ -0,0 +1,19 @@
+// TODO puhui999: 借鉴一下 form-create-designer utils 方法 🤣 (导入不了只能先 copy 过来用下)
+export function makeRequiredRule() {
+  return {
+    type: 'Required',
+    field: 'formCreate$required',
+    title: '是否必填'
+  }
+}
+
+export const localeProps = (t, prefix, rules) => {
+  return rules.map((rule) => {
+    if (rule.field === 'formCreate$required') {
+      rule.title = t('props.required') || rule.title
+    } else if (rule.field && rule.field !== '_optionType') {
+      rule.title = t('components.' + prefix + '.' + rule.field) || rule.title
+    }
+    return rule
+  })
+}

+ 0 - 1
src/components/UploadFile/src/UploadFile.vue

@@ -49,7 +49,6 @@ const emit = defineEmits(['update:modelValue'])
 
 const props = defineProps({
   modelValue: propTypes.oneOfType<string | string[]>([String, Array<String>]).isRequired,
-  title: propTypes.string.def('文件上传'),
   fileType: propTypes.array.def(['doc', 'xls', 'ppt', 'txt', 'pdf']), // 文件类型, 例如['png', 'jpg', 'jpeg']
   fileSize: propTypes.number.def(5), // 大小限制(MB)
   limit: propTypes.number.def(5), // 数量限制

+ 15 - 9
src/plugins/formCreate/index.ts

@@ -1,22 +1,24 @@
 import type { App } from 'vue'
 // 👇使用 form-create 需额外全局引入 element plus 组件
 import {
+  ElAlert,
   ElAside,
-  ElPopconfirm,
-  ElHeader,
-  ElMain,
   ElContainer,
   ElDivider,
-  ElTransfer,
-  ElAlert,
-  ElTabs,
+  ElHeader,
+  ElMain,
+  ElPopconfirm,
   ElTable,
   ElTableColumn,
-  ElTabPane
+  ElTabPane,
+  ElTabs,
+  ElTransfer
 } from 'element-plus'
-
+import FcDesigner from '@form-create/designer'
 import formCreate from '@form-create/element-ui'
 import install from '@form-create/element-ui/auto-import'
+//======================= 自定义组件 =======================
+import { UploadFile, UploadImg, UploadImgs } from '@/components/UploadFile'
 
 const components = [
   ElAside,
@@ -30,7 +32,10 @@ const components = [
   ElTabs,
   ElTable,
   ElTableColumn,
-  ElTabPane
+  ElTabPane,
+  UploadImg,
+  UploadImgs,
+  UploadFile
 ]
 
 // 参考 http://www.form-create.com/v3/element-ui/auto-import.html 文档
@@ -40,4 +45,5 @@ export const setupFormCreate = (app: App<Element>) => {
   })
   formCreate.use(install)
   app.use(formCreate)
+  app.use(FcDesigner)
 }

+ 2 - 0
src/views/bpm/form/editor/index.vue

@@ -45,6 +45,7 @@ import * as FormApi from '@/api/bpm/form'
 import FcDesigner from '@form-create/designer'
 import { encodeConf, encodeFields, setConfAndFields } from '@/utils/formCreate'
 import { useTagsViewStore } from '@/store/modules/tagsView'
+import { useFormCreateDesigner } from '@/components/FormCreate'
 
 defineOptions({ name: 'BpmFormEditor' })
 
@@ -55,6 +56,7 @@ const { query } = useRoute() // 路由信息
 const { delView } = useTagsViewStore() // 视图操作
 
 const designer = ref() // 表单设计器
+useFormCreateDesigner(designer) // 表单设计器增强
 const dialogVisible = ref(false) // 弹窗是否展示
 const formLoading = ref(false) // 表单的加载中:提交的按钮禁用
 const formData = ref({

+ 1 - 1
src/views/bpm/form/index.vue

@@ -88,7 +88,7 @@
 
   <!-- 表单详情的弹窗 -->
   <Dialog v-model="detailVisible" title="表单详情" width="800">
-    <my-form-create :option="detailData.option" :rule="detailData.rule" />
+    <form-create :option="detailData.option" :rule="detailData.rule" />
   </Dialog>
 </template>
 

+ 3 - 3
src/views/bpm/processInstance/detail/index.vue

@@ -24,15 +24,15 @@
             {{ processInstance?.startUser.nickname }}
             <el-tag size="small" type="info">{{ processInstance?.startUser.deptName }}</el-tag>
           </el-form-item>
-          <el-card class="mb-15px !-mt-10px" v-if="runningTasks[index].formId > 0">
+          <el-card v-if="runningTasks[index].formId > 0" class="mb-15px !-mt-10px">
             <template #header>
               <span class="el-icon-picture-outline">
                 填写表单【{{ runningTasks[index]?.formName }}】
               </span>
             </template>
             <form-create
-              v-model:api="approveFormFApis[index]"
               v-model="approveForms[index].value"
+              v-model:api="approveFormFApis[index]"
               :option="approveForms[index].option"
               :rule="approveForms[index].rule"
             />
@@ -91,7 +91,7 @@
       </template>
       <!-- 情况一:流程表单 -->
       <el-col v-if="processInstance?.processDefinition?.formType === 10" :offset="6" :span="16">
-        <my-form-create
+        <form-create
           v-model="detailForm.value"
           v-model:api="fApi"
           :option="detailForm.option"

+ 6 - 5
src/views/infra/build/index.vue

@@ -30,8 +30,7 @@
   </Dialog>
 </template>
 <script lang="ts" setup>
-defineOptions({ name: 'InfraBuild' })
-import FcDesigner from '@form-create/designer'
+import { useFormCreateDesigner } from '@/components/FormCreate'
 import { useClipboard } from '@vueuse/core'
 import { isString } from '@/utils/is'
 
@@ -41,6 +40,8 @@ import xml from 'highlight.js/lib/languages/java'
 import json from 'highlight.js/lib/languages/json'
 import formCreate from '@form-create/element-ui'
 
+defineOptions({ name: 'InfraBuild' })
+
 const { t } = useI18n() // 国际化
 const message = useMessage() // 消息
 
@@ -49,7 +50,7 @@ const dialogVisible = ref(false) // 弹窗的是否展示
 const dialogTitle = ref('') // 弹窗的标题
 const formType = ref(-1) // 表单的类型:0 - 生成 JSON;1 - 生成 Options;2 - 生成组件
 const formData = ref('') // 表单数据
-
+useFormCreateDesigner(designer) // 表单设计器增强
 /** 打开弹窗 */
 const openModel = (title: string) => {
   dialogVisible.value = true
@@ -81,12 +82,12 @@ const makeTemplate = () => {
   const rule = designer.value.getRule()
   const opt = designer.value.getOption()
   return `<template>
-    <my-form-create
+    <form-create
       v-model:api="fApi"
       :rule="rule"
       :option="option"
       @submit="onSubmit"
-    ></my-form-create>
+    ></form-create>
   </template>
   <script setup lang=ts>
     const faps = ref(null)