diff --git a/src/pages/AutoAnwser/index.jsx b/src/pages/AutoAnwser/index.jsx new file mode 100644 index 0000000..94dfe04 --- /dev/null +++ b/src/pages/AutoAnwser/index.jsx @@ -0,0 +1,447 @@ +import React, { useState, useRef, useEffect } from "react"; +import { + Form, + Input, + Button, + Space, + Table, + Modal, + message, + Select, +} from "antd"; +import baseRequest from "../../utils/baseRequest"; +import PagesManage from "../../components/PagesManage"; +import { useMemo } from "react"; +import dayjs from "dayjs"; +import { ConfigProvider } from "antd"; +import zhCN from "antd/es/locale/zh_CN"; +const AutoAnwserContent = (props) => { + const [messageApi, contextHolder] = message.useMessage(); + //控制创建动态modal是否出现 + const [isModalOpen, setIsModalOpen] = useState(false); + const [isPagesModalOpen, setIsPagesModalOpen] = useState(false); + //提交创建动态 + const [form] = Form.useForm(); + const [pagesOptions, setPagesOptions] = useState([]); + const { TextArea } = Input; + //表头 + const columns = [ + { + title: "关键字", + dataIndex: "keyword", + key: "keyword", + width: 200, + render: (_, record) => { + console.log(record); + return ( + <div> + <span>{record.keyword}</span> + </div> + ); + }, + }, + { + title: "自动回复内容", + dataIndex: "message", + key: "message", + }, + { + title: "优先级", + dataIndex: "priority", + key: "priority", + width: 120, + sorter: (a, b) => a.priority - b.priority, + defaultSortOrder: "ascend", + sortDirections: ["ascend", "descend"], + render: (value, record) => { + return ( + <div> + <span> + {value} + {value > 6 ? "(不展示)" : ""} + </span> + </div> + ); + }, + }, + { + title: "状态", + dataIndex: "status", + key: "status", + render: (value, record) => ( + <span className={value === 1 ? "text-green-400" : "text-red-400"}> + {value === 1 ? "启用中" : "已关闭"} + </span> + ), + }, + { + title: "操作", + dataIndex: "opeartion", + key: "opeartion", + width: 200, + render: (_, record) => { + return ( + <div> + <Space> + <Space.Compact direction="vertical"> + <Button + style={{ + background: record.status === 1 ? "#ff4d4f" : "#1677ff", + color: "#fff", + }} + onClick={() => { + // form.setFieldsValue(record); + // setIsModalOpen(true); + handleSubmit({ + ...record, + status: record.status === 1 ? 0 : 1, + }); + }} + > + {!record.status ? "启动回复" : "关闭回复"} + </Button> + <Button + style={{ background: "#999", color: "#fff" }} + onClick={() => handleDeleteItem(record?.id)} + > + 删除回复 + </Button> + </Space.Compact> + </Space> + </div> + ); + }, + }, + ]; + useEffect(() => { + getPages(); + }, []); + //创建页面路由 + const getPages = async () => { + try { + const base = baseRequest(); + const response = await fetch("/op/frontend_route/list", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + offset: 0, + limit: 10, + ...base, + }), + }); + const _data = await response.json(); + if (_data.ret === -1) { + alert(_data.msg); + return; + } + setPagesOptions(_data.data.list); + } catch (error) { + console.error(error); + } + }; + const handleEditItem = async (id, value) => { + try { + const base = baseRequest(); + const response = await fetch("/op/auto_response/update", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id, + ...value, + ...base, + }), + }); + const temData = await response.json(); + if (temData.ret === -1) { + alert(temData.msg); + return; + } + message.success("更新成功"); + getData(); + } catch (error) { + console.error(error); + } + }; + const handleDeleteItem = async (id) => { + try { + const base = baseRequest(); + const response = await fetch("/op/auto_response/delete", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + id, + ...base, + }), + }); + const temData = await response.json(); + if (temData.ret === -1) { + alert(temData.msg); + return; + } + message.success("更新成功"); + getData(); + } catch (error) { + console.error(error); + } + }; + //获取数据 + const [data, setData] = useState([]); + const [offset, setOffset] = useState(0); + const [more, setMore] = useState(1); + const [total, setTotal] = useState(0); + const [formData, setFormData] = useState({ + title: "", + message: "", + n_type: 0, + obj_user_ids: [], + push_time: dayjs(new Date()), + params: "", + pageName: null, + link: null, + action: null, + link_text: null, + thumbnail: null, + obj_type: "0", + }); + const [currentPageName, setCurrentPageName] = useState(""); + const [buttonAble, setButtonAble] = useState(false); + + const currentPagesOptions = useMemo(() => { + if (!pagesOptions.length) return []; + const pages = pagesOptions + .filter((it) => it.desc === "达人空间") + .map((it) => { + return { + label: it.desc, + value: JSON.stringify(it), + }; + }); + return pages; + }, [pagesOptions, formData.action]); + + const getData = async (offset) => { + if (!more && offset) return; + try { + const base = baseRequest(); + const response = await fetch("/op/auto_response/list", { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + offset: 0, + limit: 20 + offset, + ...base, + }), + }); + const temData = await response.json(); + console.log("response", temData); + + if (temData.ret === -1) { + alert(temData.msg); + return; + } + const data = temData.data.list.map((it) => ({ + keyword: it.keyword, + message: it.message, + priority: it.priority, + id: it.id, + status: it.status, + })); + setShowData(data); + if (temData.data.offset > total) { + setTotal(temData.data.offset); + } + setOffset(temData.data.offset); + setMore(temData.data.more); + } catch (error) { + console.error(error); + } + }; + useEffect(() => { + getData(0); + }, []); + + //展示的数据 + const [showData, setShowData] = useState(data); + + //表单提交失败 + const onFinishFailed = (errorInfo) => { + console.log("Failed:", errorInfo); + }; + //关闭弹窗 + const handleCancelModal = () => { + form.setFieldsValue(formData); + setIsModalOpen(false); + }; + const handleSubmit = async (value) => { + try { + const base = baseRequest(); + const baseBody = { + ...value, + }; + if (value.id) { + baseBody.id = value.id; + baseBody.status = value.status; + } + const response = await fetch( + `/op/auto_response/${value.id ? "update" : "create"}`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + ...baseBody, + ...base, + }), + } + ); + const data = await response.json(); + if (data.ret === -1) { + alert(data.msg); + return; + } + handleCancelModal(); + message.success(`${value.id ? "更新" : "发布"}成功`); + getData(0); + } catch (error) { + console.error(error); + } + + form.resetFields(); + }; + return ( + <div style={{ marginLeft: 20, marginRight: 20 }}> + <div className="flex justify-between items-center"> + <Button + type="primary" + className="mt-4 mb-4 float-right" + onClick={() => setIsModalOpen(true)} + > + 新建自动回复内容+ + </Button> + </div> + {contextHolder} + <ConfigProvider locale={zhCN}> + <Table + columns={columns} + dataSource={showData} + pagination={{ + pageSize: 20, + showSizeChanger: false, + total: total, + }} + scroll={{ x: "max-content", y: window.innerHeight - 280 }} + footer={() => ( + <div className="text-gray-400">获得总数:{showData.length}</div> + )} + onScroll={(e) => { + const { scrollHeight, scrollTop, clientHeight } = e.currentTarget; + console.log(scrollHeight, scrollTop + clientHeight); + + if (scrollTop + clientHeight + 5 >= scrollHeight) { + getData(offset); + } + }} + /> + </ConfigProvider> + + {/* 重复判断isModalOpen是为了重新渲染ImageUploader和VideoUploader组件 */} + <Modal + title={ + form.getFieldValue("id") ? "编辑自动回复消息" : "新建自动回复消息" + } + footer={null} + open={isModalOpen} + onCancel={handleCancelModal} + onChange={setFormData} + > + <Form + className="mt-4 flex flex-col" + form={form} + onFinish={(value) => { + handleSubmit(value, form.getFieldValue("id")); + }} + layout="vertical" + initialValues={formData} + onChange={setFormData} + > + <Form.Item + label="关键字" + name="keyword" + rules={[ + { + required: true, + message: "请填写关键字", + }, + ]} + className="mb-6" + > + <Input maxLength={10} placeholder="字数上限为10" /> + </Form.Item> + <Form.Item + label="回复内容(上限250字)" + name="message" + rules={[ + { + required: true, + message: "请填写回复内容", + }, + ]} + className="mb-6" + > + <TextArea maxLength={250} showCount placeholder="字数上限为250" /> + </Form.Item> + <Form.Item + label="优先级" + name="priority" + rules={[ + { + required: true, + message: "请选择优先级", + }, + ]} + className="mb-6" + > + <Select placeholder="选择优先级"> + <Select.Option value={1}>1</Select.Option> + <Select.Option value={2}>2</Select.Option> + <Select.Option value={3}>3</Select.Option> + <Select.Option value={4}>4</Select.Option> + <Select.Option value={5}>5</Select.Option> + <Select.Option value={6}>6</Select.Option> + <Select.Option value={0}>不展示</Select.Option> + </Select> + </Form.Item> + <Button type="primary" htmlType="submit" disabled={buttonAble}> + 确认 + </Button> + </Form> + </Modal> + <Modal + title="页面管理" + footer={null} + open={isPagesModalOpen} + style={{ minWidth: 800 }} + onCancel={() => setIsPagesModalOpen(false)} + > + <PagesManage /> + </Modal> + </div> + ); +}; + +export default function Notices() { + return ( + <div> + <AutoAnwserContent /> + </div> + ); +} diff --git a/src/pages/CreateAndEditPost/index.jsx b/src/pages/CreateAndEditPost/index.jsx index a97f857..6cf1554 100644 --- a/src/pages/CreateAndEditPost/index.jsx +++ b/src/pages/CreateAndEditPost/index.jsx @@ -14,6 +14,9 @@ const CreateAndEditPostContent = (props) => { key: "info", render: (data) => ( <div> + <p> + 主播id:<span className="text-red-400">{data.user_id}</span> + </p> <p> 动态id:<span className="text-red-400">{data.id}</span> </p> @@ -35,22 +38,25 @@ const CreateAndEditPostContent = (props) => { title: "媒体", dataIndex: "media", key: "media", + width: 600, render: (data) => ( <div> - <Image.PreviewGroup - items={data?.images?.map((item) => item.urls[0])} - > - {data?.images?.map((item, index) => ( - <Image - key={index} - src={item.urls[0]} - width={150} - style={{ marginBottom: 10 }} - /> - ))} + <Image.PreviewGroup items={data?.images?.map((item) => item.urls[0])}> + <div className="grid grid-cols-4 gap-2"> + {data?.images?.map((item, index) => ( + <Image + key={index} + src={item.urls[0]} + // width={150} + style={{ marginBottom: 10 }} + /> + ))} + </div> </Image.PreviewGroup> {data?.videos?.map((item, index) => ( - <VideoPlayer key={index} url={item.urls[0]} /> + <div className="grid grid-cols-4 gap-2"> + <VideoPlayer key={index} url={item.urls[0]} /> + </div> ))} </div> ), @@ -73,6 +79,9 @@ const CreateAndEditPostContent = (props) => { ), }, ]; + const [total, setTotal] = useState(0); + const [offset, setOffset] = useState(0); + const [more, setMore] = useState(1); //控制编辑modal是否出现 const [isEditModalOpen, setIsEditModalOpen] = useState(false); @@ -202,6 +211,7 @@ const CreateAndEditPostContent = (props) => { //获取数据 const getData = async () => { + if (!more) return; try { const base = baseRequest(); const response = await fetch("/op/moment/list", { @@ -212,7 +222,7 @@ const CreateAndEditPostContent = (props) => { body: JSON.stringify({ ct_upper_bound: Math.floor(new Date().getTime() / 1000), offset: 0, - limit: 2000, + limit: 20 + offset, ...base, }), }); @@ -221,12 +231,16 @@ const CreateAndEditPostContent = (props) => { alert(temData.msg); return; } + setTotal(temData.data.offset); + setOffset(temData.data.offset); + setMore(temData.data.more); //匹配表格格式 const structedData = temData.data.list.map((item, index) => { return { key: index, info: { id: item.id, + user_id: item.streamer_ext.user_id, like: item.thumbs_up_num, ct: new Date(item.ct * 1000).toLocaleString(), }, @@ -245,6 +259,7 @@ const CreateAndEditPostContent = (props) => { //搜索 const search = async (value) => { + if (!more) return; try { const base = baseRequest(); const detailResponse = await fetch(`/op/streamer/list_ext_by_user_id`, { @@ -277,12 +292,16 @@ const CreateAndEditPostContent = (props) => { alert(temData.msg); return; } + setTotal(temData.data.offset); + setOffset(temData.data.offset); + setMore(temData.data.more); //匹配表格格式 const structedData = temData.data.list.map((item, index) => { return { key: index, info: { id: item.id, + user_id: item.streamer_ext.user_id, like: item.thumbs_up_num, ct: new Date(item.ct * 1000).toLocaleString(), }, @@ -344,6 +363,7 @@ const CreateAndEditPostContent = (props) => { }; //提交创建动态 const [form] = Form.useForm(); + const [searchForm] = Form.useForm(); const handleSubmit = async (value) => { if (!selectedUser) { alert("还未选中用户"); @@ -410,7 +430,15 @@ const CreateAndEditPostContent = (props) => { return ( <div className="mt-4" style={{ marginLeft: 20, marginRight: 20 }}> - <Form name="search" onFinish={search} onFinishFailed={onFinishFailed}> + <Form + name="search" + onFinish={(value) => { + setMore(true); + search(value); + }} + form={searchForm} + onFinishFailed={onFinishFailed} + > <Space style={{ marginBottom: 20 }}> <Form.Item label="主播ID" name="userId" style={{ margin: 0 }}> <Input type="number" /> @@ -431,8 +459,28 @@ const CreateAndEditPostContent = (props) => { <Table columns={columns} dataSource={showData} - pagination={{ pageSize: 20 }} - scroll={{ y: window.innerHeight - 300 }} + pagination={{ + pageSize: 20, + showSizeChanger: false, + total: total, + }} + scroll={{ x: "max-content", y: window.innerHeight - 280 }} + footer={() => ( + <div className="text-gray-400">获得总数:{showData.length}</div> + )} + onScroll={(e) => { + const { scrollHeight, scrollTop, clientHeight } = e.currentTarget; + console.log(scrollHeight, scrollTop + clientHeight); + + if (scrollTop + clientHeight + 5 >= scrollHeight) { + const hasSearch = searchForm.getFieldValue("userId"); + if (hasSearch) { + search(); + } else { + getData(offset); + } + } + }} /> </Form> {/* 重复判断isModalOpen是为了重新渲染ImageUploader和VideoUploader组件 */} diff --git a/src/pages/DeletedPostReview/index.jsx b/src/pages/DeletedPostReview/index.jsx index 2888c31..5db4893 100644 --- a/src/pages/DeletedPostReview/index.jsx +++ b/src/pages/DeletedPostReview/index.jsx @@ -1,7 +1,7 @@ import React, { useState, useEffect } from "react"; import { Form, Input, Table, Image, Space, Button, Modal, message } from "antd"; import baseRequest from "../../utils/baseRequest"; -import VideoPlayer from '../../components/VideoPlayer'; +import VideoPlayer from "../../components/VideoPlayer"; export default function DeletedPostReview() { //表头 const columns = [ @@ -9,6 +9,7 @@ export default function DeletedPostReview() { title: "动态信息", dataIndex: "info", key: "info", + width: 300, render: (data) => ( <div> <p> @@ -32,18 +33,26 @@ export default function DeletedPostReview() { title: "媒体", dataIndex: "media", key: "media", + width: 600, render: (data) => ( - <div> + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > {data?.images?.map((item, index) => ( <Image key={index} src={item.urls[0]} - width={150} style={{ marginBottom: 10 }} /> ))} {data?.videos?.map((item, index) => ( - <VideoPlayer key={index} url={item.urls[0]}/> + <VideoPlayer key={index} url={item.urls[0]} /> ))} </div> ), @@ -52,6 +61,7 @@ export default function DeletedPostReview() { title: "操作", dataIndex: "opeartion", key: "opeartion", + width: 200, render: (_, record) => ( <div> <Space> diff --git a/src/pages/EditSpacePost/index.jsx b/src/pages/EditSpacePost/index.jsx index 3a8ee89..26a3192 100644 --- a/src/pages/EditSpacePost/index.jsx +++ b/src/pages/EditSpacePost/index.jsx @@ -63,13 +63,29 @@ const EditSpacePostContent = (props) => { <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} /> - ))} + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > + {data.media.images.map((item, index) => ( + <Image key={index} src={item.urls[0]} width={100} /> + ))} + </div> </Image.PreviewGroup> - {data.media.videos.map((item, index) => ( - <VideoPlayer key={index} url={item.urls[0]} /> - ))} + <div + className={`grid ${ + data[0]?.h <= data[0]?.w ? "grid-cols-2" : "grid-cols-4" + } gap-2`} + > + {data.media.videos.map((item, index) => ( + <VideoPlayer key={index} url={item.urls[0]} /> + ))} + </div> </div> </div> ), diff --git a/src/pages/Feedback/index.jsx b/src/pages/Feedback/index.jsx index ba4a917..e4d2a68 100644 --- a/src/pages/Feedback/index.jsx +++ b/src/pages/Feedback/index.jsx @@ -33,18 +33,26 @@ const FeedbackContent = (props) => { title: "辅助材料", dataIndex: "credentials", key: "credentials", + width: 500, render: (data) => ( - <div> + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > {data.images?.map((item, index) => ( - <Image - key={index} - src={item.urls[0]} - width={150} - style={{ marginBottom: 10 }} - /> + <div className="self-start" key={index}> + <Image src={item.urls[0]} style={{ marginBottom: 10 }} /> + </div> ))} {data.videos?.map((item, index) => ( - <VideoPlayer key={index} url={item.urls[0]} /> + <div className="self-start" key={index}> + <VideoPlayer url={item.urls[0]} /> + </div> ))} </div> ), diff --git a/src/pages/HotManage/components/HotList/index.jsx b/src/pages/HotManage/components/HotList/index.jsx index 966eedd..352a53c 100644 --- a/src/pages/HotManage/components/HotList/index.jsx +++ b/src/pages/HotManage/components/HotList/index.jsx @@ -342,8 +342,6 @@ const HotList = (props) => { delete dataObj.st; delete dataObj.et; } - debugger; - if ( type === "stopStart" || dataObj.priority === selectedStreamer?.priority diff --git a/src/pages/Notices/index.jsx b/src/pages/Notices/index.jsx index 254128c..7a33618 100644 --- a/src/pages/Notices/index.jsx +++ b/src/pages/Notices/index.jsx @@ -526,8 +526,6 @@ const NoticesContent = (props) => { return; } } - debugger; - try { const base = baseRequest(); const response = await fetch(`/op/notification/create`, { diff --git a/src/pages/Op/index.jsx b/src/pages/Op/index.jsx index 71a8097..cd51f11 100644 --- a/src/pages/Op/index.jsx +++ b/src/pages/Op/index.jsx @@ -91,7 +91,10 @@ export default function Op() { "manualRechargeAndWithdrawal", <MoneyCollectOutlined /> ), - getItem("消息通知推送", "notices", <NotificationOutlined />), + getItem("消息中心管理", "noticesManagement", <NotificationOutlined />, [ + getItem("消息通知推送", "notices"), + getItem("自动回复消息预设", "autoAnswer"), + ]), getItem("排行榜管理", "hotManage", <TrophyOutlined />), getItem("意见反馈", "feedback", <SoundOutlined />), getItem("客服回复", "contact", <PhoneOutlined />), @@ -143,7 +146,9 @@ export default function Op() { "manualRechargeAndWithdrawal", <MoneyCollectOutlined /> ), - getItem("消息通知推送", "notices", <NotificationOutlined />), + getItem("消息中心管理", "noticesManagement", <NotificationOutlined />, [ + getItem("消息通知推送", "notices"), + ]), getItem("排行榜管理", "hotManage", <TrophyOutlined />), getItem("意见反馈", "feedback", <SoundOutlined />), getItem("客服回复", "contact", <PhoneOutlined />), diff --git a/src/pages/PostMachineReview/index.jsx b/src/pages/PostMachineReview/index.jsx index a510caa..fb0d757 100644 --- a/src/pages/PostMachineReview/index.jsx +++ b/src/pages/PostMachineReview/index.jsx @@ -34,6 +34,7 @@ const PostMachineReviewContent = (props) => { title: "动态内容", dataIndex: "newMedia", key: "newMedia", + width: 500, render: (data) => ( <div className="flex flex-col"> <div> @@ -42,12 +43,24 @@ const PostMachineReviewContent = (props) => { </p> </div> <p className="text-red-400">媒体:</p> - <div className="flex flex-wrap gap-1"> + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > {data.media?.images?.map((item, index) => ( - <Image key={index} src={item.urls[0]} width={100} /> + <div className="self-start" key={index}> + <Image src={item.urls[0]} /> + </div> ))} {data.media?.videos?.map((item, index) => ( - <VideoPlayer key={index} url={item.urls[0]} width={150} /> + <div className="self-start" key={index}> + <VideoPlayer url={item.urls[0]} /> + </div> ))} </div> </div> diff --git a/src/pages/StreamerInformation/index.jsx b/src/pages/StreamerInformation/index.jsx index 8c2e2d7..e2b6920 100644 --- a/src/pages/StreamerInformation/index.jsx +++ b/src/pages/StreamerInformation/index.jsx @@ -126,17 +126,25 @@ const StreamerInformationContent = () => { title: "相册", dataIndex: "displayGallery", key: "displayGallery", + width: 500, render: (data) => ( <div> <Image.PreviewGroup items={data?.map((item) => item.urls[0])}> - {data.map((item) => ( - <Image - key={item.urls[0]} - src={item.urls[0]} - width={100} - style={{ marginBottom: 10 }} - /> - ))} + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > + {data.map((item) => ( + <div key={item.urls[0]} className="self-start"> + <Image src={item.urls[0]} style={{ marginBottom: 10 }} /> + </div> + ))} + </div> </Image.PreviewGroup> </div> ), diff --git a/src/pages/StreamerInformationCompleteNew/index.jsx b/src/pages/StreamerInformationCompleteNew/index.jsx index e04618b..5fc80e4 100644 --- a/src/pages/StreamerInformationCompleteNew/index.jsx +++ b/src/pages/StreamerInformationCompleteNew/index.jsx @@ -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 JoinContent = (props) => { const { TextArea } = Input; const current = props.current; @@ -104,23 +104,27 @@ const JoinContent = (props) => { 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} />, }, { title: "相册", dataIndex: "displayGallery", key: "displayGallery", + width: 500, render: (data) => ( <div> <Image.PreviewGroup items={data?.map((item) => item.urls[0])}> - {data.map((item) => ( - <Image - key={item.urls[0]} - src={item.urls[0]} - width={100} - style={{ marginBottom: 10 }} - /> - ))} + <div + className={`grid ${ + data[0]?.h <= data[0]?.w ? "grid-cols-2" : "grid-cols-4" + } gap-2`} + > + {data.map((item) => ( + <div className="self-start" key={item.urls[0]}> + <Image src={item.urls[0]} style={{ marginBottom: 10 }} /> + </div> + ))} + </div> </Image.PreviewGroup> </div> ), @@ -222,6 +226,7 @@ const JoinContent = (props) => { title: "操作", dataIndex: "opeartion", key: "opeartion", + fixed: "right", render: (_, record) => ( <div> <Space> diff --git a/src/pages/StreamerJoin/index.jsx b/src/pages/StreamerJoin/index.jsx index 9677471..2c59636 100644 --- a/src/pages/StreamerJoin/index.jsx +++ b/src/pages/StreamerJoin/index.jsx @@ -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 JoinContent = (props) => { const { TextArea } = Input; const current = props.current; @@ -133,23 +133,31 @@ const JoinContent = (props) => { title: "封面视频", dataIndex: "displayVideo", key: "displayVideo", - render: (data) => <VideoPlayer url={data}/>, + render: (data) => <VideoPlayer url={data} />, }, { title: "相册", dataIndex: "displayGallery", key: "displayGallery", + width: 500, render: (data) => ( <div> <Image.PreviewGroup items={data?.map((item) => item.urls[0])}> - {data.map((item) => ( - <Image - key={item.urls[0]} - src={item.urls[0]} - width={100} - style={{ marginBottom: 10 }} - /> - ))} + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > + {data.map((item) => ( + <div key={item.urls[0]} className="self-start"> + <Image src={item.urls[0]} style={{ marginBottom: 10 }} /> + </div> + ))} + </div> </Image.PreviewGroup> </div> ), diff --git a/src/pages/TopPosts/index.jsx b/src/pages/TopPosts/index.jsx index a8dfc54..8b9a7d8 100644 --- a/src/pages/TopPosts/index.jsx +++ b/src/pages/TopPosts/index.jsx @@ -54,9 +54,12 @@ const TopPostsContent = (props) => { //展示的数据 const [showData, setShowData] = useState([]); - + const [total, setTotal] = useState(0); + const [offset, setOffset] = useState(0); + const [more, setMore] = useState(1); //获取数据 const getData = async () => { + if (!more) return; try { const base = baseRequest(); //获取现有id @@ -88,6 +91,8 @@ const TopPostsContent = (props) => { }, body: JSON.stringify({ ids: intIds, + offset: 0, + limit: 20 + offset, ...base, }), }); @@ -97,6 +102,11 @@ const TopPostsContent = (props) => { alert(temData2.msg); return; } + if (temData.data.offset > total) { + setTotal(temData.data.offset); + } + setOffset(temData2.data.offset); + setMore(temData2.data.more); //匹配表格格式 const structedData = temData2.data.list.map((item, index) => { return { @@ -169,8 +179,25 @@ const TopPostsContent = (props) => { <Table columns={columns} dataSource={showData} - pagination={{ pageSize: 20 }} - scroll={{ y: window.innerHeight - 300 }} + // pagination={{ pageSize: 20 }} + // scroll={{ y: window.innerHeight - 300 }} + pagination={{ + pageSize: 20, + showSizeChanger: false, + total: total, + }} + scroll={{ x: "max-content", y: window.innerHeight - 280 }} + footer={() => ( + <div className="text-gray-400">获得总数:{showData.length}</div> + )} + onScroll={(e) => { + const { scrollHeight, scrollTop, clientHeight } = e.currentTarget; + console.log(scrollHeight, scrollTop + clientHeight); + + if (scrollTop + clientHeight + 5 >= scrollHeight) { + getData(offset); + } + }} /> <Modal footer={null} open={isModalOpen} onCancel={handleCancelModal}> <p className="text-sm text-red-400 font-bold"> diff --git a/src/pages/ZonePostMachineReview/index.jsx b/src/pages/ZonePostMachineReview/index.jsx index cb1d404..d688c36 100644 --- a/src/pages/ZonePostMachineReview/index.jsx +++ b/src/pages/ZonePostMachineReview/index.jsx @@ -34,6 +34,7 @@ const ZonePostMachineReviewContent = (props) => { title: "动态内容", dataIndex: "content", key: "content", + width: 500, render: (data) => ( <div className="flex flex-col"> <div> @@ -47,16 +48,28 @@ const ZonePostMachineReviewContent = (props) => { )} </div> <p className="text-red-400">媒体:</p> - <div className="flex flex-wrap gap-1"> + <div + className={`grid ${ + (data.media?.images[0]?.h <= data.media?.images[0]?.w && + data.media?.images.length < 4) || + data.media?.images.length === 0 + ? "grid-cols-2" + : "grid-cols-4" + } gap-2`} + > <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} /> + <div className="self-start" key={index}> + <Image src={item.urls[0]} /> + </div> ))} </Image.PreviewGroup> {data.media.videos.map((item, index) => ( - <VideoPlayer key={index} url={item.urls[0]} width={150} /> + <div className="self-start" key={index}> + <VideoPlayer url={item.urls[0]} width={150} /> + </div> ))} </div> </div> diff --git a/src/routes/index.js b/src/routes/index.js index e03d8c2..08682bb 100644 --- a/src/routes/index.js +++ b/src/routes/index.js @@ -8,6 +8,7 @@ import StreamerJoinNew from "../pages/StreamerJoinNew"; import StreamerInformationCompleteNew from "../pages/StreamerInformationCompleteNew"; import Feedback from "../pages/Feedback"; import Notices from "../pages/Notices"; +import AutoAnwser from "../pages/AutoAnwser"; import HotManage from "../pages/HotManage"; import Contact from "../pages/Contact"; import UploadMedia from "../pages/UploadMedia"; @@ -80,6 +81,10 @@ const routes = [ path: "notices/*", element: <Notices />, }, + { + path: "autoAnswer/*", + element: <AutoAnwser />, + }, { path: "hotManage/*", element: <HotManage />, diff --git a/src/utils/baseRequest.js b/src/utils/baseRequest.js index ddf207d..3a2e3e4 100644 --- a/src/utils/baseRequest.js +++ b/src/utils/baseRequest.js @@ -6,7 +6,7 @@ export default function baseRequest() { const account = cookies.get("account"); const b_ts = new Date().getTime(); const baseRequest = { - b_mid: account.mid, + b_mid: account?.mid, b_ch: "op", b_ts: b_ts, b_token: token,