我正在使用 AntDesign 上传图像来捕获 base64 字符串。 下面是代码:
import React, { useEffect, useState } from 'react';
import { MusicalRegisterIcon } from '../musicalRegisterIcon';
import { useAppDispatch, useAppSelector } from 'app/config/store';
import { Link, Navigate, useNavigate, useParams } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { getEntity, createEntity, updateEntity } from 'app/entities/user-profile/user-profile.reducer';
import { Row, Col } from 'reactstrap';
import { reset } from '../register.reducer';
import axios from 'axios';
import { Form, Input, Select, Space, theme, Button, Upload, message, DatePicker } from 'antd';
import { MinusCircleOutlined, PlusOutlined } from '@ant-design/icons';
import { PlaysInput } from 'app/Components/editProfile/plays';
import { parseBioPicture, parseProfilePicture } from './profileCreationUtils';
import TextArea from 'antd/es/input/TextArea';
import moment from 'moment';
export default function ProfileCreation() {
const isProfileCreated = useAppSelector(state => state.authentication.account.isProfileCreated);
// if (isProfileCreated === true) {
// return <Navigate to="/matching"></Navigate>; //reactivate later when making isProfileCreated
// }
const Instrument = [
'TROMBONE',
'ELECTRICGUITAR',
'PIANO',
'GUITAR',
'CELLO',
'CLARINET',
'BASSOON',
'VIOLIN',
'VOCALS',
'FLUTE',
'TRUMPET',
'SITAR',
'OBOE',
];
const genres = [
'ROCK',
'POP',
'BLUES',
'COUNTRY',
'ELECTRONIC',
'FOLK',
'HIPHOP',
'JAZZ',
'RANDB',
'METAL',
'PUNK',
'CLASSICAL',
'GRUNGE',
'DNB',
'HOUSE',
];
const levels = ['grade 1', 'grade 2', 'grade 3', 'grade 4', 'grade 5', 'grade 6', 'grade 7', 'grade 8'];
const dispatch = useAppDispatch();
const navigate = useNavigate();
const regExp: RegExp = /^07[0-9]{9}$/;
const id = useAppSelector(state => state.authentication.account.id);
const isNew = true;
const userProfileEntity = useAppSelector(state => state.userProfile.entity);
const loading = useAppSelector(state => state.userProfile.loading);
const updating = useAppSelector(state => state.userProfile.updating);
const updateSuccess = useAppSelector(state => state.userProfile.updateSuccess);
const [plays, setPlays] = useState([]);
const [likes, setLikes] = useState([]);
const { token } = theme.useToken();
const handleClose = () => {
navigate('/matching');
};
useEffect(() => {
if (isNew) {
dispatch(reset());
} else {
dispatch(getEntity(id));
}
}, []);
const getProfileCreated = async () => {
const accountRequest = await axios.get<any>('api/account');
const userExtras = await axios.get<any>(`api/user-extras/${accountRequest.data.id}`);
const userExtrasOnly = {
isProfileCreated: userExtras.data.isProfileCreated,
};
const result = {
id: accountRequest.data.id,
isProfileCreated: userExtras.data.isProfileCreated,
};
return result;
};
const normFile = (e: any) => {
if (Array.isArray(e)) {
return e;
}
return e?.fileList;
};
const beforeUpload = file => {
const isImage = file.type.includes('img') || file.type.includes('image');
if (!isImage) {
message.error(`${file.name} is not an image file`);
}
return false;
};
const onFinish = values => {
console.log(values);
const dateOfBirth = moment(values.dateOfBirth).format('YYYY-MM-DD');
const bioPics = parseBioPicture(values.bioPicture);
const profilePicture = parseProfilePicture(values.profilePicture);
const cleanedValuesFromBioandProfilePic = { ...values };
delete cleanedValuesFromBioandProfilePic.profilePicture;
delete cleanedValuesFromBioandProfilePic.bioPicture;
const data = { ...bioPics, ...profilePicture, ...cleanedValuesFromBioandProfilePic, dateOfBirth };
axios.post(`/api/create-user-profile/${id}`, data).then(() => {
navigate('/matching');
});
};
const defaultValues = () =>
isNew
? {}
: {
...userProfileEntity,
};
return (
<div>
<Row className="justify-content-center">
<Col md="8" style={{ marginBottom: '50px', marginTop: '50px' }}>
<h1 style={{ fontSize: 64, fontFamily: 'Capriola', fontWeight: 500 }}>Create User Profile</h1>
</Col>
</Row>
<Row className="justify-content-center">
<Col style={{ display: 'flex', flexDirection: 'column', height: '100%' }} md="8">
{loading ? (
<p>Loading...</p>
) : (
<Form onFinish={onFinish} style={{ maxWidth: 600 }} autoComplete="off">
<Form.Item name="university" label="University">
<Input style={{ width: '100%', marginLeft: '8rem' }} />
</Form.Item>
<Form.Item name="dateOfBirth" label="DatePicker">
<DatePicker style={{ marginLeft: '7.5rem' }} />
</Form.Item>
<Form.Item name="instagram" label="Instagram">
<Input style={{ width: '100%', marginLeft: '8rem' }} />
</Form.Item>
<Form.Item name="bio" label="Biography">
<TextArea style={{ marginLeft: '8rem' }} rows={4} />
</Form.Item>
<Form.Item
name="phone"
label="Phone Number"
rules={[{ required: true, message: 'Please input your phone number, the format has to start with 07', pattern: regExp }]}
>
<Input style={{ width: '100%', marginLeft: '4rem' }} />
</Form.Item>
<Form.List
name="plays"
rules={[
{
async validator(_, play) {
if (play === undefined) {
return Promise.reject(new Error("Instrument can't be empty "));
} else {
if (play.includes(undefined) === false) {
const instruments = play.map(value => value.instrument);
for (let index = 0; index < instruments.length; index++) {
if (instruments.indexOf(instruments[index]) !== instruments.lastIndexOf(instruments[index])) {
return Promise.reject(new Error("Instrument can't have duplicates "));
}
}
}
}
},
},
]}
>
{(fields, { add, remove }, { errors }) => (
<>
{fields.map(({ key, name, ...restField }) => (
<Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
<Form.Item
style={{ minWidth: '200px' }}
{...restField}
name={[name, 'instrument']}
rules={[{ required: true, message: 'Missing Instrument' }]}
>
<Select placeholder={'Instrument'} style={{ display: 'flex', minWidth: '2rem' }}>
{Instrument.map((value, index) => (
<Select.Option key={index} style={{ display: 'flex', minWidth: '2 rem' }} value={value}>
{value}
</Select.Option>
))}
</Select>
</Form.Item>
<Form.Item
{...restField}
name={[name, 'skillLevel']}
style={{ minWidth: '200px' }}
rules={[{ required: true, message: 'Missing Skill Level' }]}
>
<Select placeholder={'Skill Level'} style={{ display: 'flex', minWidth: '2rem' }}>
{levels.map((value, index) => (
<Select.Option key={index} style={{ display: 'flex', minWidth: '2 rem' }} value={value}>
{value}
</Select.Option>
))}
</Select>
</Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} />
</Space>
))}
<Form.Item>
<Button
style={{ marginLeft: '16rem', maxWidth: '200px' }}
type="dashed"
onClick={() => add()}
block
icon={<PlusOutlined />}
>
Add Your Instrument
</Button>
</Form.Item>
<Form.ErrorList errors={errors} />
</>
)}
</Form.List>
<Form.List
name="likes"
rules={[
{
async validator(_, play) {
if (play === undefined) {
return Promise.reject(new Error("Genres can't be empty "));
} else {
if (play.includes(undefined) === false) {
const likeslist = play.map(value => value.genre);
for (let index = 0; index < likeslist.length; index++) {
if (likeslist.indexOf(likeslist[index]) !== likeslist.lastIndexOf(likeslist[index])) {
return Promise.reject(new Error("Genres can't have duplicates "));
}
}
}
}
},
},
]}
>
{(fields, { add, remove }, { errors }) => (
<>
{fields.map(({ key, name, ...restField }) => (
<Space key={key} style={{ display: 'flex', marginBottom: 8 }} align="baseline">
<Form.Item
style={{ minWidth: '200px' }}
{...restField}
name={[name, 'genre']}
rules={[{ required: true, message: 'Missing Genre' }]}
>
<Select placeholder={'Genres'} style={{ display: 'flex', minWidth: '2rem' }}>
{genres.map((value, index) => (
<Select.Option key={index} style={{ display: 'flex', minWidth: '2 rem' }} value={value}>
{value}
</Select.Option>
))}
</Select>
</Form.Item>
<MinusCircleOutlined onClick={() => remove(name)} />
</Space>
))}
<Form.Item>
<Button
type="dashed"
onClick={() => add()}
style={{ marginLeft: '16rem', maxWidth: '200px' }}
block
icon={<PlusOutlined />}
>
Add Your Genre
</Button>
</Form.Item>
<Form.ErrorList errors={errors} />
</>
)}
</Form.List>
<Form.Item name="bioPicture" label="Bio Picture (Max 3)" valuePropName="bioPicture" getValueFromEvent={normFile}>
<Upload beforeUpload={beforeUpload} name="bioPicture" listType="picture-card" maxCount={3} accept=".png,.jpeg,.jpg">
<div>
<PlusOutlined />
<div style={{ marginTop: 8 }}>Upload</div>
</div>
</Upload>
</Form.Item>
<Form.Item name="profilePicture" label="Profile Picture (Max 1)" valuePropName="profilePicture" getValueFromEvent={normFile}>
<Upload beforeUpload={beforeUpload} name="profilePicture" listType="picture-card" maxCount={1} accept=".png,jpeg,.jpg">
<div>
<PlusOutlined />
<div style={{ marginTop: 8 }}>Upload</div>
</div>
</Upload>
</Form.Item>
<Form.Item>
<Button type="primary" htmlType="submit">
Submit
</Button>
</Form.Item>
</Form>
)}
</Col>
</Row>
</div>
);
}
const LikesInput = ({ likes, setLikes, token }) => {
// const [plays, setPlays] = useState(defaultPlays);
useEffect(() => {
console.log('Likes:');
console.log(likes);
}, [likes]);
const genres = [
'ROCK',
'POP',
'BLUES',
'COUNTRY',
'ELECTRONIC',
'FOLK',
'HIPHOP',
'JAZZ',
'RANDB',
'METAL',
'PUNK',
'CLASSICAL',
'GRUNGE',
'DNB',
'HOUSE',
];
return (
<Space wrap size={20} style={{ background: token.colorFillAlter, borderRadius: token.borderRadiusLG, padding: 24 }}>
{likes.map((p, i) => {
return (
<Space key={i}>
<Form.Item label="Instrument" style={{ marginBottom: 0 }}>
<Select
key={p.id}
style={{ width: 120 }}
value={likes.genre}
onSelect={newValue => {
const newLikes = [...likes];
newLikes[i].instrument = newValue;
setLikes(newLikes);
}}
>
{genres.map(instrument => {
return <Select.Option value={instrument}>{instrument}</Select.Option>;
})}
</Select>
</Form.Item>
<MinusCircleOutlined className="dynamic-delete-button" onClick={() => setLikes(likes.filter((p, j) => i !== j))} />
</Space>
);
})}
<Button
icon={<PlusOutlined />}
onClick={() => {
console.log(likes.slice(-1)[0]);
if (likes.length === 0 || !(likes.slice(-1)[0].instrument === '' && likes.slice(-1)[0].skillLevel === '')) {
// add new element if empty or last element is not blank
setLikes(likes.concat({ instrument: '' }));
}
}}
></Button>
</Space>
);
};
出于某种原因,在开发构建中使用获取 base64 字符串是可能的,这里是函数 onFinish() 的结果
const onFinish = values => {
console.log(values);
const dateOfBirth = moment(values.dateOfBirth).format('YYYY-MM-DD');
const bioPics = parseBioPicture(values.bioPicture);
const profilePicture = parseProfilePicture(values.profilePicture);
const cleanedValuesFromBioandProfilePic = { ...values };
delete cleanedValuesFromBioandProfilePic.profilePicture;
delete cleanedValuesFromBioandProfilePic.bioPicture;
const data = { ...bioPics, ...profilePicture, ...cleanedValuesFromBioandProfilePic, dateOfBirth };
axios.post(`/api/create-user-profile/${id}`, data).then(() => {
navigate('/matching');
});
};
正如您在 Prod Build 上看到的那样,它不起作用,这绝对不是 React 的问题,但更多的是我还没有弄清楚的设置。有人能告诉我这是为什么吗?谢谢