tiefen_space_app/screeens/EditSpacePost/index.jsx

758 lines
26 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 {
View,
Text,
TextInput,
ScrollView,
ActivityIndicator,
Modal,
KeyboardAvoidingView,
TouchableOpacity,
Platform,
} from "react-native";
import React, { useState, useEffect } from "react";
import { useTailwind } from "tailwind-rn";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import MediaPicker from "../../components/MediaPicker";
import Toast from "react-native-toast-message";
import { multiUpload } from "../../utils/upload";
import baseRequest from "../../utils/baseRequest";
import { generateSignature } from "../../utils/crypto";
import { Button, Switch } from "@rneui/themed";
import MediaGrid from "../../components/MediaGrid";
import requireAPI from "../../utils/requireAPI";
export default function EditSpacePost({ navigation, route }) {
// const initalData = route.params.data;
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
const [content, setContent] = useState(null);
const [isSubmitting, setIsSubmitting] = useState(false);
//付费设置弹窗是否展示
const [isModalVisible, setIsModalVisible] = useState(false);
//价格
const [price, setPrice] = useState(0);
//可预览文案行数
const [textVisibleRange, setTextVisibleRange] = useState(null);
//可预览图片张数
const [imageVisibleRange, setImageVisibleRange] = useState();
//是否模糊封面
const [blurCover, setBlurCover] = useState(true);
//是否铁粉免费查看
const [isFreeForIronfan, setIsFreeForIronfan] = useState();
//是否添加付费文案
const [isCreatingPaidText, setIsCreatingPaidText] = useState(false);
//付费文案内容
const [paidText, setPaidText] = useState();
//保存新添加的媒体
const [newMeidaAssets, setNewMediaAssets] = useState([]);
//展示旧媒体组件
const [oldMediaAssets, setOldMediaAssets] = useState([]);
const [initalData, setInitalData] = useState({});
useEffect(() => {
getData();
}, []);
const getData = async () => {
const ids = [parseInt(route.params.id, 10)];
try {
const body = {
ids,
};
const _data = await requireAPI(
"POST",
"/api/zone_moment/list_by_ids_from_creater",
{
body,
},
true
);
if (_data.ret === -1) {
Toast.show({
type: "error",
text1: _data.msg,
topOffset: 60,
});
return;
}
const {
text,
paid_text,
price,
media_visible_range,
text_visible_range,
is_creating_paid_text,
is_ironfan_visible,
is_blurring_cover,
m_type,
media_component,
} = _data.data.list[0];
setContent(
is_creating_paid_text
? text.slice(0, text.length - paid_text.length)
: text
);
setPrice((price ? price / 100 : 0).toString());
setTextVisibleRange(text_visible_range?.toString());
setImageVisibleRange(media_visible_range?.toString());
setBlurCover(is_blurring_cover === 1);
setIsFreeForIronfan(is_ironfan_visible === 1);
setPaidText(paid_text ? paid_text.substring(1) : "");
setIsCreatingPaidText(is_creating_paid_text === 1);
setOldMediaAssets(
m_type === 1 ? media_component.images : media_component.videos
);
setInitalData(_data.data.list[0]);
} catch (error) {
console.error(error);
} finally {
setIsSubmitting(false);
}
};
//保存付费设置
const handleSavePaymentSetting = () => {
if (parseFloat(price) === 0) {
Toast.show({
type: "error",
text1: "不可改为免费动态",
topOffset: 60,
});
return;
}
if (parseFloat(price) < 0) {
Toast.show({
type: "error",
text1: "请输入正确区间的价格",
topOffset: 60,
});
return;
}
if (parseFloat(price) > 0 && parseInt(parseFloat(price) * 100, 10) < 100) {
Toast.show({
type: "error",
text1: "请输入正确区间的价格",
topOffset: 60,
});
return;
}
if (parseInt(parseFloat(price) * 100, 10) > 300000) {
Toast.show({
type: "error",
text1: "请输入正确区间的价格",
topOffset: 60,
});
return;
}
if (parseInt(textVisibleRange, 10) < 1) {
Toast.show({
type: "error",
text1: "请输入正确区间的可预览文案行数",
topOffset: 60,
});
return;
}
if (
parseInt(imageVisibleRange, 10) < 0 ||
parseInt(imageVisibleRange, 10) > 3
) {
Toast.show({
type: "error",
text1: "请输入正确区间的可预览图片张数",
topOffset: 60,
});
return;
}
setIsModalVisible(false);
};
//发布更新内容
const handleSubmit = async () => {
if (!content) {
Toast.show({
type: "error",
text1: "动态内容不能为空",
topOffset: 60,
});
return;
}
if (oldMediaAssets.length === 0 && newMeidaAssets.length === 0) {
Toast.show({
type: "error",
text1: "请选择要上传的图片或视频",
topOffset: 60,
});
return;
}
if (
initalData.m_type === 1 &&
oldMediaAssets.length + newMeidaAssets.length > 30
) {
Toast.show({
type: "error",
text1: "最多只能上传30张照片哦",
topOffset: 60,
});
return;
}
if (
initalData.m_type === 2 &&
oldMediaAssets.length + newMeidaAssets.length > 1
) {
Toast.show({
type: "error",
text1: "最多只能上传1个视频哦",
topOffset: 60,
});
return;
}
if (
initalData.c_type === 1 &&
initalData.m_type === 1 &&
oldMediaAssets.length + newMeidaAssets.length <= imageVisibleRange
) {
Toast.show({
type: "error",
text1: "预览图片数不得大于等于上传图片数",
topOffset: 60,
});
return;
}
if (isCreatingPaidText && price > 0 && !paidText) {
Toast.show({
type: "error",
text1: "请填写付费文案",
topOffset: 60,
});
return;
}
//提交数据
if (isSubmitting) return;
setIsSubmitting(true);
const newMediaIds = await multiUpload(newMeidaAssets);
const oldMediaIds = oldMediaAssets.map((item) => item.id);
const media = {
image_ids:
initalData.m_type === 1
? [...oldMediaIds, ...newMediaIds?.image_ids]
: [],
video_ids:
initalData.m_type === 2
? [...oldMediaIds, ...newMediaIds?.video_ids]
: [],
};
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
try {
const base = await baseRequest();
const body = {
...base,
id: initalData.id,
c_type: initalData.c_type,
m_type: initalData.m_type,
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,
is_ironfan_visible: isFreeForIronfan ? 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 signature = await generateSignature(body);
const _response = await fetch(
`${apiUrl}/api/zone_moment/update?signature=${signature}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(body),
}
);
const _data = await _response.json();
if (_data.ret === -1) {
Toast.show({
type: "error",
text1: _data.msg,
topOffset: 60,
});
return;
}
//提交成功后显示Toast并返回上一页
Toast.show({
type: "info",
text1: "提交成功,等耐心等待审核",
topOffset: 60,
});
navigation.goBack();
} catch (error) {
console.error(error);
} finally {
setIsSubmitting(false);
}
};
//发布按钮
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<Text
onPress={handleSubmit}
style={tailwind("text-[#FF669E] text-base font-medium")}
>
{isSubmitting ? "" : "发布"}
{isSubmitting && <ActivityIndicator size="small" color="white" />}
</Text>
),
});
}, [isSubmitting, handleSubmit]);
//是否正在拖动图片用于禁用ScrollView的滚动
const [dragging, setDragging] = useState(false);
return (
<KeyboardAvoidingView
behavior={Platform.OS == "ios" ? "padding" : "height"}
keyboardVerticalOffset={insets.bottom + 60}
style={{
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind("flex-1"),
}}
>
<ScrollView scrollEnabled={!dragging}>
<View style={tailwind("p-4")}>
{initalData?.status === 3 && (
<View style={tailwind("mb-4")}>
<Text
style={tailwind("text-base font-medium text-[#F53030] mb-2")}
>
违规详情
</Text>
<View style={tailwind("p-4 rounded-2xl bg-[#FFFFFF1A]")}>
{initalData.text_audit_opinion && (
<Text style={tailwind("text-sm font-medium text-white")}>
<Text style={tailwind("text-[#F53030]")}>
文案违规原因
</Text>
{initalData.text_audit_opinion}
</Text>
)}
{initalData.image_audit_opinion && (
<Text style={tailwind("text-sm font-medium text-white")}>
<Text style={tailwind("text-[#F53030]")}>
图片/视频违规原因
</Text>
{initalData.image_audit_opinion}
</Text>
)}
{initalData.manually_review_opinion && (
<Text style={tailwind("text-sm font-medium text-white")}>
<Text style={tailwind("text-[#F53030]")}>运营追加</Text>
{initalData.manually_review_opinion}
</Text>
)}
</View>
</View>
)}
<Text style={tailwind("text-base font-medium text-white")}>
动态内容
</Text>
<TextInput
placeholder="请遵守平台准则,严禁发布违规内容"
placeholderTextColor="#FFFFFF80"
underlineColorAndroid="transparent"
multiline
textAlignVertical="top"
onChangeText={(value) => setContent(value)}
value={content}
style={tailwind(
"h-32 bg-[#FFFFFF1A] text-white rounded-2xl mt-2 mb-4 p-2"
)}
/>
{isCreatingPaidText && price > 0 && (
<>
<Text style={tailwind("text-base font-medium text-white")}>
付费文案
</Text>
<TextInput
placeholder="仅在用户解锁后展示,请勿发布违规内容"
placeholderTextColor="#FFFFFF80"
underlineColorAndroid="transparent"
multiline
textAlignVertical="top"
onChangeText={(value) => setPaidText(value)}
value={paidText}
style={tailwind(
"h-32 bg-[#FFFFFF1A] text-white rounded-2xl mt-2 mb-4 p-2"
)}
/>
</>
)}
{oldMediaAssets.length > 0 && (
<MediaGrid
setDragging={setDragging}
assets={oldMediaAssets}
setAssets={setOldMediaAssets}
/>
)}
<MediaPicker
setDragging={setDragging}
maxCount={
initalData.m_type === 1
? 30 - oldMediaAssets.length
: 1 - oldMediaAssets.length
}
type={initalData.m_type === 1 ? "image" : "video"}
setAssets={setNewMediaAssets}
/>
{initalData.c_type === 1 && (
<Button
color="#FF669E"
radius="999"
size="md"
onPress={() => setIsModalVisible(!isModalVisible)}
titleStyle={tailwind("text-base")}
containerStyle={tailwind("mt-4 w-28")}
>
付费设置
</Button>
)}
{initalData.m_type === 1 && (
<Modal
visible={isModalVisible}
transparent={true}
statusBarTranslucent
animationType="slide"
>
<TouchableOpacity
activeOpacity={1}
style={{
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind("flex flex-1 bg-[#00000080] px-4"),
}}
onPress={handleSavePaymentSetting}
>
<KeyboardAvoidingView
style={tailwind("flex-1")}
behavior="padding"
>
<TouchableOpacity
activeOpacity={1}
style={{
gap: 8,
...tailwind(
"flex flex-col mt-auto mb-2 bg-[#17161A] rounded-3xl"
),
}}
>
<View
style={{
gap: 8,
...tailwind("flex flex-col px-6 pt-6 pb-2"),
}}
>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind("text-white text-base font-medium")}
>
价格¥
</Text>
<TextInput
placeholder="¥13000"
placeholderTextColor="#FFFFFF80"
keyboardType="numeric"
underlineColorAndroid="transparent"
onChangeText={(value) => setPrice(value)}
value={price}
style={tailwind(
"flex-1 bg-[#FFFFFF1A] text-white rounded-2xl px-4 h-8 mx-2"
)}
/>
<Text
onPress={() => setPrice("0")}
style={tailwind(
"text-[#FF669E] text-base font-medium"
)}
>
免费
</Text>
</View>
{parseFloat(price) > 0 && (
<>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind(
"text-white text-base font-medium mr-2"
)}
>
可预览图片
</Text>
<Text
style={tailwind(
"text-white text-base font-medium"
)}
>
</Text>
<TextInput
placeholder="0~3"
placeholderTextColor="#FFFFFF80"
keyboardType="numeric"
underlineColorAndroid="transparent"
onChangeText={(value) =>
setImageVisibleRange(value)
}
value={imageVisibleRange}
style={tailwind(
"bg-[#FFFFFF1A] text-white rounded-2xl px-4 mx-2 h-8"
)}
/>
<Text
style={tailwind(
"text-white text-base font-medium"
)}
>
</Text>
<Text
onPress={() => setImageVisibleRange("0")}
style={tailwind(
"text-[#FF669E] text-base font-medium ml-auto"
)}
>
不可预览
</Text>
</View>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind(
"text-white text-base font-medium mr-2"
)}
>
添加付费文案
</Text>
<Switch
value={isCreatingPaidText}
onValueChange={(value) =>
setIsCreatingPaidText(value)
}
thumbColor="#ffffff"
trackColor={{
true: "#FF669E",
false: "#FFFFFF1A",
}}
/>
</View>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind(
"text-white text-base font-medium mr-2"
)}
>
铁粉免费查看
</Text>
<Switch
value={isFreeForIronfan}
onValueChange={(value) =>
setIsFreeForIronfan(value)
}
thumbColor="#ffffff"
trackColor={{
true: "#FF669E",
false: "#FFFFFF1A",
}}
/>
</View>
</>
)}
</View>
<TouchableOpacity
onPress={handleSavePaymentSetting}
style={{
height: 52,
...tailwind(
"flex justify-center items-center border-t border-[#FFFFFF14]"
),
}}
>
<Text
style={tailwind("text-white text-base font-medium")}
>
保存
</Text>
</TouchableOpacity>
</TouchableOpacity>
</KeyboardAvoidingView>
</TouchableOpacity>
<Toast />
</Modal>
)}
{initalData.m_type === 2 && (
<Modal
visible={isModalVisible}
transparent={true}
statusBarTranslucent
animationType="slide"
>
<TouchableOpacity
activeOpacity={1}
style={{
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind("flex flex-1 bg-[#00000080] px-4"),
}}
onPress={handleSavePaymentSetting}
>
<KeyboardAvoidingView
style={tailwind("flex-1")}
behavior="padding"
>
<TouchableOpacity
activeOpacity={1}
style={{
gap: 8,
...tailwind(
"flex flex-col mt-auto mb-2 bg-[#17161A] rounded-3xl"
),
}}
>
<View
style={{
gap: 8,
...tailwind("flex flex-col px-6 pt-6 pb-2"),
}}
>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind("text-white text-base font-medium")}
>
价格¥
</Text>
<TextInput
placeholder="¥13000"
placeholderTextColor="#FFFFFF80"
keyboardType="numeric"
underlineColorAndroid="transparent"
onChangeText={(value) => setPrice(value)}
value={price}
style={tailwind(
"flex-1 bg-[#FFFFFF1A] text-white rounded-2xl px-4 h-8 mx-2"
)}
/>
<Text
onPress={() => setPrice("0")}
style={tailwind(
"text-[#FF669E] text-base font-medium"
)}
>
免费
</Text>
</View>
{parseFloat(price) > 0 && (
<>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind(
"text-white text-base font-medium mr-2"
)}
>
添加付费文案
</Text>
<Switch
value={isCreatingPaidText}
onValueChange={(value) =>
setIsCreatingPaidText(value)
}
thumbColor="#ffffff"
trackColor={{
true: "#FF669E",
false: "#FFFFFF1A",
}}
/>
</View>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind(
"text-white text-base font-medium mr-2"
)}
>
封面模糊
</Text>
<Switch
value={blurCover}
onValueChange={(value) => setBlurCover(value)}
thumbColor="#ffffff"
trackColor={{
true: "#FF669E",
false: "#FFFFFF1A",
}}
/>
</View>
<View style={tailwind("flex flex-row items-center")}>
<Text
style={tailwind(
"text-white text-base font-medium mr-2"
)}
>
铁粉免费查看
</Text>
<Switch
value={isFreeForIronfan}
onValueChange={(value) =>
setIsFreeForIronfan(value)
}
thumbColor="#ffffff"
trackColor={{
true: "#FF669E",
false: "#FFFFFF1A",
}}
/>
</View>
</>
)}
</View>
<TouchableOpacity
onPress={handleSavePaymentSetting}
style={{
height: 52,
...tailwind(
"flex justify-center items-center border-t border-[#FFFFFF14]"
),
}}
>
<Text
style={tailwind("text-white text-base font-medium")}
>
保存
</Text>
</TouchableOpacity>
</TouchableOpacity>
</KeyboardAvoidingView>
</TouchableOpacity>
</Modal>
)}
</View>
</ScrollView>
</KeyboardAvoidingView>
);
}