tiefen_space_op/src/pages/CreateAndEditPost/index.jsx

577 lines
16 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useState, useEffect } from "react";
import { Form, Input, Table, Image, Space, Button, Modal, message } from "antd";
import baseRequest from "../../utils/baseRequest";
import ImageUploader from "../../components/ImageUploader";
import VideoUploader from "../../components/VideoUploader";
import VideoPlayer from "../../components/VideoPlayer";
const CreateAndEditPostContent = (props) => {
const { TextArea } = Input;
//表头
const columns = [
{
title: "动态信息",
dataIndex: "info",
key: "info",
render: (data) => (
<div>
<p>
动态id<span className="text-red-400">{data.id}</span>
</p>
<p>
点赞<span className="text-red-400">{data.like}</span>
</p>
<p>
创建时间<span className="text-red-400">{data.ct}</span>
</p>
</div>
),
},
{
title: "动态文案",
dataIndex: "content",
key: "content",
},
{
title: "媒体",
dataIndex: "media",
key: "media",
render: (data) => (
<div>
<Image.PreviewGroup
items={data?.images?.map((item) => item.urls[0])}
>
{data?.images?.map((item, index) => (
<Image
key={index}
src={item.urls[0]}
width={150}
style={{ marginBottom: 10 }}
/>
))}
</Image.PreviewGroup>
{data?.videos?.map((item, index) => (
<VideoPlayer key={index} url={item.urls[0]} />
))}
</div>
),
},
{
title: "操作",
dataIndex: "opeartion",
key: "opeartion",
render: (_, record) => (
<div>
<Space>
<Space.Compact direction="vertical">
<Button type="primary" onClick={() => onClickEdit(record)}>
编辑
</Button>
<Button onClick={() => onClickDelete(record)}>删除</Button>
</Space.Compact>
</Space>
</div>
),
},
];
//控制编辑modal是否出现
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
//modal打开时的默认值
const [defaultValues, setDefaultValues] = useState({});
const [defaultMedia, setDefaultMedia] = useState({});
//点击modal取消按钮
const handleCancel = () => {
setDefaultValues({});
setDefaultMedia({});
setEditImageId([]);
setEditVideoId([]);
setIsEditModalOpen(false);
};
//点击编辑按钮
const onClickEdit = (record) => {
setDefaultValues(record);
setDefaultMedia(record.media);
setIsEditModalOpen(true);
};
//保存上传的媒体id
const [editImageId, setEditImageId] = useState([]);
const [editVideoId, setEditVideoId] = useState([]);
//删除默认的媒体
const handleDeleteMedia = (type, id) => {
if (type === "video") {
setDefaultMedia({
...defaultMedia,
video_ids: [],
});
return;
}
if (type === "image") {
setDefaultMedia({
...defaultMedia,
image_ids: defaultMedia.image_ids.filter((item) => item !== id),
images: defaultMedia.images.filter((item) => item.id !== id),
});
return;
}
};
//点击确认提交更改动态
const handleChange = async (value) => {
const imageIds = [...defaultMedia.image_ids, ...editImageId];
const videoIds = [...defaultMedia.video_ids, ...editVideoId];
if (imageIds.length === 0 && videoIds.length === 0) {
alert("图片或视频不可为空");
return;
}
if (imageIds.length !== 0 && videoIds.length !== 0) {
alert("不可同时上传图片和视频");
return;
}
if (imageIds.length > 9) {
alert("图片不可超过9张");
return;
}
if (videoIds.length > 1) {
alert("视频不可超过1个");
return;
}
try {
const base = baseRequest();
const response = await fetch("/op/moment/update", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
id: defaultValues.info.id,
text: value.content,
media_component: {
image_ids: imageIds,
video_ids: videoIds,
},
...base,
}),
});
const temData = await response.json();
if (temData.ret === -1) {
alert(temData.msg);
return;
}
setShowData(
showData.filter((item) => item.info.id !== defaultValues.info.id)
);
handleCancel();
} catch (error) {
console.error(error);
}
};
//点击删除按钮
const onClickDelete = async (record) => {
try {
const base = baseRequest();
const response = await fetch("/op/moment/delete", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
id: record.info.id,
...base,
}),
});
const temData = await response.json();
if (temData.ret === -1) {
alert(temData.msg);
return;
}
setShowData(showData.filter((item) => item.info.id !== record.info.id));
} catch (error) {
console.error(error);
}
};
//展示的数据
const [showData, setShowData] = useState([]);
//获取数据
const getData = async () => {
try {
const base = baseRequest();
const response = await fetch("/op/moment/list", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
ct_upper_bound: Math.floor(new Date().getTime() / 1000),
offset: 0,
limit: 2000,
...base,
}),
});
const temData = await response.json();
if (temData.ret === -1) {
alert(temData.msg);
return;
}
//匹配表格格式
const structedData = temData.data.list.map((item, index) => {
return {
key: index,
info: {
id: item.id,
like: item.thumbs_up_num,
ct: new Date(item.ct * 1000).toLocaleString(),
},
content: item.text,
media: item.media_component,
};
});
setShowData(structedData);
} catch (error) {
console.error(error);
}
};
useEffect(() => {
getData();
}, []);
//搜索
const search = async (value) => {
try {
const base = baseRequest();
const detailResponse = await fetch(`/op/streamer/list_ext_by_user_id`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user_id: parseInt(value.userId, 10),
...base,
}),
});
const detailData = await detailResponse.json();
if (detailData.ret === -1) {
alert(detailData.msg);
return;
}
const response = await fetch("/op/moment/list_by_mid", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mid: detailData.data.streamer_ext.mid,
...base,
}),
});
const temData = await response.json();
if (temData.ret === -1) {
alert(temData.msg);
return;
}
//匹配表格格式
const structedData = temData.data.list.map((item, index) => {
return {
key: index,
info: {
id: item.id,
like: item.thumbs_up_num,
ct: new Date(item.ct * 1000).toLocaleString(),
},
content: item.text,
media: item.media_component,
};
});
setShowData(structedData);
} catch (error) {
console.error(error);
}
};
//表单提交失败
const onFinishFailed = (errorInfo) => {
console.log("Failed:", errorInfo);
};
//控制创建动态modal是否出现
const [isModalOpen, setIsModalOpen] = useState(false);
//保存上传的媒体的id
const [imageId, setImageId] = useState([]);
const [videoId, setVideoId] = useState([]);
//在modal中搜索用户
const [userInfo, setUserInfo] = useState();
const modalSearch = async (value) => {
try {
const base = baseRequest();
const response = await fetch(`/op/account/list_by_user_id`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user_id: parseInt(value.userId, 10),
...base,
}),
});
const data = await response.json();
if (data.ret === -1) {
alert(data.msg);
return;
}
setSelectedUser();
setUserInfo(data.data.account);
} catch (error) {
console.error(error);
}
};
//选中用户
const [selectedUser, setSelectedUser] = useState();
const handleSelected = () => {
if (selectedUser) {
setSelectedUser();
return;
}
setSelectedUser(userInfo.mid);
};
//提交创建动态
const [form] = Form.useForm();
const handleSubmit = async (value) => {
if (!selectedUser) {
alert("还未选中用户");
return;
}
if (imageId.length === 0 && videoId.length === 0) {
alert("图片或视频不可为空");
return;
}
if (imageId.length !== 0 && videoId.length !== 0) {
alert("不可同时上传图片和视频");
return;
}
if (imageId.length > 9) {
alert("图片不可超过9张");
return;
}
if (videoId.length > 1) {
alert("视频不可超过1个");
return;
}
try {
const base = baseRequest();
const response = await fetch(`/op/moment/create`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mid: selectedUser,
status: 2,
text: value.content,
media_component: { image_ids: imageId, video_ids: videoId },
...base,
}),
});
const data = await response.json();
if (data.ret === -1) {
alert(data.msg);
return;
}
message.success("发布成功");
} catch (error) {
console.error(error);
}
form.resetFields();
setUserInfo();
setSelectedUser();
setIsModalOpen(false);
setImageId([]);
setVideoId([]);
};
//关闭弹窗
const handleCancelModal = () => {
form.resetFields();
setUserInfo();
setSelectedUser();
setIsModalOpen(false);
setImageId([]);
setVideoId([]);
};
return (
<div className="mt-4" style={{ marginLeft: 20, marginRight: 20 }}>
<Form name="search" onFinish={search} onFinishFailed={onFinishFailed}>
<Space style={{ marginBottom: 20 }}>
<Form.Item label="主播ID" name="userId" style={{ margin: 0 }}>
<Input type="number" />
</Form.Item>
<Button type="primary" htmlType="submit">
搜索
</Button>
</Space>
</Form>
<Button
className="mb-4"
type="primary"
onClick={() => setIsModalOpen(true)}
>
创建动态
</Button>
<Form name="remarks">
<Table
columns={columns}
dataSource={showData}
pagination={{ pageSize: 20 }}
scroll={{ y: window.innerHeight - 300 }}
/>
</Form>
{/* 重复判断isModalOpen是为了重新渲染ImageUploader和VideoUploader组件 */}
{isModalOpen && (
<Modal footer={null} open={isModalOpen} onCancel={handleCancelModal}>
<p className="text-sm text-red-400 font-bold">
*请选中主播后再发布并确保文案不为空图片数不超过9视频数不超过1图片视频不同时存在
</p>
<Form name="modal_search" onFinish={modalSearch}>
<Space style={{ marginBottom: 20 }}>
<Form.Item label="ID" name="userId" style={{ margin: 0 }}>
<Input type="number" />
</Form.Item>
<Button type="primary" htmlType="submit">
搜索
</Button>
</Space>
</Form>
{userInfo && (
<div
className={`flex flex-row items-center p-2 rounded-xl ${
selectedUser ? "bg-green-300" : "bg-gray-300"
}`}
>
<Image
src={userInfo?.avatar?.images[0].urls[0]}
width={80}
height={80}
/>
<div className="flex flex-col justify-center mx-4">
<p className="text-lg font-bold">ID{userInfo.user_id}</p>
<p className="text-lg font-bold">昵称{userInfo.name}</p>
</div>
<Button
type={selectedUser ? "default" : "primary"}
onClick={handleSelected}
>
{selectedUser ? "取消选中" : "选中用户"}
</Button>
</div>
)}
<Form
className="mt-4 flex flex-col"
form={form}
onFinish={handleSubmit}
>
<Space>
<Form.Item
label="文案"
name="content"
rules={[
{
required: true,
message: "请填写文案",
},
]}
style={{ margin: 0 }}
>
<TextArea />
</Form.Item>
</Space>
<ImageUploader setIds={setImageId} />
<VideoUploader setIds={setVideoId} />
<Button className="ml-8" type="primary" htmlType="submit">
确认
</Button>
</Form>
</Modal>
)}
{/* 编辑动态内容的弹窗重复判断isEditModalOpen是为了重新渲染ImageUploader和VideoUploader组件 */}
{isEditModalOpen && (
<Modal footer={null} open={isEditModalOpen} onCancel={handleCancel}>
<p className="text-sm text-red-400 font-bold">
*请确保文案不为空图片数不超过9视频数不超过1图片视频不同时存在
</p>
<Form className="mt-4 flex flex-col" onFinish={handleChange}>
<Space>
<Form.Item
label="文案"
name="content"
initialValue={defaultValues.content}
rules={[
{
required: true,
message: "请填写文案",
},
]}
style={{ margin: 0 }}
>
<TextArea />
</Form.Item>
</Space>
{defaultMedia.image_ids.length !== 0 && (
<div className="flex flex-row flex-wrap gap-2 mt-4">
{defaultMedia.images.map((item) => (
<div key={item.urls[0]} className="relative">
<Image src={item.urls[0]} width={100} />
<Button
className="absolute top-0 left-0 w-full"
danger
type="primary"
onClick={() => handleDeleteMedia("image", item.id)}
>
删除
</Button>
</div>
))}
</div>
)}
{defaultMedia.video_ids.length !== 0 && (
<div className="flex flex-row mt-4">
<div className="relative">
<div className="mr-auto">
<VideoPlayer url={defaultMedia.videos[0].urls[0]} />
</div>
<Button
className="absolute top-0 left-0 w-full"
danger
type="primary"
onClick={() => handleDeleteMedia("video")}
>
删除
</Button>
</div>
</div>
)}
<ImageUploader setIds={setEditImageId} />
<VideoUploader setIds={setEditVideoId} />
<Button className="ml-8" type="primary" htmlType="submit">
确认
</Button>
</Form>
</Modal>
)}
</div>
);
};
export default function CreateAndEditPost() {
return <CreateAndEditPostContent />;
}