更改广场动态审核功能
This commit is contained in:
parent
a02e57e404
commit
647bbe9ff3
|
@ -1,7 +1,7 @@
|
|||
import React, { useState } from "react";
|
||||
import { uploadImage } from "../../utils/upload";
|
||||
|
||||
const ImageUploader = ({ setIds }) => {
|
||||
const ImageUploader = ({ setIds, uploadOne }) => {
|
||||
const [selectedImages, setSelectedImages] = useState([]);
|
||||
const [uploading, setUploading] = useState(false);
|
||||
|
||||
|
@ -86,40 +86,42 @@ const ImageUploader = ({ setIds }) => {
|
|||
)}
|
||||
</div>
|
||||
))}
|
||||
<label
|
||||
htmlFor="fileInput"
|
||||
style={{
|
||||
width: "100px",
|
||||
height: "100px",
|
||||
margin: "5px",
|
||||
background: "#9ca3af",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
>
|
||||
<span className="text-white">
|
||||
{uploading ? "正在上传..." : "添加图片"}
|
||||
</span>
|
||||
<input
|
||||
id="fileInput"
|
||||
type="file"
|
||||
multiple
|
||||
onChange={handleFileChange}
|
||||
{uploadOne && selectedImages.length ? null : (
|
||||
<label
|
||||
htmlFor="fileInput"
|
||||
style={{
|
||||
opacity: 0,
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
width: "100px",
|
||||
height: "100px",
|
||||
margin: "5px",
|
||||
background: "#9ca3af",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
cursor: "pointer",
|
||||
position: "relative",
|
||||
borderRadius: "8px",
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
>
|
||||
<span className="text-white">
|
||||
{uploading ? "正在上传..." : "添加图片"}
|
||||
</span>
|
||||
<input
|
||||
id="fileInput"
|
||||
type="file"
|
||||
multiple
|
||||
onChange={handleFileChange}
|
||||
style={{
|
||||
opacity: 0,
|
||||
position: "absolute",
|
||||
top: 0,
|
||||
left: 0,
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
import React, { useState, useRef, useEffect, useMemo } from "react";
|
||||
import {
|
||||
List,
|
||||
Input,
|
||||
Button,
|
||||
message,
|
||||
// Spin,
|
||||
} from "antd";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
export default function PagesManage() {
|
||||
const [pages, setPages] = useState([
|
||||
{ title: "主播空间", name: "streamerSpace", params: "name=text" },
|
||||
{ title: "主播主页", name: "streamerProfile", params: "" },
|
||||
{ title: "充值页面", name: "payCenter", params: "" },
|
||||
{ title: "主播空间", name: "streamerSpace", params: "" },
|
||||
{ title: "主播空间", name: "streamerSpace", params: "" },
|
||||
{ title: "主播空间", name: "streamerSpace", params: "" },
|
||||
]);
|
||||
//创建页面路由
|
||||
const handleCreate = async ({ id, route_path, action, desc }) => {
|
||||
try {
|
||||
const base = baseRequest();
|
||||
const response = await fetch("/op/frontend_route/create", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
id,
|
||||
route_path,
|
||||
action,
|
||||
desc,
|
||||
...base,
|
||||
}),
|
||||
});
|
||||
const _data = await response.json();
|
||||
if (_data.ret === -1) {
|
||||
alert(_data.msg);
|
||||
return;
|
||||
}
|
||||
message.success("创建成功");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
return (
|
||||
<div className="my-4">
|
||||
<List split={false}>
|
||||
<div className="my-6 flex items-center justify-between">
|
||||
<div className="flex-1 grid grid-cols-[20%,20%,auto] gap-2">
|
||||
<Input placeholder="页面名称" />
|
||||
<Input placeholder="页面值" />
|
||||
<Input placeholder="页面参数" />
|
||||
</div>
|
||||
<Button type="primary" className="ml-2">
|
||||
新增+
|
||||
</Button>
|
||||
</div>
|
||||
{pages.map((it) => (
|
||||
<div className="mt-2 ">
|
||||
<List.Item style={{ padding: 0 }}>
|
||||
<div className="w-full">
|
||||
<div className="flex items-center justify-between rounded-t-lg px-4 py-2 bg-[#dcdcdc80]">
|
||||
<p className="flex items-center">
|
||||
<span className="text-base">{it.title}</span>
|
||||
<span className="mx-1">|</span>
|
||||
<span className="text-[gray]">{it.name}</span>
|
||||
</p>
|
||||
<div>
|
||||
<span className="px-2 py-1 rounded-lg cursor-pointer">
|
||||
编辑
|
||||
</span>
|
||||
<span className="px-2 py-1 rounded-lg text-[#ff000064] cursor-pointer">
|
||||
删除
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex rounded-b-lg px-4 py-0.5 bg-[#dcdcdc41] text-xs text-[#9d9d9d]">
|
||||
{it.params && (
|
||||
<div className="py-2">
|
||||
<span>参数:</span>
|
||||
<span>{`?${it.params}`}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</List.Item>
|
||||
</div>
|
||||
))}
|
||||
</List>
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
import React, { useEffect, useState } from "react";
|
||||
import { Spin, Image, ImageViewer } from "antd";
|
||||
import { uploadImage } from "../../utils/upload";
|
||||
// import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
// import { faAdd, faClose } from "@fortawesome/free-solid-svg-icons";
|
||||
import { FileAddFilled, CloseCircleFilled } from "@ant-design/icons";
|
||||
export default function UploadImgs({ assets, getImgs, multiple }) {
|
||||
const maxCount = 6;
|
||||
const [fileList, setFileList] = useState([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// useEffect(() => {
|
||||
// if (!assets) {
|
||||
// setFileList([]);
|
||||
// }
|
||||
// }, assets);
|
||||
const handleUploadImage = async (e) => {
|
||||
let file = e.target.files[0];
|
||||
if (!file) return;
|
||||
setLoading(true);
|
||||
if (file.type.indexOf("image/") != -1) {
|
||||
// const image = await uploadImage(file);
|
||||
// getImgs((old) => [...old, image.id]);
|
||||
const newFiles = [file];
|
||||
const newAssets = newFiles.map((item) => ({
|
||||
type: "img",
|
||||
src: URL.createObjectURL(item),
|
||||
}));
|
||||
const uploadPromise = uploadImage(file);
|
||||
const uploadResult = await Promise.race([
|
||||
uploadPromise,
|
||||
new Promise((_, reject) =>
|
||||
setTimeout(() => reject(new Error("Upload timeout")), 30000)
|
||||
),
|
||||
]);
|
||||
console.log("uploadResult", uploadResult);
|
||||
setFileList(newAssets);
|
||||
getImgs(uploadResult);
|
||||
} else if (file.type.indexOf("video/") != -1) {
|
||||
if (typeof window == "undefined") return;
|
||||
const videoD = document.getElementById("videoD");
|
||||
const videoC = document.getElementById("videoC");
|
||||
// console.log("videoC", videoC);
|
||||
const ctx = videoC?.getContext("2d");
|
||||
// 设置Canvas的宽度和高度与视频一致
|
||||
videoC.width = videoD.videoWidth;
|
||||
videoC.height = videoD.videoHeight;
|
||||
// 在Canvas上绘制当前视频帧
|
||||
ctx.drawImage(videoD, 0, 0, videoC.width, videoC.height);
|
||||
// 将Canvas转换为图片URL
|
||||
const frameImageUrl = videoC.toDataURL();
|
||||
|
||||
// 输出图片URL
|
||||
// console.log(frameImageUrl);
|
||||
// console.log("ddddd", file, {
|
||||
// type: "video",
|
||||
// src: frameImageUrl,
|
||||
// });
|
||||
// const video = await uploadVideo(file);
|
||||
// getImgs((old) => [...old, video.id]);
|
||||
// setFileList((old) => [...old, video]);
|
||||
const newFiles = [...assets, file];
|
||||
const newAssets = newFiles.map((item) => ({
|
||||
type: "video",
|
||||
src: URL.createObjectURL(item),
|
||||
}));
|
||||
setFileList(newAssets);
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
};
|
||||
const handleRemoveItem = (index) => {
|
||||
// console.log(index);
|
||||
let newArr = [...fileList];
|
||||
newArr.splice(index, 1);
|
||||
setFileList(newArr);
|
||||
getImgs(newArr);
|
||||
};
|
||||
return (
|
||||
<div>
|
||||
<div className="grid grid-cols-4 gap-1 h-28">
|
||||
{fileList.map((item, index) => {
|
||||
return (
|
||||
<div key={index} className="rounded relative">
|
||||
<Image
|
||||
src={item?.src}
|
||||
width="100%"
|
||||
height="100%"
|
||||
className="rounded"
|
||||
/>
|
||||
<div
|
||||
className="h-4 w-4 bg-[#33333380] absolute top-0 right-0 flex justify-center items-center"
|
||||
onClick={() => handleRemoveItem(index)}
|
||||
>
|
||||
<CloseCircleFilled />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
{loading && (
|
||||
<div className="rounded border-[#00000040] text-[#00000040] flex flex-col justify-center items-center">
|
||||
<Spin />
|
||||
<p>上传中</p>
|
||||
</div>
|
||||
)}
|
||||
{(multiple || (!multiple && !fileList.length)) && !loading && (
|
||||
<label htmlFor="uploadAvatarBtn">
|
||||
<div
|
||||
className="border-2 border-[#00000040] text-[#00000040] rounded border-dashed w-full h-full flex justify-center items-center"
|
||||
// style={{ minHeight: "calc(25vw - 0.75rem)" }}
|
||||
>
|
||||
<FileAddFilled />
|
||||
</div>
|
||||
</label>
|
||||
)}
|
||||
<input
|
||||
type="file"
|
||||
id="uploadAvatarBtn"
|
||||
multiple={multiple}
|
||||
style={{ display: "none" }}
|
||||
// accept="image/png, image/jpeg, video/*"
|
||||
accept="image/png, image/jpeg, image/jpg"
|
||||
// capture="camera"
|
||||
onChange={handleUploadImage}
|
||||
/>
|
||||
</div>
|
||||
<div className="hidden">
|
||||
<video id="videoD">
|
||||
<source src={fileList[0]?.src} />
|
||||
您的浏览器不支持 Video 标签。
|
||||
</video>
|
||||
<canvas id="videoC" />
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// export async function mockUpload(file) {
|
||||
// await sleep(3000)
|
||||
// return {
|
||||
// url: URL.createObjectURL(file),
|
||||
// }
|
||||
// }
|
|
@ -1,11 +1,18 @@
|
|||
import React, { useState } from "react";
|
||||
import { Select } from "antd";
|
||||
import ReactPlayer from "react-player";
|
||||
export default function VideoPlayer({url,key,style}) {
|
||||
export default function VideoPlayer({ url, key, style }) {
|
||||
const [rate, setRate] = useState(1);
|
||||
return (
|
||||
<div key={key} >
|
||||
<ReactPlayer playbackRate={rate} url={url} width={150} controls style={style}/>
|
||||
<div key={key}>
|
||||
<ReactPlayer
|
||||
playbackRate={rate}
|
||||
url={url}
|
||||
width="100%"
|
||||
height="auto"
|
||||
controls
|
||||
style={style}
|
||||
/>
|
||||
<Select onChange={(e) => setRate(e)} value={rate}>
|
||||
<Select.Option value={1}>x1</Select.Option>
|
||||
<Select.Option value={2}>x2</Select.Option>
|
||||
|
|
|
@ -0,0 +1,752 @@
|
|||
import React, { useState, useRef, useEffect, useMemo } from "react";
|
||||
import {
|
||||
Form,
|
||||
Input,
|
||||
Button,
|
||||
Space,
|
||||
Table,
|
||||
Modal,
|
||||
Image,
|
||||
Select,
|
||||
message,
|
||||
// Upload,
|
||||
DatePicker,
|
||||
Radio,
|
||||
Tag,
|
||||
// Spin,
|
||||
} from "antd";
|
||||
import { LoadingOutlined, PlusOutlined, LayoutFilled } from "@ant-design/icons";
|
||||
import zh from "antd/es/date-picker/locale/zh_CN";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import UploadImgs from "../../components/UploadImgs";
|
||||
import { formatDeadline } from "../../utils/tools";
|
||||
import PagesManage from "../../components/PagesManage";
|
||||
const NoticesContent = (props) => {
|
||||
//控制创建动态modal是否出现
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [isPagesModalOpen, setIsPagesModalOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
// const [assets, setAssets] = useState([]);
|
||||
const [isSubmitting, setIsSubmitting] = useState(false);
|
||||
//提交创建动态
|
||||
const [form] = Form.useForm();
|
||||
|
||||
const { TextArea } = Input;
|
||||
const current = props.current;
|
||||
|
||||
//表头
|
||||
const columns = [
|
||||
{
|
||||
title: "推送消息类型",
|
||||
dataIndex: "n_type",
|
||||
key: "n_type",
|
||||
filters: [
|
||||
{
|
||||
text: "系统通知",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
text: "付费通知",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
text: "活动通知",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
text: "审核通知",
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
filterMode: "tree",
|
||||
onFilter: (value, record) => record.status == value,
|
||||
render: (data) => {
|
||||
return (
|
||||
<div>
|
||||
{data == 0
|
||||
? "系统通知"
|
||||
: data == 1
|
||||
? "付费通知"
|
||||
: data == 2
|
||||
? "活动通知"
|
||||
: "审核通知"}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "推送消息正文",
|
||||
dataIndex: "message",
|
||||
key: "message",
|
||||
},
|
||||
{
|
||||
title: "推送消息主图",
|
||||
dataIndex: "thumbnail",
|
||||
key: "thumbnail",
|
||||
render: (data) => (
|
||||
<div>
|
||||
{data
|
||||
? data.images?.map((item, index) => (
|
||||
<Image
|
||||
key={index}
|
||||
src={item.urls[0]}
|
||||
style={{ marginBottom: 10 }}
|
||||
/>
|
||||
))
|
||||
: "-"}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "链接标语",
|
||||
dataIndex: "link_text",
|
||||
key: "link_text",
|
||||
render: (data) => <div>{data || "-"}</div>,
|
||||
},
|
||||
{
|
||||
title: "链接",
|
||||
dataIndex: "params",
|
||||
key: "params",
|
||||
render: (data) => <div>{data || "-"}</div>,
|
||||
},
|
||||
{
|
||||
title: "推送时间",
|
||||
dataIndex: "push_time",
|
||||
key: "push_time",
|
||||
render: (data) => {
|
||||
return <div>{formatDeadline(data)}</div>;
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "推送角色",
|
||||
dataIndex: "obj_mids",
|
||||
key: "obj_mids",
|
||||
render: (data) => (
|
||||
<div>
|
||||
{data?.length > 0 ? data.map((it) => <span>{it}</span>) : "-"}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "推送角色类型",
|
||||
dataIndex: "obj_type",
|
||||
key: "obj_type",
|
||||
render: (data) => {
|
||||
return (
|
||||
<div>
|
||||
{data == 0
|
||||
? "所有主播"
|
||||
: data == 1
|
||||
? "所有个人"
|
||||
: data == 2
|
||||
? "所有主播和个人"
|
||||
: "自定义角色"}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: "推送状态",
|
||||
dataIndex: "status",
|
||||
key: "status",
|
||||
filters: [
|
||||
{
|
||||
text: "待推送",
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
text: "已推送",
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
text: "推送失败",
|
||||
value: 2,
|
||||
},
|
||||
{
|
||||
text: "已撤销",
|
||||
value: 3,
|
||||
},
|
||||
],
|
||||
filterMode: "tree",
|
||||
onFilter: (value, record) => record.status == value,
|
||||
render: (data) => (
|
||||
<div>
|
||||
{data == 0 ? (
|
||||
<Tag color="green">待推送</Tag>
|
||||
) : data == 1 ? (
|
||||
<Tag color="blue">已推送</Tag>
|
||||
) : data == 2 ? (
|
||||
<Tag color="red">推送失败</Tag>
|
||||
) : (
|
||||
<Tag color="orange">已撤销</Tag>
|
||||
)}
|
||||
</div>
|
||||
),
|
||||
},
|
||||
{
|
||||
title: "操作",
|
||||
dataIndex: "opeartion",
|
||||
key: "opeartion",
|
||||
render: (_, record) => {
|
||||
console.log("eeeeee", record);
|
||||
return (
|
||||
<div>
|
||||
<Space>
|
||||
<Space.Compact direction="vertical">
|
||||
{record.status == 0 && (
|
||||
<Button
|
||||
style={{ background: "#ff4d4f", color: "#fff" }}
|
||||
onClick={() => handleCancleNotice(record?.id)}
|
||||
>
|
||||
撤销通知
|
||||
</Button>
|
||||
)}
|
||||
</Space.Compact>
|
||||
</Space>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
//给表单绑定ref
|
||||
const formRef = useRef(null);
|
||||
//点击修改状态按钮
|
||||
const onClickSubmit = (record) => {
|
||||
formRef.current.key = record.key;
|
||||
formRef.current.btn = "submit";
|
||||
formRef.current.submit();
|
||||
};
|
||||
//点击无效按钮
|
||||
const onClickInvalid = (record) => {
|
||||
formRef.current.key = record.key;
|
||||
formRef.current.btn = "invalid";
|
||||
formRef.current.submit();
|
||||
};
|
||||
//点击迭代相关按钮
|
||||
const onClickIteration = (record) => {
|
||||
formRef.current.key = record.key;
|
||||
formRef.current.btn = "iteration";
|
||||
formRef.current.submit();
|
||||
};
|
||||
//通知撤销
|
||||
const handleCancleNotice = async (nid) => {
|
||||
try {
|
||||
const base = baseRequest();
|
||||
const response = await fetch("/op/notification/cancel", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nid,
|
||||
...base,
|
||||
}),
|
||||
});
|
||||
const temData = await response.json();
|
||||
if (temData.ret === -1) {
|
||||
alert(temData.msg);
|
||||
return;
|
||||
}
|
||||
message.success("撤销成功");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
const buddhistLocale = {
|
||||
...zh,
|
||||
lang: {
|
||||
...zh.lang,
|
||||
fieldDateFormat: "YYYY-MM-DD",
|
||||
fieldDateTimeFormat: "YYYY-MM-DD HH:mm:ss",
|
||||
yearFormat: "YYYY",
|
||||
cellYearFormat: "YYYY",
|
||||
},
|
||||
};
|
||||
//获取数据
|
||||
const [data, setData] = useState([]);
|
||||
const [offset, setOffset] = useState(0);
|
||||
const [more, setMore] = useState(1);
|
||||
const [formData, setFormData] = useState({
|
||||
message: "",
|
||||
n_type: 0,
|
||||
obj_mids: [],
|
||||
// push_time: 1111111111111,
|
||||
params: null,
|
||||
pageName: null,
|
||||
link: null,
|
||||
action: null,
|
||||
link_text: null,
|
||||
thumbnail: null,
|
||||
obj_type: "0",
|
||||
});
|
||||
const getData = async () => {
|
||||
if (!more) return;
|
||||
let querryStatus;
|
||||
switch (current) {
|
||||
case "pushing":
|
||||
querryStatus = 0;
|
||||
break;
|
||||
case "pushed":
|
||||
querryStatus = 1;
|
||||
break;
|
||||
case "fail":
|
||||
querryStatus = 2;
|
||||
break;
|
||||
case "backed":
|
||||
querryStatus = 3;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
try {
|
||||
const base = baseRequest();
|
||||
const response = await fetch("/op/notification/list", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
n_type: 0,
|
||||
// push_time: 0,
|
||||
// status: querryStatus,
|
||||
// offset: offset,
|
||||
// limit: 200,
|
||||
...base,
|
||||
}),
|
||||
});
|
||||
const temData = await response.json();
|
||||
console.log("response", temData);
|
||||
|
||||
if (temData.ret === -1) {
|
||||
alert(temData.msg);
|
||||
return;
|
||||
}
|
||||
setShowData([...temData.data.list]);
|
||||
setOffset(temData.data.offset);
|
||||
setMore(temData.data.more);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
};
|
||||
useEffect(() => {
|
||||
getData();
|
||||
}, [current]);
|
||||
|
||||
//展示的数据
|
||||
const [showData, setShowData] = useState(data);
|
||||
|
||||
//表单提交失败
|
||||
const onFinishFailed = (errorInfo) => {
|
||||
console.log("Failed:", errorInfo);
|
||||
};
|
||||
//关闭弹窗
|
||||
const handleCancelModal = () => {
|
||||
form.resetFields();
|
||||
setIsModalOpen(false);
|
||||
};
|
||||
const handleSubmit = async (value) => {
|
||||
// if (!selectedUser) {
|
||||
// alert("还未选中用户");
|
||||
// return;
|
||||
// }
|
||||
const newValue = { ...value };
|
||||
newValue["thumbnail"] = formData.thumbnail;
|
||||
newValue["obj_mids"] = newValue.obj_mids
|
||||
?.split(" ")
|
||||
.map((it) => Number(it));
|
||||
newValue["push_time"] = Math.ceil(
|
||||
new Date(newValue.push_time).getTime() / 1000
|
||||
);
|
||||
newValue["obj_type"] = parseInt(newValue.obj_type, 10);
|
||||
console.log("newValue", newValue);
|
||||
|
||||
debugger;
|
||||
try {
|
||||
const base = baseRequest();
|
||||
const response = await fetch(`/op/notification/create`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
sub_mid: 0,
|
||||
...base,
|
||||
...newValue,
|
||||
}),
|
||||
});
|
||||
const data = await response.json();
|
||||
if (data.ret === -1) {
|
||||
alert(data.msg);
|
||||
return;
|
||||
}
|
||||
message.success("发布成功");
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
}
|
||||
|
||||
form.resetFields();
|
||||
};
|
||||
const onTimeOk = (value) => {
|
||||
console.log("onOk: ", value);
|
||||
};
|
||||
const uploadButton = (
|
||||
<button
|
||||
style={{
|
||||
border: 0,
|
||||
background: "none",
|
||||
}}
|
||||
type="button"
|
||||
>
|
||||
{loading ? <LoadingOutlined /> : <PlusOutlined />}
|
||||
<div
|
||||
style={{
|
||||
marginTop: 8,
|
||||
}}
|
||||
>
|
||||
上传图片
|
||||
</div>
|
||||
</button>
|
||||
);
|
||||
return (
|
||||
<div style={{ marginLeft: 20, marginRight: 20 }}>
|
||||
<div className="flex justify-between items-center">
|
||||
<Button
|
||||
type="default"
|
||||
className="mt-4 mb-4 float-right"
|
||||
onClick={() => setIsPagesModalOpen(true)}
|
||||
icon={<LayoutFilled className="text-primary" />}
|
||||
>
|
||||
页面管理
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
className="mt-4 mb-4 float-right"
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
>
|
||||
新建推送+
|
||||
</Button>
|
||||
</div>
|
||||
<Table
|
||||
columns={columns}
|
||||
dataSource={showData}
|
||||
pagination={{ pageSize: 20 }}
|
||||
scroll={{ y: window.innerHeight - 300 }}
|
||||
/>
|
||||
{/* 重复判断isModalOpen是为了重新渲染ImageUploader和VideoUploader组件 */}
|
||||
<Modal
|
||||
title="新建消息推送通知"
|
||||
footer={null}
|
||||
open={isModalOpen}
|
||||
onCancel={handleCancelModal}
|
||||
>
|
||||
<Form
|
||||
className="mt-4 flex flex-col"
|
||||
form={form}
|
||||
onFinish={handleSubmit}
|
||||
layout="vertical"
|
||||
initialValues={formData}
|
||||
>
|
||||
<Form.Item
|
||||
label="添加活动消息正文(上限250字)"
|
||||
name="message"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请填写活动消息内容",
|
||||
},
|
||||
]}
|
||||
className="mb-6"
|
||||
>
|
||||
<TextArea maxLength={250} showCount />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="推送消息类型"
|
||||
name="n_type"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请选择推送消息类型",
|
||||
},
|
||||
]}
|
||||
className="mb-6"
|
||||
>
|
||||
<Select
|
||||
// defaultValue={1}
|
||||
style={{
|
||||
width: 120,
|
||||
}}
|
||||
// onChange={handleChange}
|
||||
options={[
|
||||
{
|
||||
value: 0,
|
||||
label: "系统通知",
|
||||
},
|
||||
{
|
||||
value: 1,
|
||||
label: "付费通知",
|
||||
},
|
||||
{
|
||||
value: 2,
|
||||
label: "活动通知",
|
||||
},
|
||||
{
|
||||
value: 3,
|
||||
label: "审核通知",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="推送角色"
|
||||
name="obj_type"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请填写推送角色",
|
||||
},
|
||||
]}
|
||||
className={formData.obj_type == 3 ? "mb-2" : "mb-6"}
|
||||
>
|
||||
<div>
|
||||
<Radio.Group
|
||||
defaultValue={0}
|
||||
onChange={(e) => {
|
||||
console.log(e.target.value);
|
||||
setFormData((old) => {
|
||||
return {
|
||||
...old,
|
||||
obj_type: e.target.value,
|
||||
};
|
||||
});
|
||||
}}
|
||||
>
|
||||
<Radio value={0}>所有主播</Radio>
|
||||
<Radio value={1}>所有个人</Radio>
|
||||
<Radio value={2}>所有主播和个人</Radio>
|
||||
<Radio value={3}>自定义角色</Radio>
|
||||
</Radio.Group>
|
||||
</div>
|
||||
</Form.Item>
|
||||
{formData.obj_type == 3 && (
|
||||
<Form.Item
|
||||
name="obj_mids"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请填写推送角色",
|
||||
},
|
||||
]}
|
||||
className="mb-6"
|
||||
>
|
||||
<div>
|
||||
<TextArea
|
||||
value={formData.obj_mids}
|
||||
onChange={(e) =>
|
||||
setFormData((old) => ({
|
||||
...old,
|
||||
obj_mids: e.target.value,
|
||||
}))
|
||||
}
|
||||
placeholder="用户ID以空格隔开"
|
||||
/>
|
||||
</div>
|
||||
</Form.Item>
|
||||
)}
|
||||
|
||||
<Form.Item
|
||||
label="推送时间"
|
||||
name="push_time"
|
||||
format="YYYY-MM-DD HH:mm"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请选择时间",
|
||||
},
|
||||
]}
|
||||
className="mb-6"
|
||||
>
|
||||
<DatePicker
|
||||
showTime
|
||||
// locale={{
|
||||
// lang: { locale: "zh_CN", placeholder: "选择日期时间" },
|
||||
// }}
|
||||
locale={buddhistLocale}
|
||||
onChange={(value, dateString) => {
|
||||
// console.log("Time: ", new Date());
|
||||
console.log("Selected Time: ", value);
|
||||
console.log("Formatted Selected Time: ", dateString);
|
||||
}}
|
||||
onOk={onTimeOk}
|
||||
/>
|
||||
</Form.Item>
|
||||
<p className="mb-2">添加跳转内容:</p>
|
||||
<Space
|
||||
direction="vertical"
|
||||
className="bg-[#00000011] rounded-md p-4 mb-4"
|
||||
>
|
||||
<Form.Item label="跳转形式" name="action" className="mb-2">
|
||||
<Select
|
||||
placeholder="选择跳转形式"
|
||||
style={{
|
||||
width: 120,
|
||||
}}
|
||||
// onChange={handleChange}
|
||||
options={[
|
||||
{
|
||||
value: "app",
|
||||
label: "APP内跳转",
|
||||
},
|
||||
{
|
||||
value: "h5",
|
||||
label: "内部H5跳转",
|
||||
},
|
||||
{
|
||||
value: "out",
|
||||
label: "外部浏览器跳转",
|
||||
},
|
||||
]}
|
||||
onChange={(value) => {
|
||||
setFormData((old) => ({
|
||||
...old,
|
||||
action: value,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
|
||||
{formData.action && (
|
||||
<div>
|
||||
<div>
|
||||
{formData.action == "out" ? (
|
||||
<Form.Item
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请填写具体链接地址",
|
||||
},
|
||||
]}
|
||||
label="添加链接"
|
||||
name="link"
|
||||
className="mb-2"
|
||||
>
|
||||
<Input
|
||||
onChange={(value) => {
|
||||
console.log("value", value);
|
||||
setFormData((old) => ({
|
||||
...old,
|
||||
link: value.target.value,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
) : (
|
||||
<Space direction="vertical" className="w-full">
|
||||
<label>
|
||||
<span className="text-[red] mr-1">*</span>添加链接
|
||||
</label>
|
||||
<div className="flex items-center">
|
||||
<Form.Item name="pageName" className="mb-2">
|
||||
<Select
|
||||
placeholder="选择页面"
|
||||
style={{
|
||||
width: 120,
|
||||
}}
|
||||
// onChange={handleChange}
|
||||
options={[
|
||||
{
|
||||
value: "app",
|
||||
label: "空间主页",
|
||||
},
|
||||
{
|
||||
value: "h5",
|
||||
label: "活动页",
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Form.Item>
|
||||
<div className="-mt-2 mx-2">?</div>
|
||||
<Form.Item
|
||||
layout="horizontal"
|
||||
name="params"
|
||||
className="mb-2 w-full flex-1"
|
||||
style={{ width: "100%" }}
|
||||
>
|
||||
<Input
|
||||
className="w-full"
|
||||
placeholder="填写连接参数"
|
||||
onChange={(value) => {
|
||||
console.log("value", value);
|
||||
setFormData((old) => ({
|
||||
...old,
|
||||
params: value.target.value,
|
||||
}));
|
||||
}}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
</Space>
|
||||
)}
|
||||
</div>
|
||||
<Form.Item
|
||||
label="添加链接标题"
|
||||
name="link_text"
|
||||
rules={[
|
||||
{
|
||||
required: true,
|
||||
message: "请填写链接标题",
|
||||
},
|
||||
]}
|
||||
className="mb-2"
|
||||
>
|
||||
<Input placeholder="链接标题" />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
label="添加主图"
|
||||
name="thumbnail"
|
||||
// rules={[
|
||||
// {
|
||||
// required: true,
|
||||
// message: "请上传主图",
|
||||
// },
|
||||
// ]}
|
||||
className="mb-2"
|
||||
>
|
||||
<UploadImgs
|
||||
assets={formData.thumbnail}
|
||||
getImgs={(value) => {
|
||||
setFormData((old) => ({
|
||||
...old,
|
||||
thumbnail: { image_ids: [value] },
|
||||
}));
|
||||
}}
|
||||
multiple={false}
|
||||
/>
|
||||
</Form.Item>
|
||||
</div>
|
||||
)}
|
||||
</Space>
|
||||
<Button type="primary" htmlType="submit">
|
||||
确认
|
||||
</Button>
|
||||
</Form>
|
||||
</Modal>
|
||||
<Modal
|
||||
title="页面管理"
|
||||
footer={null}
|
||||
open={isPagesModalOpen}
|
||||
style={{ minWidth: 800 }}
|
||||
onCancel={() => setIsPagesModalOpen(false)}
|
||||
>
|
||||
<PagesManage />
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default function Notices() {
|
||||
return (
|
||||
<div>
|
||||
<NoticesContent />
|
||||
</div>
|
||||
);
|
||||
}
|
|
@ -4,6 +4,7 @@ import {
|
|||
ShopOutlined,
|
||||
UsergroupAddOutlined,
|
||||
SoundOutlined,
|
||||
// NotificationOutlined,
|
||||
PhoneOutlined,
|
||||
SafetyCertificateOutlined,
|
||||
PoweroffOutlined,
|
||||
|
@ -50,7 +51,7 @@ export default function Op() {
|
|||
getItem("主播文本机审回查", "streamerTextMachineReview"),
|
||||
getItem("头像机审回查", "imageMachineReview"),
|
||||
getItem("昵称机审回查", "textMachineReview"),
|
||||
getItem("动态机审回查", "postMachineReview"),
|
||||
getItem("广场动态审核", "postMachineReview"),
|
||||
getItem("空间动态审核", "zonePostMachineReview"),
|
||||
getItem("已删除动态回捞", "deletedPostReview"),
|
||||
]),
|
||||
|
@ -81,6 +82,7 @@ export default function Op() {
|
|||
"manualRechargeAndWithdrawal",
|
||||
<MoneyCollectOutlined />
|
||||
),
|
||||
// getItem("消息通知推送", "notices", <NotificationOutlined />),
|
||||
getItem("意见反馈", "feedback", <SoundOutlined />),
|
||||
getItem("客服回复", "contact", <PhoneOutlined />),
|
||||
getItem("退出登录", "signOut", <PoweroffOutlined />),
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
useLocation,
|
||||
} from "react-router-dom";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import VideoPlayer from '../../components/VideoPlayer';
|
||||
import VideoPlayer from "../../components/VideoPlayer";
|
||||
const PostMachineReviewContent = (props) => {
|
||||
const { TextArea } = Input;
|
||||
const current = props.current;
|
||||
|
@ -31,7 +31,7 @@ const PostMachineReviewContent = (props) => {
|
|||
),
|
||||
},
|
||||
{
|
||||
title: "现内容",
|
||||
title: "动态内容",
|
||||
dataIndex: "newMedia",
|
||||
key: "newMedia",
|
||||
render: (data) => (
|
||||
|
@ -47,7 +47,7 @@ const PostMachineReviewContent = (props) => {
|
|||
<Image key={index} src={item.urls[0]} width={100} />
|
||||
))}
|
||||
{data.media?.videos?.map((item, index) => (
|
||||
<VideoPlayer key={index} url={item.urls[0]} width={150} />
|
||||
<VideoPlayer key={index} url={item.urls[0]} width={150} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -68,7 +68,7 @@ const PostMachineReviewContent = (props) => {
|
|||
<Image key={index} src={item.urls[0]} width={100} />
|
||||
))}
|
||||
{data.media?.videos?.map((item, index) => (
|
||||
<VideoPlayer key={index} url={item.urls[0]} width={150} />
|
||||
<VideoPlayer key={index} url={item.urls[0]} width={150} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -247,16 +247,10 @@ const PostMachineReviewContent = (props) => {
|
|||
render: (_, record) => (
|
||||
<div className="flex flex-col">
|
||||
<Form.Item
|
||||
name={record.id.text}
|
||||
initialValue={`文案:${record.remarks.text}`}
|
||||
name={record.momentId}
|
||||
initialValue={record.remarks.manually_review_opinion}
|
||||
>
|
||||
<TextArea disabled rows={4} />
|
||||
</Form.Item>
|
||||
<Form.Item
|
||||
name={record.id.media}
|
||||
initialValue={`媒体:${record.remarks.media}`}
|
||||
>
|
||||
<TextArea disabled rows={4} />
|
||||
<TextArea rows={4} disabled={current != "operatorReviewing"} />
|
||||
</Form.Item>
|
||||
</div>
|
||||
),
|
||||
|
@ -268,12 +262,14 @@ const PostMachineReviewContent = (props) => {
|
|||
render: (_, record) => (
|
||||
<div>
|
||||
<Space>
|
||||
<Space.Compact direction="vertical">
|
||||
<Button type="primary" onClick={() => onClickPass(record)}>
|
||||
通过
|
||||
</Button>
|
||||
<Button onClick={() => onClickReject(record)}>拒绝</Button>
|
||||
</Space.Compact>
|
||||
{current === "operatorReviewing" && (
|
||||
<Space.Compact direction="vertical">
|
||||
<Button type="primary" onClick={() => onClickPass(record)}>
|
||||
通过
|
||||
</Button>
|
||||
<Button onClick={() => onClickReject(record)}>拒绝</Button>
|
||||
</Space.Compact>
|
||||
)}
|
||||
</Space>
|
||||
</div>
|
||||
),
|
||||
|
@ -294,7 +290,14 @@ const PostMachineReviewContent = (props) => {
|
|||
formRef.current.submit();
|
||||
};
|
||||
//提交表单
|
||||
const handleSubmit = async () => {
|
||||
const handleSubmit = async (value) => {
|
||||
const cc = {
|
||||
moment_ids: [parseInt(formRef.current.record.momentId, 10)],
|
||||
op_type: formRef.current.type,
|
||||
manually_review_opinion: value[formRef.current.record.momentId]
|
||||
? value[formRef.current.record.momentId]
|
||||
: "",
|
||||
};
|
||||
try {
|
||||
//通过图片审核,如果是视频直接跳过
|
||||
const base = baseRequest();
|
||||
|
@ -306,6 +309,9 @@ const PostMachineReviewContent = (props) => {
|
|||
body: JSON.stringify({
|
||||
moment_ids: [parseInt(formRef.current.record.momentId, 10)],
|
||||
op_type: formRef.current.type,
|
||||
manually_review_opinion: value[formRef.current.record.momentId]
|
||||
? value[formRef.current.record.momentId]
|
||||
: "",
|
||||
...base,
|
||||
}),
|
||||
});
|
||||
|
@ -332,14 +338,14 @@ const PostMachineReviewContent = (props) => {
|
|||
if (!more) return;
|
||||
let querryStatus;
|
||||
switch (current) {
|
||||
case "rollbackbymachine":
|
||||
case "operatorReviewing":
|
||||
querryStatus = 4;
|
||||
break;
|
||||
case "machinereviewfail":
|
||||
querryStatus = 10;
|
||||
case "machineReviewing":
|
||||
querryStatus = 3;
|
||||
break;
|
||||
case "passbymachine":
|
||||
querryStatus = 2;
|
||||
case "onlySelfCanSee":
|
||||
querryStatus = 6;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -386,23 +392,31 @@ const PostMachineReviewContent = (props) => {
|
|||
media: item.moment_audit_task.audited_media,
|
||||
text: item.moment_audit_task.audited_text,
|
||||
},
|
||||
info: {
|
||||
mediaType:
|
||||
item.moment_audit_task.audited_media.videos.length === 0
|
||||
? "image"
|
||||
: "video",
|
||||
media:
|
||||
item.moment_audit_task.audited_media.videos.length === 0
|
||||
? item.image_audit_task_vo.image_audits
|
||||
: item.moment_audit_task.image_audit_opinion,
|
||||
text: item.text_audit_task_vo.text_audit,
|
||||
},
|
||||
info: item.moment_audit_task.audited_media
|
||||
? {
|
||||
mediaType:
|
||||
item.moment_audit_task.audited_media.videos.length === 0
|
||||
? "image"
|
||||
: "video",
|
||||
media:
|
||||
item.moment_audit_task.audited_media.videos.length === 0
|
||||
? item.image_audit_task_vo.image_audits
|
||||
: item.moment_audit_task.image_audit_opinion,
|
||||
text: item.text_audit_task_vo.text_audit,
|
||||
}
|
||||
: { text: item.text_audit_task_vo.text_audit },
|
||||
submitTime: new Date(
|
||||
item.moment_audit_task.ct * 1000
|
||||
).toLocaleString(),
|
||||
remarks: {
|
||||
media: item.image_audit_task_vo.remarks,
|
||||
text: item.text_audit_task_vo.remarks,
|
||||
// media: item.image_audit_task_vo.remarks,
|
||||
// text: item.moment_audit_task.remarks,
|
||||
manually_review_status:
|
||||
item.moment_audit_task?.manually_review_status,
|
||||
manually_review_opinion:
|
||||
item.moment_audit_task?.manually_review_opinion,
|
||||
manually_review_operator:
|
||||
item.moment_audit_task?.manually_review_operator,
|
||||
},
|
||||
others: {
|
||||
media: {
|
||||
|
@ -455,8 +469,8 @@ const PostMachineReviewContent = (props) => {
|
|||
return (
|
||||
<div style={{ marginLeft: 20, marginRight: 20 }}>
|
||||
<p>
|
||||
{current === "rollbackbymachine" && `机审核违规${showData.length}条`}
|
||||
{current === "passbymachine" && `机审核通过${showData.length}条`}
|
||||
{current === "operatorReviewing" && `运营待审核${showData.length}条`}
|
||||
{current === "onlySelfCanSee" && `审核未通过${showData.length}条`}
|
||||
</p>
|
||||
<Form
|
||||
ref={formRef}
|
||||
|
@ -479,21 +493,21 @@ export default function PostMachineReview() {
|
|||
const navigate = useNavigate();
|
||||
//当前tab
|
||||
const location = useLocation();
|
||||
const pathname = location.pathname.split("/")[2] || "rollbackbymachine";
|
||||
const pathname = location.pathname.split("/")[2] || "onlySelfCanSee";
|
||||
const [current, setCurrent] = useState(pathname);
|
||||
//tab名称
|
||||
const items = [
|
||||
{
|
||||
label: "机审回退",
|
||||
key: "rollbackbymachine",
|
||||
label: "运营待审核",
|
||||
key: "operatorReviewing",
|
||||
},
|
||||
{
|
||||
label: "机审失败",
|
||||
key: "machinereviewfail",
|
||||
label: "审核中",
|
||||
key: "machineReviewing",
|
||||
},
|
||||
{
|
||||
label: "机审通过",
|
||||
key: "passbymachine",
|
||||
label: "审核未通过",
|
||||
key: "onlySelfCanSee",
|
||||
},
|
||||
];
|
||||
const onClick = (e) => {
|
||||
|
@ -513,19 +527,19 @@ export default function PostMachineReview() {
|
|||
<Routes>
|
||||
<Route
|
||||
path="/"
|
||||
element={<Navigate to="/postMachineReview/rollbackbymachine" />}
|
||||
element={<Navigate to="/postMachineReview/operatorReviewing" />}
|
||||
/>
|
||||
<Route
|
||||
path="/rollbackbymachine"
|
||||
element={<PostMachineReviewContent current="rollbackbymachine" />}
|
||||
path="/operatorReviewing"
|
||||
element={<PostMachineReviewContent current="operatorReviewing" />}
|
||||
/>
|
||||
<Route
|
||||
path="/machinereviewfail"
|
||||
element={<PostMachineReviewContent current="machinereviewfail" />}
|
||||
path="/machineReviewing"
|
||||
element={<PostMachineReviewContent current="machineReviewing" />}
|
||||
/>
|
||||
<Route
|
||||
path="/passbymachine"
|
||||
element={<PostMachineReviewContent current="passbymachine" />}
|
||||
path="/onlySelfCanSee"
|
||||
element={<PostMachineReviewContent current="onlySelfCanSee" />}
|
||||
/>
|
||||
</Routes>
|
||||
</div>
|
||||
|
|
|
@ -13,7 +13,7 @@ import Modal from "../../components/Modal";
|
|||
import VideoUploader from "../../components/VideoUploader";
|
||||
import ImageUploader from "../../components/ImageUploader";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import VideoPlayer from '../../components/VideoPlayer';
|
||||
import VideoPlayer from "../../components/VideoPlayer";
|
||||
//tab内容
|
||||
const StreamerInformationContent = () => {
|
||||
const { TextArea } = Input;
|
||||
|
@ -119,9 +119,7 @@ const StreamerInformationContent = () => {
|
|||
title: "封面视频",
|
||||
dataIndex: "displayVideo",
|
||||
key: "displayVideo",
|
||||
render: (data) => (
|
||||
<VideoPlayer url={data[0].urls[0]} width={150} />
|
||||
),
|
||||
render: (data) => <VideoPlayer url={data[0].urls[0]} width={150} />,
|
||||
};
|
||||
case "displayGallery":
|
||||
return {
|
||||
|
@ -753,7 +751,10 @@ const StreamerInformationContent = () => {
|
|||
</p>
|
||||
{defaultMedia.displayVideo.length !== 0 && (
|
||||
<div className="relative">
|
||||
<VideoPlayer url={defaultMedia.displayVideo[0].urls[0]} width={150} />
|
||||
<VideoPlayer
|
||||
url={defaultMedia.displayVideo[0].urls[0]}
|
||||
width={150}
|
||||
/>
|
||||
<Button
|
||||
className="absolute top-0 left-0 w-full"
|
||||
danger
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
useLocation,
|
||||
} from "react-router-dom";
|
||||
import baseRequest from "../../utils/baseRequest";
|
||||
import VideoPlayer from '../../components/VideoPlayer';
|
||||
import VideoPlayer from "../../components/VideoPlayer";
|
||||
const StreamerVideoMachineReviewContent = (props) => {
|
||||
const { TextArea } = Input;
|
||||
const current = props.current;
|
||||
|
@ -45,10 +45,11 @@ const StreamerVideoMachineReviewContent = (props) => {
|
|||
title: "新内容",
|
||||
dataIndex: "newMedia",
|
||||
key: "newMedia",
|
||||
width: "18%",
|
||||
render: (data) => (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{data?.map((item, index) => (
|
||||
<VideoPlayer url={item.urls[0]}width={150}/>
|
||||
<VideoPlayer url={item.urls[0]} width={150} />
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
|
@ -57,10 +58,11 @@ const StreamerVideoMachineReviewContent = (props) => {
|
|||
title: "旧内容",
|
||||
dataIndex: "oldMedia",
|
||||
key: "oldMedia",
|
||||
width: "18%",
|
||||
render: (data) => (
|
||||
<div className="flex flex-wrap gap-1">
|
||||
{data?.map((item, index) => (
|
||||
<VideoPlayer key={index} url={item.urls[0]} width={150} />
|
||||
<VideoPlayer key={index} url={item.urls[0]} />
|
||||
))}
|
||||
</div>
|
||||
),
|
||||
|
|
|
@ -48,7 +48,9 @@ const ZonePostMachineReviewContent = (props) => {
|
|||
</div>
|
||||
<p className="text-red-400">媒体:</p>
|
||||
<div className="flex flex-wrap gap-1">
|
||||
<Image.PreviewGroup items={data.media.images?.map((item) => item.urls[0])}>
|
||||
<Image.PreviewGroup
|
||||
items={data.media.images?.map((item) => item.urls[0])}
|
||||
>
|
||||
{data.media.images.map((item, index) => (
|
||||
<Image key={index} src={item.urls[0]} width={100} />
|
||||
))}
|
||||
|
@ -146,7 +148,7 @@ const ZonePostMachineReviewContent = (props) => {
|
|||
name={record.momentId}
|
||||
initialValue={record.remarks.manually_review_opinion}
|
||||
>
|
||||
<TextArea rows={4} />
|
||||
<TextArea rows={4} disabled={current != "operatorReviewing"} />
|
||||
</Form.Item>
|
||||
</div>
|
||||
),
|
||||
|
|
|
@ -7,6 +7,7 @@ import StreamerJoin from "../pages/StreamerJoin";
|
|||
import StreamerJoinNew from "../pages/StreamerJoinNew";
|
||||
import StreamerInformationCompleteNew from "../pages/StreamerInformationCompleteNew";
|
||||
import Feedback from "../pages/Feedback";
|
||||
import Notices from "../pages/Notices";
|
||||
import Contact from "../pages/Contact";
|
||||
import UploadMedia from "../pages/UploadMedia";
|
||||
import GoodsReview from "../pages/GoodsReview";
|
||||
|
@ -71,6 +72,10 @@ const routes = [
|
|||
path: "streamerVerification/*",
|
||||
element: <StreamerVerification />,
|
||||
},
|
||||
{
|
||||
path: "notices/*",
|
||||
element: <Notices />,
|
||||
},
|
||||
{
|
||||
path: "feedback/*",
|
||||
element: <Feedback />,
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
//格式化时间戳
|
||||
export function formatDeadline(timestamp) {
|
||||
const date = new Date(timestamp); // 时间戳以秒为单位,需要乘以1000转换成毫秒
|
||||
const year = date.getFullYear();
|
||||
const month = ("0" + (date.getMonth() + 1)).slice(-2);
|
||||
const day = ("0" + date.getDate()).slice(-2);
|
||||
const hours = ("0" + date.getHours()).slice(-2);
|
||||
const minutes = ("0" + date.getMinutes()).slice(-2);
|
||||
const seconds = ("0" + date.getSeconds()).slice(-2);
|
||||
|
||||
return `${year}年${month}月${day}日 ${hours}:${minutes}:${seconds}`;
|
||||
}
|
|
@ -2,7 +2,34 @@
|
|||
module.exports = {
|
||||
content: ["./src/**/*.{js,jsx,ts,tsx}"],
|
||||
theme: {
|
||||
extend: {},
|
||||
extend: {
|
||||
colors: {
|
||||
primary: { DEFAULT: "#FF669E", 500: "#FF669E50" },
|
||||
secondary: { DEFAULT: "#838284" },
|
||||
neutral: { DEFAULT: "#2c2b2f" },
|
||||
info: { DEFAULT: "#3B69B8" },
|
||||
success: { DEFAULT: "#27F5B7" },
|
||||
warning: { DEFAULT: "#FFF04C" },
|
||||
error: { DEFAULT: "#F53030" },
|
||||
deepBg: { DEFAULT: "#07050A" },
|
||||
btn: { DEFAULT: "#3763b7" },
|
||||
super: {
|
||||
DEFAULT: "#FFD685",
|
||||
500: "#FFD68550",
|
||||
},
|
||||
},
|
||||
backgroundImage: {
|
||||
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
||||
"gradient-conic":
|
||||
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
||||
},
|
||||
},
|
||||
backgroundSize: {
|
||||
auto: "auto",
|
||||
cover: "cover",
|
||||
contain: "contain",
|
||||
"40%": "40%",
|
||||
},
|
||||
},
|
||||
plugins: [],
|
||||
corePlugins: {
|
||||
|
|
Loading…
Reference in New Issue