返回 AiToEarn
1 import styles from './video.module.scss';
2 import VideoChoose from '@/components/Choose/VideoChoose';
3 import React, { useEffect, useRef, useState } from 'react';
4 import { Button, message, Modal, Popconfirm, Spin, Tooltip } from 'antd';
5 import {
6 DeleteOutlined,
7 ExclamationCircleFilled,
8 PlusOutlined,
9 } from '@ant-design/icons';
10 import ChooseAccountModule from '@/views/publish/components/ChooseAccountModule/ChooseAccountModule';
11 import NoChoosePage from '@/views/publish/children/videoPage/components/NoChoosePage';
12 import { useVideoPageStore } from '@/views/publish/children/videoPage/useVideoPageStore';
13 import { useShallow } from 'zustand/react/shallow';
14 import { PubType } from '@@/publish/PublishEnum';
15 import VideoChooseItem from '@/views/publish/children/videoPage/components/VideoChooseItem';
16 import CommonPubSetting from '@/views/publish/children/videoPage/components/CommonPubSetting';
17 import VideoPubSetModal from '@/views/publish/children/videoPage/components/VideoPubSetModal/VideoPubSetModal';
18 import { usePubStroe } from '@/store/pubStroe';
19 import { IVideoChooseItem } from '@/views/publish/children/videoPage/videoPage';
20 import { toolsApi } from '@/api/tools';
21 import { sensitivityLoading } from '@/utils';
22
23 export enum AccountChooseType {
24 // 多选
25 MultiSelect = 0,
26 // 单选
27 Radio = 1,
28 // 替换
29 Replace = 2,
30 }
31
32 const { confirm } = Modal;
33
34 export default function Page() {
35 const {
36 videoListChoose,
37 addVideos,
38 clearVideoList,
39 clear,
40 addAccount,
41 aloneAdd,
42 setVideoPubSetModalOpen,
43 loadingPageLoading,
44 setLoadingPageLoading,
45 setCurrChooseAccountId,
46 setTempSaveParams,
47 } = useVideoPageStore(
48 useShallow((state) => ({
49 videoListChoose: state.videoListChoose,
50 addVideos: state.addVideos,
51 addAccount: state.addAccount,
52 clearVideoList: state.clearVideoList,
53 clear: state.clear,
54 aloneAdd: state.aloneAdd,
55 setVideoPubSetModalOpen: state.setVideoPubSetModalOpen,
56 loadingPageLoading: state.loadingPageLoading,
57 setLoadingPageLoading: state.setLoadingPageLoading,
58 setCurrChooseAccountId: state.setCurrChooseAccountId,
59 setTempSaveParams: state.setTempSaveParams,
60 })),
61 );
62 // 账户选择弹框显示隐藏状态
63 const [chooseAccountOpen, setChooseAccountOpen] = useState(false);
64 // 账户选择类型
65 const accountChooseType = useRef(AccountChooseType.MultiSelect);
66 // 用户单选ID
67 const accountOneChooseId = useRef<string>();
68 const [sensitiveDetLoading, setSensitiveDetLoading] = useState(false);
69
70 useEffect(() => {
71 let confirmRes: { destroy: () => void };
72 if (videoListChoose.length === 0) {
73 const history = usePubStroe.getState().getVideoPubSaveData();
74
75 if (history?.videoListChoose && history?.videoListChoose.length !== 0) {
76 confirmRes = confirm({
77 title: '恢复草稿',
78 icon: <ExclamationCircleFilled />,
79 content: '您之前有未发布的视频,是否需要恢复?',
80 okText: '恢复',
81 cancelText: '放弃',
82 onOk() {
83 setTempSaveParams(history);
84 },
85 onCancel() {
86 usePubStroe.getState().clearVideoPubSaveData();
87 },
88 });
89 }
90 }
91
92 return () => {
93 clear();
94 confirmRes?.destroy();
95 };
96 }, []);
97
98 const sensitiveDetCore = async (
99 content: string,
100 videoItem: IVideoChooseItem,
101 ) => {
102 const res = await toolsApi.textModeration(content);
103
104 return {
105 sensitive: res !== 'Normal',
106 videoItem,
107 };
108 };
109
110 return (
111 <div className={styles.video}>
112 <Spin spinning={loadingPageLoading}>
113 <VideoPubSetModal onClose={setVideoPubSetModalOpen} />
114 <ChooseAccountModule
115 platChooseProps={{
116 disableAllSelect:
117 accountChooseType.current === AccountChooseType.Radio ||
118 accountChooseType.current === AccountChooseType.Replace,
119 choosedAccounts: videoListChoose
120 .map((v) => v.account)
121 .filter((v) => v !== undefined),
122 pubType: PubType.VIDEO,
123 isCancelChooseAccount: true,
124 }}
125 open={chooseAccountOpen}
126 onClose={setChooseAccountOpen}
127 onPlatConfirm={(aList) => {
128 addAccount(aList);
129 }}
130 onPlatChange={(_, account) => {
131 if (
132 accountChooseType.current === AccountChooseType.Radio ||
133 accountChooseType.current === AccountChooseType.Replace
134 ) {
135 setChooseAccountOpen(false);
136 aloneAdd({
137 account,
138 id: accountOneChooseId.current!,
139 });
140 }
141 }}
142 />
143
144 {videoListChoose.length !== 0 ? (
145 // 视频已选择
146 <div className="video-pubAfter">
147 <div className="video-pubAfter-con">
148 <div className="video-pubAfter-left">
149 <div className="video-pubAfter-left-options">
150 <div className="video-pubAfter-left-options-video">
151 <h1>视频</h1>
152 <VideoChoose
153 onMultipleChoose={addVideos}
154 onStartShoose={() => {
155 setLoadingPageLoading(true);
156 }}
157 onChooseFail={() => {
158 setLoadingPageLoading(false);
159 }}
160 >
161 <Tooltip title="批量添加视频">
162 <Button type="dashed" icon={<PlusOutlined />}>
163 批量添加
164 </Button>
165 </Tooltip>
166 </VideoChoose>
167 <Tooltip title="删除所有视频">
168 <Button
169 type="dashed"
170 icon={<DeleteOutlined />}
171 onClick={() => clearVideoList(0)}
172 >
173 清空视频
174 </Button>
175 </Tooltip>
176 </div>
177 <div className="video-pubAfter-left-options-account">
178 <h1>账号</h1>
179 <Tooltip title="批量添加账号">
180 <Button
181 type="dashed"
182 icon={<PlusOutlined />}
183 onClick={() => {
184 accountChooseType.current =
185 AccountChooseType.MultiSelect;
186 setChooseAccountOpen(true);
187 }}
188 >
189 批量添加
190 </Button>
191 </Tooltip>
192 <Tooltip title="删除所有账号">
193 <Button
194 type="dashed"
195 icon={<DeleteOutlined />}
196 onClick={() => {
197 clearVideoList(1);
198 }}
199 >
200 清空账号
201 </Button>
202 </Tooltip>
203 </div>
204 </div>
205
206 <div className="video-pubAfter-left-list">
207 {videoListChoose.map((v) => {
208 return (
209 <VideoChooseItem
210 key={v.id + v.video + v.account}
211 videoChooseItem={v}
212 onAccountOneChoose={(id, type) => {
213 accountChooseType.current = type;
214 accountOneChooseId.current = id;
215 setChooseAccountOpen(true);
216 }}
217 />
218 );
219 })}
220 </div>
221 </div>
222 <div className="video-pubAfter-right">
223 <CommonPubSetting />
224 </div>
225 </div>
226 <div className="video-pubAfter-footer">
227 <Popconfirm
228 title="温馨提示"
229 description="是否确认清空内容和账号?"
230 onConfirm={() => {
231 clear();
232 usePubStroe.getState().clearVideoPubSaveData();
233 }}
234 okText="确认"
235 cancelText="取消"
236 >
237 <Button>一键清空</Button>
238 </Popconfirm>
239
240 <Button
241 loading={sensitiveDetLoading}
242 color="danger"
243 variant="solid"
244 disabled={!videoListChoose.every((v) => v.account && v.video)}
245 onClick={async () => {
246 setSensitiveDetLoading(true);
247 const core = async () => {
248 const tasks: Promise<{
249 // 作品
250 videoItem: IVideoChooseItem;
251 // 是否敏感 true=敏感 false=正常
252 sensitive: boolean;
253 }>[] = [];
254 // 如果检测内容重复不会进行检测
255 const contentSet = new Set<string>();
256 videoListChoose.map((v) => {
257 const content = `
258 ${v.pubParams.title}
259 ${v.pubParams.describe}
260 `;
261 if (content.trim() !== '' && !contentSet.has(content)) {
262 contentSet.add(content);
263 tasks.push(sensitiveDetCore(content, v));
264 }
265 });
266 return await Promise.all(tasks);
267 };
268
269 const taskRes = await Promise.all([
270 core(),
271 sensitivityLoading(),
272 ]);
273 const res = taskRes[0];
274
275 setSensitiveDetLoading(false);
276
277 if (res.length === 0) return message.success('检测正常');
278 if (res.every((v) => !v.sensitive)) {
279 message.success('检测正常');
280 return;
281 }
282 for (const { sensitive, videoItem } of res) {
283 if (sensitive) {
284 message.warning('检测到此条作品存在敏感信息!');
285 setVideoPubSetModalOpen(true);
286 setCurrChooseAccountId(videoItem.id);
287 break;
288 }
289 }
290 }}
291 >
292 内容安全检测
293 </Button>
294
295 <Button
296 type="primary"
297 disabled={!videoListChoose.every((v) => v.account && v.video)}
298 onClick={() => {
299 setVideoPubSetModalOpen(true);
300 setCurrChooseAccountId(videoListChoose[0].id);
301 }}
302 >
303 预览及发布
304 </Button>
305 </div>
306 </div>
307 ) : (
308 // 视频未选择
309 <NoChoosePage />
310 )}
311 </Spin>
312 </div>
313 );
314 }
315
315 lines Plain Text