Explorar o código

🎈 perf: 仅上传mp3

wolyshaw %!s(int64=3) %!d(string=hai) anos
pai
achega
2ac81db45f
Modificáronse 3 ficheiros con 193 adicións e 35 borrados
  1. 12 0
      src/constant/music.ts
  2. 10 1
      src/helpers/music-xml.ts
  3. 171 34
      src/teacher/music/upload/index.tsx

+ 12 - 0
src/constant/music.ts

@@ -29,3 +29,15 @@ export const teachershowFingeringType = {
   0: '否',
   1: '是'
 }
+
+/** 老师端展示播放类型 */
+export const teachershowAudiType = {
+  MIDI: 'MIDI',
+  MP3: 'MP3'
+}
+
+/** 老师端展示是否包含节拍器类型 */
+export const teachershowHasBeatType = {
+  0: '否',
+  1: '是'
+}

+ 10 - 1
src/helpers/music-xml.ts

@@ -50,6 +50,7 @@ export type FormatXMLInfo = {
   speed: number
   title: string
   composer: string
+  partNames: string[]
 }
 
 /** 获取xml基本信息,标题,速度等信息 */
@@ -60,7 +61,9 @@ export const getXmlInfo = (xml: string): FormatXMLInfo => {
     /** 标题 */
     title: '',
     /** 作曲人 */
-    composer: ''
+    composer: '',
+    /** 声部列表 */
+    partNames: []
   }
 
   const xmlParse = new DOMParser().parseFromString(xml, 'text/xml')
@@ -68,6 +71,12 @@ export const getXmlInfo = (xml: string): FormatXMLInfo => {
   data.composer = xmlParse.getElementsByTagName('creator')[0]?.textContent || ''
   const measures = xmlParse.getElementsByTagName('measure')
 
+  for (const item of Array.from(xmlParse.getElementsByTagName('part-name'))) {
+    if (item.textContent) {
+      data.partNames.push(item.textContent)
+    }
+  }
+
   for (const measure of Array.from(measures)) {
     const perMinute = measure.getElementsByTagName('per-minute')
     if (perMinute.length && perMinute[perMinute.length - 1]) {

+ 171 - 34
src/teacher/music/upload/index.tsx

@@ -20,7 +20,9 @@ import ColField from '@/components/col-field'
 import {
   teachercanEvaluateType,
   teacherChargeType,
-  teachershowFingeringType
+  teachershowAudiType,
+  teachershowFingeringType,
+  teachershowHasBeatType
 } from '@/constant/music'
 import { getXmlInfo, FormatXMLInfo } from '@/helpers/music-xml'
 import Upload from './upload'
@@ -28,23 +30,31 @@ import styles from './index.module.less'
 import SelectTag from '@/student/music/search/select-tag'
 import { browser } from '@/helpers/utils'
 import { postMessage } from '@/helpers/native-message'
-import classNames from 'classnames'
 import { teacherState } from '@/teacher/teacher-cert/teacherState'
 import request from '@/helpers/request'
 import requestOrigin from 'umi-request'
 import UploadIcon from './upload.svg'
 
+export type BackgroundMp3 = {
+  url?: string
+  track?: string
+}
+
 export default defineComponent({
   name: 'MusicUpload',
   data() {
     return {
+      audioType: 'MP3',
       xmlFileUrl: '',
       xmlFileLoading: false,
       midiUrl: '',
       midiLoading: false,
+      mp3Url: '',
+      mp3Loading: false,
       musicSheetName: '',
       composer: '',
       speed: '',
+      hasBeat: 0,
       chargeType: 0,
       showFingering: 1,
       canEvaluate: 1,
@@ -60,7 +70,13 @@ export default defineComponent({
       vlewSubjectList: null as any,
       submitLoading: false,
       showPicker: false,
-      music_sheet_service_fee: 0
+      music_sheet_service_fee: 0,
+      backgroundMp3s: [
+        {
+          url: '',
+          track: ''
+        }
+      ] as BackgroundMp3[]
     }
   },
   watch: {
@@ -120,10 +136,15 @@ export default defineComponent({
     async submit(vals: any) {
       this.submitLoading = true
       try {
+        const beatType = this.hasBeat ? 'MP3_METRONOME' : 'MP3'
+        const mp3Type = this.audioType === 'MP3' ? beatType : 'MIDI'
         await request.post('/api-teacher/music/sheet/create', {
           data: {
-            audioType: 'MIDI',
+            audioType: this.audioType,
             sourceType: 'TEACHER',
+            mp3Type,
+            url: this.hasBeat ? '' : this.mp3Url,
+            metronomeUrl: this.hasBeat ? this.mp3Url : '',
             showFingering: Number(this.showFingering) || undefined,
             musicTag: this.tags.join(','),
             musicSubject: Number(this.selectedSubjectList?.label) || undefined,
@@ -133,7 +154,12 @@ export default defineComponent({
             canEvaluate: Number(this.canEvaluate) || undefined,
             chargeType: this.chargeType === 0 ? 'FREE' : 'CHARGE',
             composer: this.composer,
-            musicPrice: this.musicPrice
+            musicPrice: this.musicPrice,
+            background: this.backgroundMp3s.map(item => ({
+              audioFileUrl: this.hasBeat ? '' : item.url,
+              track: item.track,
+              metronomeUrl: this.hasBeat ? item.url : ''
+            }))
           }
         })
       } catch (error) {}
@@ -160,10 +186,13 @@ export default defineComponent({
       return data
     },
     failed() {
-      console.log('failed', this.musicSheetName)
+      console.log('failed', this.backgroundMp3s)
     },
     mergeXmlData(data: FormatXMLInfo) {
       this.formated = data
+      this.backgroundMp3s = data.partNames.map((partName: string) => ({
+        track: partName
+      }))
       if (!this.musicSheetName) {
         this.musicSheetName = data.title
       }
@@ -215,11 +244,21 @@ export default defineComponent({
         // this.midiUrl = path
       })
     },
+    naiveMp3File() {
+      this.mp3Loading = true
+      postMessage({ api: 'chooseFile', content: { type: 'mp3' } }, evt => {
+        // @ts-ignore
+        this.mp3Url = evt?.fileUrl || this.mp3Url || ''
+        this.mp3Loading = false
+        // this.midiUrl = path
+      })
+    },
     fileName(name = '') {
       return name.split('/').pop()
     }
   },
   render() {
+    console.log(this.formated)
     const browserInfo = browser()
     return (
       <Form onSubmit={this.submit} onFailed={this.failed}>
@@ -254,34 +293,132 @@ export default defineComponent({
                 }}
               />
             </ColField>
-            <ColField border={false} required title="MIDI文件">
-              <Field
-                name="midiUrl"
-                modelValue={this.midiUrl}
-                rules={[{ required: true, message: '请选择MIDI文件' }]}
-                // @ts-ignore
-                vSlots={{
-                  input: () =>
-                    browserInfo.isApp ? (
-                      <Button
-                        icon={UploadIcon}
-                        class={styles.upbtn}
-                        onClick={this.naiveMidFile}
-                        loading={this.midiLoading}
-                      >
-                        {this.midiUrl
-                          ? this.fileName(this.midiUrl)
-                          : '上传文件'}
-                      </Button>
-                    ) : (
-                      <Upload
-                        onUpdate:modelValue={val => (this.midiUrl = val)}
-                        accept=".mid"
-                      />
-                    )
-                }}
-              />
-            </ColField>
+            {/* <ColField required title="播放类型" border={false}>
+              <RadioGroup
+                class={styles['radio-group']}
+                modelValue={this.audioType}
+                onUpdate:modelValue={val => (this.audioType = val)}
+              >
+                {Object.keys(teachershowAudiType).map((item: string) => {
+                  const isActive = item === this.audioType
+                  const type = isActive ? 'primary' : 'default'
+                  return (
+                    <Radio class={styles.radio} name={item}>
+                      <Tag size="large" plain={isActive} type={type}>
+                        {teachershowAudiType[item]}
+                      </Tag>
+                    </Radio>
+                  )
+                })}
+              </RadioGroup>
+            </ColField> */}
+            {this.audioType === 'MP3' ? (
+              <>
+                <ColField required title="是否带节拍器" border={false}>
+                  <RadioGroup
+                    class={styles['radio-group']}
+                    modelValue={this.hasBeat}
+                    onUpdate:modelValue={val => (this.hasBeat = val)}
+                  >
+                    {Object.keys(teachershowHasBeatType).map((item: string) => {
+                      const isActive = item === String(this.hasBeat)
+                      const type = isActive ? 'primary' : 'default'
+                      return (
+                        <Radio class={styles.radio} name={item}>
+                          <Tag size="large" plain={isActive} type={type}>
+                            {teachershowHasBeatType[item]}
+                          </Tag>
+                        </Radio>
+                      )
+                    })}
+                  </RadioGroup>
+                </ColField>
+                <ColField border={false} title="伴奏文件">
+                  <Field
+                    name="mp3Url"
+                    modelValue={this.mp3Url}
+                    // @ts-ignore
+                    vSlots={{
+                      input: () =>
+                        browserInfo.isApp ? (
+                          <Button
+                            icon={UploadIcon}
+                            class={styles.upbtn}
+                            onClick={this.naiveMp3File}
+                            loading={this.mp3Loading}
+                          >
+                            {this.mp3Url
+                              ? this.fileName(this.mp3Url)
+                              : '上传文件'}
+                          </Button>
+                        ) : (
+                          <Upload
+                            onUpdate:modelValue={val => (this.mp3Url = val)}
+                            accept=".mp3"
+                          />
+                        )
+                    }}
+                  />
+                </ColField>
+              </>
+            ) : (
+              <ColField border={false} required title="MIDI文件">
+                <Field
+                  name="midiUrl"
+                  modelValue={this.midiUrl}
+                  rules={[{ required: true, message: '请选择MIDI文件' }]}
+                  // @ts-ignore
+                  vSlots={{
+                    input: () =>
+                      browserInfo.isApp ? (
+                        <Button
+                          icon={UploadIcon}
+                          class={styles.upbtn}
+                          onClick={this.naiveMidFile}
+                          loading={this.midiLoading}
+                        >
+                          {this.midiUrl
+                            ? this.fileName(this.midiUrl)
+                            : '上传文件'}
+                        </Button>
+                      ) : (
+                        <Upload
+                          onUpdate:modelValue={val => (this.midiUrl = val)}
+                          accept=".mid"
+                        />
+                      )
+                  }}
+                />
+              </ColField>
+            )}
+            {this.backgroundMp3s.map(item => (
+              <ColField required border={false} title="原音文件">
+                <Field
+                  name="url"
+                  modelValue={item.url}
+                  rules={[{ required: true, message: '请选择原音文件' }]}
+                  // @ts-ignore
+                  vSlots={{
+                    input: () =>
+                      browserInfo.isApp ? (
+                        <Button
+                          icon={UploadIcon}
+                          class={styles.upbtn}
+                          onClick={this.naiveMp3File}
+                          loading={this.mp3Loading}
+                        >
+                          {item.url ? this.fileName(item.url) : '上传文件'}
+                        </Button>
+                      ) : (
+                        <Upload
+                          onUpdate:modelValue={val => (item.url = val)}
+                          accept=".mp3"
+                        />
+                      )
+                  }}
+                />
+              </ColField>
+            ))}
           </ColFieldGroup>
           <ColFieldGroup class={styles.area}>
             <ColField required title="曲目名称">