WIP: 新建专辑接口联调

main
fadeaway 3 months ago
parent 6a7e914a41
commit 283e8e2ab4

@ -0,0 +1,196 @@
import React, { useEffect, useMemo, useState } from 'react';
import {
Radio,
Form,
InputNumber,
Input,
Select,
Checkbox,
} from '@arco-design/web-react';
import { IconInfoCircle } from '@arco-design/web-react/icon';
import type { UploadItem } from '@arco-design/web-react/es/Upload';
export interface SongInfoItemProps {
originNode?: React.ReactNode;
file?: UploadItem;
fileList?: UploadItem[];
}
const { Item: FormItem, useForm, useWatch } = Form;
const RadioGroup = Radio.Group;
const { TextArea } = Input;
const AlbumTypeOpt = [
{
label: '录音室',
value: 'recordingStudio',
},
{
label: 'Live',
value: 'live',
},
{
label: 'Demo',
value: 'demo',
},
{
label: '伴奏',
value: 'accompaniment',
},
{
label: '其它',
value: 'other',
},
];
const IsChargeOpt = [
{
label: '收费',
value: 'charge',
},
{
label: '免费',
value: 'free',
},
];
export default function SongInfoItem(props: SongInfoItemProps) {
const { originNode, file, fileList } = props || {};
const [form] = useForm();
const [iamLyricist, setIamLyricist] = useState(false); // 我是作词人?
const [iamComposer, setIamComposer] = useState(false); // 我是作曲人?
const fileName = useMemo(() => file?.name, [file?.name]);
const filedNames = useMemo(
() => ({
albumType: `${fileName}.albumType`,
isCharge: `${fileName}.isCharge`,
songPricing: `${fileName}.songPricing`,
singer: `${fileName}.singer`,
songStyle: `${fileName}.songStyle`,
language: `${fileName}.language`,
lyricist: `${fileName}.lyricist`,
composer: `${fileName}.composer`,
lyric: `${fileName}.lyric`,
}),
[fileName]
);
return (
<>
<FormItem
label="专辑类型"
field={filedNames.albumType}
initialValue={AlbumTypeOpt[0].value}
rules={[{ required: true, message: '请选择专辑类型' }]}
>
<RadioGroup options={AlbumTypeOpt} />
</FormItem>
<FormItem
label="是否收费"
field={filedNames.isCharge}
initialValue={IsChargeOpt[0].value}
rules={[{ required: true, message: '请选择是否收费' }]}
>
<RadioGroup options={IsChargeOpt} />
</FormItem>
<FormItem
label="歌曲定价"
field={filedNames.songPricing}
rules={[{ required: true, message: '请输入歌曲定价' }]}
>
<InputNumber
min={0.01}
suffix="元"
step={1}
placeholder="请输入专辑价格"
/>
</FormItem>
<FormItem
label="歌手名称"
field={filedNames.singer}
rules={[{ required: true, message: '请输入歌手名称' }]}
>
<Input
allowClear
suffix={<IconInfoCircle />}
placeholder="请输入歌手名称"
/>
</FormItem>
<FormItem
label="曲风"
field={filedNames.songStyle}
rules={[{ required: true, message: '请选择曲风' }]}
>
<Select
mode="multiple"
placeholder="请选择曲风"
allowClear
options={[
{ label: '后摇', value: '1' },
{ label: '后朋克', value: '2' },
]}
/>
</FormItem>
<FormItem
label="语种"
field={filedNames.language}
rules={[{ required: true, message: '请选择语种' }]}
>
<Select
placeholder="请选择语种"
allowClear
options={[
{ label: '中文', value: '1' },
{ label: '英文', value: '2' },
]}
/>
</FormItem>
<FormItem
label="作词"
field={filedNames.lyricist}
rules={[{ required: true, message: '请输入作词人' }]}
>
<Input
allowClear
suffix={
<Checkbox
checked={iamLyricist}
onChange={(checked) => {
setIamLyricist(checked);
form?.setFieldValue('lyricist', checked ? 'me' : undefined); // TODO:
}}
>
</Checkbox>
}
placeholder="请输入"
/>
</FormItem>
<FormItem
label="作曲"
field={filedNames.composer}
rules={[{ required: true, message: '请输入作曲人' }]}
>
<Input
allowClear
suffix={
<Checkbox
checked={iamComposer}
onChange={(checked) => {
setIamComposer(checked);
form?.setFieldValue('composer', checked ? 'me' : undefined); // TODO:
}}
>
</Checkbox>
}
placeholder="请输入"
/>
</FormItem>
<FormItem label="歌词" field={filedNames.lyric}>
<TextArea allowClear placeholder="请输入歌词,注意断句换行" rows={3} />
</FormItem>
</>
);
}

@ -7,6 +7,7 @@ import {
Typography, Typography,
} from '@arco-design/web-react'; } from '@arco-design/web-react';
import { IconInfoCircle, IconDown } from '@arco-design/web-react/icon'; import { IconInfoCircle, IconDown } from '@arco-design/web-react/icon';
import SongInfoItem from '../SongInfoItem';
import type { UploadItem } from '@arco-design/web-react/es/Upload'; import type { UploadItem } from '@arco-design/web-react/es/Upload';
@ -21,29 +22,35 @@ export interface SongUploadItemProps {
const CollapseItem = Collapse.Item; const CollapseItem = Collapse.Item;
const { Row, Col } = Grid; const { Row, Col } = Grid;
export function SongUploadItem(props: SongUploadItemProps) { export default function SongUploadItem(props: SongUploadItemProps) {
const { originNode, file, fileList } = props || {}; const { originNode, file, fileList } = props || {};
console.log(111, originNode); // console.log(111, originNode);
console.log(222, file); // console.log(222, file);
console.log(333, fileList); // console.log(333, fileList);
return ( return (
<Row align="center" gutter={12} className={styles.songUploadItem}> <Row align="center" gutter={12} className={styles.songUploadItem}>
<Col flex={1}> <Col flex={1}>
<Card className={styles.songUploadItemCard} hoverable> <Card className={styles.songUploadItemCard} hoverable>
<Collapse expandIconPosition="right" expandIcon={<IconDown />}> <Collapse
expandIconPosition="right"
expandIcon={<IconDown />}
destroyOnHide={false}
defaultActiveKey="1"
>
<CollapseItem <CollapseItem
header={originNode} header={originNode}
name="1" name="1"
// extra={<IconInfoCircle />} // extra={<IconInfoCircle />}
destroyOnHide={false}
> >
Beijing Toutiao Technology Co., Ltd. <SongInfoItem {...props} />
</CollapseItem> </CollapseItem>
</Collapse> </Collapse>
</Card> </Card>
</Col> </Col>
<Col flex="50px">123</Col> {/* <Col flex="50px">123</Col> */}
</Row> </Row>
); );
} }

@ -1,5 +1,7 @@
import React, { useMemo, useState } from 'react'; import React, { useMemo, useState } from 'react';
import cs from 'classnames';
import { Breadcrumb, Steps } from '@arco-design/web-react'; import { Breadcrumb, Steps } from '@arco-design/web-react';
import request from '@/utils/request';
import Step1 from './step1'; import Step1 from './step1';
import Step2 from './step2'; import Step2 from './step2';
import Step3, { AgreeStep3 } from './step3'; import Step3, { AgreeStep3 } from './step3';
@ -14,11 +16,13 @@ const AllSteps = [
]; ];
function CreateAlbum() { function CreateAlbum() {
const [curStep, setCurStep] = useState(2); const [curStep, setCurStep] = useState(1);
const [stepFormValues, setStepFormValues] = useState<any>({});
const steps = useMemo(() => AllSteps.slice(0, curStep), [curStep]); const steps = useMemo(() => AllSteps.slice(0, curStep), [curStep]);
const handleStep1Next = (step1Values) => { const handleStep1Next = (step1Values) => {
console.log(step1Values); console.log(step1Values);
setStepFormValues({ ...stepFormValues, step1: step1Values });
setCurStep(2); setCurStep(2);
}; };
@ -26,12 +30,38 @@ function CreateAlbum() {
setCurStep(1); setCurStep(1);
}; };
const handleStep2Next = () => { const handleStep2Next = (step2Values) => {
console.log(step2Values);
setStepFormValues({ ...stepFormValues, step2: step2Values });
setCurStep(3); setCurStep(3);
}; };
const handleStep3Next = () => { const handleStep3Next = () => {
// TOOD: // TOOD:
console.log(stepFormValues);
const { step1, step2 } = stepFormValues;
const songAddList = [];
const oParam = {
name: step1.albumName, // 专辑名称
version: step1.albumVersion, // 专辑版本
type: step1.albumType, // 专辑类型
mainStyle: step1.albumStyle, // 专辑风格
publishDate: step1.date, // 发行日期
barcode: step1.albumCode, // 专辑条码
description: step1.albumDesc, // 专辑描述
image: step1.albumCover, // 专辑封面
songAddList,
};
return request
.post('/luoo-music/album/add', oParam)
.then((res: any) => {
if (res?.code === 200) {
// Message.success('操作成功');
}
})
.finally(() => {
//
});
}; };
return ( return (
@ -51,11 +81,15 @@ function CreateAlbum() {
<Step title={title} description={desc} key={title} /> <Step title={title} description={desc} key={title} />
))} ))}
</Steps> </Steps>
{curStep === 1 && <Step1 onNext={handleStep1Next} />} <div className={cs(styles.stepWrap, curStep !== 1 && styles.hide)}>
{curStep === 2 && ( <Step1 onNext={handleStep1Next} />
</div>
<div className={cs(styles.stepWrap, curStep !== 2 && styles.hide)}>
<Step2 onPre={handleStep2Pre} onNext={handleStep2Next} /> <Step2 onPre={handleStep2Pre} onNext={handleStep2Next} />
)} </div>
{curStep === 3 && <Step3 />} <div className={cs(styles.stepWrap, curStep !== 3 && styles.hide)}>
<Step3 />
</div>
</section> </section>
{curStep === 3 && <AgreeStep3 onNext={handleStep3Next} />} {curStep === 3 && <AgreeStep3 onNext={handleStep3Next} />}
</div> </div>

@ -33,7 +33,6 @@ function CreateAlbumStep1(props: CreateAlbumStep1Props) {
const handleNext = () => { const handleNext = () => {
form.validate().then((values) => { form.validate().then((values) => {
console.log(values);
onNext?.(values); onNext?.(values);
}); });
}; };

@ -16,7 +16,7 @@ import {
IconFileAudio, IconFileAudio,
IconFaceFrownFill, IconFaceFrownFill,
} from '@arco-design/web-react/icon'; } from '@arco-design/web-react/icon';
import { SongUploadItem } from './components/SongUploadItem'; import SongUploadItem from './components/SongUploadItem';
import type { UploadItem } from '@arco-design/web-react/es/Upload'; import type { UploadItem } from '@arco-design/web-react/es/Upload';
@ -65,6 +65,8 @@ const isAcceptFile = (file, accept) => {
return !!file; return !!file;
}; };
const UploadAccept = 'audio/mp3,audio/wav';
function CreateAlbumStep2(props: CreateAlbumStep1Props) { function CreateAlbumStep2(props: CreateAlbumStep1Props) {
const [form] = useForm(); const [form] = useForm();
const { onPre, onNext } = props || {}; const { onPre, onNext } = props || {};
@ -80,97 +82,97 @@ function CreateAlbumStep2(props: CreateAlbumStep1Props) {
const handleNext = () => { const handleNext = () => {
form.validate().then((values) => { form.validate().then((values) => {
console.log(values);
onNext?.(values); onNext?.(values);
}); });
}; };
return ( return (
<> <>
{songs && songs.length > 0 ? ( <Form
<div className={styles.uploadBtnWrap}> form={form}
<Upload labelCol={{ flex: '100px' }}
showUploadList={{ wrapperCol={{ flex: '468px' }}
// reuploadIcon: <IconUpload />, >
// reuploadIcon: ( {songs && songs.length > 0 ? (
// <Button size="mini" type="text"> <div className={styles.uploadBtnWrap}>
// 替换 <Upload
// </Button> showUploadList={{
// ), // reuploadIcon: <IconUpload />,
// cancelIcon: <IconClose />, // reuploadIcon: (
// fileIcon: <IconFileAudio />, // <Button size="mini" type="text">
// previewIcon: null, // 替换
// errorIcon: <IconFaceFrownFill />, // </Button>
fileName: (file) => { // ),
// cancelIcon: <IconClose />,
// fileIcon: <IconFileAudio />,
// previewIcon: null,
// errorIcon: <IconFaceFrownFill />,
fileName: (file) => {
return (
<a
onClick={() => {
Message.info('click ' + file.name);
}}
>
{file.name}
</a>
);
},
}}
progressProps={{
formatText: (percent) => `${percent}%`,
}}
renderUploadItem={(
originNode: React.ReactNode,
file: UploadItem,
fileList: UploadItem[],
...others
) => {
console.log(123456, others);
return ( return (
<a <SongUploadItem
onClick={() => { originNode={originNode}
Message.info('click ' + file.name); file={file}
}} fileList={fileList}
> />
{file.name}
</a>
); );
}, }}
}} onReupload={(file: UploadItem) => {
progressProps={{ // console.log(file);
formatText: (percent) => `${percent}%`, }}
}} multiple
renderUploadItem={( listType="text"
originNode: React.ReactNode, action="/luoo-music/cms/song/upload/song"
file: UploadItem, fileList={songs}
fileList: UploadItem[] onChange={handleFileChange}
) => { accept={UploadAccept}
return ( />
<SongUploadItem </div>
originNode={originNode} ) : (
file={file} <Upload
fileList={fileList} className={styles.uploadArea}
/> drag
);
}}
onReupload={(file: UploadItem) => {
console.log(123);
}}
multiple multiple
listType="text" accept={UploadAccept}
action="/luoo-music/cms/song/upload/song" action="/luoo-music/cms/song/upload/song"
fileList={songs} onDrop={(e) => {
const uploadFile = e.dataTransfer.files[0];
if (isAcceptFile(uploadFile, UploadAccept)) {
return;
} else {
Message.info('不接受的文件类型,请重新上传指定文件类型~');
}
}}
tip={
<div className={styles.uploadAreaTip}>
{
'歌曲须为MP3/WAV建议优先上传WAV播放效果更佳音质≥320kbps采样率≥44.1kHz,文件大小<200MB'
}
</div>
}
onChange={handleFileChange} onChange={handleFileChange}
/> />
</div> )}
) : (
<Upload
className={styles.uploadArea}
drag
multiple
accept="image/*"
action="/luoo-music/cms/song/upload/song"
onDrop={(e) => {
const uploadFile = e.dataTransfer.files[0];
if (isAcceptFile(uploadFile, 'image/*')) {
return;
} else {
Message.info('不接受的文件类型,请重新上传指定文件类型~');
}
}}
tip={
<div className={styles.uploadAreaTip}>
{
'歌曲须为MP3/WAV建议优先上传WAV播放效果更佳音质≥320kbps采样率≥44.1kHz,文件大小<200MB'
}
</div>
}
onChange={handleFileChange}
/>
)}
<Form
form={form}
labelCol={{ flex: '100px' }}
wrapperCol={{ flex: '468px' }}
>
{/* <FormItem field="albumName">
</FormItem> */}
<div className={stylesIndex.submitWrap}> <div className={stylesIndex.submitWrap}>
<Space size={24}> <Space size={24}>
<Button onClick={handlePre}></Button> <Button onClick={handlePre}></Button>

@ -31,18 +31,21 @@ function CreateAlbumStep3() {
} }
export interface AgreeStep3Props { export interface AgreeStep3Props {
onNext?: () => void; onNext?: () => Promise<any>;
} }
function AgreeStep3(props: AgreeStep3Props) { function AgreeStep3(props: AgreeStep3Props) {
const { onNext } = props || {}; const { onNext } = props || {};
const [agree, setAgree] = useState(false); const [agree, setAgree] = useState(false);
const [loading, setLoading] = useState(false);
const handleNext = () => { const handleNext = async () => {
if (!agree) { if (!agree) {
Message.warning('请阅读协议并同意向雀乐音乐人授权'); Message.warning('请阅读协议并同意向雀乐音乐人授权');
} else { } else {
onNext?.(); setLoading(true);
await onNext?.();
setLoading(false);
} }
}; };
@ -51,7 +54,7 @@ function AgreeStep3(props: AgreeStep3Props) {
<Radio checked={agree} onChange={(checked: boolean) => setAgree(checked)}> <Radio checked={agree} onChange={(checked: boolean) => setAgree(checked)}>
</Radio> </Radio>
<Button type="primary" onClick={handleNext}> <Button type="primary" loading={loading} onClick={handleNext}>
</Button> </Button>
</div> </div>

@ -31,6 +31,10 @@
} }
} }
.stepWrap {
width: 100%;
}
.submitWrap { .submitWrap {
width: 100%; width: 100%;
display: flex; display: flex;
@ -39,3 +43,7 @@
text-align: center; text-align: center;
margin-top: 40px; margin-top: 40px;
} }
.hide {
display: none;
}

Loading…
Cancel
Save