新增新版入驻流程相关审核页面

This commit is contained in:
yezian 2024-07-09 23:13:45 +08:00
parent 91abe5a96c
commit b6719b2af2
4 changed files with 840 additions and 0 deletions

View File

@ -42,6 +42,8 @@ export default function Op() {
const items = [
getItem("审核专区", "review", <SafetyCertificateOutlined />, [
getItem("网红入驻审核", "streamerJoin"),
getItem("(新)网红入驻审核", "streamerJoinNew"),
getItem("(新)网红资料审核", "streamerInformationCompleteNew"),
getItem("网红实名认证审核", "streamerVerification"),
getItem("图片机审回查", "imageMachineReview"),
getItem("文本机审回查", "textMachineReview"),

View File

@ -0,0 +1,490 @@
import React, { useState, useRef, useEffect } from "react";
import { Form, Input, Button, Space, Table, Menu, Image } from "antd";
import {
Routes,
Route,
Navigate,
useNavigate,
useLocation,
} from "react-router-dom";
import baseRequest from "../../utils/baseRequest";
const JoinContent = (props) => {
const { TextArea } = Input;
const current = props.current;
//
const columns = [
{
title: "基本信息",
dataIndex: "baseInfo",
key: "baseInfo",
render: (data) => (
<div>
{/* <Image
src={data.avatar}
width={50}
height={50}
className="rounded-full"
/> */}
<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.submitTime}</span>
</p>
</div>
),
},
{
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.bio}</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>
),
},
{
title: "封面图片",
dataIndex: "displayPoster",
key: "displayPoster",
render: (data) => <Image src={data[0].urls[0]} width={100} />,
},
{
title: "封面视频",
dataIndex: "displayVideo",
key: "displayVideo",
render: (data) => <video src={data[0].urls[0]} width={150} controls />,
},
{
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>
),
},
{
title: "机审结果",
dataIndex: "audit",
key: "audit",
render: (data) => (
<div>
<p>
个性签名审核
<span
className={
data.bioAudit?.audit_status === 2
? "text-green-400"
: "text-red-400"
}
>
{data.bioAudit?.audit_opinion
? data.bioAudit?.audit_opinion
: "机审中"}
</span>
</p>
<hr />
<p>
私信自动回复审核
<span
className={
data.autoResponseMessageAudit?.audit_status === 2
? "text-green-400"
: "text-red-400"
}
>
{data.autoResponseMessageAudit?.audit_opinion
? data.autoResponseMessageAudit?.audit_opinion
: "机审中"}
</span>
</p>
<hr />
<p>
封面图片审核
<span
className={
data.coverAudit?.audit_status === 2
? "text-green-400"
: "text-red-400"
}
>
{data.coverAudit?.audit_opinion
? data.coverAudit?.audit_opinion
: "机审中"}
</span>
</p>
<hr />
<p>
相册审核
<span
className={
data.albumAudit?.audit_status === 2
? "text-green-400"
: "text-red-400"
}
>
{data.albumAudit?.audit_opinion
? data.albumAudit?.audit_opinion
: "机审中"}
</span>
</p>
<hr />
<p>
封面视频审核
<span
className={
data.shortsAudit?.audit_status === 2
? "text-green-400"
: "text-red-400"
}
>
{data.shortsAudit?.audit_opinion
? data.shortsAudit?.audit_opinion
: "机审中"}
</span>
</p>
</div>
),
},
{
title: "备注",
dataIndex: "remark",
key: "remark",
render: (_, record) => (
<Form.Item name={record.id} initialValue={record.remark}>
<TextArea rows={4} />
</Form.Item>
),
},
{
title: "操作",
dataIndex: "opeartion",
key: "opeartion",
render: (_, record) => (
<div>
<Space>
<Space.Compact direction="vertical">
{current === "pending" && (
<Button type="primary" onClick={() => onClickSubmit(record)}>
{current === "pending" && "通过"}
</Button>
)}
{current !== "notQualified" && current !== "settled" && (
<Button onClick={() => onClickNotQualified(record)}>
未符合
</Button>
)}
</Space.Compact>
</Space>
</div>
),
},
];
//ref
const formRef = useRef(null);
//
const onClickSubmit = (record) => {
formRef.current.id = record.id;
formRef.current.btn = "submit";
formRef.current.submit();
};
//
const onClickNotQualified = (record) => {
formRef.current.id = record.id;
formRef.current.btn = "notQualified";
formRef.current.submit();
};
//
const handleSubmit = async (value) => {
//
let approve_status;
if (formRef.current.btn === "notQualified") {
approve_status = 2;
} else {
switch (current) {
case "pending":
approve_status = 3;
break;
default:
break;
}
}
const submitData = {
ids: [formRef.current.id],
remarks: value[formRef.current.id] ? value[formRef.current.id] : "",
approve_status: approve_status,
};
//
try {
const base = baseRequest();
const response = await fetch(
"/op/streamer_auth_approval/approve_details",
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
...submitData,
...base,
}),
}
);
const approveData = await response.json();
if (approveData.ret === -1) {
alert(approveData.msg);
return;
}
} catch (error) {
console.error(error);
}
//
setShowData(showData.filter((item) => item.id !== submitData.ids[0]));
};
//
const [data, setData] = useState([]);
const [offset, setOffset] = useState(0);
const [more, setMore] = useState(1);
const getData = async () => {
if (!more) return;
let querryStatus;
switch (current) {
case "pending":
querryStatus = 0;
break;
case "settled":
querryStatus = 1;
break;
case "notQualified":
querryStatus = 2;
break;
default:
break;
}
try {
const base = baseRequest();
const response = await fetch("/op/streamer_auth_approval/list_details", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
approve_status: querryStatus,
offset: offset,
limit: 200,
...base,
}),
});
const temData = await response.json();
console.log(temData);
if (temData.ret === -1) {
alert(temData.msg);
return;
}
const structedData = temData.data.list.map((item, index) => {
return {
key: index,
id: item.id,
baseInfo: {
id: item.account.user_id,
name: item.account.name,
avatar: item.account.avatar.images[0].urls[0],
submitTime: new Date(item.ct * 1000).toLocaleString(),
},
displayInfo: {
gender: item.gender,
fans: item.fans,
wechat_lock_type: item.wechat_lock_type,
wechat: item.wechat_contact,
wechat_price: item.wechat_coin_price,
bio: item.bio,
age: item.age,
height: item.height,
weight: item.weight,
constellation: item.constellation,
location: item.city,
auto_response_message: item.auto_response_message,
},
displayPoster: item.cover.images,
displayVideo: item.shorts.videos,
displayGallery: item.album.images,
audit: {
bioAudit: item.BioAudit,
autoResponseMessageAudit: item.AutoResponseMessageAudit,
coverAudit: item.CoverAudit,
shortsAudit: item.ShortsAudit,
albumAudit: item.AlbumAudit,
},
remark: item.remarks,
};
});
setData([...data, ...structedData]);
setOffset(temData.data.offset);
setMore(temData.data.more);
} catch (error) {
console.error(error);
}
};
useEffect(() => {
getData();
}, [current]);
//
const [showData, setShowData] = useState([]);
useEffect(() => {
setShowData(data);
}, [data]);
//
const search = (value) => {
value.id
? setShowData(data.filter((item) => item.info.id == value.id))
: setShowData(data);
};
//
const onFinishFailed = (errorInfo) => {
console.log("Failed:", errorInfo);
};
return (
<div style={{ marginLeft: 20, marginRight: 20 }}>
<p>
{current === "pending" && `待处理${showData.length}`}
{current === "settled" && `已通过${showData.length}`}
{current === "notQualified" && `运营驳回${showData.length}`}
</p>
<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>
<Form
ref={formRef}
name="remark"
onFinish={handleSubmit}
onFinishFailed={onFinishFailed}
>
<Table
columns={columns}
dataSource={showData}
pagination={{ pageSize: 20 }}
scroll={{ y: window.innerHeight - 300 }}
/>
</Form>
</div>
);
};
export default function StreamerInformationCompleteNew() {
const navigate = useNavigate();
//tab
const location = useLocation();
const pathname = location.pathname.split("/")[2] || "pending";
const [current, setCurrent] = useState(pathname);
//tab
const items = [
{
label: "待处理",
key: "pending",
},
{
label: "已通过",
key: "settled",
},
{
label: "运营驳回",
key: "notQualified",
},
];
const onClick = (e) => {
setCurrent(e.key);
navigate(e.key);
window.location.reload();
};
return (
<div>
<Menu
onClick={onClick}
selectedKeys={[current]}
mode="horizontal"
items={items}
/>
<Routes>
<Route
path="/"
element={<Navigate to="/streamerInformationCompleteNew/pending" />}
/>
<Route path="/pending" element={<JoinContent current="pending" />} />
<Route path="/settled" element={<JoinContent current="settled" />} />
<Route
path="/notQualified"
element={<JoinContent current="notQualified" />}
/>
</Routes>
</div>
);
}

View File

@ -0,0 +1,338 @@
import React, { useState, useRef, useEffect } from "react";
import { Form, Input, Button, Space, Table, Menu, Image } from "antd";
import {
Routes,
Route,
Navigate,
useNavigate,
useLocation,
} from "react-router-dom";
import baseRequest from "../../utils/baseRequest";
const JoinContent = (props) => {
const { TextArea } = Input;
const current = props.current;
//
const columns = [
{
title: "基本信息",
dataIndex: "info",
key: "info",
render: (data) => (
<div>
<Image
src={data.avatar}
width={50}
height={50}
className="rounded-full"
/>
<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.platforms}</span>
</p>
<p>
联系方式<span className="text-red-400">{data.contact}</span>
</p>
</div>
),
},
{
title: "账号截图",
dataIndex: "mediaInfo",
key: "mediaInfo",
render: (mediaInfo) => (
<div>
{mediaInfo
? mediaInfo.map((item) => (
<Image
key={item.urls[0]}
src={item.urls[0]}
width={100}
style={{ marginBottom: 10 }}
/>
))
: "无"}
</div>
),
},
{
title: "提交时间",
dataIndex: "submitTime",
key: "submitTime",
},
{
title: "备注",
dataIndex: "remark",
key: "remark",
render: (_, record) => (
<Form.Item name={record.id} initialValue={record.remark}>
<TextArea rows={4} />
</Form.Item>
),
},
{
title: "操作",
dataIndex: "opeartion",
key: "opeartion",
render: (_, record) => (
<div>
<Space>
<Space.Compact direction="vertical">
{(current === "pending" || current === "inProgress") && (
<Button type="primary" onClick={() => onClickSubmit(record)}>
{current === "pending" && "跟进"}
{current === "inProgress" && "入驻"}
</Button>
)}
{current !== "notQualified" && current !== "settled" && (
<Button onClick={() => onClickNotQualified(record)}>
未符合
</Button>
)}
</Space.Compact>
</Space>
</div>
),
},
];
//ref
const formRef = useRef(null);
//
const onClickSubmit = (record) => {
formRef.current.id = record.id;
formRef.current.btn = "submit";
formRef.current.submit();
};
//
const onClickNotQualified = (record) => {
formRef.current.id = record.id;
formRef.current.btn = "notQualified";
formRef.current.submit();
};
//
const handleSubmit = async (value) => {
//
let approve_status;
if (formRef.current.btn === "notQualified") {
approve_status = 2;
} else {
switch (current) {
case "pending":
approve_status = 3;
break;
case "inProgress":
approve_status = 1;
break;
default:
break;
}
}
const submitData = {
ids: [formRef.current.id],
remarks: value[formRef.current.id] ? value[formRef.current.id] : "",
approve_status: approve_status,
};
//
try {
const base = baseRequest();
const response = await fetch("/op/streamer_auth_approval/approve_basic", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
...submitData,
...base,
}),
});
const approveData = await response.json();
if (approveData.ret === -1) {
alert(approveData.msg);
return;
}
} catch (error) {
console.error(error);
}
//
setShowData(showData.filter((item) => item.id !== submitData.ids[0]));
};
//
const [data, setData] = useState([]);
const [offset, setOffset] = useState(0);
const [more, setMore] = useState(1);
const getData = async () => {
if (!more) return;
let querryStatus;
switch (current) {
case "pending":
querryStatus = 0;
break;
case "inProgress":
querryStatus = 3;
break;
case "settled":
querryStatus = 1;
break;
case "notQualified":
querryStatus = 2;
break;
default:
break;
}
try {
const base = baseRequest();
const response = await fetch("/op/streamer_auth_approval/list_basic", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
approve_status: querryStatus,
offset: offset,
limit: 200,
...base,
}),
});
const temData = await response.json();
if (temData.ret === -1) {
alert(temData.msg);
return;
}
const structedData = temData.data.list.map((item, index) => {
return {
key: index,
id: item.id,
info: {
id: item.user_id,
name: item.name,
avatar: item.avatar?.images[0].urls[0],
platforms: item.main_platform,
contact: item.contact_way,
inviter: item.inviters,
},
mediaInfo: item.account_shot.images,
submitTime: new Date(item.ut * 1000).toLocaleString(),
remark: item.remarks,
};
});
setData([...data, ...structedData]);
setOffset(temData.data.offset);
setMore(temData.data.more);
} catch (error) {
console.error(error);
}
};
useEffect(() => {
getData();
}, [current]);
//
const [showData, setShowData] = useState([]);
useEffect(() => {
setShowData(data);
}, [data]);
//
const search = (value) => {
value.id
? setShowData(data.filter((item) => item.info.id == value.id))
: setShowData(data);
};
//
const onFinishFailed = (errorInfo) => {
console.log("Failed:", errorInfo);
};
return (
<div style={{ marginLeft: 20, marginRight: 20 }}>
<p>
{current === "pending" && `待处理${showData.length}`}
{current === "inProgress" && `跟进中${showData.length}`}
{current === "settled" && `已入驻${showData.length}`}
{current === "notQualified" && `未符合要求${showData.length}`}
</p>
<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>
<Form
ref={formRef}
name="remark"
onFinish={handleSubmit}
onFinishFailed={onFinishFailed}
>
<Table
columns={columns}
dataSource={showData}
pagination={{ pageSize: 20 }}
scroll={{ y: window.innerHeight - 300 }}
/>
</Form>
</div>
);
};
export default function StreamerJoinNew() {
const navigate = useNavigate();
//tab
const location = useLocation();
const pathname = location.pathname.split("/")[2] || "pending";
const [current, setCurrent] = useState(pathname);
//tab
const items = [
{
label: "待处理",
key: "pending",
},
{
label: "跟进中",
key: "inProgress",
},
{
label: "已入驻",
key: "settled",
},
{
label: "未符合要求",
key: "notQualified",
},
];
const onClick = (e) => {
setCurrent(e.key);
navigate(e.key);
window.location.reload();
};
return (
<div>
<Menu
onClick={onClick}
selectedKeys={[current]}
mode="horizontal"
items={items}
/>
<Routes>
<Route path="/" element={<Navigate to="/streamerJoinNew/pending" />} />
<Route path="/pending" element={<JoinContent current="pending" />} />
<Route
path="/inProgress"
element={<JoinContent current="inProgress" />}
/>
<Route path="/settled" element={<JoinContent current="settled" />} />
<Route
path="/notQualified"
element={<JoinContent current="notQualified" />}
/>
</Routes>
</div>
);
}

View File

@ -4,6 +4,8 @@ import Op from "../pages/Op";
import Feed from "../pages/Feed";
import StreamerInformation from "../pages/StreamerInformation";
import StreamerJoin from "../pages/StreamerJoin";
import StreamerJoinNew from "../pages/StreamerJoinNew";
import StreamerInformationCompleteNew from "../pages/StreamerInformationCompleteNew";
import Feedback from "../pages/Feedback";
import Contact from "../pages/Contact";
import UploadMedia from "../pages/UploadMedia";
@ -53,6 +55,14 @@ const routes = [
path: "streamerJoin/*",
element: <StreamerJoin />,
},
{
path: "streamerJoinNew/*",
element: <StreamerJoinNew />,
},
{
path: "streamerInformationCompleteNew/*",
element: <StreamerInformationCompleteNew />,
},
{
path: "streamerVerification/*",
element: <StreamerVerification />,