form-content.vue 3 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="140" class="aside">
        <Steps :current="currentStep" direction="vertical">
          <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>