528 lines
17 KiB
JavaScript
528 lines
17 KiB
JavaScript
"use client";
|
||
|
||
import React, { useState, useEffect } from "react";
|
||
import {
|
||
List,
|
||
Toast,
|
||
Image,
|
||
Space,
|
||
Picker,
|
||
TextArea,
|
||
Modal,
|
||
Mask,
|
||
SpinLoading,
|
||
Button,
|
||
} from "antd-mobile";
|
||
import { DragDropContext, Draggable, Droppable } from "@hello-pangea/dnd";
|
||
import { useRouter } from "next/navigation";
|
||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||
import {
|
||
faAngleLeft,
|
||
faAdd,
|
||
faEdit,
|
||
faTrashCan,
|
||
faSortDown,
|
||
} from "@fortawesome/free-solid-svg-icons";
|
||
import OwnInput from "@/components/OwnInput";
|
||
import requireAPI from "@/utils/requireAPI";
|
||
import { get } from "@/utils/storeInfo";
|
||
|
||
const reorder = (list, startIndex, endIndex) => {
|
||
const result = Array.from(list);
|
||
const [removed] = result.splice(startIndex, 1);
|
||
result.splice(endIndex, 0, removed);
|
||
|
||
return result;
|
||
};
|
||
const defaultFormData = {
|
||
nickname: "",
|
||
url: "",
|
||
selectedPlatform: [],
|
||
};
|
||
export default function EditPlace() {
|
||
const router = useRouter();
|
||
const [formData, setFormData] = useState(defaultFormData);
|
||
const [allPlatforms, setAllPlatforms] = useState([]);
|
||
const [platform, setPlatform] = useState([]);
|
||
const [currentPlat, setcurrentPlat] = useState(null);
|
||
//正在提交状态
|
||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||
const [platformEditable, setPlatformEditable] = useState(false);
|
||
useEffect(() => {
|
||
getAllPlatforms();
|
||
}, []);
|
||
const getAllPlatforms = async () => {
|
||
try {
|
||
const detailData = await requireAPI("POST", "/api/platform/list", {});
|
||
if (detailData.ret === -1) {
|
||
Toast.show({
|
||
icon: "fail",
|
||
content: detailData.msg,
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
const detailDataValues = Object.entries(detailData.data);
|
||
const temAllPlatforms = detailDataValues.map((item) => {
|
||
return {
|
||
label: item[1].name,
|
||
value: {
|
||
link_no: parseInt(item[0], 10),
|
||
link_name: item[1].name,
|
||
link_icon: item[1].icon,
|
||
},
|
||
};
|
||
});
|
||
|
||
//获取主播当前所有平台
|
||
const streamerPlatformData = await requireAPI(
|
||
"POST",
|
||
"/api/streamer_link/list_by_mid",
|
||
{},
|
||
true
|
||
);
|
||
if (streamerPlatformData.ret === -1) {
|
||
Toast.show({
|
||
icon: "error",
|
||
content: streamerPlatformData.msg,
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
|
||
const streamerPlatList = streamerPlatformData.data.list;
|
||
setAllPlatforms(temAllPlatforms);
|
||
const platformsWithIcon = streamerPlatList.map((item) => {
|
||
return {
|
||
...item,
|
||
link_icon: detailData.data[item.link_no].icon,
|
||
};
|
||
});
|
||
setPlatform(platformsWithIcon);
|
||
} catch (error) {
|
||
console.error(error);
|
||
}
|
||
};
|
||
//点击删除按钮
|
||
const handleDelete = (index) => {
|
||
const updatedPlatform = [...platform];
|
||
updatedPlatform.splice(index, 1);
|
||
setPlatform(updatedPlatform);
|
||
};
|
||
const handSubmit = async () => {
|
||
const account = get("account");
|
||
const newPlatforms = [...platform];
|
||
newPlatforms.forEach((item, index) => {
|
||
item.order = index + 1;
|
||
item.mid = account.mid;
|
||
});
|
||
try {
|
||
//获取主播当前所有平台
|
||
const streamerPlatformData = await requireAPI(
|
||
"POST",
|
||
"/api/streamer_link/list_by_mid",
|
||
{},
|
||
true
|
||
);
|
||
if (streamerPlatformData.ret === -1) {
|
||
Toast.show({
|
||
icon: "fail",
|
||
content: streamerPlatformData.msg,
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
//删除全部现有平台
|
||
const ids = streamerPlatformData.data.list.map((item) => item.id);
|
||
if (ids.length !== 0) {
|
||
const deleteData = await requireAPI(
|
||
"POST",
|
||
"/api/streamer_link/delete_batch",
|
||
{
|
||
body: {
|
||
ids: ids,
|
||
},
|
||
}
|
||
);
|
||
if (deleteData.ret === -1) {
|
||
Toast.show({
|
||
icon: "fail",
|
||
content: deleteData.msg,
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
}
|
||
//批量创建新的平台
|
||
if (newPlatforms.length === 0) {
|
||
Toast.show({
|
||
icon: "success",
|
||
content: "更改成功",
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
const data = await requireAPI("POST", "/api/streamer_link/create_batch", {
|
||
body: {
|
||
streamer_links: newPlatforms,
|
||
},
|
||
});
|
||
if (data.ret === -1) {
|
||
Toast.show({
|
||
icon: "fail",
|
||
content: data.msg,
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
Toast.show({
|
||
icon: "success",
|
||
content: "更改成功",
|
||
position: "top",
|
||
});
|
||
router.back();
|
||
} catch (error) {
|
||
console.error(error);
|
||
} finally {
|
||
setPlatformEditable(false);
|
||
setFormData(defaultFormData);
|
||
setIsSubmitting(false);
|
||
}
|
||
};
|
||
const handleEditPlatform = (values) => {
|
||
if (!values.nickname || !values.selectedPlatform.length || !values.url) {
|
||
Toast.show({
|
||
icon: "fail",
|
||
content: "请完整填写信息",
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
if (
|
||
values.url.indexOf("http://") == -1 &&
|
||
values.url.indexOf("https://") == -1
|
||
) {
|
||
Toast.show({
|
||
icon: "fail",
|
||
content: "链接必须以https://或http://开头",
|
||
position: "top",
|
||
});
|
||
return;
|
||
}
|
||
let newPlatforms = [];
|
||
if (!formData.id) {
|
||
const currentPlatFormEle = allPlatforms.filter(
|
||
(it) => it.label == values.selectedPlatform[0]
|
||
)[0];
|
||
const newPlatform = {
|
||
link_name: values.selectedPlatform[0],
|
||
link_icon: currentPlatFormEle.value.link_icon,
|
||
link_no: currentPlatFormEle.value.link_no,
|
||
nickname: values.nickname,
|
||
url: values.url,
|
||
};
|
||
newPlatforms = platform.concat(newPlatform);
|
||
// setIsSubmitting(true);
|
||
} else {
|
||
const index = platform.findIndex(
|
||
(it) => it.link_name == formData.selectedPlatform
|
||
);
|
||
newPlatforms = [...platform];
|
||
newPlatforms[index].link_name = formData.selectedPlatform;
|
||
newPlatforms[index] = {
|
||
...newPlatforms[index],
|
||
link_name: formData.selectedPlatform,
|
||
nickname: formData.nickname,
|
||
url: formData.url,
|
||
};
|
||
}
|
||
setFormData(defaultFormData);
|
||
setPlatform(newPlatforms);
|
||
setPlatformEditable(false);
|
||
};
|
||
|
||
const onDragEnd = (result) => {
|
||
if (!result.destination) return;
|
||
const newList = reorder(
|
||
platform,
|
||
result.source.index,
|
||
result.destination.index
|
||
);
|
||
setPlatform([...newList]);
|
||
};
|
||
return (
|
||
<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="pt-16 p-4">
|
||
<div
|
||
className="mt-2 text-sm flex justify-center items-center font-medium border border-dashed border-white rounded-md px-4 py-3"
|
||
onClick={() => setPlatformEditable(true)}
|
||
>
|
||
<FontAwesomeIcon
|
||
icon={faAdd}
|
||
style={{ maxWidth: "12px" }}
|
||
size="xl"
|
||
/>
|
||
<span className="ml-2">添加</span>
|
||
</div>
|
||
<List
|
||
className="mt-4"
|
||
style={{
|
||
"--padding-left": 0,
|
||
"--padding-right": 0,
|
||
"--border-inner": "none",
|
||
}}
|
||
>
|
||
<DragDropContext onDragEnd={onDragEnd}>
|
||
<Droppable droppableId="droppable11">
|
||
{(droppableProvided) => (
|
||
<div
|
||
{...droppableProvided.droppableProps}
|
||
ref={droppableProvided.innerRef}
|
||
>
|
||
{platform.map((item, index) => (
|
||
<Draggable
|
||
key={item.id + index}
|
||
draggableId={(item.id || index).toString()}
|
||
index={index}
|
||
>
|
||
{(provided, snapshot) => (
|
||
<div
|
||
key={item.name}
|
||
ref={provided.innerRef}
|
||
{...provided.draggableProps}
|
||
{...provided.dragHandleProps}
|
||
style={{
|
||
...provided.draggableProps.style,
|
||
opacity: snapshot.isDragging ? 0.8 : 1,
|
||
}}
|
||
>
|
||
<div
|
||
key={index}
|
||
className="w-full grid grid-cols-[auto,20px] gap-4 justify-between bg-[#13121F] rounded-lg p-4 my-2"
|
||
>
|
||
<div className="text-base font-medium">
|
||
<div className="flex items-center">
|
||
<span>平台:</span>
|
||
<div className="flex items-center">
|
||
<Image
|
||
src={item?.link_icon?.images[0]?.urls[0]}
|
||
width={18}
|
||
/>
|
||
<span className="ml-2">{item.link_name}</span>
|
||
</div>
|
||
</div>
|
||
<p className="flex items-center">
|
||
<span>昵称:</span>
|
||
<span>{item.nickname}</span>
|
||
</p>
|
||
<p className="flex">
|
||
<span className="whitespace-nowrap">
|
||
链接:
|
||
</span>
|
||
<span
|
||
className="whitespace-normal inline-block"
|
||
style={{ overflowWrap: "anywhere" }}
|
||
>
|
||
{item.url}
|
||
</span>
|
||
</p>
|
||
</div>
|
||
<div className="grid grid-rows-[32px,32px] gap-2 items-center">
|
||
<div onClick={() => handleDelete(index)}>
|
||
<FontAwesomeIcon
|
||
icon={faTrashCan}
|
||
style={{ maxWidth: "18px" }}
|
||
size="xl"
|
||
/>
|
||
</div>
|
||
<div
|
||
onClick={() => {
|
||
setPlatformEditable(true);
|
||
setFormData({
|
||
nickname: item.nickname,
|
||
url: item.url,
|
||
selectedPlatform: item.link_name,
|
||
id: item.id,
|
||
});
|
||
}}
|
||
>
|
||
<FontAwesomeIcon
|
||
icon={faEdit}
|
||
style={{ maxWidth: "18px" }}
|
||
size="xl"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</Draggable>
|
||
))}
|
||
{droppableProvided.placeholder}
|
||
</div>
|
||
)}
|
||
</Droppable>
|
||
</DragDropContext>
|
||
</List>
|
||
<div className="fixed bottom-8 flex justify-center w-full">
|
||
<Button
|
||
size="middle"
|
||
shape="rounded"
|
||
style={{
|
||
"--background-color": "#FF669E",
|
||
paddingLeft: "32px",
|
||
paddingRight: "32px",
|
||
}}
|
||
disabled={isSubmitting}
|
||
onClick={() => handSubmit()}
|
||
>
|
||
{isSubmitting ? "正在提交..." : "确认修改"}
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
<Modal
|
||
visible={platformEditable}
|
||
content={
|
||
<div className="w-full px-4">
|
||
<p className="text-lg font-medium text-center mb-2">
|
||
编辑/添加平台
|
||
</p>
|
||
<div className="flex items-center my-4">
|
||
<span className="text-base font-medium mr-1">平台:</span>
|
||
{!formData.id ? (
|
||
<div className="w-1/2">
|
||
<Picker
|
||
columns={[
|
||
[
|
||
...allPlatforms
|
||
.map((it) => {
|
||
return {
|
||
label: it.label,
|
||
value: it.label,
|
||
};
|
||
})
|
||
.filter((it) => {
|
||
return !platform.some(
|
||
(el) => el.link_name == it.label
|
||
);
|
||
}),
|
||
],
|
||
]}
|
||
onSelect={(value) => {
|
||
setFormData((old) => ({
|
||
...old,
|
||
selectedPlatform: value,
|
||
}));
|
||
}}
|
||
value={formData.selectedPlatform}
|
||
>
|
||
{(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>
|
||
) : (
|
||
<span className="text-base font-medium mr-1">
|
||
{formData?.selectedPlatform}
|
||
</span>
|
||
)}
|
||
</div>
|
||
<div className="flex items-center my-4">
|
||
<span className="text-base font-medium mr-1">昵称:</span>
|
||
<OwnInput
|
||
placeholder="请输入昵称"
|
||
onChange={(value) => {
|
||
setFormData((old) => ({ ...old, nickname: value }));
|
||
}}
|
||
value={formData.nickname}
|
||
className="border border-[#2c2b2f] font-medium rounded-lg h-10 px-2"
|
||
/>
|
||
</div>
|
||
<div className="flex my-4">
|
||
<span className="text-base font-medium mr-1 whitespace-nowrap">
|
||
链接:
|
||
</span>
|
||
<TextArea
|
||
placeholder="请输入链接"
|
||
onChange={(value) => {
|
||
setFormData((old) => ({ ...old, url: value }));
|
||
}}
|
||
value={formData.url}
|
||
style={{
|
||
"--placeholder-color": "#FFFFFF80",
|
||
"--font-size": "16px",
|
||
}}
|
||
className="border border-[#2c2b2f] font-medium rounded-lg h-24 p-2 "
|
||
/>
|
||
</div>
|
||
</div>
|
||
}
|
||
actions={[
|
||
{
|
||
key: "confirm",
|
||
text: "确认",
|
||
className: "rounded-full",
|
||
style: {
|
||
background: "#FF669E",
|
||
border: "none",
|
||
borderRadius: "100px",
|
||
},
|
||
primary: true,
|
||
},
|
||
{
|
||
key: "cancle",
|
||
text: "取消",
|
||
style: { color: "#ffffff80" },
|
||
},
|
||
]}
|
||
onAction={(action, index) => {
|
||
if (action.key == "confirm") {
|
||
handleEditPlatform(formData);
|
||
} else {
|
||
setPlatformEditable(false);
|
||
setFormData(defaultFormData);
|
||
}
|
||
}}
|
||
></Modal>
|
||
<Mask visible={isSubmitting}>
|
||
<div className="w-full h-screen flex justify-center items-center">
|
||
<SpinLoading color="default" />
|
||
</div>
|
||
</Mask>
|
||
</div>
|
||
);
|
||
}
|