tiefen_space_app/screeens/CreateImagePost/index.jsx

485 lines
16 KiB
JavaScript
Raw Permalink 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,
Modal,
TouchableOpacity,
KeyboardAvoidingView,
ActivityIndicator,
} 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 { Button, Switch } from "@rneui/themed";
import Toast from "react-native-toast-message";
import { multiUpload } from "../../utils/upload";
import baseRequest from "../../utils/baseRequest";
import { generateSignature } from "../../utils/crypto";
import MyModal from "../../components/MyModal";
export default function CreateImagePost({ navigation, route }) {
const tailwind = useTailwind();
const insets = useSafeAreaInsets();
//文案
const [content, setContent] = useState();
//图片
const [imageAssets, setImageAssets] = useState([]);
//付费设置弹窗是否展示
const [isModalVisible, setIsModalVisible] = useState(false);
//价格
const [price, setPrice] = useState();
//可预览文案行数
const [textVisibleRange, setTextVisibleRange] = useState("999");
//可预览图片张数
const [imageVisibleRange, setImageVisibleRange] = useState("1");
//是否铁粉免费查看
const [isFreeForIronfan, setIsFreeForIronfan] = useState(false);
//正在提交
const [isSubmitting, setIsSubmitting] = useState(false);
//保存付费设置
const handleSavePaymentSetting = () => {
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 (imageAssets.length === 0) {
Toast.show({
type: "error",
text1: "请上传至少一张图片",
topOffset: 60,
});
return;
}
if (
parseFloat(price) &&
imageAssets.length <= parseInt(imageVisibleRange, 10)
) {
Toast.show({
type: "error",
text1: "预览图片数不得大于等于上传图片数",
topOffset: 60,
});
return;
}
//提交数据
if (isSubmitting) return;
setIsSubmitting(true);
const media = await multiUpload(imageAssets);
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
try {
const base = await baseRequest();
const body = {
...base,
c_type: parseFloat(price) ? 1 : 0,
is_ironfan_visible: isFreeForIronfan ? 1 : 0,
m_type: 1,
text: content,
media_component: media,
text_visible_range: textVisibleRange
? parseInt(textVisibleRange, 10)
: 999,
media_visible_range: imageVisibleRange
? parseInt(imageVisibleRange, 10)
: 1,
price: parseFloat(price) ? parseInt(parseFloat(price) * 100, 10) : null,
};
const signature = await generateSignature(body);
const response = await fetch(
`${apiUrl}/api/zone_moment/create?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: "success",
text1: "发布成功",
topOffset: 60,
});
navigation.goBack();
} catch (error) {
console.error(error);
} finally {
setIsSubmitting(false);
}
};
//查询已发布空间内免费帖数量、付费帖数量、发布付费帖剩余额度、审核未通过帖数量
const [postCount, setPostCount] = useState();
const [isBlockModalVisible, setIsBlockModalVisible] = useState(false);
useEffect(() => {
const getPostCountData = async () => {
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
try {
const base = await baseRequest();
const body = {
...base,
};
const signature = await generateSignature(body);
const _response = await fetch(
`${apiUrl}/api/zone_moment/list_statistics_by_creater_mid?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;
}
setPostCount(_data.data);
if (_data.data.rejected_count >= 5) setIsBlockModalVisible(true);
} catch (error) {
console.error(error);
}
};
getPostCountData();
}, []);
//发布按钮
useEffect(() => {
navigation.setOptions({
headerRight: () => (
<Text
onPress={handleSubmit}
style={tailwind("text-[#FF669E] text-base font-medium")}
>
{isSubmitting ? "" : "发布"}
{isSubmitting && <ActivityIndicator size="small" color="white" />}
</Text>
),
});
}, [navigation, handleSubmit, isSubmitting]);
return (
<ScrollView
style={{
paddingBottom: insets.bottom,
paddingLeft: insets.left,
paddingRight: insets.right,
...tailwind("flex-1"),
}}
>
<MyModal
visible={isBlockModalVisible}
setVisible={setIsBlockModalVisible}
title="当前无法发帖"
content="您当前审核未通过动态过多,请修改后再试"
custom={() => {
setIsBlockModalVisible(false);
setTimeout(
() => navigation.replace("VisibleToOneselfSpacePosts"),
500
);
}}
customText="去修改"
/>
<View style={tailwind("p-4")}>
<View style={tailwind("mb-4")}>
<Text style={tailwind("text-sm font-medium text-[#27F5B7] mb-2")}>
为了空间良性发展请保持免费/付费比例为1/1
</Text>
<View
style={tailwind(
"flex flex-row flex-wrap justify-between p-4 rounded-2xl bg-[#FFFFFF1A]"
)}
>
<Text style={tailwind("text-xs font-medium text-white basis-1/2")}>
已发布免费动态{postCount?.free_count}
</Text>
<Text style={tailwind("text-xs font-medium text-white basis-1/2")}>
已发布付费动态{postCount?.paid_count}
</Text>
<Text style={tailwind("text-xs font-medium text-white basis-1/2")}>
<Text style={tailwind("text-[#27F5B7]")}>可发布付费动态</Text>
{postCount?.paid_limit}
</Text>
<Text style={tailwind("text-xs font-medium text-white basis-1/2")}>
<Text style={tailwind("text-[#F53030]")}>审核未通过动态</Text>
{postCount?.rejected_count}
</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"
)}
/>
<MediaPicker maxCount={30} type="image" setAssets={setImageAssets} />
<Button
color="#FF669E"
radius="999"
size="md"
onPress={() => setIsModalVisible(!isModalVisible)}
titleStyle={tailwind("text-base")}
containerStyle={tailwind("mt-4 w-28")}
>
付费设置
</Button>
<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="1~10"
placeholderTextColor="#FFFFFF80"
keyboardType="numeric"
underlineColorAndroid="transparent"
onChangeText={(value) => setTextVisibleRange(value)}
value={textVisibleRange}
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={() => setTextVisibleRange("999")}
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>
<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={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>
</View>
</ScrollView>
);
}