tiefen_space_op/src/pages/StreamerInformation/index.jsx

812 lines
27 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 React, { useState } from "react";
import {
Form,
Input,
Button,
Space,
Table,
Checkbox,
InputNumber,
Image,
} from "antd";
import Modal from "../../components/Modal";
import VideoUploader from "../../components/VideoUploader";
import ImageUploader from "../../components/ImageUploader";
import baseRequest from "../../utils/baseRequest";
//tab内容
const StreamerInformationContent = () => {
const { TextArea } = Input;
//展示的表头
const [showColumns, setShowColumns] = useState([
"baseInfo",
"displayInfo",
"displayPoster",
"displayVideo",
"displayGallery",
]);
//动态的表头
const dynamicColumns = showColumns.map((item) => {
switch (item) {
case "baseInfo":
return {
title: "基础信息",
dataIndex: "baseInfo",
key: "baseInfo",
render: (data) => (
<div>
<Image src={data.avatar} width={50} />
<p>
ID<span className="text-red-400">{data.id}</span>
</p>
<p>
昵称<span className="text-red-400">{data.name}</span>
</p>
<p>
入驻时间<span className="text-red-400">{data.joinTime}</span>
</p>
</div>
),
};
case "displayInfo":
return {
title: "个人展示信息",
dataIndex: "displayInfo",
key: "displayInfo",
render: (data) => (
<div>
<p>
性别
<span className="text-red-400">
{data.gender === 1 ? "女" : "男"}
</span>
</p>
<p>
全网粉丝<span className="text-red-400">{data.fans}</span>
</p>
<p>
微信添加方式
<span className="text-red-400">
{data.wechat_lock_type === 1 ? "主动添加" : "直接展示"}
</span>
</p>
<p>
微信
<span className="text-red-400">
{data.wechat ? data.wechat : "空"}
</span>
</p>
<p>
微信价格
<span className="text-red-400">¥{data.wechat_price / 10}</span>
</p>
<p>
个性签名<span className="text-red-400">{data.signature}</span>
</p>
<p>
私信自动回复
<span className="text-red-400">
{data.auto_response_message}
</span>
</p>
<p>
年龄<span className="text-red-400">{data.age}</span>
</p>
<p>
身高<span className="text-red-400">{data.height}</span>
</p>
<p>
体重<span className="text-red-400">{data.weight}</span>
</p>
<p>
星座<span className="text-red-400">{data.constellation}</span>
</p>
<p>
居住地<span className="text-red-400">{data.location}</span>
</p>
</div>
),
};
case "displayPoster":
return {
title: "封面图片",
dataIndex: "displayPoster",
key: "displayPoster",
render: (data) => <Image src={data[0].urls[0]} width={100} />,
};
case "displayVideo":
return {
title: "封面视频",
dataIndex: "displayVideo",
key: "displayVideo",
render: (data) => (
<video src={data[0].urls[0]} width={150} controls />
),
};
case "displayGallery":
return {
title: "相册",
dataIndex: "displayGallery",
key: "displayGallery",
render: (data) => (
<div>
{data.map((item) => (
<Image
key={item.urls[0]}
src={item.urls[0]}
width={100}
style={{ marginBottom: 10 }}
/>
))}
</div>
),
};
default:
return {};
}
});
dynamicColumns.push({
title: "操作",
dataIndex: "opeartion",
key: "opeartion",
render: (_, record) => (
<div>
<Button type="primary" onClick={() => handleModal(record)}>
修改
</Button>
</div>
),
});
//modal中select选项
const constellations = [
{ label: "白羊座", value: "白羊座" },
{ label: "金牛座", value: "金牛座" },
{ label: "双子座", value: "双子座" },
{ label: "巨蟹座", value: "巨蟹座" },
{ label: "狮子座", value: "狮子座" },
{ label: "处女座", value: "处女座" },
{ label: "天秤座", value: "天秤座" },
{ label: "天蝎座", value: "天蝎座" },
{ label: "射手座", value: "射手座" },
{ label: "摩羯座", value: "摩羯座" },
{ label: "水瓶座", value: "水瓶座" },
{ label: "双鱼座", value: "双鱼座" },
];
const provinces = [
{ label: "北京市", value: "北京市" },
{ label: "天津市", value: "天津市" },
{ label: "河北省", value: "河北省" },
{ label: "山西省", value: "山西省" },
{ label: "内蒙古自治区", value: "内蒙古自治区" },
{ label: "辽宁省", value: "辽宁省" },
{ label: "吉林省", value: "吉林省" },
{ label: "黑龙江省", value: "黑龙江省" },
{ label: "上海市", value: "上海市" },
{ label: "江苏省", value: "江苏省" },
{ label: "浙江省", value: "浙江省" },
{ label: "安徽省", value: "安徽省" },
{ label: "福建省", value: "福建省" },
{ label: "江西省", value: "江西省" },
{ label: "山东省", value: "山东省" },
{ label: "河南省", value: "河南省" },
{ label: "湖北省", value: "湖北省" },
{ label: "湖南省", value: "湖南省" },
{ label: "广东省", value: "广东省" },
{ label: "广西壮族自治区", value: "广西壮族自治区" },
{ label: "海南省", value: "海南省" },
{ label: "重庆市", value: "重庆市" },
{ label: "四川省", value: "四川省" },
{ label: "贵州省", value: "贵州省" },
{ label: "云南省", value: "云南省" },
{ label: "西藏自治区", value: "西藏自治区" },
{ label: "陕西省", value: "陕西省" },
{ label: "甘肃省", value: "甘肃省" },
{ label: "青海省", value: "青海省" },
{ label: "宁夏回族自治区", value: "宁夏回族自治区" },
{ label: "新疆维吾尔自治区", value: "新疆维吾尔自治区" },
{ label: "台湾省", value: "台湾省" },
{ label: "香港特别行政区", value: "香港特别行政区" },
{ label: "澳门特别行政区", value: "澳门特别行政区" },
];
//modal中平台checkbox名称
const platformList = ["抖音", "微博", "哔哩哔哩", "快手", "秘live"];
//表头可见性表单的checkbox选项
const showColumnsOptions = [
{
label: "基础信息",
value: "baseInfo",
},
{
label: "个人展示信息",
value: "displayInfo",
},
{
label: "封面图片",
value: "displayPoster",
},
{
label: "封面视频",
value: "displayVideo",
},
{
label: "相册",
value: "displayGallery",
},
];
//展示的数据
const [showData, setShowData] = useState([]);
//搜索名人
const search = async (value) => {
try {
const base = baseRequest();
const detailResponse = await fetch(`/op/streamer/list_ext_by_user_id`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
user_id: parseInt(value.id, 10),
...base,
}),
});
const detailData = await detailResponse.json();
if (detailData.ret === -1) {
alert(detailData.msg);
return;
}
setShowData([
{
key: detailData.data.streamer_ext.mid,
baseInfo: {
id: detailData.data.streamer_ext.user_id,
name: detailData.data.streamer_ext.name,
avatar: detailData.data.streamer_ext.avatar.images[0].urls[0],
joinTime: new Date(
detailData.data.streamer_ext.ct * 1000
).toLocaleString(),
},
displayInfo: {
gender: detailData.data.streamer_ext.gender,
fans: detailData.data.streamer_ext.fans,
wechat_lock_type: detailData.data.streamer_ext.wechat_lock_type,
wechat: detailData.data.streamer_ext.wechat_contact,
wechat_price: detailData.data.streamer_ext.wechat_coin_price,
signature: detailData.data.streamer_ext.bio,
age: detailData.data.streamer_ext.age,
height: detailData.data.streamer_ext.height,
weight: detailData.data.streamer_ext.weight,
constellation: detailData.data.streamer_ext.constellation,
location: detailData.data.streamer_ext.city,
auto_response_message:
detailData.data.streamer_ext.auto_response_message,
},
displayPoster: detailData.data.streamer_ext.cover.images,
displayVideo: detailData.data.streamer_ext.shorts.videos,
displayGallery: detailData.data.streamer_ext.album.images,
},
]);
} catch (error) {
console.error(error);
}
};
//表单提交失败
const onFinishFailed = (errorInfo) => {
console.log("Failed:", errorInfo);
};
//modal是否展示
const [isModalOpen, setIsModalOpen] = useState(false);
//点击modal取消按钮
const handleCancel = () => {
setShowData([]);
setDefaultValues({});
setDefaultMedia({});
setDisplayVideoId([]);
setDisplayPosterId([]);
setDisplayGalleryId([]);
setIsModalOpen(false);
};
//modal打开时的默认值
const [defaultValues, setDefaultValues] = useState({});
const [defaultMedia, setDefaultMedia] = useState({});
//点击修改按钮
const handleModal = (record) => {
setDefaultValues(record);
setDefaultMedia({
displayPoster: record.displayPoster,
displayVideo: record.displayVideo,
displayGallery: record.displayGallery,
});
setIsModalOpen(true);
};
//表单提交成功
const onModalFormFinish = async (value) => {
//上传表单操作...
const oldPosterId = defaultMedia.displayPoster.map((item) => item.id);
const oldVideoId = defaultMedia.displayVideo.map((item) => item.id);
const oldGalleryId = defaultMedia.displayGallery.map((item) => item.id);
const newPosterId = [...oldPosterId, ...displayPosterId];
const newVideoId = [...oldVideoId, ...displayVideoId];
const newGalleryId = [...oldGalleryId, ...displayGalleryId];
if (
newPosterId.length === 0 ||
newVideoId.length === 0 ||
newGalleryId.length < 2
) {
alert("请确保封面、视频不为空且相册大于2");
return;
}
if (
newPosterId.length > 1 ||
newVideoId.length > 1 ||
newGalleryId.length > 9
) {
alert("请确保封面、视频、相册数量未超过上限");
return;
}
if (
!defaultValues.key ||
!value.signature ||
!value.age ||
!value.height ||
!value.weight ||
!value.constellation ||
!value.location ||
!value.fans ||
!value.wechat_price ||
!value.auto_response_message
) {
alert("请完善信息后提交");
return;
}
if (value.wechat_lock_type === 0 && !value.wechat) {
alert("请填写微信后提交");
return;
}
try {
const base = baseRequest();
const detailResponse = await fetch(`/op/streamer/update`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
mid: defaultValues.key,
gender: parseInt(value.gender, 10),
wechat_contact: value.wechat,
bio: value.signature,
cover: { image_ids: newPosterId },
shorts: { video_ids: newVideoId },
album: { image_ids: newGalleryId },
age: parseInt(value.age, 10),
height: parseInt(value.height, 10),
weight: parseInt(value.weight, 10),
constellation: value.constellation,
city: value.location,
wechat_lock_type: parseInt(value.wechat_lock_type, 10),
fans: parseInt(value.fans, 10),
wechat_coin_price: parseInt(value.wechat_price, 10) * 10,
auto_response_message: value.auto_response_message,
...base,
}),
});
const detailData = await detailResponse.json();
if (detailData.ret === -1) {
alert(detailData.msg);
return;
}
} catch (error) {
console.error(error);
}
//关闭模态
setShowData([]);
setDefaultValues({});
setDefaultMedia({});
setDisplayVideoId([]);
setDisplayPosterId([]);
setDisplayGalleryId([]);
setIsModalOpen(false);
};
//表单提交失败
const onModalFormFinishFailed = (errorInfo) => {
console.log("Failed:", errorInfo);
};
//保存上传的封面id
const [displayVideoId, setDisplayVideoId] = useState([]);
const [displayPosterId, setDisplayPosterId] = useState([]);
const [displayGalleryId, setDisplayGalleryId] = useState([]);
//删除默认的媒体
const handleDeleteMedia = (type, id) => {
if (type === "displayPoster") {
setDefaultMedia({
...defaultMedia,
displayPoster: [],
});
return;
}
if (type === "displayVideo") {
setDefaultMedia({
...defaultMedia,
displayVideo: [],
});
return;
}
if (type === "displayGallery") {
setDefaultMedia({
...defaultMedia,
displayGallery: defaultMedia.displayGallery.filter(
(item) => item.id !== id
),
});
return;
}
};
return (
<div style={{ marginLeft: 20, marginRight: 20 }}>
<div style={{ marginTop: 20, marginBottom: 10 }}>
<p style={{ display: "inline" }}>数据可见性</p>
<Checkbox.Group
options={showColumnsOptions}
defaultValue={showColumns}
onChange={(value) => setShowColumns(value)}
/>
</div>
<Form name="search" onFinish={search} onFinishFailed={onFinishFailed}>
<Space style={{ marginBottom: 20 }}>
<Form.Item label="ID" name="id" style={{ margin: 0 }}>
<Input />
</Form.Item>
<Button type="primary" htmlType="submit">
搜索
</Button>
</Space>
</Form>
<Table
columns={dynamicColumns}
dataSource={showData}
pagination={{ pageSize: 20 }}
scroll={{ y: window.innerHeight - 300 }}
/>
{/* 模态框是否显示 */}
{isModalOpen && (
<Form
name="change"
onFinish={onModalFormFinish}
onFinishFailed={onModalFormFinishFailed}
autoComplete="off"
>
<Modal
title="修改资料"
cancel={handleCancel}
content={
<div
className="flex flex-col overflow-y-scroll"
style={{ height: (window.innerHeight * 2) / 3 }}
>
<div className="flex flex-row">
<Image
width={80}
height={80}
className="rounded-full"
src={defaultValues.baseInfo.avatar}
/>
<div className="flex flex-col justify-between ml-2">
<p className="font-bold">ID{defaultValues.baseInfo.id}</p>
<p className="font-bold">
昵称{defaultValues.baseInfo.name}
</p>
<p className="font-bold">
入驻时间{defaultValues.baseInfo.joinTime}
</p>
</div>
</div>
<div
className="flex flex-row flex-wrap"
style={{ width: (window.innerWidth * 2) / 3 }}
>
<Form.Item
className="basis-1/2 px-2"
name="fans"
label="全网粉丝(万)"
initialValue={defaultValues.displayInfo.fans}
rules={[
{
required: true,
message: "请输入全网粉丝数量",
},
]}
>
<InputNumber min={0} />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="gender"
label="性别"
initialValue={defaultValues.displayInfo.gender}
rules={[
{
required: true,
message: "填写性别",
},
]}
>
<select
style={{
height: 32,
padding: "4px 11px",
border: "1px solid #d9d9d9",
borderRadius: 4,
outline: "none",
}}
>
<option value={1}></option>
<option value={0}></option>
</select>
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="wechat_lock_type"
label="微信添加方式"
initialValue={defaultValues.displayInfo.wechat_lock_type}
rules={[
{
required: true,
message: "填写添加微信方式",
},
]}
>
<select
style={{
height: 32,
padding: "4px 11px",
border: "1px solid #d9d9d9",
borderRadius: 4,
outline: "none",
}}
>
<option value={1}>主动添加</option>
<option value={0}>直接展示</option>
</select>
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="wechat"
label="微信号"
initialValue={defaultValues.displayInfo.wechat}
>
<Input />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="wechat_price"
label="微信价格"
rules={[
{
required: true,
message: "请输入微信价格",
},
]}
initialValue={defaultValues.displayInfo.wechat_price / 10}
>
<Input />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="signature"
label="个性签名"
initialValue={defaultValues.displayInfo.signature}
rules={[
{
required: true,
message: "请输入个性签名",
},
]}
>
<Input />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="auto_response_message"
label="私信自动回复"
initialValue={
defaultValues.displayInfo.auto_response_message
}
rules={[
{
required: true,
message: "请输入私信自动回复",
},
]}
>
<Input />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="age"
label="年龄"
initialValue={defaultValues.displayInfo.age}
rules={[
{
required: true,
message: "请填写年龄",
},
]}
>
<InputNumber min={18} max={60} />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="height"
label="身高cm"
initialValue={defaultValues.displayInfo.height}
rules={[
{
required: true,
message: "请填写身高",
},
]}
>
<InputNumber min={140} max={200} />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="weight"
label="体重kg"
initialValue={defaultValues.displayInfo.weight}
rules={[
{
required: true,
message: "请填写体重",
},
]}
>
<InputNumber min={35} max={100} />
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="constellation"
label="星座"
initialValue={defaultValues.displayInfo.constellation}
rules={[
{
required: true,
message: "请填写星座",
},
]}
>
<select
style={{
height: 32,
padding: "4px 11px",
border: "1px solid #d9d9d9",
borderRadius: 4,
outline: "none",
}}
>
{constellations.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
</Form.Item>
<Form.Item
className="basis-1/2 px-2"
name="location"
label="居住地"
initialValue={defaultValues.displayInfo.location}
rules={[
{
required: true,
message: "请填写居住地",
},
]}
>
<select
style={{
height: 32,
padding: "4px 11px",
border: "1px solid #d9d9d9",
borderRadius: 4,
outline: "none",
}}
>
{provinces.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</select>
</Form.Item>
</div>
<div>
<div className="flex flexp-row flex-wrap gap-2 mb-2">
<p>
<span className="text-red-400 text-base">*</span>
封面图片
</p>
{defaultMedia.displayPoster.length !== 0 && (
<div className="relative">
<Image
src={defaultMedia.displayPoster[0].urls[0]}
width={100}
/>
<Button
className="absolute top-0 left-0 w-full"
danger
type="primary"
onClick={() => handleDeleteMedia("displayPoster")}
>
删除
</Button>
</div>
)}
<ImageUploader setIds={setDisplayPosterId} />
</div>
<div className="flex flexp-row flex-wrap gap-2 mb-2">
<p>
<span className="text-red-400 text-base">*</span>
封面视频
</p>
{defaultMedia.displayVideo.length !== 0 && (
<div className="relative">
<video
src={defaultMedia.displayVideo[0].urls[0]}
width={150}
controls
/>
<Button
className="absolute top-0 left-0 w-full"
danger
type="primary"
onClick={() => handleDeleteMedia("displayVideo")}
>
删除
</Button>
</div>
)}
<VideoUploader setIds={setDisplayVideoId} />
</div>
<div className="flex flexp-row flex-wrap gap-2">
<p>
<span className="text-red-400 text-base">*</span>
相册图片
</p>
{defaultMedia.displayGallery.length !== 0 && (
<div className="flex flex-row flex-wrap gap-2">
{defaultMedia.displayGallery.map((item) => (
<div key={item.urls[0]} className="relative">
<Image src={item.urls[0]} width={100} />
<Button
className="absolute top-0 left-0 w-full"
danger
type="primary"
onClick={() =>
handleDeleteMedia("displayGallery", item.id)
}
>
删除
</Button>
</div>
))}
</div>
)}
<ImageUploader setIds={setDisplayGalleryId} />
</div>
</div>
</div>
}
/>
</Form>
)}
</div>
);
};
export default function StreamerInformation() {
return <StreamerInformationContent />;
}