custom-parameters.ts 4.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

18
import { defineComponent, h, unref, renderSlot } from 'vue'
19
import { useFormItem } from 'naive-ui/es/_mixins'
20
import { NFormItemGi, NSpace, NButton, NGrid, NGridItem } from 'naive-ui'
21
import { isFunction } from 'lodash'
22
import { PlusOutlined, DeleteOutlined } from '@vicons/antd'
23 24
import getField from './get-field'
import { formatValidate } from '../utils'
25
import type { IJsonItem, FormItemRule } from '../types'
26

27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
const CustomParameters = defineComponent({
  name: 'CustomParameters',
  emits: ['add'],
  setup(props, ctx) {
    const formItem = useFormItem({})

    const onAdd = () => void ctx.emit('add')

    return { onAdd, disabled: formItem.mergedDisabledRef }
  },
  render() {
    const { disabled, $slots, onAdd } = this
    return h(NSpace, null, {
      default: () => {
        return [
          renderSlot($slots, 'default', { disabled }),
          h(
            NButton,
            {
              circle: true,
47
              size: 'small',
48 49 50 51
              type: 'info',
              disabled,
              onClick: onAdd
            },
52 53 54
            {
              icon: () => h(PlusOutlined)
            }
55 56 57 58 59 60 61
          )
        ]
      }
    })
  }
})

62 63 64 65 66 67 68 69 70
const getDefaultValue = (children: IJsonItem[]) => {
  const defaultValue: { [field: string]: any } = {}
  const ruleItem: { [key: string]: FormItemRule[] | FormItemRule } = {}
  const loop = (
    children: IJsonItem[],
    parent: { [field: string]: any },
    ruleParent: { [key: string]: FormItemRule[] | FormItemRule }
  ) => {
    children.forEach((child) => {
71 72
      const mergedChild = isFunction(child) ? child() : child
      if (Array.isArray(mergedChild.children)) {
73 74
        const childDefaultValue = {}
        const childRuleItem = {}
75 76 77
        loop(mergedChild.children, childDefaultValue, childRuleItem)
        parent[mergedChild.field] = [childDefaultValue]
        ruleParent[mergedChild.field] = {
78 79 80 81 82
          type: 'array',
          fields: childRuleItem
        }
        return
      } else {
83 84 85
        parent[mergedChild.field] = mergedChild.value || null
        if (mergedChild.validate)
          ruleParent[mergedChild.field] = formatValidate(mergedChild.validate)
86 87 88 89 90 91 92 93 94 95 96
      }
    })
  }

  loop(children, defaultValue, ruleItem)
  return {
    defaultValue,
    ruleItem
  }
}

97 98 99
export function renderCustomParameters(
  item: IJsonItem,
  fields: { [field: string]: any },
100
  rules: { [key: string]: FormItemRule | FormItemRule[] }[]
101
) {
102 103
  const mergedItem = isFunction(item) ? item() : item
  const { field, children = [] } = mergedItem
104 105 106
  const { defaultValue, ruleItem } = getDefaultValue(children)
  rules.push(ruleItem)
  const getChild = (item: object, i: number, disabled: boolean) =>
107
    children.map((child: IJsonItem) => {
108
      const mergedChild = isFunction(child) ? child(i) : child
109
      return h(
110
        NFormItemGi,
111 112
        {
          showLabel: false,
113 114 115
          path: `${field}[${i}].${mergedChild.field}`,
          span: unref(mergedChild.span),
          class: mergedChild.class
116
        },
117
        () => getField(mergedChild, item)
118 119
      )
    })
120
  const getChildren = ({ disabled }: { disabled: boolean }) =>
121
    fields[field].map((item: object, i: number) => {
122
      return h(NGrid, { xGap: 10 }, () => [
123
        ...getChild(item, i, disabled),
124
        h(
125
          NGridItem,
126
          {
127
            span: 2
128
          },
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
          () =>
            h(
              NButton,
              {
                circle: true,
                type: 'error',
                size: 'small',
                disabled,
                onClick: () => {
                  fields[field].splice(i, 1)
                  rules.splice(i, 1)
                }
              },
              {
                icon: () => h(DeleteOutlined)
              }
            )
146 147 148
        )
      ])
    })
149 150 151 152 153 154 155 156 157 158 159 160
  return h(
    CustomParameters,
    {
      onAdd: () => {
        rules.push(ruleItem)
        fields[field].push({ ...defaultValue })
      }
    },
    {
      default: getChildren
    }
  )
161
}