530 lines
17 KiB
JavaScript
530 lines
17 KiB
JavaScript
import {
|
||
View,
|
||
Text,
|
||
ScrollView,
|
||
Modal,
|
||
TextInput,
|
||
KeyboardAvoidingView,
|
||
TouchableOpacity,
|
||
Image as NativeImage,
|
||
} from "react-native";
|
||
import React, { useState, useEffect, useCallback, useMemo } from "react";
|
||
import { useTailwind } from "tailwind-rn";
|
||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||
import Toast from "react-native-toast-message";
|
||
import { Image } from "expo-image";
|
||
import { Icon, Button } from "@rneui/themed";
|
||
import baseRequest from "../../../utils/baseRequest";
|
||
import { generateSignature } from "../../../utils/crypto";
|
||
import { get } from "../../../utils/storeInfo";
|
||
import { JSEncrypt } from "jsencrypt";
|
||
import Picker from "../../../components/Picker";
|
||
|
||
export default function AgencySetting({ navigation, route }) {
|
||
const blurhash = "LcKUTa%gOYWBYRt6xuoJo~s8V@fk";
|
||
|
||
const tailwind = useTailwind();
|
||
const insets = useSafeAreaInsets();
|
||
|
||
//获取环境变量
|
||
const apiUrl = process.env.EXPO_PUBLIC_API_URL;
|
||
|
||
//获取数据
|
||
const [data, setData] = useState();
|
||
useEffect(() => {
|
||
const getData = async () => {
|
||
try {
|
||
const base = await baseRequest();
|
||
const body = {
|
||
zid: route.params.data.id,
|
||
...base,
|
||
};
|
||
const signature = await generateSignature(body);
|
||
const _response = await fetch(
|
||
`${apiUrl}/api/zone_third_partner/list?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;
|
||
}
|
||
setData(_data.data.zone_third_partner);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
getData();
|
||
}, []);
|
||
|
||
//获取当前用户的手机号
|
||
const [regionCode, setRegionCode] = useState("");
|
||
const [mobilePhone, setMobilePhone] = useState("");
|
||
useEffect(() => {
|
||
async function getMobilePhone() {
|
||
setMobilePhone(await get("mobile_phone"));
|
||
setRegionCode(await get("region_code"));
|
||
}
|
||
getMobilePhone();
|
||
}, []);
|
||
|
||
//添加代运营Modal
|
||
const [idAddAgencyModalVisible, setIsAddAgencyModalVisible] = useState(false);
|
||
|
||
//搜索用户ID,以及是否选中用户
|
||
const [userId, setUserId] = useState();
|
||
const [agencyData, setAgencyData] = useState();
|
||
const [isSelected, setIsSelected] = useState(false);
|
||
const handleSearch = async () => {
|
||
if (!userId) {
|
||
Toast.show({
|
||
type: "error",
|
||
text1: "请先输入ID",
|
||
topOffset: 60,
|
||
});
|
||
return;
|
||
}
|
||
const base = await baseRequest();
|
||
const signature = await generateSignature({
|
||
...base,
|
||
user_id: parseInt(userId, 10),
|
||
});
|
||
try {
|
||
//获取账号基本信息
|
||
const _response = await fetch(
|
||
`${apiUrl}/api/account/list_others_by_user_id?signature=${signature}`,
|
||
{
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
...base,
|
||
user_id: parseInt(userId, 10),
|
||
}),
|
||
}
|
||
);
|
||
const _data = await _response.json();
|
||
if (_data.ret === -1) {
|
||
Toast.show({
|
||
type: "error",
|
||
text1: _data.msg,
|
||
topOffset: 60,
|
||
});
|
||
return;
|
||
}
|
||
setAgencyData(_data.data.account);
|
||
setIsSelected(false);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
//验证码
|
||
const [veriCode, setVeriCode] = useState();
|
||
//重新获取验证码的计时器
|
||
const [isCounting, setIsCounting] = useState(false);
|
||
const [seconds, setSeconds] = useState(60);
|
||
useEffect(() => {
|
||
let interval;
|
||
if (isCounting && seconds > 0) {
|
||
interval = setInterval(() => {
|
||
setSeconds(seconds - 1);
|
||
}, 1000);
|
||
} else {
|
||
setIsCounting(false);
|
||
setSeconds(60);
|
||
clearInterval(interval);
|
||
}
|
||
return () => {
|
||
clearInterval(interval);
|
||
};
|
||
}, [isCounting, seconds]);
|
||
|
||
//点击获取验证码
|
||
const handleVerification = async () => {
|
||
if (!isSelected) {
|
||
Toast.show({
|
||
type: "error",
|
||
text1: "请先选中用户",
|
||
topOffset: 60,
|
||
});
|
||
return;
|
||
}
|
||
//开始倒计时
|
||
setIsCounting(true);
|
||
//对手机号进行RSA加密
|
||
const encrypt = new JSEncrypt();
|
||
encrypt.setPublicKey(process.env.EXPO_PUBLIC_RSA_KEY);
|
||
const mobile_phone = encrypt.encrypt(mobilePhone);
|
||
//发送短信验证码
|
||
const base = await baseRequest();
|
||
const signature = await generateSignature({
|
||
mobile_phone: mobile_phone,
|
||
region_code: regionCode,
|
||
...base,
|
||
});
|
||
try {
|
||
await fetch(`${apiUrl}/api/veri_code/send?signature=${signature}`, {
|
||
method: "POST",
|
||
headers: {
|
||
"Content-Type": "application/json",
|
||
},
|
||
body: JSON.stringify({
|
||
mobile_phone: mobile_phone,
|
||
region_code: regionCode,
|
||
...base,
|
||
}),
|
||
});
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
//分成比例
|
||
const [rate, setRate] = useState();
|
||
|
||
//生成比例选项
|
||
const generateItems = useCallback((min, max) => {
|
||
const items = [];
|
||
for (let i = min; i <= max; i++) {
|
||
items.push({ label: `${i.toString()}%`, value: i.toString() });
|
||
}
|
||
return items;
|
||
}, []);
|
||
const rates = useMemo(() => generateItems(1, 50), []);
|
||
|
||
//提交
|
||
const handleSubmit = async () => {
|
||
if (!isSelected) {
|
||
Toast.show({
|
||
type: "error",
|
||
text1: "请先选中用户",
|
||
topOffset: 60,
|
||
});
|
||
return;
|
||
}
|
||
if (!veriCode) {
|
||
Toast.show({
|
||
type: "error",
|
||
text1: "请输入验证码",
|
||
topOffset: 60,
|
||
});
|
||
return;
|
||
}
|
||
if (!rate) {
|
||
Toast.show({
|
||
type: "error",
|
||
text1: "请选择分成比例",
|
||
topOffset: 60,
|
||
});
|
||
return;
|
||
}
|
||
try {
|
||
const base = await baseRequest();
|
||
//对手机号进行RSA加密
|
||
const encrypt = new JSEncrypt();
|
||
encrypt.setPublicKey(process.env.EXPO_PUBLIC_RSA_KEY);
|
||
const mobile_phone = encrypt.encrypt(mobilePhone);
|
||
const body = {
|
||
zid: route.params.data.id,
|
||
third_partner_mid: agencyData.mid,
|
||
region_code: regionCode,
|
||
mobile_phone: mobile_phone,
|
||
veri_code: veriCode,
|
||
sharing_ratio: parseInt(rate, 10) / 100,
|
||
...base,
|
||
};
|
||
const signature = await generateSignature(body);
|
||
const _response = await fetch(
|
||
`${apiUrl}/api/zone_third_partner/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;
|
||
}
|
||
navigation.goBack();
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
|
||
//关闭
|
||
const handleCancel = () => {
|
||
setIsAddAgencyModalVisible(false);
|
||
setIsSelected(false);
|
||
setAgencyData();
|
||
setUserId();
|
||
setRate();
|
||
setVeriCode();
|
||
};
|
||
|
||
return (
|
||
<ScrollView
|
||
style={{
|
||
paddingBottom: insets.bottom,
|
||
paddingLeft: insets.left,
|
||
paddingRight: insets.right,
|
||
...tailwind("flex-1"),
|
||
}}
|
||
>
|
||
<View style={tailwind("flex flex-col items-center p-4")}>
|
||
{data ? (
|
||
<Image
|
||
source={data.third_partner_account.avatar.images[0].urls[0]}
|
||
contentFit="cover"
|
||
transition={1000}
|
||
placeholder={blurhash}
|
||
cachePolicy="disk"
|
||
style={tailwind("w-[4.6rem] h-[4.6rem] rounded-full")}
|
||
/>
|
||
) : (
|
||
<Icon
|
||
onPress={() => setIsAddAgencyModalVisible(true)}
|
||
type="ionicon"
|
||
name="add"
|
||
size={40}
|
||
color="white"
|
||
containerStyle={tailwind(
|
||
"border border-white rounded-full w-[4.6rem] h-[4.6rem] flex items-center justify-center"
|
||
)}
|
||
/>
|
||
)}
|
||
{data && (
|
||
<View
|
||
style={{
|
||
gap: 8,
|
||
...tailwind(
|
||
"flex flex-col border border-2 border-[#2c2b2f] rounded-2xl p-4 w-full mt-6"
|
||
),
|
||
}}
|
||
>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
代运营昵称:{data.third_partner_account.name}
|
||
</Text>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
ID:{data.third_partner_account.user_id}
|
||
</Text>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
分成比例:{(data.sharing_ratio * 100).toFixed()}%
|
||
</Text>
|
||
</View>
|
||
)}
|
||
<View style={tailwind("mt-8")}>
|
||
<Text style={tailwind("text-[#FFFFFF80] text-base font-medium")}>
|
||
注意事项:
|
||
</Text>
|
||
<Text style={tailwind("text-[#FFFFFF80] text-sm")}>
|
||
1、一个空间仅可设置一个代运营,若您的代运营团队为多人,请设置代运营主账号后,让代运营主账号进入当前空间设置合伙人;
|
||
</Text>
|
||
<Text style={tailwind("text-[#FFFFFF80] text-sm")}>
|
||
2、设置完成后无法再次修改人员和分成比例,请确认后再提交,后续如需修改请联系人工客服;
|
||
</Text>
|
||
<Text style={tailwind("text-[#FFFFFF80] text-sm")}>
|
||
3、您获得的收益会按照您设置的分成比例直接转移至代运营及协作者账户,您将不会得到这部分的收益,如有疑问请咨询人工客服。
|
||
</Text>
|
||
</View>
|
||
</View>
|
||
<Modal
|
||
visible={idAddAgencyModalVisible}
|
||
transparent={true}
|
||
statusBarTranslucent
|
||
animationType="fade"
|
||
>
|
||
<TouchableOpacity
|
||
activeOpacity={1}
|
||
onPress={handleCancel}
|
||
style={tailwind("flex flex-1 bg-[#00000080] px-4")}
|
||
>
|
||
<KeyboardAvoidingView
|
||
style={tailwind("flex flex-1 items-center justify-center")}
|
||
behavior="padding"
|
||
>
|
||
<TouchableOpacity
|
||
activeOpacity={1}
|
||
style={{
|
||
gap: 12,
|
||
...tailwind(
|
||
"flex flex-col w-full bg-[#17161A] rounded-3xl px-4 py-6"
|
||
),
|
||
}}
|
||
>
|
||
<View style={tailwind("flex flex-row items-center")}>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
搜索用户:
|
||
</Text>
|
||
<TextInput
|
||
placeholder="请输入用户ID"
|
||
placeholderTextColor="#FFFFFF80"
|
||
keyboardType="numeric"
|
||
underlineColorAndroid="transparent"
|
||
onChangeText={(value) => setUserId(value)}
|
||
value={userId}
|
||
style={tailwind(
|
||
"flex-1 bg-[#FFFFFF1A] text-white rounded-2xl px-4 h-8 mx-2"
|
||
)}
|
||
/>
|
||
<Text
|
||
onPress={handleSearch}
|
||
style={tailwind("text-[#FF669E] text-base font-medium")}
|
||
>
|
||
搜索
|
||
</Text>
|
||
</View>
|
||
{agencyData && (
|
||
<View
|
||
style={[
|
||
tailwind("flex flex-row items-center rounded-2xl p-4"),
|
||
isSelected
|
||
? { borderColor: "#FF669E", ...tailwind("border") }
|
||
: { borderColor: "#2c2b2f", ...tailwind("border") },
|
||
]}
|
||
>
|
||
<Image
|
||
source={agencyData?.avatar?.images[0]?.urls[0]}
|
||
contentFit="cover"
|
||
transition={1000}
|
||
placeholder={blurhash}
|
||
cachePolicy="disk"
|
||
style={tailwind("w-12 h-12 rounded-full")}
|
||
/>
|
||
<View
|
||
style={tailwind(
|
||
"flex flex-1 flex-col justify-around items-start ml-2"
|
||
)}
|
||
>
|
||
<Text
|
||
style={tailwind("text-base text-white font-medium")}
|
||
numberOfLines={1}
|
||
ellipsizeMode="tail"
|
||
>
|
||
{agencyData?.name}
|
||
</Text>
|
||
<View
|
||
style={tailwind(
|
||
"flex flex-row items-center py-0.5 px-2 bg-[#FFFFFF1A] rounded-full"
|
||
)}
|
||
>
|
||
<NativeImage
|
||
source={require("../../../assets/icon/12DP/ID.png")}
|
||
/>
|
||
<Text
|
||
style={tailwind(
|
||
"text-white text-xs font-medium ml-0.5"
|
||
)}
|
||
>
|
||
{agencyData?.user_id}
|
||
</Text>
|
||
</View>
|
||
</View>
|
||
<Button
|
||
color={isSelected ? "#FFFFFF1A" : "#FF669E"}
|
||
radius="999"
|
||
size="md"
|
||
onPress={() => setIsSelected(!isSelected)}
|
||
titleStyle={tailwind("text-base")}
|
||
containerStyle={{ width: 80 }}
|
||
>
|
||
{isSelected ? "取消" : "选择"}
|
||
</Button>
|
||
</View>
|
||
)}
|
||
<View style={tailwind("flex flex-row items-center")}>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
手机号:
|
||
<Text style={tailwind("text-[#FFFFFF80]")}>
|
||
{mobilePhone?.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2")}
|
||
</Text>
|
||
</Text>
|
||
</View>
|
||
<View style={tailwind("flex flex-row items-center")}>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
验证码:
|
||
</Text>
|
||
<TextInput
|
||
placeholder="请输入验证码"
|
||
placeholderTextColor="#FFFFFF80"
|
||
keyboardType="numeric"
|
||
underlineColorAndroid="transparent"
|
||
onChangeText={(value) => setVeriCode(value)}
|
||
value={veriCode}
|
||
style={tailwind(
|
||
"flex-1 bg-[#FFFFFF1A] text-white rounded-2xl px-4 h-8 mx-2"
|
||
)}
|
||
/>
|
||
<Button
|
||
color="#FF669E"
|
||
radius="999"
|
||
size="sm"
|
||
disabled={isCounting}
|
||
disabledStyle={tailwind("bg-[#FFFFFF1A]")}
|
||
titleStyle={tailwind("text-sm mx-2")}
|
||
onPress={handleVerification}
|
||
>
|
||
{isCounting ? `(${seconds})重新发送` : "获取验证码"}
|
||
</Button>
|
||
</View>
|
||
<View style={tailwind("flex flex-row items-center")}>
|
||
<Text style={tailwind("text-white text-base font-medium")}>
|
||
分成比例:
|
||
</Text>
|
||
<View style={tailwind("w-1/3")}>
|
||
<Picker items={rates} onChange={(value) => setRate(value)} />
|
||
</View>
|
||
</View>
|
||
<Text style={tailwind("text-[#F53030] text-xs font-medium")}>
|
||
注意事项:分成比例不得超过50%且确认后无法修改
|
||
</Text>
|
||
<View style={tailwind("flex flex-row mt-2")}>
|
||
<Button
|
||
color="#FF669E"
|
||
radius="999"
|
||
size="md"
|
||
titleStyle={tailwind("text-sm mx-2")}
|
||
containerStyle={tailwind("flex-1 px-2")}
|
||
onPress={handleSubmit}
|
||
>
|
||
确认
|
||
</Button>
|
||
<Button
|
||
color="#FFFFFF1A"
|
||
radius="999"
|
||
size="md"
|
||
titleStyle={tailwind("text-sm mx-2")}
|
||
containerStyle={tailwind("flex-1 px-2")}
|
||
onPress={handleCancel}
|
||
>
|
||
取消
|
||
</Button>
|
||
</View>
|
||
</TouchableOpacity>
|
||
</KeyboardAvoidingView>
|
||
</TouchableOpacity>
|
||
<Toast />
|
||
</Modal>
|
||
</ScrollView>
|
||
);
|
||
}
|