step3-form-content.vue 5.05 KB
<script setup lang="ts">
import { ref, computed, createVNode } from 'vue';
import { FieldRule, FormInstance } from '@arco-design/web-vue/es/form';
import { useVModels } from '@vueuse/core';
import { Form, FormItem, Link, Textarea, TypographyText } from '@arco-design/web-vue';
import InputUpload from '@/components/input-upload/index.vue';
import { useSelectionStore } from '@/store';
import { get, set } from 'lodash';
import axios from 'axios';
import AudioPreview from '@/views/demo/components/audio-preview.vue';
import AudioPlayer from '@/components/audio-player/index.vue';
import { createModalVNode } from '@/utils/createVNode';
import useAuthApi from "@/api/auth";

const props = defineProps<{ loading?: boolean; modelValue?: any }>();
const emits = defineEmits(['update:modelValue', 'update:loading']);

const formRef = ref<FormInstance>();
const { loading, modelValue: formValue } = useVModels(props, emits);

const guideSourceUrl = computed({
  get: () => get(formValue.value, 'expand.guide_source.url', ''),
  set: (val) => set(formValue.value, 'expand.guide_source.url', val),
});

const karaokeSourceUrl = computed({
  get: () => get(formValue.value, 'expand.karaoke_source.url', ''),
  set: (val) => set(formValue.value, 'expand.karaoke_source.url', val),
});

const onUpdateGuide = (file: { name: string; url: string; size: number }) => {
  set(formValue.value, 'expand.guide_source', { name: file.name, url: file.url, size: file.size });
};

const onUpdateKaraoke = (file: { name: string; url: string; size: number }) => {
  set(formValue.value, 'expand.karaoke_source', { name: file.name, url: file.url, size: file.size });
};

const { activityAudioAccept } = useSelectionStore();

const formRule = {
  'expand.guide_source.url': [{ required: true, message: '请上传导唱文件' }],
  'expand.karaoke_source.url': [{ required: false, message: '请上传伴奏文件' }],
  'lyric': [{ type: 'string', required: true, message: '请填写歌词内容' }],
  'clip_lyric': [{ type: 'string', required: true, message: '请填写推荐歌词内容' }],
} as Record<string, FieldRule[]>;

const onDownload = (url: string, fileName: string) => useAuthApi.downloadFile(url, `${formValue.value.song_name}(${fileName})`);

const onFormatLyric = (key: string) => {
  formValue.value[key] = formValue.value[key].replace(/(\n[\s\t]*\r*\n)/g, '\n').replace(/^[\n\r\t]*|[\n\r\t]*$/g, '');
};

const guideFile = ref<File | undefined>();

const getGuideFile = async () => {
  if (!guideFile.value) {
    guideFile.value = await axios
      .get(`${guideSourceUrl.value}?response-content-type=Blob`, { responseType: 'blob', timeout: 60000 })
      .then(({ data }) => Promise.resolve(data));
  }

  return guideFile.value;
};

const onAudioPreview = async () => {
  const src = await getGuideFile();
  createModalVNode(() => createVNode(AudioPreview, { src, lyric: formValue.value.lyric }), {
    title: '预览歌词-整首',
    footer: false,
    closable: true,
  });
};

defineExpose({
  onValid: (callback?: () => void) => formRef.value?.validate((errors) => !errors && callback?.()),
});
</script>

<template>
  <Form ref="formRef" :model="formValue" :rules="formRule" :auto-label-width="true" size="small">
    <FormItem label="音频文件" field="expand.guide_source.url" :show-colon="true">
      <InputUpload v-model="guideSourceUrl" :accept="activityAudioAccept" :limit="100" @success="onUpdateGuide"
        @choose-file="(file: any) => (guideFile = file)" @update:loading="(value: boolean) => (loading = value)" />
    </FormItem>
    <FormItem v-if="guideSourceUrl">
      <template #label>
        <Link icon @click="onDownload(guideSourceUrl, '音频文件')">下载音频</Link>
      </template>
      <AudioPlayer name="音频文件" :url="guideSourceUrl" />
    </FormItem>
    <FormItem label="伴奏文件" field="expand.karaoke_source.url" :show-colon="true">
      <InputUpload v-model="karaokeSourceUrl" :accept="activityAudioAccept" :limit="100" @success="onUpdateKaraoke"
        @update:loading="(value: boolean) => (loading = value)" />
    </FormItem>
    <FormItem v-if="karaokeSourceUrl">
      <template #label>
        <Link icon @click="onDownload(karaokeSourceUrl, '伴奏文件')">下载伴奏</Link>
      </template>
      <AudioPlayer name="伴奏文件" :url="karaokeSourceUrl" />
    </FormItem>
    <FormItem class="lyric" label="歌词文本" field="lyric" :show-colon="true">
      <Textarea v-model="formValue.lyric" :auto-size="{ minRows: 6, maxRows: 6 }" placeholder="请粘贴带时间的lrc歌词文本至输入框"
        @blur="() => onFormatLyric('lyric')" />
      <!-- <template #extra>
        <Link :hoverable="false" :disabled="!guideSourceUrl || !formValue.lyric" @click="onAudioPreview"> 预览歌词</Link>
      </template> -->
    </FormItem>
    <TypographyText type="danger" style="font-size: 13px">
      注意:demo上架后,存在于您的私库。需要在App应用内,您的个人主页下,进行1对1分享给对方试听
    </TypographyText>
  </Form>
</template>

<style scoped lang="less">
.lyric {
  :deep(.arco-form-item-extra) {
    width: 100%;
    text-align: right;
  }
}
</style>