form-control.tsx 2.5 KB
Newer Older
1 2 3 4 5 6 7 8
import { FormController } from '@ibiz-template/controller';
import { IBizContext } from '@ibiz-template/core';
import {
  FormDetailModel,
  FormGroupPanelModel,
  FormItemModel,
  FormModel,
} from '@ibiz-template/model';
9 10
import { useNamespace } from '@ibiz-template/vue-util';
import { defineComponent, PropType, CreateElement, VNode } from 'vue';
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
import '@ibiz-template/theme/style/components/widgets/form/form.scss';

/**
 * 根据类型绘制表单成员
 *
 * @author lxm
 * @date 2022-08-23 16:08:31
 * @param {FormDetailModel} detail 成员模型
 * @param {FormController} controller 表单控制器
 * @returns {*}
 */
function renderByDetailType(
  h: CreateElement,
  detail: FormDetailModel,
  controller: FormController,
): VNode | undefined {
  if ((detail as FormItemModel).source.hidden) {
    return;
  }
  const commonProps = {
    modelData: detail,
32
    controller: controller.details[detail.source.name],
33 34 35 36 37 38 39 40
  };
  const provider = controller.providers[detail.source.name];
  if (!provider) {
    <div>
      暂未支持的表单项类型: {detail.source.detailType}或找不到对应适配器
    </div>;
  }
  return h(
41
    provider.component,
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
    {
      props: {
        ...commonProps,
      },
      key: detail.id,
    },
    (detail as FormGroupPanelModel).children?.map(child => {
      return renderByDetailType(h, child, controller);
    }),
  );
}

export const FormControl = defineComponent({
  name: 'FormControl',
  props: {
    modelData: {
      type: FormModel,
      required: true,
    },
    context: IBizContext,
    controller: {
      type: Object as PropType<FormController>,
      required: true,
    },
  },
  setup(props) {
    const ns = useNamespace('form');

70
    const c = props.controller;
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

    return { ns, c };
  },
  render(h) {
    return (
      <control-layout modelData={this.c.model}>
        {this.c.complete && (
          <div class={this.ns.b()}>
            <form-page modelData={this.c.model}>
              {this.$props.modelData.children.map(page => {
                return (
                  <form-page-item
                    key={page.id}
                    caption={page.source.caption}
                    model-data={page}
                    controller={this.c.details[page.source.name]}
                  >
                    {page.children.map(detail =>
                      renderByDetailType(h, detail, this.c),
                    )}
                  </form-page-item>
                );
              })}
            </form-page>
          </div>
        )}
      </control-layout>
    );
  },
});