form-control.tsx 2.5 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
import { FormController } from '@ibiz-template/controller';
import {
  FormDetailModel,
  FormGroupPanelModel,
  FormItemModel,
  FormModel,
} from '@ibiz-template/model';
import { useNamespace } from '@ibiz-template/vue-util';
import { defineComponent, PropType, CreateElement, VNode } from 'vue';
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,
    controller: controller.details[detail.source.name],
  };
  const provider = controller.providers[detail.source.name];
  if (!provider) {
    <div>
      暂未支持的表单项类型: {detail.source.detailType}或找不到对应适配器
    </div>;
  }
  return h(
    provider.component,
    {
      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,
    },
60
    context: { type: Object as PropType<IContext>, required: true },
61 62 63 64 65 66 67 68 69 70 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
    controller: {
      type: Object as PropType<FormController>,
      required: true,
    },
  },
  setup(props) {
    const ns = useNamespace('form');

    const c = props.controller;

    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>
    );
  },
});