tiefen_space_h5/app/space/setting/agencySetting/page.jsx

462 lines
14 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,
useRef,
} from "react";
import {
Image,
Toast,
Dialog,
Picker,
Avatar,
Space,
SpinLoading,
} from "antd-mobile";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
faAngleLeft,
faAdd,
faSortDown,
} from "@fortawesome/free-solid-svg-icons";
import requireAPI from "@/utils/requireAPI";
import { useRouter, useSearchParams } from "next/navigation";
import OwnInput from "@/components/OwnInput";
import { get } from "@/utils/storeInfo";
import { JSEncrypt } from "jsencrypt";
export default function AgencySetting() {
const [data, setData] = useState(null);
const [modalVisible, setModalVisible] = useState(false);
const [isloading, setIsloading] = useState([]);
const searchParams = useSearchParams();
const router = useRouter();
const handler = useRef(null);
const getData = async () => {
const zid = Number(searchParams.get("zid"));
try {
setIsloading(true);
const body = {
zid,
};
const _data = await requireAPI("POST", "/api/zone_third_partner/list", {
body,
});
if (_data.ret === -1) {
setIsloading(false);
Toast.show({
icon: "fail",
content: _data.msg,
position: "top",
});
return;
}
setData(_data.data.zone_third_partner);
} catch (error) {
console.error(error);
}
setIsloading(false);
};
useEffect(() => {
getData();
}, []);
useEffect(() => {
if (!modalVisible && handler.current) {
handler.current?.close();
}
}, [modalVisible]);
const handleAddAgency = () => {
setModalVisible(!modalVisible);
const zid = Number(searchParams.get("zid"));
handler.current = Dialog.show({
content: (
<ModalMask
setModalVisible={setModalVisible}
zid={zid}
router={router}
/>
),
bodyStyle: {
backgroundColor: "#17161A",
maxHeight: "none",
width: "90vw",
position: "fixed",
top: "200px",
left: "5vw",
"--text-color": "#fff",
color: "#fff",
},
});
};
return (
<div>
{isloading && (
<div
className="bg-[#00000099] fixed top-0 w-full text-center flex items-center justify-center h-screen"
// style={{ height: scrollHeight - 60 + "px" }}
>
<SpinLoading />
</div>
)}
{/* 头部标题 */}
<div className="p-4 fixed top-0 z-10 w-full bg-black">
<div className="w-9 h-9 flex items-center justify-center bg-[#FFFFFF1A] rounded-full absolute">
<FontAwesomeIcon
icon={faAngleLeft}
style={{ maxWidth: "12px" }}
size="xl"
onClick={() => {
router.back();
}}
/>
</div>
<p className="text-base text-center leading-9">代运营设置</p>
</div>
{/* 内容 */}
<div className="p-4 pt-20">
<div className="flex justify-center items-center">
{data ? (
<div className="flex-1 flex flex-col justify-center items-center">
<Image
src={data?.third_partner_account.avatar.images[0].urls[0]}
width={74}
height={74}
className="h-full mr-1"
placeholder=""
/>
<div className="flex flex-col border-2 border-[#2c2b2f] rounded-2xl p-4 w-full mt-6 text-base font-medium">
<p>代运营昵称{data.third_partner_account.name}</p>
<p>ID{data.third_partner_account.user_id}</p>
<p>分成比例{(data.sharing_ratio * 100).toFixed()}%</p>
</div>
</div>
) : (
<div
onClick={handleAddAgency}
className="border border-white rounded-full w-[4.6rem] h-[4.6rem] flex items-center justify-center"
>
<FontAwesomeIcon
icon={faAdd}
style={{ maxWidth: "20px" }}
size="2xl"
/>
</div>
)}
</div>
<div className="mt-8 text-[#FFFFFF80] text-sm">
<p className="text-base font-medium">注意事项</p>
<p>
1一个空间仅可设置一个代运营若您的代运营团队为多人请设置代运营主账号后让代运营主账号进入当前空间设置合伙人
</p>
<p>
2设置完成后无法再次修改人员和分成比例请确认后再提交后续如需修改请联系人工客服
</p>
<p>
3您获得的收益会按照您设置的分成比例直接转移至代运营及协作者账户您将不会得到这部分的收益如有疑问请咨询人工客服
</p>
</div>
</div>
</div>
);
}
const ModalMask = ({ setModalVisible, zid, router }) => {
const [isloading, setIsloading] = useState([]);
const [isSelected, setIsSelected] = useState(false);
const [seconds, setSeconds] = useState(60);
const [agencyData, setAgencyData] = useState(null);
const [mobilePhone, setMobilePhone] = useState("");
const [regionCode, setRegionCode] = useState("");
const [veriCode, setVeriCode] = useState("");
const [userId, setUserId] = useState("");
const [isCounting, setIsCounting] = useState(false);
const [rate, setRate] = useState([null]);
// const router = useRouter();
//生成比例选项
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), []);
useEffect(() => {
async function getMobilePhone() {
setMobilePhone(await get("mobile_phone"));
setRegionCode(await get("region_code"));
}
getMobilePhone();
}, []);
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 handleSearch = async (id) => {
try {
setIsloading(true);
const body = {
user_id: parseInt(id, 10),
};
const _data = await requireAPI(
"POST",
"/api/account/list_others_by_user_id",
{
body,
}
);
if (_data.ret === -1) {
setIsloading(false);
Toast.show({
icon: "fail",
content: _data.msg,
position: "top",
});
return;
}
setAgencyData(_data.data.account);
setIsSelected(false);
} catch (error) {
console.error(error);
}
};
//点击获取验证码
const handleVerification = async () => {
if (!isSelected) {
Toast.show({
icon: "fail",
content: "请先选中用户",
position: "top",
});
return;
}
//开始倒计时
setIsCounting(true);
//对手机号进行RSA加密
const encrypt = new JSEncrypt();
encrypt.setPublicKey(process.env.NEXT_PUBLIC_RSA_KEY);
const mobile_phone = encrypt.encrypt(mobilePhone);
//发送短信验证码
try {
const data = await fetch(`/api/veri_code/send`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mobile_phone,
region_code: regionCode,
}),
});
if (data.ret === -1) {
Toast.show({
icon: "fail",
content: data.msg,
position: "top",
});
return;
}
} catch (error) {
// console.error(error);
}
};
const handleSubmit = async () => {
if (!isSelected) {
Toast.show({
icon: "fail",
content: "请先选中用户",
position: "top",
});
return;
}
if (!veriCode) {
Toast.show({
icon: "fail",
content: "请输入验证码",
position: "top",
});
return;
}
if (!rate[0]) {
Toast.show({
icon: "fail",
content: "请选择分成比例",
position: "top",
});
return;
}
try {
//对手机号进行RSA加密
const encrypt = new JSEncrypt();
encrypt.setPublicKey(process.env.NEXT_PUBLIC_RSA_KEY);
const mobile_phone = encrypt.encrypt(mobilePhone);
const body = {
zid,
third_partner_mid: agencyData.mid,
region_code: regionCode,
mobile_phone: mobile_phone,
veri_code: veriCode,
sharing_ratio: parseInt(rate[0], 10) / 100,
};
const _data = await requireAPI("POST", "/api/zone_third_partner/create", {
body,
});
if (_data.ret === -1) {
Toast.show({
icon: "fail",
content: _data.msg,
position: "top",
});
return;
}
setModalVisible(false);
router.back();
} catch (error) {
console.error(error);
}
};
return (
<div className="flex flex-col w-full rounded-3xl text-white">
<div className="flex flex-row items-center mb-4">
<span className="text-base font-medium">搜索用户:</span>
<OwnInput
placeholder="请输入用户ID"
type="number"
onChange={(value) => {
setUserId(value);
}}
value={userId}
className="flex-1 bg-[#FFFFFF1A] text-white rounded-2xl px-4 h-8 mx-2"
/>
<span
onClick={() => handleSearch(userId)}
className="text-[#FF669E] text-base font-medium"
>
搜索
</span>
</div>
{agencyData && (
<div
className="flex flex-row items-center rounded-2xl p-4 mb-4 border"
style={{ borderColor: isSelected ? "#FF669E" : "#2c2b2f" }}
>
<Avatar
src={agencyData?.avatar?.images[0]?.urls[0]}
fit="cover"
style={{ "--border-radius": "100px", "--size": "42px" }}
/>
<div className="flex flex-1 flex-col justify-around items-start ml-2">
<span className="text-base font-medium whitespace-nowrap">
{agencyData?.name}
</span>
<div className="flex flex-row items-center py-0.5 px-2 bg-[#FFFFFF1A] rounded-full">
<Image
src={
process.env.NEXT_PUBLIC_WEB_ASSETS_URL + "/icons/info/ID.png"
}
width={14}
height={14}
className="w-4 h-full mr-1"
/>
<span className="text-xs font-medium ml-0.5 whitespace-nowrap">
{agencyData?.user_id}
</span>
</div>
</div>
<div
className="px-4 py-2 text-sm font-medium rounded-full"
style={{
backgroundColor: isSelected ? "#FFFFFF1A" : "#FF669E",
}}
onClick={() => setIsSelected(!isSelected)}
>
{isSelected ? "取消" : "选择"}
</div>
</div>
)}
<div className="flex flex-row items-center mb-4">
<span className="text-base font-medium">
手机号:
<span className="text-[#FFFFFF80] ml-2">
{mobilePhone?.replace(/(\d{3})\d{4}(\d{4})/, "$1****$2")}
</span>
</span>
</div>
<div className="flex flex-row items-center mb-4">
<span className="text-base font-medium">验证码:</span>
<OwnInput
placeholder="请输入验证码"
type="number"
onChange={(value) => setVeriCode(value)}
value={veriCode}
className="flex-1 bg-[#FFFFFF1A] rounded-2xl px-4 h-8 mx-2"
/>
<div
className="bg-[#FF669E] px-2 py-1 text-sm font-medium rounded-full"
disabled={isCounting}
onClick={handleVerification}
>
{isCounting ? `(${seconds})重新发送` : "获取验证码"}
</div>
</div>
<div className="flex flex-row items-center mb-4">
<span className="text-base font-medium">分成比例</span>
<div className="w-1/3">
<Picker columns={[rates]} onConfirm={setRate} value={rate}>
{(items, { open }) => {
return (
<Space
align="center"
direction="horizontal"
justify="center"
onClick={open}
>
{items.every((item) => item === null)
? "未选择"
: items.map((item) => item?.label ?? "未选择").join("")}
<FontAwesomeIcon
icon={faSortDown}
style={{ maxWidth: "12px", marginBottom: 6 }}
size="lg"
/>
</Space>
);
}}
</Picker>
</div>
</div>
<span className="text-[#F53030] text-xs font-medium">
注意事项分成比例不得超过50%且确认后无法修改
</span>
<div className="grid grid-cols-2 gap-2 mt-2">
<div
className="bg-[#FF669E] text-center w-full py-2 text-md font-medium rounded-full"
onClick={handleSubmit}
>
确认
</div>
<div
className="bg-[#FFFFFF1A] text-center w-full py-2 text-md font-medium rounded-full"
onClick={() => setModalVisible(false)}
>
取消
</div>
</div>
</div>
);
};