router-shell.tsx 2.2 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 60 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
import {
  defineComponent,
  onUnmounted,
  ref,
  toRaw,
  h,
  resolveComponent,
  PropType,
} from 'vue';
import { parseRouteViewData } from '@ibiz-template/vue3-util';
import { useRoute, useRouter } from 'vue-router';
import { IModal } from '@ibiz-template/runtime';
import { IBizContext } from '@ibiz-template/core';
import { IAppView } from '@ibiz/model-core';
import { mergeDeepLeft } from 'ramda';

export const RouterShell = defineComponent({
  name: 'RouterShell',
  props: {
    modal: {
      type: Object as PropType<IModal>,
      required: true,
    },
  },
  setup(props) {
    const route = useRoute();
    const router = useRouter();
    const viewData = ref<{
      viewModel?: IAppView;
      context?: IContext;
      params?: IParams;
      srfnav?: string;
    }>({});
    const isLoaded = ref(false);
    const destroyContext = () => {
      if (viewData.value.context) {
        const { context } = toRaw(viewData.value);
        if (context) context.destroy();
      }
    };
    const routeDepth = props.modal?.routeDepth! || 1;

    // 销毁视图上下文
    onUnmounted(() => {
      destroyContext();
    });

    // 根据应用模型解析视图参数
    const calcViewData = async () => {
      // 获取视图
      try {
        const _viewData = await parseRouteViewData(route, routeDepth);
        // 封装IBizContext
        const _context = IBizContext.create(_viewData.context);
        viewData.value = {
          ..._viewData,
          context: _context,
        };
        // 确定视图组件
        isLoaded.value = true;
      } catch (error) {
        router.push({ name: `404View${routeDepth}` });
      }
    };
    calcViewData();
    return {
      route,
      viewData,
      isLoaded,
    };
  },
  render() {
    if (!this.isLoaded) {
      return null;
    }
    const { context, params, srfnav, viewModel } = this.viewData;
    const props = mergeDeepLeft(
      {
        ...this.$props,
        ...this.$attrs,
        context,
        params,
        modelData: viewModel,
        key: viewModel!.codeName,
      },
      { state: { srfnav } },
    );

    return h(resolveComponent('IBizViewShell') as string, props, this.$slots);
  },
});