需求的数据结构为可编辑的二维数组结构,在Form表单中提交数据到服务端,下面为数据结构的例子:
[
[{
"text": "",
"audioUrl": "",
"emotion": ""
}, {
"text": "",
"audioUrl": "",
"emotion": ""
}],
[{
"text": "",
"audioUrl": "",
"emotion": ""
}, {
"text": "",
"audioUrl": "",
"emotion": ""
}]
]
实现效果:实现元素的动态添加,包含音频的上传与播放
在Form表单组件中使用Tabs标签页组件(数据为第一层数组),然后再Tabs选项卡组件中使用Form.List组件(数据为第二层数组),最终提交Form表单获取想要的数据结构。
import React from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import {
Tabs,
Form,
Row,
Col,
Divider,
Input,
Select,
Button,
Upload,
message
} from "antd";
import {
MinusCircleOutlined,
PlusOutlined,
UploadOutlined,
SoundTwoTone
} from "@ant-design/icons";
const { TabPane } = Tabs;
const formItemLayout = {
labelCol: { span: 4 },
wrapperCol: { span: 14 }
};
// 音频样式
const formItemYin = {
labelCol: { span: 4 },
wrapperCol: { span: 20 }
};
const initialPanes = [
{ title: "方案1", key: "1" },
{ title: "方案2", key: "2" },
{ title: "方案3", key: "3" }
];
const initialForm = {
data1: [
{
audioUrl: "",
text:
"因为怕水痘乘着风就跑到别人身上去了呀#哈哈大笑#这样我就不痒了,别人痒。",
emotion: "Default"
}
],
data2: [
{ audioUrl: "", text: "哈哈大笑#这样我就不痒了,别人痒。", emotion: "sad" }
],
data3: [{ audioUrl: "", text: "因为怕水痘乘着风就跑到", emotion: "angry" }]
};
class Demo extends React.Component {
newTabIndex = 0;
state = {
activeKey: initialPanes[0].key,
panes: initialPanes,
formValues: initialForm
};
formRef = React.createRef();
// tab 改变触发
onChange = (activeKey) => {
this.setState({ activeKey });
};
// tab 修改触发
onEdit = (targetKey, action) => {
this[action](targetKey);
};
// tab 新增触发
add = () => {
const { panes } = this.state;
const activeKey = panes.length + 1;
const newPanes = [...panes];
newPanes.push({
title: "方案" + activeKey,
key: activeKey.toString()
});
this.setState({
panes: newPanes,
activeKey: activeKey.toString()
});
};
// tab 移除触发
remove = (targetKey) => {
const { panes, activeKey } = this.state;
let newActiveKey = activeKey;
let lastIndex = 0;
panes.forEach((pane, i) => {
if (pane.key === targetKey) {
lastIndex = i - 1;
}
});
const newPanes = panes.filter((pane) => pane.key !== targetKey);
if (newPanes.length && newActiveKey === targetKey) {
if (lastIndex >= 0) {
newActiveKey = newPanes[lastIndex].key;
} else {
newActiveKey = newPanes[0].key;
}
}
this.setState({
panes: newPanes,
activeKey: newActiveKey
});
};
// 提交form 表单
onFinish = (values) => {
console.log(values);
};
// 上传组件触发
handleChange(info, index) {
if (info.file.status === "uploading") {
console.log("正在上传");
}
if (info.file.status !== "uploading") {
console.log(info.file, info.fileList);
}
if (info.file.status === "done") {
if (info.file.response.result === true) {
console.log(info.file.response.message);
this.formRef.current.setFields([
{ name: index, value: info.file.response.message }
]);
} else {
message.error(`上传失败:${info.file.response.message}.`);
}
message.success(`${info.file.name} 上传成功`);
} else if (info.file.status === "error") {
message.error(`${info.file.name}上传失败.`);
}
}
// 多媒体播放/暂停
handleAudio = (index) => {
var audio = document.getElementById("audio");
if (audio && audio.src) {
if (audio.src === this.formRef.current.getFieldValue(index)) {
// 当前的资源
if (audio.paused) {
audio.play(); // 这个就是播放
} else {
audio.pause(); // 这个就是暂停
}
} else {
// 存在src 但不是当前点击的资源,则播放当前资源
audio.src = this.formRef.current.getFieldValue(index);
audio.play();
}
} else {
// 没有音频路径 则是播放
audio && (audio.src = this.formRef.current.getFieldValue(index));
audio && audio.play();
}
};
// 手动录入音频地址 拆分出音频名称
handleSelf = (e) => {
if (e.target.value) {
const a = e.target.value.split("/");
if (a && a.length > 0) {
console.log("name", a[a.length - 1]); // 上传音频后更新节点标题名称
} else {
message.warning("请输入正确的音频地址");
}
}
};
render() {
const { panes, activeKey, formValues } = this.state;
return (
<>
>
);
}
}
ReactDOM.render( , document.getElementById("container"));
1、Form.List中的音频上传成功后,回显到对应的输入框中
this.handleChange(info,[`data${pane.key}`,index, 'audioUrl'])}
>
// 上传组件触发
handleChange (info:any, index:any){
if (info.file.status === 'uploading') {
console.log("正在上传")
}
if (info.file.status !== 'uploading') {
console.log(info.file, info.fileList);
}
if (info.file.status === 'done') {
if(info.file.response.result === true){
console.log(info.file.response.message);
this.formRef.current.setFields([{name:index,value:info.file.response.message}])
}else{
message.error(`上传失败:${info.file.response.message}.`);
}
message.success(`${info.file.name} 上传成功`);
} else if (info.file.status === 'error') {
message.error(`${info.file.name}上传失败.`);
}
}
this.formRef.current.setFields([{name:index,value:info.file.response.message}]) 实现上传后的回显