perf: formdesign
							parent
							
								
									45a4ac80d9
								
							
						
					
					
						commit
						f4ca72a7a2
					
				| 
						 | 
				
			
			@ -1,18 +1,10 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import type { PropType } from 'vue'
 | 
			
		||||
import { defineComponent } from 'vue'
 | 
			
		||||
import { Col, Row } from 'ant-design-vue'
 | 
			
		||||
import type { IFormConfig, IVFormComponent } from '../../../typings/v-form-component'
 | 
			
		||||
import VFormItem from '../../VFormItem/index.vue'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'FormRender',
 | 
			
		||||
  components: {
 | 
			
		||||
    VFormItem,
 | 
			
		||||
    Row,
 | 
			
		||||
    Col,
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
defineProps({
 | 
			
		||||
  formData: {
 | 
			
		||||
    type: Object,
 | 
			
		||||
    default: () => ({}),
 | 
			
		||||
| 
						 | 
				
			
			@ -29,16 +21,20 @@ export default defineComponent({
 | 
			
		|||
    type: Function as PropType<(key: string, value: any) => void>,
 | 
			
		||||
    default: null,
 | 
			
		||||
  },
 | 
			
		||||
  },
 | 
			
		||||
  emits: ['change', 'submit', 'reset'],
 | 
			
		||||
  setup(_props) {},
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['change', 'submit', 'reset'])
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <template v-if="['Grid'].includes(schema.component)">
 | 
			
		||||
    <Row class="grid-row">
 | 
			
		||||
      <Col v-for="(colItem, index) in schema.columns" :key="index" class="grid-col" :span="colItem.span">
 | 
			
		||||
      <Col
 | 
			
		||||
        v-for="(colItem, index) in schema.columns"
 | 
			
		||||
        :key="index"
 | 
			
		||||
        class="grid-col"
 | 
			
		||||
        :span="colItem.span"
 | 
			
		||||
      >
 | 
			
		||||
        <FormRender
 | 
			
		||||
          v-for="(item, k) in colItem.children"
 | 
			
		||||
          :key="k"
 | 
			
		||||
| 
						 | 
				
			
			@ -56,11 +52,14 @@ export default defineComponent({
 | 
			
		|||
    :schema="schema"
 | 
			
		||||
    :form-data="formData"
 | 
			
		||||
    :set-form-model="setFormModel"
 | 
			
		||||
    @change="$emit('change', { schema, value: $event })"
 | 
			
		||||
    @submit="$emit('submit', schema)"
 | 
			
		||||
    @reset="$emit('reset')"
 | 
			
		||||
    @change="emit('change', { schema, value: $event })"
 | 
			
		||||
    @submit="emit('submit', schema)"
 | 
			
		||||
    @reset="emit('reset')"
 | 
			
		||||
  >
 | 
			
		||||
    <template
 | 
			
		||||
      v-if="schema.componentProps && schema.componentProps.slotName"
 | 
			
		||||
      #[schema.componentProps!.slotName]
 | 
			
		||||
    >
 | 
			
		||||
    <template v-if="schema.componentProps && schema.componentProps.slotName" #[schema.componentProps!.slotName]>
 | 
			
		||||
      <slot :name="schema.componentProps!.slotName" />
 | 
			
		||||
    </template>
 | 
			
		||||
  </VFormItem>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,12 +45,16 @@ export default defineComponent({
 | 
			
		|||
    })
 | 
			
		||||
 | 
			
		||||
    const noHiddenList = computed(() => {
 | 
			
		||||
      return props.formConfig.schemas && props.formConfig.schemas.filter(item => item.hidden !== true)
 | 
			
		||||
      return (
 | 
			
		||||
        props.formConfig.schemas
 | 
			
		||||
          && props.formConfig.schemas.filter(item => item.hidden !== true)
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    const fApi = useVModel(props, 'fApi', emit)
 | 
			
		||||
 | 
			
		||||
    const { submit, validate, clearValidate, resetFields, validateField } = useFormInstanceMethods(props, formModelNew, context, eFormModel)
 | 
			
		||||
    const { submit, validate, clearValidate, resetFields, validateField }
 | 
			
		||||
        = useFormInstanceMethods(props, formModelNew, context, eFormModel)
 | 
			
		||||
 | 
			
		||||
    const { linkOn, ...methods } = useVFormMethods(
 | 
			
		||||
      { formConfig: props.formConfig, formData: props.formModel } as unknown as IProps,
 | 
			
		||||
| 
						 | 
				
			
			@ -78,7 +82,9 @@ export default defineComponent({
 | 
			
		|||
    /**
 | 
			
		||||
     * 获取表单属性
 | 
			
		||||
     */
 | 
			
		||||
    const formModelProps = computed(() => omit(props.formConfig, ['disabled', 'labelWidth', 'schemas']) as Recordable)
 | 
			
		||||
    const formModelProps = computed(
 | 
			
		||||
      () => omit(props.formConfig, ['disabled', 'labelWidth', 'schemas']) as Recordable,
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    const handleSubmit = () => {
 | 
			
		||||
      submit()
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +133,10 @@ export default defineComponent({
 | 
			
		|||
          @reset="resetFields"
 | 
			
		||||
        >
 | 
			
		||||
          <template v-if="schema && schema.componentProps" #[`schema.componentProps!.slotName`]>
 | 
			
		||||
            <slot :name="schema.componentProps!.slotName" v-bind="{ formModel, field: schema.field, schema }" />
 | 
			
		||||
            <slot
 | 
			
		||||
              :name="schema.componentProps!.slotName"
 | 
			
		||||
              v-bind="{ formModel, field: schema.field, schema }"
 | 
			
		||||
            />
 | 
			
		||||
          </template>
 | 
			
		||||
        </FormRender>
 | 
			
		||||
      </Row>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description: 渲染代码
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { computed, defineComponent, reactive, toRefs } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, reactive } from 'vue'
 | 
			
		||||
import { Modal } from 'ant-design-vue'
 | 
			
		||||
import { formatRules, removeAttrs } from '../../../utils'
 | 
			
		||||
import type { IFormConfig } from '../../../typings/v-form-component'
 | 
			
		||||
| 
						 | 
				
			
			@ -38,37 +38,31 @@ let codeVueLast = `
 | 
			
		|||
     }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
<\/script>`
 | 
			
		||||
<\/script>`;
 | 
			
		||||
//
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'CodeModal',
 | 
			
		||||
  components: { PreviewCode, Modal },
 | 
			
		||||
  setup() {
 | 
			
		||||
const state = reactive({
 | 
			
		||||
  open: false,
 | 
			
		||||
      jsonData: {} as IFormConfig
 | 
			
		||||
    })
 | 
			
		||||
  jsonData: {} as IFormConfig,
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
const showModal = (formConfig: IFormConfig) => {
 | 
			
		||||
      formConfig.schemas && formatRules(formConfig.schemas)
 | 
			
		||||
      state.open = true
 | 
			
		||||
      state.jsonData = formConfig
 | 
			
		||||
    }
 | 
			
		||||
  formConfig.schemas && formatRules(formConfig.schemas);
 | 
			
		||||
  state.open = true;
 | 
			
		||||
  state.jsonData = formConfig;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
const editorVueJson = computed(() => {
 | 
			
		||||
      return codeVueFront + JSON.stringify(removeAttrs(state.jsonData), null, '\t') + codeVueLast
 | 
			
		||||
    })
 | 
			
		||||
  return codeVueFront + JSON.stringify(removeAttrs(state.jsonData), null, '\t') + codeVueLast;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
    return { ...toRefs(state), editorVueJson, showModal }
 | 
			
		||||
  }
 | 
			
		||||
})
 | 
			
		||||
defineExpose({ showModal })
 | 
			
		||||
</script>
 | 
			
		||||
<template>
 | 
			
		||||
  <Modal
 | 
			
		||||
    title="代码"
 | 
			
		||||
    :footer="null"
 | 
			
		||||
    :open="open"
 | 
			
		||||
    @cancel="open = false"
 | 
			
		||||
    :open="state.open"
 | 
			
		||||
    @cancel="state.open = false"
 | 
			
		||||
    wrapClassName="v-code-modal"
 | 
			
		||||
    style="top: 20px"
 | 
			
		||||
    width="850px"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,20 @@
 | 
			
		|||
 * @Description: 组件属性控件
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { Checkbox, Col, Empty, Form, FormItem, Input, InputNumber, RadioGroup, Row, Select, Switch } from 'ant-design-vue'
 | 
			
		||||
import {
 | 
			
		||||
  Checkbox,
 | 
			
		||||
  Col,
 | 
			
		||||
  Empty,
 | 
			
		||||
  Form,
 | 
			
		||||
  FormItem,
 | 
			
		||||
  Input,
 | 
			
		||||
  InputNumber,
 | 
			
		||||
  RadioGroup,
 | 
			
		||||
  Row,
 | 
			
		||||
  Select,
 | 
			
		||||
  Switch,
 | 
			
		||||
} from 'ant-design-vue'
 | 
			
		||||
import RadioButtonGroup from '/@/components/Form/src/components/RadioButtonGroup.vue'
 | 
			
		||||
import { computed, defineComponent, ref, watch } from 'vue'
 | 
			
		||||
import { useFormDesignState } from '../../../hooks/useFormDesignState'
 | 
			
		||||
import {
 | 
			
		||||
| 
						 | 
				
			
			@ -14,7 +27,6 @@ import {
 | 
			
		|||
import { formItemsForEach, remove } from '../../../utils'
 | 
			
		||||
import type { IBaseFormAttrs } from '../config/formItemPropsConfig'
 | 
			
		||||
import FormOptions from './FormOptions.vue'
 | 
			
		||||
import RadioButtonGroup from '@/components/Form/src/components/RadioButtonGroup.vue'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'ComponentProps',
 | 
			
		||||
| 
						 | 
				
			
			@ -45,8 +57,10 @@ export default defineComponent({
 | 
			
		|||
 | 
			
		||||
    const { formConfig } = useFormDesignState()
 | 
			
		||||
 | 
			
		||||
    if (formConfig.value.currentItem)
 | 
			
		||||
      formConfig.value.currentItem.componentProps = formConfig.value.currentItem.componentProps || {}
 | 
			
		||||
    if (formConfig.value.currentItem) {
 | 
			
		||||
      formConfig.value.currentItem.componentProps
 | 
			
		||||
          = formConfig.value.currentItem.componentProps || {}
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    watch(
 | 
			
		||||
      () => formConfig.value.currentItem?.field,
 | 
			
		||||
| 
						 | 
				
			
			@ -114,14 +128,14 @@ export default defineComponent({
 | 
			
		|||
    // 控制性的选项
 | 
			
		||||
    const controlOptions = computed(() => {
 | 
			
		||||
      return allOptions.value.filter((item) => {
 | 
			
		||||
        return item.category === 'control'
 | 
			
		||||
        return item.category == 'control'
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    // 非控制性选择
 | 
			
		||||
    const inputOptions = computed(() => {
 | 
			
		||||
      return allOptions.value.filter((item) => {
 | 
			
		||||
        return item.category === 'input'
 | 
			
		||||
        return item.category == 'input'
 | 
			
		||||
      })
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -199,12 +213,23 @@ export default defineComponent({
 | 
			
		|||
          </FormItem>
 | 
			
		||||
        </div>
 | 
			
		||||
        <FormItem label="关联字段">
 | 
			
		||||
          <Select v-model:value="formConfig.currentItem.link" mode="multiple" :options="linkOptions" />
 | 
			
		||||
          <Select
 | 
			
		||||
            v-model:value="formConfig.currentItem.link"
 | 
			
		||||
            mode="multiple"
 | 
			
		||||
            :options="linkOptions"
 | 
			
		||||
          />
 | 
			
		||||
        </FormItem>
 | 
			
		||||
 | 
			
		||||
        <FormItem
 | 
			
		||||
          v-if="
 | 
			
		||||
            ['Select', 'CheckboxGroup', 'RadioGroup', 'TreeSelect', 'Cascader', 'AutoComplete'].includes(formConfig.currentItem.component)
 | 
			
		||||
            [
 | 
			
		||||
              'Select',
 | 
			
		||||
              'CheckboxGroup',
 | 
			
		||||
              'RadioGroup',
 | 
			
		||||
              'TreeSelect',
 | 
			
		||||
              'Cascader',
 | 
			
		||||
              'AutoComplete',
 | 
			
		||||
            ].includes(formConfig.currentItem.component)
 | 
			
		||||
          "
 | 
			
		||||
          label="选项"
 | 
			
		||||
        >
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,7 +3,18 @@
 | 
			
		|||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { computed, defineComponent, watch } from 'vue'
 | 
			
		||||
import { Checkbox, Col, Empty, Form, FormItem, Input, RadioGroup, Select, Slider, Switch } from 'ant-design-vue'
 | 
			
		||||
import {
 | 
			
		||||
  Checkbox,
 | 
			
		||||
  Col,
 | 
			
		||||
  Empty,
 | 
			
		||||
  Form,
 | 
			
		||||
  FormItem,
 | 
			
		||||
  Input,
 | 
			
		||||
  RadioGroup,
 | 
			
		||||
  Select,
 | 
			
		||||
  Slider,
 | 
			
		||||
  Switch,
 | 
			
		||||
} from 'ant-design-vue'
 | 
			
		||||
import { isArray } from 'lodash-es'
 | 
			
		||||
import {
 | 
			
		||||
  advanceFormItemColProps,
 | 
			
		||||
| 
						 | 
				
			
			@ -40,8 +51,10 @@ export default defineComponent({
 | 
			
		|||
      () => {
 | 
			
		||||
        if (formConfig.value.currentItem) {
 | 
			
		||||
          formConfig.value.currentItem.itemProps = formConfig.value.currentItem.itemProps || {}
 | 
			
		||||
          formConfig.value.currentItem.itemProps.labelCol = formConfig.value.currentItem.itemProps.labelCol || {}
 | 
			
		||||
          formConfig.value.currentItem.itemProps.wrapperCol = formConfig.value.currentItem.itemProps.wrapperCol || {}
 | 
			
		||||
          formConfig.value.currentItem.itemProps.labelCol
 | 
			
		||||
              = formConfig.value.currentItem.itemProps.labelCol || {}
 | 
			
		||||
          formConfig.value.currentItem.itemProps.wrapperCol
 | 
			
		||||
              = formConfig.value.currentItem.itemProps.wrapperCol || {}
 | 
			
		||||
        }
 | 
			
		||||
      },
 | 
			
		||||
      { deep: true, immediate: true },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -40,13 +40,19 @@ export default defineComponent({
 | 
			
		|||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="drag-move-box" :class="{ active: schema.key === formConfig.currentItem?.key }" @click.stop="handleSelectItem">
 | 
			
		||||
  <div
 | 
			
		||||
    class="drag-move-box"
 | 
			
		||||
    :class="{ active: schema.key === formConfig.currentItem?.key }"
 | 
			
		||||
    @click.stop="handleSelectItem"
 | 
			
		||||
  >
 | 
			
		||||
    <div class="form-item-box">
 | 
			
		||||
      <VFormItem :form-config="formConfig" :schema="schema" />
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <div class="show-key-box">
 | 
			
		||||
      {{ schema.label + (schema.field ? `/${schema.field}` : '') }}
 | 
			
		||||
    </div>
 | 
			
		||||
 | 
			
		||||
    <FormNodeOperate :schema="schema" :current-item="formConfig.currentItem" />
 | 
			
		||||
  </div>
 | 
			
		||||
</template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,19 +1,14 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description: 节点操作复制删除控件
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { computed, defineComponent } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed } from 'vue'
 | 
			
		||||
import type { IVFormComponent } from '../../../typings/v-form-component'
 | 
			
		||||
import { remove } from '../../../utils'
 | 
			
		||||
import { useFormDesignState } from '../../../hooks/useFormDesignState'
 | 
			
		||||
import Icon from '@/components/Icon/index'
 | 
			
		||||
import { Icon } from '@/components/Icon'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'FormNodeOperate',
 | 
			
		||||
  components: {
 | 
			
		||||
    Icon,
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  schema: {
 | 
			
		||||
    type: Object,
 | 
			
		||||
    default: () => ({}),
 | 
			
		||||
| 
						 | 
				
			
			@ -22,8 +17,8 @@ export default defineComponent({
 | 
			
		|||
    type: Object,
 | 
			
		||||
    default: () => ({}),
 | 
			
		||||
  },
 | 
			
		||||
  },
 | 
			
		||||
  setup(props) {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const { formConfig, formDesignMethods } = useFormDesignState()
 | 
			
		||||
const activeClass = computed(() => {
 | 
			
		||||
  return props.schema.key === props.currentItem.key ? 'active' : 'unactivated'
 | 
			
		||||
| 
						 | 
				
			
			@ -31,15 +26,20 @@ export default defineComponent({
 | 
			
		|||
/**
 | 
			
		||||
       * 删除当前项
 | 
			
		||||
       */
 | 
			
		||||
    const handleDelete = () => {
 | 
			
		||||
function handleDelete() {
 | 
			
		||||
  const traverse = (schemas: IVFormComponent[]) => {
 | 
			
		||||
    schemas.some((formItem, index) => {
 | 
			
		||||
          const { component, key } = formItem
 | 
			
		||||
      const { component, key } = formItem;
 | 
			
		||||
      // 处理栅格和标签页布局
 | 
			
		||||
          ;['Grid', 'Tabs'].includes(component) && formItem.columns?.forEach(item => traverse(item.children))
 | 
			
		||||
      ['Grid', 'Tabs'].includes(component)
 | 
			
		||||
              && formItem.columns?.forEach(item => traverse(item.children))
 | 
			
		||||
      if (key === props.currentItem.key) {
 | 
			
		||||
        const params: IVFormComponent
 | 
			
		||||
              = schemas.length === 1 ? { component: '' } : schemas.length - 1 > index ? schemas[index + 1] : schemas[index - 1]
 | 
			
		||||
                = schemas.length === 1
 | 
			
		||||
                  ? { component: '' }
 | 
			
		||||
                  : schemas.length - 1 > index
 | 
			
		||||
                    ? schemas[index + 1]
 | 
			
		||||
                    : schemas[index - 1]
 | 
			
		||||
        formDesignMethods.handleSetSelectItem(params)
 | 
			
		||||
        remove(schemas, index)
 | 
			
		||||
        return true
 | 
			
		||||
| 
						 | 
				
			
			@ -49,12 +49,9 @@ export default defineComponent({
 | 
			
		|||
  traverse(formConfig.value!.schemas)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    const handleCopy = () => {
 | 
			
		||||
function handleCopy() {
 | 
			
		||||
  formDesignMethods.handleCopy()
 | 
			
		||||
}
 | 
			
		||||
    return { activeClass, handleDelete, handleCopy }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,20 +1,13 @@
 | 
			
		|||
<script lang="ts">
 | 
			
		||||
import { defineComponent, reactive, toRefs } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { Input } from 'ant-design-vue'
 | 
			
		||||
import { useFormDesignState } from '../../../hooks/useFormDesignState'
 | 
			
		||||
import { remove } from '../../../utils'
 | 
			
		||||
import message from '../../../utils/message'
 | 
			
		||||
import Icon from '@/components/Icon/index'
 | 
			
		||||
import { Icon } from '@/components/Icon'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'FormOptions',
 | 
			
		||||
  components: { Input, Icon },
 | 
			
		||||
  // props: {},
 | 
			
		||||
  setup() {
 | 
			
		||||
    const state = reactive({})
 | 
			
		||||
const { formConfig } = useFormDesignState()
 | 
			
		||||
const key = formConfig.value.currentItem?.component === 'TreeSelect' ? 'treeData' : 'options'
 | 
			
		||||
    const addOptions = () => {
 | 
			
		||||
function addOptions() {
 | 
			
		||||
  if (!formConfig.value.currentItem?.componentProps?.[key])
 | 
			
		||||
    formConfig.value.currentItem!.componentProps![key] = []
 | 
			
		||||
  const len = formConfig.value.currentItem?.componentProps?.[key].length + 1
 | 
			
		||||
| 
						 | 
				
			
			@ -23,33 +16,22 @@ export default defineComponent({
 | 
			
		|||
    value: `${len}`,
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
    const deleteOptions = (index: number) => {
 | 
			
		||||
function deleteOptions(index: number) {
 | 
			
		||||
  remove(formConfig.value.currentItem?.componentProps?.[key], index)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    const addGridOptions = () => {
 | 
			
		||||
function addGridOptions() {
 | 
			
		||||
  formConfig.value.currentItem?.columns?.push({
 | 
			
		||||
    span: 12,
 | 
			
		||||
    children: [],
 | 
			
		||||
  })
 | 
			
		||||
}
 | 
			
		||||
    const deleteGridOptions = (index: number) => {
 | 
			
		||||
function deleteGridOptions(index: number) {
 | 
			
		||||
  if (index === 0)
 | 
			
		||||
    return message.warning('请至少保留一个栅格')
 | 
			
		||||
 | 
			
		||||
  remove(formConfig.value.currentItem!.columns!, index)
 | 
			
		||||
}
 | 
			
		||||
    return {
 | 
			
		||||
      ...toRefs(state),
 | 
			
		||||
      formConfig,
 | 
			
		||||
      addOptions,
 | 
			
		||||
      deleteOptions,
 | 
			
		||||
      key,
 | 
			
		||||
      deleteGridOptions,
 | 
			
		||||
      addGridOptions,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,28 +1,19 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description: 右侧属性面板控件 表单属性面板
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import type { RadioChangeEvent } from 'ant-design-vue'
 | 
			
		||||
import { Checkbox, Col, InputNumber, Slider } from 'ant-design-vue'
 | 
			
		||||
 | 
			
		||||
// import RadioButtonGroup from '/@/components/RadioButtonGroup.vue';
 | 
			
		||||
import { Form, FormItem, Radio } from 'ant-design-vue'
 | 
			
		||||
import { useFormDesignState } from '../../../hooks/useFormDesignState'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'FormProps',
 | 
			
		||||
  components: {
 | 
			
		||||
    InputNumber,
 | 
			
		||||
    Slider,
 | 
			
		||||
import {
 | 
			
		||||
  Checkbox,
 | 
			
		||||
    RadioGroup: Radio.Group,
 | 
			
		||||
    RadioButton: Radio.Button,
 | 
			
		||||
  Col,
 | 
			
		||||
  Form,
 | 
			
		||||
  FormItem,
 | 
			
		||||
    Col,
 | 
			
		||||
  },
 | 
			
		||||
  setup() {
 | 
			
		||||
  InputNumber,
 | 
			
		||||
  Radio,
 | 
			
		||||
  Slider,
 | 
			
		||||
} from 'ant-design-vue'
 | 
			
		||||
import { useFormDesignState } from '../../../hooks/useFormDesignState'
 | 
			
		||||
 | 
			
		||||
const { formConfig } = useFormDesignState()
 | 
			
		||||
 | 
			
		||||
formConfig.value = formConfig.value || {
 | 
			
		||||
| 
						 | 
				
			
			@ -30,14 +21,10 @@ export default defineComponent({
 | 
			
		|||
  wrapperCol: { span: 24 },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    const lableLayoutChange = (e: RadioChangeEvent) => {
 | 
			
		||||
function lableLayoutChange(e: RadioChangeEvent) {
 | 
			
		||||
  if (e.target.value === 'Grid')
 | 
			
		||||
    formConfig.value.layout = 'horizontal'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    return { formConfig, lableLayoutChange }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
| 
						 | 
				
			
			@ -46,33 +33,42 @@ export default defineComponent({
 | 
			
		|||
      <!--      <e-upload v-model="fileList"></e-upload> -->
 | 
			
		||||
 | 
			
		||||
      <FormItem label="表单布局">
 | 
			
		||||
        <RadioGroup v-model:value="formConfig.layout" button-style="solid">
 | 
			
		||||
          <RadioButton value="horizontal">
 | 
			
		||||
        <Radio.Group v-model:value="formConfig.layout" button-style="solid">
 | 
			
		||||
          <Radio.Button value="horizontal">
 | 
			
		||||
            水平
 | 
			
		||||
          </RadioButton>
 | 
			
		||||
          <RadioButton value="vertical" :disabled="formConfig.labelLayout === 'Grid'">
 | 
			
		||||
          </Radio.Button>
 | 
			
		||||
          <Radio.Button value="vertical" :disabled="formConfig.labelLayout === 'Grid'">
 | 
			
		||||
            垂直
 | 
			
		||||
          </RadioButton>
 | 
			
		||||
          <RadioButton value="inline" :disabled="formConfig.labelLayout === 'Grid'">
 | 
			
		||||
          </Radio.Button>
 | 
			
		||||
          <Radio.Button value="inline" :disabled="formConfig.labelLayout === 'Grid'">
 | 
			
		||||
            行内
 | 
			
		||||
          </RadioButton>
 | 
			
		||||
        </RadioGroup>
 | 
			
		||||
          </Radio.Button>
 | 
			
		||||
        </Radio.Group>
 | 
			
		||||
      </FormItem>
 | 
			
		||||
 | 
			
		||||
      <!-- <Row> -->
 | 
			
		||||
      <FormItem label="标签布局">
 | 
			
		||||
        <RadioGroup v-model:value="formConfig.labelLayout" button-style="solid" @change="lableLayoutChange">
 | 
			
		||||
          <RadioButton value="flex">
 | 
			
		||||
        <Radio.Group
 | 
			
		||||
          v-model:value="formConfig.labelLayout"
 | 
			
		||||
          button-style="solid"
 | 
			
		||||
          @change="lableLayoutChange"
 | 
			
		||||
        >
 | 
			
		||||
          <Radio.Button value="flex">
 | 
			
		||||
            固定
 | 
			
		||||
          </RadioButton>
 | 
			
		||||
          <RadioButton value="Grid" :disabled="formConfig.layout !== 'horizontal'">
 | 
			
		||||
          </Radio.Button>
 | 
			
		||||
          <Radio.Button value="Grid" :disabled="formConfig.layout !== 'horizontal'">
 | 
			
		||||
            栅格
 | 
			
		||||
          </RadioButton>
 | 
			
		||||
        </RadioGroup>
 | 
			
		||||
          </Radio.Button>
 | 
			
		||||
        </Radio.Group>
 | 
			
		||||
      </FormItem>
 | 
			
		||||
      <!-- </Row> -->
 | 
			
		||||
      <FormItem v-show="formConfig.labelLayout === 'flex'" label="标签宽度(px)">
 | 
			
		||||
        <InputNumber v-model:value="formConfig.labelWidth" :style="{ width: '100%' }" :min="0" :step="1" />
 | 
			
		||||
        <InputNumber
 | 
			
		||||
          v-model:value="formConfig.labelWidth"
 | 
			
		||||
          :style="{ width: '100%' }"
 | 
			
		||||
          :min="0"
 | 
			
		||||
          :step="1"
 | 
			
		||||
        />
 | 
			
		||||
      </FormItem>
 | 
			
		||||
      <div v-if="formConfig.labelLayout === 'Grid'">
 | 
			
		||||
        <FormItem label="labelCol">
 | 
			
		||||
| 
						 | 
				
			
			@ -83,28 +79,28 @@ export default defineComponent({
 | 
			
		|||
        </FormItem>
 | 
			
		||||
 | 
			
		||||
        <FormItem label="标签对齐">
 | 
			
		||||
          <RadioGroup v-model:value="formConfig.labelAlign" button-style="solid">
 | 
			
		||||
            <RadioButton value="left">
 | 
			
		||||
          <Radio.Group v-model:value="formConfig.labelAlign" button-style="solid">
 | 
			
		||||
            <Radio.Button value="left">
 | 
			
		||||
              靠左
 | 
			
		||||
            </RadioButton>
 | 
			
		||||
            <RadioButton value="right">
 | 
			
		||||
            </Radio.Button>
 | 
			
		||||
            <Radio.Button value="right">
 | 
			
		||||
              靠右
 | 
			
		||||
            </RadioButton>
 | 
			
		||||
          </RadioGroup>
 | 
			
		||||
            </Radio.Button>
 | 
			
		||||
          </Radio.Group>
 | 
			
		||||
        </FormItem>
 | 
			
		||||
 | 
			
		||||
        <FormItem label="控件大小">
 | 
			
		||||
          <RadioGroup v-model:value="formConfig.size" button-style="solid">
 | 
			
		||||
            <RadioButton value="default">
 | 
			
		||||
          <Radio.Group v-model:value="formConfig.size" button-style="solid">
 | 
			
		||||
            <Radio.Button value="default">
 | 
			
		||||
              默认
 | 
			
		||||
            </RadioButton>
 | 
			
		||||
            <RadioButton value="small">
 | 
			
		||||
            </Radio.Button>
 | 
			
		||||
            <Radio.Button value="small">
 | 
			
		||||
              小
 | 
			
		||||
            </RadioButton>
 | 
			
		||||
            <RadioButton value="large">
 | 
			
		||||
            </Radio.Button>
 | 
			
		||||
            <Radio.Button value="large">
 | 
			
		||||
              大
 | 
			
		||||
            </RadioButton>
 | 
			
		||||
          </RadioGroup>
 | 
			
		||||
            </Radio.Button>
 | 
			
		||||
          </Radio.Group>
 | 
			
		||||
        </FormItem>
 | 
			
		||||
      </div>
 | 
			
		||||
      <FormItem label="表单属性">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description: 导入JSON模板
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent, reactive, ref, toRefs } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { reactive, ref } from 'vue'
 | 
			
		||||
 | 
			
		||||
// import message from '../../../utils/message';
 | 
			
		||||
import { Modal, Upload } from 'ant-design-vue'
 | 
			
		||||
| 
						 | 
				
			
			@ -14,14 +14,6 @@ import { formItemsForEach, generateKey } from '../../../utils'
 | 
			
		|||
import { CodeEditor, MODE } from '@/components/CodeEditor'
 | 
			
		||||
import { useMessage } from '@/hooks/web/useMessage'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'ImportJsonModal',
 | 
			
		||||
  components: {
 | 
			
		||||
    CodeEditor,
 | 
			
		||||
    Upload,
 | 
			
		||||
    Modal,
 | 
			
		||||
  },
 | 
			
		||||
  setup() {
 | 
			
		||||
const { createMessage } = useMessage()
 | 
			
		||||
 | 
			
		||||
const myEditor = ref(null)
 | 
			
		||||
| 
						 | 
				
			
			@ -53,13 +45,13 @@ export default defineComponent({
 | 
			
		|||
  handleSetSelectItem: null,
 | 
			
		||||
})
 | 
			
		||||
const { formDesignMethods } = useFormDesignState()
 | 
			
		||||
    const handleCancel = () => {
 | 
			
		||||
function handleCancel() {
 | 
			
		||||
  state.open = false
 | 
			
		||||
}
 | 
			
		||||
    const showModal = () => {
 | 
			
		||||
function showModal() {
 | 
			
		||||
  state.open = true
 | 
			
		||||
}
 | 
			
		||||
    const handleImportJson = () => {
 | 
			
		||||
function handleImportJson() {
 | 
			
		||||
  // 导入JSON
 | 
			
		||||
  try {
 | 
			
		||||
    const editorJsonData = JSON.parse(state.json) as IFormConfig
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +71,7 @@ export default defineComponent({
 | 
			
		|||
    createMessage.error('导入失败,数据格式不对')
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
    const beforeUpload = (e: File) => {
 | 
			
		||||
function beforeUpload(e: File) {
 | 
			
		||||
  // 通过json文件导入
 | 
			
		||||
  const reader = new FileReader()
 | 
			
		||||
  reader.readAsText(e)
 | 
			
		||||
| 
						 | 
				
			
			@ -90,23 +82,13 @@ export default defineComponent({
 | 
			
		|||
  return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    return {
 | 
			
		||||
      myEditor,
 | 
			
		||||
      handleImportJson,
 | 
			
		||||
      beforeUpload,
 | 
			
		||||
      handleCancel,
 | 
			
		||||
      showModal,
 | 
			
		||||
      ...toRefs(state),
 | 
			
		||||
      MODE,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
defineExpose({ showModal })
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Modal
 | 
			
		||||
    title="JSON数据"
 | 
			
		||||
    :open="open"
 | 
			
		||||
    :open="state.open"
 | 
			
		||||
    cancel-text="关闭"
 | 
			
		||||
    :destroy-on-close="true"
 | 
			
		||||
    wrap-class-name="v-code-modal"
 | 
			
		||||
| 
						 | 
				
			
			@ -126,7 +108,12 @@ export default defineComponent({
 | 
			
		|||
      <a-button @click="handleCancel">
 | 
			
		||||
        取消
 | 
			
		||||
      </a-button>
 | 
			
		||||
      <Upload class="upload-button" :before-upload="beforeUpload" :show-upload-list="false" accept="application/json">
 | 
			
		||||
      <Upload
 | 
			
		||||
        class="upload-button"
 | 
			
		||||
        :before-upload="beforeUpload"
 | 
			
		||||
        :show-upload-list="false"
 | 
			
		||||
        accept="application/json"
 | 
			
		||||
      >
 | 
			
		||||
        <a-button type="primary">
 | 
			
		||||
          导入json文件
 | 
			
		||||
        </a-button>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,21 +1,15 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description: 渲染JSON数据
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { computed, defineComponent, reactive, toRefs } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, reactive } from 'vue'
 | 
			
		||||
import { Modal } from 'ant-design-vue'
 | 
			
		||||
import type { IFormConfig } from '../../../typings/v-form-component'
 | 
			
		||||
import { formatRules, removeAttrs } from '../../../utils'
 | 
			
		||||
import PreviewCode from './PreviewCode.vue'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'JsonModal',
 | 
			
		||||
  components: {
 | 
			
		||||
    PreviewCode,
 | 
			
		||||
    Modal,
 | 
			
		||||
  },
 | 
			
		||||
  emits: ['cancel'],
 | 
			
		||||
  setup(_props, { emit }) {
 | 
			
		||||
const emit = defineEmits(['cancel'])
 | 
			
		||||
 | 
			
		||||
const state = reactive<{
 | 
			
		||||
  open: boolean
 | 
			
		||||
  jsonData: IFormConfig
 | 
			
		||||
| 
						 | 
				
			
			@ -27,7 +21,7 @@ export default defineComponent({
 | 
			
		|||
     * 显示Json数据弹框
 | 
			
		||||
     * @param jsonData
 | 
			
		||||
     */
 | 
			
		||||
    const showModal = (jsonData: IFormConfig) => {
 | 
			
		||||
function showModal(jsonData: IFormConfig) {
 | 
			
		||||
  formatRules(jsonData.schemas)
 | 
			
		||||
  state.jsonData = jsonData
 | 
			
		||||
  state.open = true
 | 
			
		||||
| 
						 | 
				
			
			@ -39,21 +33,19 @@ export default defineComponent({
 | 
			
		|||
})
 | 
			
		||||
 | 
			
		||||
// 关闭弹框
 | 
			
		||||
    const handleCancel = () => {
 | 
			
		||||
function handleCancel() {
 | 
			
		||||
  state.open = false
 | 
			
		||||
  emit('cancel')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    return { ...toRefs(state), editorJson, handleCancel, showModal }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
defineExpose({ showModal })
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Modal
 | 
			
		||||
    title="JSON数据"
 | 
			
		||||
    :footer="null"
 | 
			
		||||
    :open="open"
 | 
			
		||||
    :open="state.open"
 | 
			
		||||
    :destroy-on-close="true"
 | 
			
		||||
    wrap-class-name="v-code-modal"
 | 
			
		||||
    style="top: 20px"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,13 @@ export default defineComponent({
 | 
			
		|||
      <CodeEditor ref="myEditor" :value="editorJson" :mode="MODE.JSON" />
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="copy-btn-box">
 | 
			
		||||
      <a-button type="primary" class="copy-btn" data-clipboard-action="copy" :data-clipboard-text="editorJson" @click="handleCopyJson">
 | 
			
		||||
      <a-button
 | 
			
		||||
        type="primary"
 | 
			
		||||
        class="copy-btn"
 | 
			
		||||
        data-clipboard-action="copy"
 | 
			
		||||
        :data-clipboard-text="editorJson"
 | 
			
		||||
        @click="handleCopyJson"
 | 
			
		||||
      >
 | 
			
		||||
        复制数据
 | 
			
		||||
      </a-button>
 | 
			
		||||
      <a-button type="primary" @click="handleExportJson">
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -183,7 +183,9 @@ export const baseFormItemProps: IBaseFormAttrs[] = [
 | 
			
		|||
    label: '控件-FormItem',
 | 
			
		||||
    component: 'Select',
 | 
			
		||||
    componentProps: {
 | 
			
		||||
      options: baseComponents.concat(customComponents).map(item => ({ value: item.component, label: item.label })),
 | 
			
		||||
      options: baseComponents
 | 
			
		||||
        .concat(customComponents)
 | 
			
		||||
        .map(item => ({ value: item.component, label: item.label })),
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,10 @@
 | 
			
		|||
<script lang="ts" setup>
 | 
			
		||||
import { type Ref, provide, ref } from 'vue'
 | 
			
		||||
import type { Ref } from 'vue'
 | 
			
		||||
import { provide, ref } from 'vue'
 | 
			
		||||
import { Layout, LayoutContent, LayoutSider } from 'ant-design-vue'
 | 
			
		||||
 | 
			
		||||
import { cloneDeep } from 'lodash-es'
 | 
			
		||||
import { type UseRefHistoryReturn, useRefHistory } from '@vueuse/core'
 | 
			
		||||
import type { UseRefHistoryReturn } from '@vueuse/core'
 | 
			
		||||
import { useRefHistory } from '@vueuse/core'
 | 
			
		||||
import VFormPreview from '../VFormPreview/index.vue'
 | 
			
		||||
import VFormPreview2 from '../VFormPreview/useForm.vue'
 | 
			
		||||
import type { IFormConfig, IVFormComponent, PropsTabKey } from '../../typings/v-form-component'
 | 
			
		||||
| 
						 | 
				
			
			@ -13,18 +14,14 @@ import type { IFormDesignMethods, IPropsPanel, IToolbarMethods } from '../../typ
 | 
			
		|||
import CollapseItem from './modules/CollapseItem.vue'
 | 
			
		||||
import FormComponentPanel from './modules/FormComponentPanel.vue'
 | 
			
		||||
import JsonModal from './components/JsonModal.vue'
 | 
			
		||||
 | 
			
		||||
import Toolbar from './modules/Toolbar.vue'
 | 
			
		||||
import PropsPanel from './modules/PropsPanel.vue'
 | 
			
		||||
import ImportJsonModal from './components/ImportJsonModal.vue'
 | 
			
		||||
import CodeModal from './components/CodeModal.vue'
 | 
			
		||||
 | 
			
		||||
import 'codemirror/mode/javascript/javascript'
 | 
			
		||||
 | 
			
		||||
import { globalConfigState } from './config/formItemPropsConfig'
 | 
			
		||||
import { useDesign } from '@/hooks/web/useDesign'
 | 
			
		||||
 | 
			
		||||
import { CollapseContainer } from '@/components/Container/index'
 | 
			
		||||
import 'codemirror/mode/javascript/javascript'
 | 
			
		||||
 | 
			
		||||
defineProps({
 | 
			
		||||
  title: {
 | 
			
		||||
| 
						 | 
				
			
			@ -94,7 +91,9 @@ const historyReturn = useRefHistory(formConfig, {
 | 
			
		|||
 */
 | 
			
		||||
function handleSetSelectItem(schema: IVFormComponent) {
 | 
			
		||||
  formConfig.value.currentItem = schema
 | 
			
		||||
  handleChangePropsTabs(schema.key ? (formConfig.value.activeKey! === 1 ? 2 : formConfig.value.activeKey!) : 1)
 | 
			
		||||
  handleChangePropsTabs(
 | 
			
		||||
    schema.key ? (formConfig.value.activeKey! === 1 ? 2 : formConfig.value.activeKey!) : 1,
 | 
			
		||||
  )
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function setGlobalConfigState(formItem: IVFormComponent) {
 | 
			
		||||
| 
						 | 
				
			
			@ -154,7 +153,8 @@ function copyFormItem(formItem: IVFormComponent) {
 | 
			
		|||
 * @param item {IVFormComponent} 当前点击的组件
 | 
			
		||||
 * @param isCopy {boolean} 是否复制
 | 
			
		||||
 */
 | 
			
		||||
function handleCopy(item: IVFormComponent = formConfig.value.currentItem as IVFormComponent, isCopy = true) {
 | 
			
		||||
function handleCopy(item: IVFormComponent = formConfig.value.currentItem as IVFormComponent,
 | 
			
		||||
  isCopy = true) {
 | 
			
		||||
  const key = formConfig.value.currentItem?.key
 | 
			
		||||
  /**
 | 
			
		||||
   * 遍历当表单项配置,如果是复制,则复制一份表单项,如果不是复制,则直接添加到表单项中
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +165,9 @@ function handleCopy(item: IVFormComponent = formConfig.value.currentItem as IVFo
 | 
			
		|||
    schemas.some((formItem: IVFormComponent, index: number) => {
 | 
			
		||||
      if (formItem.key === key) {
 | 
			
		||||
        // 判断是不是复制
 | 
			
		||||
        isCopy ? schemas.splice(index, 0, copyFormItem(formItem)) : schemas.splice(index + 1, 0, item)
 | 
			
		||||
        isCopy
 | 
			
		||||
          ? schemas.splice(index, 0, copyFormItem(formItem))
 | 
			
		||||
          : schemas.splice(index + 1, 0, item)
 | 
			
		||||
        const event = {
 | 
			
		||||
          newIndex: index + 1,
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +256,7 @@ provide<IFormDesignMethods>('formDesignMethods', {
 | 
			
		|||
      collapsed-width="0"
 | 
			
		||||
      width="270"
 | 
			
		||||
      :zero-width-trigger-style="{
 | 
			
		||||
        'margin-top': '-70px',
 | 
			
		||||
        'margin-top': '-60px',
 | 
			
		||||
        'background-color': 'gray',
 | 
			
		||||
      }"
 | 
			
		||||
      breakpoint="md"
 | 
			
		||||
| 
						 | 
				
			
			@ -293,7 +295,11 @@ provide<IFormDesignMethods>('formDesignMethods', {
 | 
			
		|||
        @handle-open-code-modal="handleOpenModal(codeModal!)"
 | 
			
		||||
        @handle-clear-form-items="handleClearFormItems"
 | 
			
		||||
      />
 | 
			
		||||
      <FormComponentPanel :current-item="formConfig.currentItem" :data="formConfig" @handle-set-select-item="handleSetSelectItem" />
 | 
			
		||||
      <FormComponentPanel
 | 
			
		||||
        :current-item="formConfig.currentItem"
 | 
			
		||||
        :data="formConfig"
 | 
			
		||||
        @handle-set-select-item="handleSetSelectItem"
 | 
			
		||||
      />
 | 
			
		||||
    </LayoutContent>
 | 
			
		||||
    <LayoutSider
 | 
			
		||||
      :class="`right ${prefixCls}-sider`"
 | 
			
		||||
| 
						 | 
				
			
			@ -301,12 +307,15 @@ provide<IFormDesignMethods>('formDesignMethods', {
 | 
			
		|||
      :reverse-arrow="true"
 | 
			
		||||
      collapsed-width="0"
 | 
			
		||||
      width="270"
 | 
			
		||||
      :zero-width-trigger-style="{ 'margin-top': '-70px', 'background-color': 'gray' }"
 | 
			
		||||
      :zero-width-trigger-style="{ 'margin-top': '-60px', 'background-color': 'gray' }"
 | 
			
		||||
      breakpoint="lg"
 | 
			
		||||
    >
 | 
			
		||||
      <PropsPanel ref="propsPanel" :active-key="formConfig.activeKey">
 | 
			
		||||
        <template v-for="item of formConfig.schemas" #[`${item.component}Props`]="data">
 | 
			
		||||
          <slot :name="`${item.component}Props`" v-bind="{ formItem: data, props: data.componentProps }" />
 | 
			
		||||
          <slot
 | 
			
		||||
            :name="`${item.component}Props`"
 | 
			
		||||
            v-bind="{ formItem: data, props: data.componentProps }"
 | 
			
		||||
          />
 | 
			
		||||
        </template>
 | 
			
		||||
      </PropsPanel>
 | 
			
		||||
    </LayoutSider>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,24 +2,25 @@
 | 
			
		|||
import { defineComponent, reactive } from 'vue'
 | 
			
		||||
import draggable from 'vuedraggable'
 | 
			
		||||
import type { IVFormComponent } from '../../../typings/v-form-component'
 | 
			
		||||
 | 
			
		||||
// import { toRefs } from '@vueuse/core';
 | 
			
		||||
import { Icon } from '@/components/Icon'
 | 
			
		||||
import { useDesign } from '@/hooks/web/useDesign'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'CollapseItem',
 | 
			
		||||
  components: { Draggable: draggable, Icon },
 | 
			
		||||
  props: {
 | 
			
		||||
    list: {
 | 
			
		||||
      type: [Array] as PropType<IVFormComponent[]>,
 | 
			
		||||
      type: [Array],
 | 
			
		||||
      default: () => [],
 | 
			
		||||
    },
 | 
			
		||||
    handleListPush: {
 | 
			
		||||
      type: Function as PropType<(item: IVFormComponent) => void>,
 | 
			
		||||
      type: Function,
 | 
			
		||||
      default: null,
 | 
			
		||||
    },
 | 
			
		||||
  },
 | 
			
		||||
  setup(props, { emit }) {
 | 
			
		||||
    const { prefixCls } = useDesign('form-design-collapse-item')
 | 
			
		||||
 | 
			
		||||
    const state = reactive({})
 | 
			
		||||
    const handleStart = (e: any, list1: IVFormComponent[]) => {
 | 
			
		||||
      emit('start', list1[e.oldIndex].component)
 | 
			
		||||
| 
						 | 
				
			
			@ -32,13 +33,13 @@ export default defineComponent({
 | 
			
		|||
    const cloneItem = (one) => {
 | 
			
		||||
      return props.handleListPush(one)
 | 
			
		||||
    }
 | 
			
		||||
    return { state, handleStart, handleAdd, cloneItem }
 | 
			
		||||
    return { prefixCls, state, handleStart, handleAdd, cloneItem }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <div>
 | 
			
		||||
  <div :class="prefixCls">
 | 
			
		||||
    <Draggable
 | 
			
		||||
      tag="ul"
 | 
			
		||||
      :model-value="list"
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +55,11 @@ export default defineComponent({
 | 
			
		|||
      @add="handleAdd"
 | 
			
		||||
    >
 | 
			
		||||
      <template #item="{ element, index }">
 | 
			
		||||
        <li class="bs-box text-ellipsis" @dragstart="$emit('add-attrs', list, index)" @click="$emit('handle-list-push', element)">
 | 
			
		||||
        <li
 | 
			
		||||
          class="bs-box text-ellipsis"
 | 
			
		||||
          @dragstart="$emit('add-attrs', list, index)"
 | 
			
		||||
          @click="$emit('handle-list-push', element)"
 | 
			
		||||
        >
 | 
			
		||||
          <!-- <svg v-if="element.icon.indexOf('icon-') > -1" class="icon" aria-hidden="true">
 | 
			
		||||
            <use :xlink:href="`#${element.icon}`" />
 | 
			
		||||
          </svg> -->
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +72,11 @@ export default defineComponent({
 | 
			
		|||
</template>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped>
 | 
			
		||||
  @prefix-cls: ~'@{namespace}-form-design-collapse-item';
 | 
			
		||||
 | 
			
		||||
  @import url('../styles/variable.less');
 | 
			
		||||
 | 
			
		||||
  .@{prefix-cls} {
 | 
			
		||||
    ul {
 | 
			
		||||
      display: flex;
 | 
			
		||||
      flex-wrap: wrap;
 | 
			
		||||
| 
						 | 
				
			
			@ -84,12 +92,16 @@ ul {
 | 
			
		|||
        margin: 2.7px;
 | 
			
		||||
        line-height: 20px;
 | 
			
		||||
        cursor: move;
 | 
			
		||||
    border: 1px solid var(--border-color);
 | 
			
		||||
        border: 1px solid @border-color;
 | 
			
		||||
        border-radius: 3px;
 | 
			
		||||
        transition: all 0.3s;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
          position: relative;
 | 
			
		||||
          color: @primary-color;
 | 
			
		||||
          border: 1px solid @primary-color;
 | 
			
		||||
          // z-index: 1;
 | 
			
		||||
          box-shadow: 0 2px 6px @primary-color;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -97,4 +109,5 @@ ul {
 | 
			
		|||
    svg {
 | 
			
		||||
      display: inline !important;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
</style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,8 +7,8 @@ import draggable from 'vuedraggable'
 | 
			
		|||
import { computed, defineComponent } from 'vue'
 | 
			
		||||
import { cloneDeep } from 'lodash-es'
 | 
			
		||||
import { Empty, Form } from 'ant-design-vue'
 | 
			
		||||
import LayoutItem from '../components/LayoutItem.vue'
 | 
			
		||||
import { useFormDesignState } from '../../../hooks/useFormDesignState'
 | 
			
		||||
import LayoutItem from '../components/LayoutItem.vue'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'FormComponentPanel',
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ export default defineComponent({
 | 
			
		|||
  },
 | 
			
		||||
  emits: ['handleSetSelectItem'],
 | 
			
		||||
  setup(_, { emit }) {
 | 
			
		||||
    const { formConfig } = useFormDesignState() as Recordable
 | 
			
		||||
    const { formConfig } = useFormDesignState()
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       * 拖拽完成事件
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,11 @@ export default defineComponent({
 | 
			
		|||
 | 
			
		||||
<template>
 | 
			
		||||
  <div class="form-panel v-form-container">
 | 
			
		||||
    <Empty v-show="formConfig.schemas.length === 0" class="empty-text" description="从左侧选择控件添加" />
 | 
			
		||||
    <Empty
 | 
			
		||||
      v-show="formConfig.schemas.length === 0"
 | 
			
		||||
      class="empty-text"
 | 
			
		||||
      description="从左侧选择控件添加"
 | 
			
		||||
    />
 | 
			
		||||
    <Form v-bind="formConfig">
 | 
			
		||||
      <div class="draggable-box">
 | 
			
		||||
        <Draggable
 | 
			
		||||
| 
						 | 
				
			
			@ -77,7 +81,12 @@ export default defineComponent({
 | 
			
		|||
          @start="handleDragStart"
 | 
			
		||||
        >
 | 
			
		||||
          <template #item="{ element }">
 | 
			
		||||
            <LayoutItem class="drag-move" :schema="element" :data="formConfig" :current-item="formConfig.currentItem || {}" />
 | 
			
		||||
            <LayoutItem
 | 
			
		||||
              class="drag-move"
 | 
			
		||||
              :schema="element"
 | 
			
		||||
              :data="formConfig"
 | 
			
		||||
              :current-item="formConfig.currentItem || {}"
 | 
			
		||||
            />
 | 
			
		||||
          </template>
 | 
			
		||||
        </Draggable>
 | 
			
		||||
      </div>
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +133,7 @@ export default defineComponent({
 | 
			
		|||
 | 
			
		||||
    .draggable-box {
 | 
			
		||||
      height: calc(100vh - 200px);
 | 
			
		||||
      // width: 100%;
 | 
			
		||||
      overflow: auto;
 | 
			
		||||
 | 
			
		||||
      .drag-move {
 | 
			
		||||
| 
						 | 
				
			
			@ -132,8 +142,6 @@ export default defineComponent({
 | 
			
		|||
      }
 | 
			
		||||
 | 
			
		||||
      .list-main {
 | 
			
		||||
      // height: 100%;
 | 
			
		||||
      // overflow: auto;
 | 
			
		||||
        // 列表动画
 | 
			
		||||
        .list-enter-active {
 | 
			
		||||
          transition: all 0.5s;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,7 +28,9 @@ export default defineComponent({
 | 
			
		|||
  setup() {
 | 
			
		||||
    const { formConfig } = useFormDesignState()
 | 
			
		||||
    const slotProps = computed(() => {
 | 
			
		||||
      return customComponents.find(item => item.component === formConfig.value.currentItem?.component)
 | 
			
		||||
      return customComponents.find(
 | 
			
		||||
        item => item.component === formConfig.value.currentItem?.component,
 | 
			
		||||
      )
 | 
			
		||||
    })
 | 
			
		||||
    return { formConfig, customComponents, slotProps }
 | 
			
		||||
  },
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ import { defineComponent, inject, reactive, toRefs } from 'vue'
 | 
			
		|||
import type { UseRefHistoryReturn } from '@vueuse/core'
 | 
			
		||||
import { Divider, Tooltip } from 'ant-design-vue'
 | 
			
		||||
import type { IFormConfig } from '../../../typings/v-form-component'
 | 
			
		||||
import Icon from '@/components/Icon/index'
 | 
			
		||||
import { Icon } from '@/components/Icon'
 | 
			
		||||
 | 
			
		||||
interface IToolbarsConfig {
 | 
			
		||||
  type: string
 | 
			
		||||
| 
						 | 
				
			
			@ -109,11 +109,11 @@ export default defineComponent({
 | 
			
		|||
    justify-content: space-between;
 | 
			
		||||
    height: @operating-area-height;
 | 
			
		||||
    padding: 0 12px;
 | 
			
		||||
  padding-left: 30px;
 | 
			
		||||
    padding-left: 40px;
 | 
			
		||||
    font-size: 16px;
 | 
			
		||||
    line-height: @operating-area-height;
 | 
			
		||||
    text-align: left;
 | 
			
		||||
  border-bottom: 2px solid var(--border-color);
 | 
			
		||||
    border-bottom: 2px solid @border-color;
 | 
			
		||||
 | 
			
		||||
    a {
 | 
			
		||||
      margin: 0 5px;
 | 
			
		||||
| 
						 | 
				
			
			@ -124,6 +124,10 @@ export default defineComponent({
 | 
			
		|||
        color: #ccc;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        color: @primary-color;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      > span {
 | 
			
		||||
        padding-left: 2px;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,7 +2,6 @@
 | 
			
		|||
  height: 100%;
 | 
			
		||||
  overflow: auto;
 | 
			
		||||
 | 
			
		||||
  /* stylelint-disable-next-line selector-pseudo-class-no-unknown */
 | 
			
		||||
  :deep(.list-main) {
 | 
			
		||||
    position: relative;
 | 
			
		||||
    padding: 5px;
 | 
			
		||||
| 
						 | 
				
			
			@ -17,12 +16,13 @@
 | 
			
		|||
      overflow: hidden;
 | 
			
		||||
 | 
			
		||||
      &::before {
 | 
			
		||||
        content: '';
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0;
 | 
			
		||||
        right: 0;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 5px;
 | 
			
		||||
        content: "";
 | 
			
		||||
        background-color: @primary-color;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -34,19 +34,25 @@
 | 
			
		|||
      overflow: hidden;
 | 
			
		||||
      transition: all 0.3s;
 | 
			
		||||
 | 
			
		||||
      &:hover {
 | 
			
		||||
        background-color: @primary-hover-bg-color;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      // 选择时 start
 | 
			
		||||
      &::before {
 | 
			
		||||
        content: '';
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0;
 | 
			
		||||
        right: -100%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 5px;
 | 
			
		||||
        content: "";
 | 
			
		||||
        transition: all 0.3s;
 | 
			
		||||
        background-color: @primary-color;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &.active {
 | 
			
		||||
        outline-offset: 0;
 | 
			
		||||
        background-color: @primary-hover-bg-color;
 | 
			
		||||
 | 
			
		||||
        &::before {
 | 
			
		||||
          right: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -60,18 +66,18 @@
 | 
			
		|||
        word-wrap: break-word;
 | 
			
		||||
 | 
			
		||||
        &::before {
 | 
			
		||||
          content: '';
 | 
			
		||||
          position: absolute;
 | 
			
		||||
          top: 0;
 | 
			
		||||
          left: 0;
 | 
			
		||||
          width: 100%;
 | 
			
		||||
          height: 100%;
 | 
			
		||||
          content: "";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .ant-form-item {
 | 
			
		||||
          padding-bottom: 6px;
 | 
			
		||||
          // 修改ant form-item的margin为padding
 | 
			
		||||
          margin: 0;
 | 
			
		||||
          padding-bottom: 6px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -80,8 +86,9 @@
 | 
			
		|||
        position: absolute;
 | 
			
		||||
        right: 5px;
 | 
			
		||||
        bottom: 2px;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
        // z-index: 999;
 | 
			
		||||
        color: @primary-color;
 | 
			
		||||
        font-size: 14px;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .copy,
 | 
			
		||||
| 
						 | 
				
			
			@ -90,15 +97,15 @@
 | 
			
		|||
        top: 0;
 | 
			
		||||
        width: 30px;
 | 
			
		||||
        height: 30px;
 | 
			
		||||
        line-height: 30px;
 | 
			
		||||
        color: #fff;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
        // z-index: 989;
 | 
			
		||||
        transition: all 0.3s;
 | 
			
		||||
        color: #fff;
 | 
			
		||||
        line-height: 30px;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
 | 
			
		||||
        &.unactivated {
 | 
			
		||||
          pointer-events: none;
 | 
			
		||||
          opacity: 0 !important;
 | 
			
		||||
          pointer-events: none;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.active {
 | 
			
		||||
| 
						 | 
				
			
			@ -109,10 +116,12 @@
 | 
			
		|||
      .copy {
 | 
			
		||||
        right: 30px;
 | 
			
		||||
        border-radius: 0 0 0 8px;
 | 
			
		||||
        background-color: @primary-color;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      .delete {
 | 
			
		||||
        right: 0;
 | 
			
		||||
        background-color: @primary-color;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -122,17 +131,17 @@
 | 
			
		|||
      width: 100%;
 | 
			
		||||
      padding: 5px;
 | 
			
		||||
      overflow: hidden;
 | 
			
		||||
      background-color: @layout-background-color;
 | 
			
		||||
      transition: all 0.3s;
 | 
			
		||||
      background-color: @layout-background-color;
 | 
			
		||||
 | 
			
		||||
      .form-item-box {
 | 
			
		||||
        position: relative;
 | 
			
		||||
        box-sizing: border-box;
 | 
			
		||||
 | 
			
		||||
        .ant-form-item {
 | 
			
		||||
          padding-bottom: 15px;
 | 
			
		||||
          // 修改ant form-item的margin为padding
 | 
			
		||||
          margin: 0;
 | 
			
		||||
          padding-bottom: 15px;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -157,19 +166,19 @@
 | 
			
		|||
 | 
			
		||||
      // 选择时 start
 | 
			
		||||
      &::before {
 | 
			
		||||
        content: '';
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0;
 | 
			
		||||
        right: -100%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        height: 5px;
 | 
			
		||||
        content: "";
 | 
			
		||||
        background: transparent;
 | 
			
		||||
        transition: all 0.3s;
 | 
			
		||||
        background: transparent;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      &.active {
 | 
			
		||||
        background-color: @layout-hover-bg-color;
 | 
			
		||||
        outline-offset: 0;
 | 
			
		||||
        background-color: @layout-hover-bg-color;
 | 
			
		||||
 | 
			
		||||
        &::before {
 | 
			
		||||
          right: 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -184,15 +193,15 @@
 | 
			
		|||
          top: 0;
 | 
			
		||||
          width: 30px;
 | 
			
		||||
          height: 30px;
 | 
			
		||||
          line-height: 30px;
 | 
			
		||||
          color: #fff;
 | 
			
		||||
          text-align: center;
 | 
			
		||||
          // z-index: 989;
 | 
			
		||||
          transition: all 0.3s;
 | 
			
		||||
          color: #fff;
 | 
			
		||||
          line-height: 30px;
 | 
			
		||||
          text-align: center;
 | 
			
		||||
 | 
			
		||||
          &.unactivated {
 | 
			
		||||
            pointer-events: none;
 | 
			
		||||
            opacity: 0 !important;
 | 
			
		||||
            pointer-events: none;
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          &.active {
 | 
			
		||||
| 
						 | 
				
			
			@ -202,8 +211,8 @@
 | 
			
		|||
 | 
			
		||||
        > .copy {
 | 
			
		||||
          right: 30px;
 | 
			
		||||
          background-color: @layout-color;
 | 
			
		||||
          border-radius: 0 0 0 8px;
 | 
			
		||||
          background-color: @layout-color;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        > .delete {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,32 +1,19 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description:
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import type { PropType } from 'vue'
 | 
			
		||||
import { computed, defineComponent, reactive, toRefs, unref } from 'vue'
 | 
			
		||||
import { computed, unref } from 'vue'
 | 
			
		||||
import { asyncComputed } from '@vueuse/core'
 | 
			
		||||
import { omit } from 'lodash-es'
 | 
			
		||||
import { Col, Divider, FormItem, Tooltip } from 'ant-design-vue'
 | 
			
		||||
import { componentMap } from '../../core/formItemConfig'
 | 
			
		||||
import type { IFormConfig, IVFormComponent } from '../../typings/v-form-component'
 | 
			
		||||
import { handleAsyncOptions } from '../../utils'
 | 
			
		||||
 | 
			
		||||
// import FormItem from '/@/components/Form/src/components/FormItem.vue';
 | 
			
		||||
 | 
			
		||||
import { useFormModelState } from '../../hooks/useFormDesignState'
 | 
			
		||||
import { Icon } from '@/components/Icon'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'VFormItem',
 | 
			
		||||
  components: {
 | 
			
		||||
    Tooltip,
 | 
			
		||||
    Icon,
 | 
			
		||||
    FormItem,
 | 
			
		||||
    Divider,
 | 
			
		||||
    Col,
 | 
			
		||||
  },
 | 
			
		||||
 | 
			
		||||
  props: {
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  formData: {
 | 
			
		||||
    type: Object,
 | 
			
		||||
    default: () => ({}),
 | 
			
		||||
| 
						 | 
				
			
			@ -39,13 +26,10 @@ export default defineComponent({
 | 
			
		|||
    type: Object as PropType<IFormConfig>,
 | 
			
		||||
    required: true,
 | 
			
		||||
  },
 | 
			
		||||
  },
 | 
			
		||||
  emits: ['update:form-data', 'change'],
 | 
			
		||||
  setup(props, { emit }) {
 | 
			
		||||
    const state = reactive({
 | 
			
		||||
      componentMap,
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const emit = defineEmits(['update:form-data', 'change'])
 | 
			
		||||
 | 
			
		||||
const { formModel: formData1, setFormModel } = useFormModelState()
 | 
			
		||||
const colPropsComputed = computed(() => {
 | 
			
		||||
  const { colProps = {} } = props.schema
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +55,10 @@ export default defineComponent({
 | 
			
		|||
      : formConfig.wrapperCol
 | 
			
		||||
    : {})
 | 
			
		||||
 | 
			
		||||
      const style = formConfig.layout === 'horizontal' && formConfig.labelLayout === 'flex' ? { display: 'flex' } : {}
 | 
			
		||||
  const style
 | 
			
		||||
          = formConfig.layout === 'horizontal' && formConfig.labelLayout === 'flex'
 | 
			
		||||
            ? { display: 'flex' }
 | 
			
		||||
            : {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
       * 将字符串正则格式化成正则表达式
 | 
			
		||||
| 
						 | 
				
			
			@ -100,12 +87,12 @@ export default defineComponent({
 | 
			
		|||
    newConfig.rules = rules
 | 
			
		||||
 | 
			
		||||
  return newConfig
 | 
			
		||||
    }) as Recordable
 | 
			
		||||
}) as Recordable<any>
 | 
			
		||||
 | 
			
		||||
const componentItem = computed(() => componentMap.get(props.schema.component as string))
 | 
			
		||||
 | 
			
		||||
// console.log('component change:', props.schema.component, componentItem.value);
 | 
			
		||||
    const handleClick = (schema: IVFormComponent) => {
 | 
			
		||||
function handleClick(schema: IVFormComponent) {
 | 
			
		||||
  if (schema.component === 'Button' && schema.componentProps?.handle)
 | 
			
		||||
    emit(schema.componentProps?.handle)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -128,10 +115,12 @@ export default defineComponent({
 | 
			
		|||
     * 处理同步属性
 | 
			
		||||
     */
 | 
			
		||||
const cmpProps = computed(() => {
 | 
			
		||||
      const isCheck = props.schema && ['Switch', 'Checkbox', 'Radio'].includes(props.schema.component)
 | 
			
		||||
  const isCheck
 | 
			
		||||
          = props.schema && ['Switch', 'Checkbox', 'Radio'].includes(props.schema.component)
 | 
			
		||||
  const { field } = props.schema
 | 
			
		||||
 | 
			
		||||
      let { disabled, ...attrs } = omit(props.schema.componentProps, ['options', 'treeData']) ?? {}
 | 
			
		||||
  let { disabled, ...attrs }
 | 
			
		||||
          = omit(props.schema.componentProps, ['options', 'treeData']) ?? {}
 | 
			
		||||
 | 
			
		||||
  disabled = props.formConfig.disabled || disabled
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -149,18 +138,6 @@ export default defineComponent({
 | 
			
		|||
  setFormModel(props.schema.field!, value)
 | 
			
		||||
  emit('change', value)
 | 
			
		||||
}
 | 
			
		||||
    return {
 | 
			
		||||
      ...toRefs(state),
 | 
			
		||||
      componentItem,
 | 
			
		||||
      formItemProps,
 | 
			
		||||
      handleClick,
 | 
			
		||||
      asyncProps,
 | 
			
		||||
      cmpProps,
 | 
			
		||||
      handleChange,
 | 
			
		||||
      colPropsComputed,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
| 
						 | 
				
			
			@ -176,8 +153,14 @@ export default defineComponent({
 | 
			
		|||
        </Tooltip>
 | 
			
		||||
      </template>
 | 
			
		||||
 | 
			
		||||
      <slot v-if="schema.componentProps && schema.componentProps?.slotName" :name="schema.componentProps.slotName" v-bind="schema" />
 | 
			
		||||
      <Divider v-else-if="schema.component === 'Divider' && schema.label && !formItemProps.hiddenLabel">
 | 
			
		||||
      <slot
 | 
			
		||||
        v-if="schema.componentProps && schema.componentProps?.slotName"
 | 
			
		||||
        :name="schema.componentProps.slotName"
 | 
			
		||||
        v-bind="schema"
 | 
			
		||||
      />
 | 
			
		||||
      <Divider
 | 
			
		||||
        v-else-if="schema.component === 'Divider' && schema.label && !formItemProps.hiddenLabel"
 | 
			
		||||
      >
 | 
			
		||||
        {{ schema.label }}
 | 
			
		||||
      </Divider>
 | 
			
		||||
      <!-- 部分控件需要一个空div -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -11,19 +11,14 @@
 | 
			
		|||
  >
 | 
			
		||||
-->
 | 
			
		||||
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { computed, defineComponent, unref } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { computed, unref } from 'vue'
 | 
			
		||||
import type { IFormConfig, IVFormComponent } from '../../typings/v-form-component'
 | 
			
		||||
import type { FormProps, FormSchema } from '@/components/Form'
 | 
			
		||||
 | 
			
		||||
import FormItem from '/@/components/Form/src/components/FormItem.vue'
 | 
			
		||||
import FormItem from '@/components/Form/src/components/FormItem.vue'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'VFormItem',
 | 
			
		||||
  components: {
 | 
			
		||||
    FormItem,
 | 
			
		||||
  },
 | 
			
		||||
  props: {
 | 
			
		||||
const props = defineProps({
 | 
			
		||||
  formData: {
 | 
			
		||||
    type: Object,
 | 
			
		||||
    default: () => ({}),
 | 
			
		||||
| 
						 | 
				
			
			@ -36,8 +31,8 @@ export default defineComponent({
 | 
			
		|||
    type: Object as PropType<IFormConfig>,
 | 
			
		||||
    required: true,
 | 
			
		||||
  },
 | 
			
		||||
  },
 | 
			
		||||
  setup(props) {
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
const schema = computed(() => {
 | 
			
		||||
  const schema: FormSchema = {
 | 
			
		||||
    ...unref(props.schema),
 | 
			
		||||
| 
						 | 
				
			
			@ -50,20 +45,12 @@ export default defineComponent({
 | 
			
		|||
const getProps = computed((): FormProps => {
 | 
			
		||||
  return { ...unref(props.formConfig) } as FormProps
 | 
			
		||||
})
 | 
			
		||||
    return {
 | 
			
		||||
      schemaNew: schema,
 | 
			
		||||
      getProps,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <FormItem :schema="schemaNew" :form-props="getProps">
 | 
			
		||||
  <FormItem :schema="schema" :form-props="getProps">
 | 
			
		||||
    <template v-for="item in Object.keys($slots)" #[item]="data">
 | 
			
		||||
      <slot :name="item" v-bind="data || {}" />
 | 
			
		||||
    </template>
 | 
			
		||||
  </FormItem>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<style lang="less" scoped></style>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
<!--
 | 
			
		||||
 * @Description: 渲染组件,无法使用Vben的组件
 | 
			
		||||
-->
 | 
			
		||||
<script lang="ts">
 | 
			
		||||
import { defineComponent, reactive, ref, toRefs } from 'vue'
 | 
			
		||||
<script lang="ts" setup>
 | 
			
		||||
import { reactive, ref } from 'vue'
 | 
			
		||||
import { Modal } from 'ant-design-vue'
 | 
			
		||||
import type { IFormConfig } from '../../typings/v-form-component'
 | 
			
		||||
import type { IAnyObject } from '../../typings/base-type'
 | 
			
		||||
| 
						 | 
				
			
			@ -12,14 +12,6 @@ import type { IVFormMethods } from '../../hooks/useVFormMethods'
 | 
			
		|||
import JsonModal from '../VFormDesign/components/JsonModal.vue'
 | 
			
		||||
import type { IToolbarMethods } from '../../typings/form-type'
 | 
			
		||||
 | 
			
		||||
export default defineComponent({
 | 
			
		||||
  name: 'VFormPreview',
 | 
			
		||||
  components: {
 | 
			
		||||
    JsonModal,
 | 
			
		||||
    VFormCreate,
 | 
			
		||||
    Modal,
 | 
			
		||||
  },
 | 
			
		||||
  setup() {
 | 
			
		||||
const jsonModal = ref<IToolbarMethods | null>(null)
 | 
			
		||||
const state = reactive<{
 | 
			
		||||
  formModel: IAnyObject
 | 
			
		||||
| 
						 | 
				
			
			@ -37,7 +29,7 @@ export default defineComponent({
 | 
			
		|||
     * 显示Json数据弹框
 | 
			
		||||
     * @param jsonData
 | 
			
		||||
     */
 | 
			
		||||
    const showModal = (jsonData: IFormConfig) => {
 | 
			
		||||
function showModal(jsonData: IFormConfig) {
 | 
			
		||||
  // console.log('showModal-', jsonData);
 | 
			
		||||
  formatRules(jsonData.schemas)
 | 
			
		||||
  state.formConfig = jsonData
 | 
			
		||||
| 
						 | 
				
			
			@ -48,38 +40,29 @@ export default defineComponent({
 | 
			
		|||
     * 获取表单数据
 | 
			
		||||
     * @return {Promise<void>}
 | 
			
		||||
     */
 | 
			
		||||
    const handleCancel = () => {
 | 
			
		||||
function handleCancel() {
 | 
			
		||||
  state.open = false
 | 
			
		||||
      state.formModel = {}
 | 
			
		||||
  onCancel()
 | 
			
		||||
}
 | 
			
		||||
    const handleGetData = async () => {
 | 
			
		||||
async function handleGetData() {
 | 
			
		||||
  const _data = await state.fApi.submit?.()
 | 
			
		||||
  jsonModal.value?.showModal?.(_data)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    const onSubmit = (_data: IAnyObject) => {
 | 
			
		||||
function onSubmit(_data: IAnyObject) {
 | 
			
		||||
  //
 | 
			
		||||
}
 | 
			
		||||
    const onCancel = () => {
 | 
			
		||||
function onCancel() {
 | 
			
		||||
  state.formModel = {}
 | 
			
		||||
}
 | 
			
		||||
    return {
 | 
			
		||||
      handleGetData,
 | 
			
		||||
      handleCancel,
 | 
			
		||||
      ...toRefs(state),
 | 
			
		||||
      showModal,
 | 
			
		||||
      jsonModal,
 | 
			
		||||
      onSubmit,
 | 
			
		||||
      onCancel,
 | 
			
		||||
    }
 | 
			
		||||
  },
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
defineExpose({ showModal, onCancel })
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<template>
 | 
			
		||||
  <Modal
 | 
			
		||||
    title="预览(支持布局)"
 | 
			
		||||
    :open="open"
 | 
			
		||||
    :open="state.open"
 | 
			
		||||
    ok-text="获取数据"
 | 
			
		||||
    cancel-text="关闭"
 | 
			
		||||
    style="top: 20px"
 | 
			
		||||
| 
						 | 
				
			
			@ -88,7 +71,12 @@ export default defineComponent({
 | 
			
		|||
    @ok="handleGetData"
 | 
			
		||||
    @cancel="handleCancel"
 | 
			
		||||
  >
 | 
			
		||||
    <VFormCreate v-model:fApi="fApi" v-model:formModel="formModel" :form-config="formConfig" @submit="onSubmit">
 | 
			
		||||
    <VFormCreate
 | 
			
		||||
      v-model:fApi="state.fApi"
 | 
			
		||||
      v-model:formModel="state.formModel"
 | 
			
		||||
      :form-config="state.formConfig"
 | 
			
		||||
      @submit="onSubmit"
 | 
			
		||||
    >
 | 
			
		||||
      <template #slotName="{ formModel, field }">
 | 
			
		||||
        <a-input v-model:value="formModel[field]" placeholder="我是插槽传递的输入框" />
 | 
			
		||||
      </template>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,11 +1,16 @@
 | 
			
		|||
import { getCurrentInstance, toRaw } from 'vue'
 | 
			
		||||
import type { Ref, SetupContext } from 'vue'
 | 
			
		||||
import { getCurrentInstance, toRaw } from 'vue'
 | 
			
		||||
import { cloneDeep, forOwn, isFunction } from 'lodash-es'
 | 
			
		||||
import { Form } from 'ant-design-vue'
 | 
			
		||||
import type { AForm, IVFormComponent } from '../typings/v-form-component'
 | 
			
		||||
import type { IAnyObject } from '../typings/base-type'
 | 
			
		||||
 | 
			
		||||
export function useFormInstanceMethods(props: IAnyObject, formdata, context: Partial<SetupContext>, _formInstance: Ref<AForm | null>) {
 | 
			
		||||
export function useFormInstanceMethods(
 | 
			
		||||
  props: IAnyObject,
 | 
			
		||||
  formdata,
 | 
			
		||||
  context: Partial<SetupContext>,
 | 
			
		||||
  _formInstance: Ref<AForm | null>,
 | 
			
		||||
) {
 | 
			
		||||
  /**
 | 
			
		||||
   * 绑定props和on中的上下文为parent
 | 
			
		||||
   */
 | 
			
		||||
| 
						 | 
				
			
			@ -13,8 +18,9 @@ export function useFormInstanceMethods(props: IAnyObject, formdata, context: Par
 | 
			
		|||
    const instance = getCurrentInstance()
 | 
			
		||||
    const vm = instance?.parent
 | 
			
		||||
    if (!vm)
 | 
			
		||||
      return
 | 
			
		||||
    ;(props.formConfig.schemas as IVFormComponent[]).forEach((item) => {
 | 
			
		||||
      return;
 | 
			
		||||
 | 
			
		||||
    (props.formConfig.schemas as IVFormComponent[]).forEach((item) => {
 | 
			
		||||
      // 绑定 props 中的上下文
 | 
			
		||||
      forOwn(item.componentProps, (value: any, key) => {
 | 
			
		||||
        if (isFunction(value))
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +41,7 @@ export function useFormInstanceMethods(props: IAnyObject, formdata, context: Par
 | 
			
		|||
 | 
			
		||||
  const { resetFields, validate, clearValidate, validateField } = useForm(formdata, [])
 | 
			
		||||
 | 
			
		||||
  const submit = () => {
 | 
			
		||||
  const submit = async () => {
 | 
			
		||||
    // const _result = await validate();
 | 
			
		||||
 | 
			
		||||
    const data = cloneDeep(toRaw(formdata.value))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -13,7 +13,11 @@ export interface IProps {
 | 
			
		|||
  formModel: IAnyObject
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type ISet = <T extends keyof IVFormComponent>(field: string, key: T, value: IVFormComponent[T]) => void
 | 
			
		||||
type ISet = <T extends keyof IVFormComponent>(
 | 
			
		||||
  field: string,
 | 
			
		||||
  key: T,
 | 
			
		||||
  value: IVFormComponent[T],
 | 
			
		||||
) => void
 | 
			
		||||
// 获取当前field绑定的表单项
 | 
			
		||||
type IGet = (field: string) => IVFormComponent | undefined
 | 
			
		||||
// 获取field在formData中的值
 | 
			
		||||
| 
						 | 
				
			
			@ -59,7 +63,8 @@ export function useVFormMethods(
 | 
			
		|||
   * @param {string} field
 | 
			
		||||
   * @return {IVFormComponent | undefined}
 | 
			
		||||
   */
 | 
			
		||||
  const get: IGet = field => findFormItem(props.formConfig.schemas, item => item.field === field)
 | 
			
		||||
  const get: IGet = field =>
 | 
			
		||||
    findFormItem(props.formConfig.schemas, item => item.field === field)
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 根据表单field设置表单项字段值
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +78,20 @@ export function useVFormMethods(
 | 
			
		|||
      formItem[key] = value
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
   * 设置表单项的props
 | 
			
		||||
   * @param {string} field 需要设置的表单项field
 | 
			
		||||
   * @param {string} key 需要设置的key
 | 
			
		||||
   * @param value 需要设置的值
 | 
			
		||||
   */
 | 
			
		||||
  const setProps: ISetProps = (field, key, value) => {
 | 
			
		||||
    const formItem = get(field)
 | 
			
		||||
    if (formItem?.componentProps) {
 | 
			
		||||
      ['options', 'treeData'].includes(key) && setValue(field, undefined)
 | 
			
		||||
 | 
			
		||||
      formItem.componentProps[key] = value
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  /**
 | 
			
		||||
   * 设置字段的值,设置后触发校验
 | 
			
		||||
   * @param {string} field  需要设置的字段
 | 
			
		||||
| 
						 | 
				
			
			@ -92,20 +111,6 @@ export function useVFormMethods(
 | 
			
		|||
      })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  /**
 | 
			
		||||
   * 设置表单项的props
 | 
			
		||||
   * @param {string} field 需要设置的表单项field
 | 
			
		||||
   * @param {string} key 需要设置的key
 | 
			
		||||
   * @param value 需要设置的值
 | 
			
		||||
   */
 | 
			
		||||
  const setProps: ISetProps = (field, key, value) => {
 | 
			
		||||
    const formItem = get(field)
 | 
			
		||||
    if (formItem?.componentProps) {
 | 
			
		||||
      ;['options', 'treeData'].includes(key) && setValue(field, undefined)
 | 
			
		||||
 | 
			
		||||
      formItem.componentProps[key] = value
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  /**
 | 
			
		||||
   * 设置表单配置方法
 | 
			
		||||
   * @param {string} key
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +148,9 @@ export function useVFormMethods(
 | 
			
		|||
   * @param {string | undefined} field
 | 
			
		||||
   */
 | 
			
		||||
  const disable: IDisable = (field) => {
 | 
			
		||||
    typeof field === 'string' ? setProps(field, 'disabled', true) : setFormConfig('disabled', field !== false)
 | 
			
		||||
    typeof field === 'string'
 | 
			
		||||
      ? setProps(field, 'disabled', true)
 | 
			
		||||
      : setFormConfig('disabled', field !== false)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,5 +44,9 @@ export interface IFormDesignMethods {
 | 
			
		|||
  handleAddAttrs(schemas: IVFormComponent[], index: number): void
 | 
			
		||||
  setFormConfig(config: IFormConfig): void
 | 
			
		||||
  // 添加到表单中之前触发
 | 
			
		||||
  handleBeforeColAdd(event: { newIndex: string }, schemas: IVFormComponent[], isCopy?: boolean): void
 | 
			
		||||
  handleBeforeColAdd(
 | 
			
		||||
    event: { newIndex: string },
 | 
			
		||||
    schemas: IVFormComponent[],
 | 
			
		||||
    isCopy?: boolean,
 | 
			
		||||
  ): void
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -177,7 +177,12 @@ export interface AForm {
 | 
			
		|||
   * validate one or several form items
 | 
			
		||||
   * @type Function
 | 
			
		||||
   */
 | 
			
		||||
  validateField: (name: string, value: any, rules: Record<string, unknown>[], option?: validateOptions) => Promise<RuleError[]>
 | 
			
		||||
  validateField: (
 | 
			
		||||
    name: string,
 | 
			
		||||
    value: any,
 | 
			
		||||
    rules: Record<string, unknown>[],
 | 
			
		||||
    option?: validateOptions,
 | 
			
		||||
  ) => Promise<RuleError[]>
 | 
			
		||||
  /**
 | 
			
		||||
   * reset all the fields and remove validation result
 | 
			
		||||
   */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,5 @@
 | 
			
		|||
// import { VueConstructor } from 'vue';
 | 
			
		||||
import { cloneDeep, isArray, isFunction, isNumber, uniqueId } from 'lodash-es'
 | 
			
		||||
import type { Ref } from 'vue'
 | 
			
		||||
import type { IFormConfig, IVFormComponent, IValidationRule } from '../typings/v-form-component'
 | 
			
		||||
 | 
			
		||||
// import { del } from '@vue/composition-api';
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +39,10 @@ export function generateKey(formItem?: IVFormComponent): string | boolean {
 | 
			
		|||
 * @param value {number | ((item: T, index: number, array: Array<T>) => boolean}
 | 
			
		||||
 * @returns {T} 返回删除的数组项
 | 
			
		||||
 */
 | 
			
		||||
export function remove<T>(array: Array<T>, value: number | ((item: T, index: number, array: Array<T>) => boolean)): T | undefined {
 | 
			
		||||
export function remove<T>(
 | 
			
		||||
  array: Array<T>,
 | 
			
		||||
  value: number | ((item: T, index: number, array: Array<T>) => boolean),
 | 
			
		||||
): T | undefined {
 | 
			
		||||
  let removeVal: Array<T | undefined> = []
 | 
			
		||||
  if (!isArray(array))
 | 
			
		||||
    return undefined
 | 
			
		||||
| 
						 | 
				
			
			@ -107,10 +109,10 @@ export function formItemsForEach(array: IVFormComponent[], cb: (item: IVFormComp
 | 
			
		|||
/**
 | 
			
		||||
 * 查找表单项
 | 
			
		||||
 */
 | 
			
		||||
export const findFormItem: (schemas: IVFormComponent[], cb: (formItem: IVFormComponent) => boolean) => IVFormComponent | undefined = (
 | 
			
		||||
  schemas,
 | 
			
		||||
  cb,
 | 
			
		||||
) => {
 | 
			
		||||
export const findFormItem: (
 | 
			
		||||
  schemas: IVFormComponent[],
 | 
			
		||||
  cb: (formItem: IVFormComponent) => boolean,
 | 
			
		||||
) => IVFormComponent | undefined = (schemas, cb) => {
 | 
			
		||||
  let res
 | 
			
		||||
  const traverse = (schemas: IVFormComponent[]): boolean => {
 | 
			
		||||
    return schemas.some((formItem: IVFormComponent) => {
 | 
			
		||||
| 
						 | 
				
			
			@ -203,45 +205,3 @@ export function runCode<T>(code: any): T {
 | 
			
		|||
    return code
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * 针对 https://github.com/xaboy/form-create-designer 封装的工具类
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// 编码表单 Conf
 | 
			
		||||
export function encodeConf(designerRef: Ref<Recordable>) {
 | 
			
		||||
  return JSON.stringify(designerRef.value.getOption())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 编码表单 Fields
 | 
			
		||||
export function encodeFields(designerRef: Ref<Recordable>) {
 | 
			
		||||
  const rule = designerRef.value.getRule()
 | 
			
		||||
  const fields: string[] = []
 | 
			
		||||
  rule.forEach((item) => {
 | 
			
		||||
    fields.push(JSON.stringify(item))
 | 
			
		||||
  })
 | 
			
		||||
  return fields
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 解码表单 Fields
 | 
			
		||||
export function decodeFields(fields: string[]) {
 | 
			
		||||
  const rule: object[] = []
 | 
			
		||||
  fields.forEach((item) => {
 | 
			
		||||
    rule.push(JSON.parse(item))
 | 
			
		||||
  })
 | 
			
		||||
  return rule
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 设置表单的 Conf 和 Fields
 | 
			
		||||
export function setConfAndFields(designerRef: Ref<Recordable>, conf: string, fields: string[]) {
 | 
			
		||||
  designerRef.value.setOption(JSON.parse(conf))
 | 
			
		||||
  designerRef.value.setRule(decodeFields(fields))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 设置表单的 Conf 和 Fields
 | 
			
		||||
export function setConfAndFields2(detailPreview: Ref<Recordable>, conf: string, fields: string[], value?: object) {
 | 
			
		||||
  detailPreview.value.option = JSON.parse(conf)
 | 
			
		||||
  detailPreview.value.rule = decodeFields(fields)
 | 
			
		||||
  if (value)
 | 
			
		||||
    detailPreview.value.value = value
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue