form-content.vue 3.1 KB
<script setup lang="ts">
  import { useSelectionStore } from '@/store';

  import { Layout, LayoutSider, LayoutContent, LayoutFooter, Step, Steps, Space, Divider, Link } from '@arco-design/web-vue';
  import Step1FormContent from '@/views/audition/demo-apply/components/step1-form-content.vue';
  import Step2FormContent from '@/views/audition/demo-apply/components/step2-form-content.vue';
  import Step3FormContent from '@/views/audition/demo-apply/components/step3-form-content.vue';
  import IconButton from '@/components/icon-button/index.vue';

  import { AnyObject } from '@/types/global';
  import useLoading from '@/hooks/loading';
  import { computed, markRaw, ref } from 'vue';
  import { cloneDeep } from 'lodash';

  const props = defineProps<{
    initValue: AnyObject;
    filterProject?: (value: unknown) => boolean;
    onSubmit: (data: AnyObject) => Promise<any>;
  }>();

  const { loading, setLoading } = useLoading(false);
  const formRef = ref();
  const formValue = ref({ ...cloneDeep(props.initValue) });

  const stepItems = [
    { value: 1, label: '基本信息', template: markRaw(Step1FormContent) },
    { value: 2, label: '补充信息', template: markRaw(Step2FormContent) },
    { value: 3, label: '上传文件', template: markRaw(Step3FormContent) },
  ];

  const currentStep = ref(1);
  const currentContent = computed(() => stepItems.find((item) => item.value === currentStep.value)?.template);
  const nextBtnLabel = computed(() => (currentStep.value === 3 ? '提交' : '下一步'));

  const onPrev = (): void => {
    currentStep.value = Math.max(1, currentStep.value - 1);
  };

  const onNext = () => {
    formRef.value.onValid(async () => {
      if (currentStep.value === stepItems.length) {
        setLoading(true);
        props.onSubmit(formValue.value).finally(() => setLoading(false));
      }
      currentStep.value = Math.min(stepItems.length, currentStep.value + 1);
    });
  };
</script>

<template>
  <Layout>
    <Layout has-sider>
      <LayoutSider :width="120" class="aside">
        <Steps :current="currentStep" direction="vertical" :small="true">
          <Step v-for="item in stepItems" :key="item.value">{{ item.label }}</Step>
        </Steps>
      </LayoutSider>
      <LayoutContent class="main">
        <component :is="currentContent" ref="formRef" v-model="formValue" v-model:loading="loading" :filter-project="filterProject" />
      </LayoutContent>
    </Layout>
    <LayoutFooter>
      <Divider style="margin-top: 8px; margin-bottom: 20px" />
      <Link :href="useSelectionStore().lyricTool" :hoverable="false" class="link-hover" icon>歌词制作工具</Link>
      <Space style="float: right">
        <IconButton v-show="currentStep !== 1" icon="left" label="上一步" @click="onPrev" />
        <IconButton icon="right" icon-align="right" :loading="loading" :label="nextBtnLabel" @click="onNext" />
      </Space>
    </LayoutFooter>
  </Layout>
</template>

<style scoped lang="less">
  .aside {
    box-shadow: unset !important;
    border-right: 1px solid var(--color-border);
    margin-right: 20px;
    background-color: transparent;
  }

  .main {
    min-width: 640px;
  }
</style>