tiefen_space_h5/app/space/editSpacePost/page.jsx

467 lines
15 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.

"use client";
import React, { useState, useEffect, useMemo, useCallback } from "react";
import { DotLoading, Popup, Toast, TextArea, Switch } from "antd-mobile";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faAngleLeft } from "@fortawesome/free-solid-svg-icons";
import requireAPI from "@/utils/requireAPI";
import { useRouter, useSearchParams } from "next/navigation";
import { multiUploadImage } from "@/utils/upload";
import UploadImgs from "@/components/UploadImgs";
import OwnInput from "@/components/OwnInput";
export default function EditSpacePost() {
const searchParams = useSearchParams();
const [data, setData] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
const [priceEdit, setPriceEdit] = useState(false);
//价格
const [formData, setFormData] = useState({
price: "",
content: "",
paidText: "",
imageAssets: [],
imageVisibleRange: 0,
isCreatingPaidText: false,
isFreeForIronfan: false,
});
const [priceEditData, setPriceEditData] = useState({
price: "",
imageVisibleRange: 1,
isCreatingPaidText: false,
isFreeForIronfan: false,
blurCover: true,
});
const router = useRouter();
useEffect(() => {
const dataStr = searchParams.get("data");
const data = JSON.parse(decodeURIComponent(dataStr));
setData(data);
const publicData = {
price: data?.price ? data?.price / 100 : 0,
imageVisibleRange: data?.media_visible_range,
isCreatingPaidText: data?.is_creating_paid_text,
isFreeForIronfan: data?.is_ironfan_visible,
blurCover: data?.is_blurring_cover == 1,
};
// const imgs = getExistImgs(data);
setFormData({
content: data?.paid_text
? data?.text.slice(0, data?.text.length - data?.paid_text.length)
: data?.text,
paidText: data?.paid_text,
imageAssets: [],
...publicData,
});
setPriceEditData(publicData);
}, []);
//发布内容
const handleSubmit = async () => {
if (formData.content == "") {
Toast.show({
icon: "fail",
content: "动态内容不能为空",
position: "top",
});
return;
}
if (data?.m_type && formData.imageAssets.length === 0) {
Toast.show({
icon: "fail",
content: "请上传至少一张图片",
position: "top",
});
return;
}
if (data?.m_type == 1) {
if (
parseFloat(formData.price) &&
formData.imageAssets.length <= parseInt(formData.imageVisibleRange, 10)
) {
Toast.show({
icon: "fail",
content: "预览图片数不得大于等于上传图片数",
position: "top",
});
return;
}
}
if (
formData.isCreatingPaidText &&
formData.price > 0 &&
formData.paidText == ""
) {
Toast.show({
icon: "fail",
content: "请填写付费文案",
position: "top",
});
return;
}
//提交数据
if (isSubmitting) return;
setIsSubmitting(true);
const {
price,
isFreeForIronfan,
content,
imageAssets,
textVisibleRange,
imageVisibleRange,
isCreatingPaidText,
paidText,
blurCover,
} = formData;
const mType = data?.m_type;
const newMedia = imageAssets.filter((it) => it.id == undefined);
const media = await multiUploadImage(newMedia, mType);
if (mType == 1) {
media.image_ids = [
...imageAssets.filter((it) => it.id != undefined).map((it) => it.id),
...media.image_ids,
];
} else {
media.video_ids = [
...imageAssets.filter((it) => it.id != undefined).map((it) => it.id),
...media.video_ids,
];
}
try {
const body = {
id: data.id,
c_type: parseInt(price) ? 1 : 0,
is_ironfan_visible: isFreeForIronfan ? 1 : 0,
m_type: mType,
text: content,
media_component: media,
text_visible_range: textVisibleRange
? parseInt(textVisibleRange, 10)
: 999,
media_visible_range: imageVisibleRange
? parseInt(imageVisibleRange, 10)
: 1,
is_blurring_cover: blurCover ? 1 : 0,
price: parseFloat(price) ? parseInt(parseFloat(price) * 100, 10) : null,
is_creating_paid_text: isCreatingPaidText && price > 0 ? 1 : 0,
paid_text: isCreatingPaidText && price > 0 ? paidText : null,
};
const _data = await requireAPI("POST", "/api/zone_moment/update", {
body,
});
if (_data.ret === -1) {
Toast.show({
icon: "fail",
content: _data.msg,
position: "top",
});
return;
}
//提交成功后显示Toast并返回上一页
Toast.show({
icon: "success",
content: "提交成功,等耐心等待审核",
position: "top",
});
router.back();
} catch (error) {
console.error(error);
} finally {
setIsSubmitting(false);
}
};
const getExistImgs = useMemo(() => {
if (data) {
const list =
data?.m_type === 1
? data.media_component.images
: data.media_component.videos;
const imgs = list.map((it, index) =>
data?.m_type === 1
? {
url: it.urls[0],
id: data.media_component.image_ids[index],
}
: {
url: it.cover_urls[0],
id: data.media_component.video_ids[index],
}
);
return imgs;
}
return [];
}, [data]);
useEffect(() => {
setFormData((old) => ({ ...old, imageAssets: getExistImgs }));
}, [getExistImgs]);
return (
<div className="flex-1">
{/* 头部标题 */}
<div className="p-4 fixed top-0 z-10 w-full flex justify-between items-center bg-black">
<div className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full">
<FontAwesomeIcon
icon={faAngleLeft}
style={{ maxWidth: "12px" }}
size="xl"
onClick={() => {
router.back();
}}
/>
</div>
<p className="text-base text-center leading-9">重新编辑</p>
{isSubmitting ? (
<DotLoading />
) : (
<span className="text-primary text-lg" onClick={handleSubmit}>
发布
</span>
)}
</div>
{/* 内容 */}
<div className="pt-16 p-4">
{data?.status === 3 &&
(data.text_audit_opinion ||
data.image_audit_opinion ||
data.manually_review_opinion) && (
<div className="mb-4">
<span className="text-base font-medium text-[#F53030] mb-2">
违规详情
</span>
<div className="mt-2 p-4 rounded-2xl bg-[#FFFFFF1A]">
{data.text_audit_opinion && (
<p className="text-sm font-medium text-white">
<span className="text-[#F53030]">文案违规原因</span>
{data.text_audit_opinion}
</p>
)}
{data.image_audit_opinion && (
<p className="text-sm font-medium text-white">
<span className="text-[#F53030]">图片/视频违规原因</span>
{data.image_audit_opinion}
</p>
)}
{data.manually_review_opinion && (
<p className="text-sm font-medium text-white">
<span className="text-[#F53030]">运营追加</span>
{data.manually_review_opinion}
</p>
)}
</div>
</div>
)}
<div className="mt-2">
<p className="text-base font-medium text-white">动态内容</p>
<div className="h-32">
<TextArea
placeholder="请遵守平台准则,严禁发布违规内容"
value={formData.content}
onChange={(value) =>
setFormData((old) => ({ ...old, content: value }))
}
autoSize={{ minRows: 6, maxRows: 15 }}
style={{ "--font-size": "14px" }}
className="h-full bg-[#FFFFFF1A] rounded-2xl mt-2 mb-4 p-2"
/>
</div>
{!!formData.isCreatingPaidText && formData.price > 0 && (
<div className="mt-2">
<span className="text-base font-medium text-white">付费文案</span>
<div className="h-32">
<TextArea
placeholder="仅在用户解锁后展示,请勿发布违规内容"
onChange={(value) =>
setFormData((old) => ({
...old,
paidText: value,
}))
}
autoSize={{ minRows: 6, maxRows: 15 }}
value={formData.paidText && formData.paidText.slice(2)}
style={{ "--font-size": "14px" }}
className="bg-[#FFFFFF1A] rounded-2xl mt-2 mb-4 p-2 h-full"
/>
</div>
</div>
)}
</div>
{data?.m_type && (
<div className="mt-2">
<UploadImgs
type={data?.m_type}
existImages={getExistImgs}
accept={
data?.m_type === 1
? "image/png, image/jpeg, image/jpg"
: "video/*"
}
assets={formData.imageAssets}
videoSrc={data.media_component?.videos[0]?.urls[0]}
getImgs={(imgs) =>
setFormData((old) => ({ ...old, imageAssets: imgs }))
}
/>
</div>
)}
{data?.c_type === 1 && (
<div
color="#FF669E"
radius="999"
size="md"
className="mt-4 w-28 bg-primary rounded-full text-center text-base py-2"
onClick={() => setPriceEdit(true)}
>
付费设置
</div>
)}
</div>
<Popup
visible={priceEdit}
onMaskClick={() => {
setPriceEdit(false);
}}
className="p-4"
bodyStyle={{
borderRadius: "16px",
width: "calc(100% - 48px)",
margin: "24px",
padding: "14px",
}}
>
<div
style={{
gap: 8,
}}
className="flex flex-col py-2"
>
<div className="flex flex-row items-center">
<span className="text-base font-medium whitespace-nowrap">
价格¥
</span>
<div className="px-2 mx-1 rounded-full bg-[#ffffff1a]">
<OwnInput
placeholder="¥13000"
placeholderTextColor="#FFFFFF80"
keyboardType="numeric"
underlineColorAndroid="transparent"
onChange={(value) =>
setPriceEditData((old) => ({ ...old, price: value }))
}
value={priceEditData.price}
// className="flex-1 bg-[#FFFFFF1A] rounded-2xl px-4 h-8 mx-2"
/>
</div>
<span
onClick={() =>
setPriceEditData((old) => ({ ...old, price: "0" }))
}
className="text-[#FF669E] text-base font-medium whitespace-nowrap"
>
免费
</span>
</div>
{Math.floor(priceEditData.price) > 0 && (
<>
{data?.m_type === 1 && (
<div className="flex justify-between items-center my-1">
<div className="flex items-center">
<span className="text-base font-medium mr-2 whitespace-nowrap">
可预览图片
</span>
<span className="text-base font-medium"></span>
<div className="px-2 mx-1 rounded-full max-w-[60px] bg-[#ffffff1a]">
<OwnInput
placeholder="0~3"
placeholderTextColor="#FFFFFF80"
onChange={(value) =>
setPriceEditData((old) => ({
...old,
imageVisibleRange: value,
}))
}
value={priceEditData.imageVisibleRange}
// className="bg-[#FFFFFF1A] rounded-2xl px-4 mx-2 h-8"
/>
</div>
<span className="text-base font-medium"></span>
</div>
<span
onClick={() =>
setPriceEditData((old) => ({
...old,
imageVisibleRange: "0",
}))
}
className="text-[#FF669E] text-base font-medium ml-auto whitespace-nowrap"
>
不可预览
</span>
</div>
)}
<div className="flex items-center my-1">
<span className="text-base font-medium mr-2">
添加付费文案
</span>
<Switch
checked={priceEditData.isCreatingPaidText}
onChange={(value) => {
setPriceEditData((old) => ({
...old,
isCreatingPaidText: value,
}));
}}
style={{
"--checked-color": "#FF669E",
}}
/>
</div>
{data?.m_type === 2 && (
<div className="flex items-center my-1">
<span className="text-base font-medium mr-2">封面模糊</span>
<Switch
checked={priceEditData.blurCover}
onChange={(value) => {
setPriceEditData((old) => ({
...old,
blurCover: value,
}));
}}
style={{
"--checked-color": "#FF669E",
}}
/>
</div>
)}
<div className="flex items-center my-1">
<span className="text-base font-medium mr-2">
铁粉免费查看
</span>
<Switch
checked={priceEditData.isFreeForIronfan}
onChange={(value) =>
setPriceEditData((old) => ({
...old,
isFreeForIronfan: value,
}))
}
style={{
"--checked-color": "#FF669E",
}}
/>
</div>
</>
)}
</div>
<p
className="pt-4 text-center border-t border-[#ffffff40]"
onClick={() => {
setPriceEdit(false);
setFormData((old) => ({ ...old, ...priceEditData }));
}}
>
保存
</p>
</Popup>
</div>
);
}