|
@@ -14,6 +14,8 @@ import {
|
|
|
Tabs,
|
|
Tabs,
|
|
|
Popover,
|
|
Popover,
|
|
|
Descriptions,
|
|
Descriptions,
|
|
|
|
|
+ Input,
|
|
|
|
|
+ Tooltip,
|
|
|
} from 'antd';
|
|
} from 'antd';
|
|
|
import { CheckCircleFilled, CaretRightFilled, HeartOutlined, HistoryOutlined, FireOutlined } from '@ant-design/icons';
|
|
import { CheckCircleFilled, CaretRightFilled, HeartOutlined, HistoryOutlined, FireOutlined } from '@ant-design/icons';
|
|
|
import { VideoItem, VideoListResponse } from '../types';
|
|
import { VideoItem, VideoListResponse } from '../types';
|
|
@@ -123,6 +125,12 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
const { uploadLogVideoListQuery, uploadLogVideoPlay, uploadLogVideoPlayEnd, uploadLogVideoCollect } = useLogger();
|
|
const { uploadLogVideoListQuery, uploadLogVideoPlay, uploadLogVideoPlayEnd, uploadLogVideoCollect } = useLogger();
|
|
|
const debouncedUploadLogVideoListQuery = useMemo(() => debounce(uploadLogVideoListQuery, 500), [uploadLogVideoListQuery]);
|
|
const debouncedUploadLogVideoListQuery = useMemo(() => debounce(uploadLogVideoListQuery, 500), [uploadLogVideoListQuery]);
|
|
|
const [category, setCategory] = useState<string>();
|
|
const [category, setCategory] = useState<string>();
|
|
|
|
|
+ const [title, setTitle] = useState<string>('');
|
|
|
|
|
+ // 搜索框仅对自营/代理(type ∈ {2 内部, 3 代理})放开;小程序投流入口需要 crowdPackage 才能搜
|
|
|
|
|
+ const SEARCH_ENABLED_TYPES = new Set([2, 3]);
|
|
|
|
|
+ const canSeeSearch = SEARCH_ENABLED_TYPES.has(getUserInfo()?.type as number);
|
|
|
|
|
+ const isXcxEntry = planType === GzhPlanType.小程序投流;
|
|
|
|
|
+ const searchDisabledTip = isXcxEntry && !crowdPackage ? '请先选人群包再搜索' : '';
|
|
|
const sort = VideoSortType.平台推荐;
|
|
const sort = VideoSortType.平台推荐;
|
|
|
const PAGE_SIZE = 10;
|
|
const PAGE_SIZE = 10;
|
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
const [currentPage, setCurrentPage] = useState(1);
|
|
@@ -184,13 +192,13 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
planType: getVideoListType(planType),
|
|
planType: getVideoListType(planType),
|
|
|
subChannel: 'weGZH',
|
|
subChannel: 'weGZH',
|
|
|
category: category ?? '',
|
|
category: category ?? '',
|
|
|
- title: '',
|
|
|
|
|
|
|
+ title: title ?? '',
|
|
|
sortType: sort,
|
|
sortType: sort,
|
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const requestParams = {
|
|
const requestParams = {
|
|
|
category,
|
|
category,
|
|
|
- title: '',
|
|
|
|
|
|
|
+ title: title ?? '',
|
|
|
sort,
|
|
sort,
|
|
|
type: getVideoListType(planType),
|
|
type: getVideoListType(planType),
|
|
|
pageNum,
|
|
pageNum,
|
|
@@ -355,6 +363,19 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
setTimeout(() => getVideoListRef.current?.(1, 'replace'), 0);
|
|
setTimeout(() => getVideoListRef.current?.(1, 'replace'), 0);
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const handleSearch = (value: string) => {
|
|
|
|
|
+ const next = (value ?? '').trim();
|
|
|
|
|
+ setTitle(next);
|
|
|
|
|
+ reqIdRef.current++;
|
|
|
|
|
+ setHasMore(true);
|
|
|
|
|
+ setVideoList([]);
|
|
|
|
|
+ setViewingPage(1);
|
|
|
|
|
+ setPageAnchors(new Map());
|
|
|
|
|
+ passedPagesRef.current.clear();
|
|
|
|
|
+ drawerBodyRef.current?.scrollTo({ top: 0 });
|
|
|
|
|
+ setTimeout(() => getVideoListRef.current?.(1, 'replace'), 0);
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
const handleSelectVideo = (videoId: number) => {
|
|
const handleSelectVideo = (videoId: number) => {
|
|
|
setSelectedVideoIds(prev => {
|
|
setSelectedVideoIds(prev => {
|
|
|
const newSet = new Set(prev);
|
|
const newSet = new Set(prev);
|
|
@@ -456,7 +477,7 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
items={SOURCE_TABS.map(t => ({ key: t.key, label: t.label }))}
|
|
items={SOURCE_TABS.map(t => ({ key: t.key, label: t.label }))}
|
|
|
className="!mb-3"
|
|
className="!mb-3"
|
|
|
/>
|
|
/>
|
|
|
- <div className="flex flex-wrap gap-2 mb-6">
|
|
|
|
|
|
|
+ <div className="flex flex-wrap gap-2 mb-6 items-center">
|
|
|
<div className="flex items-center gap-2">
|
|
<div className="flex items-center gap-2">
|
|
|
<span className="text-gray-600">品类:</span>
|
|
<span className="text-gray-600">品类:</span>
|
|
|
<Select
|
|
<Select
|
|
@@ -468,6 +489,22 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
|
|
|
options={videoCategoryOptions.map(option => ({ label: option, value: option }))}
|
|
options={videoCategoryOptions.map(option => ({ label: option, value: option }))}
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
|
|
+ {canSeeSearch && (
|
|
|
|
|
+ <div className="flex items-center gap-2">
|
|
|
|
|
+ <span className="text-gray-600">搜索:</span>
|
|
|
|
|
+ <Tooltip title={searchDisabledTip}>
|
|
|
|
|
+ <Input.Search
|
|
|
|
|
+ placeholder="按视频标题搜索"
|
|
|
|
|
+ style={{ width: 240 }}
|
|
|
|
|
+ allowClear
|
|
|
|
|
+ enterButton
|
|
|
|
|
+ disabled={!!searchDisabledTip}
|
|
|
|
|
+ defaultValue={title}
|
|
|
|
|
+ onSearch={handleSearch}
|
|
|
|
|
+ />
|
|
|
|
|
+ </Tooltip>
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<Spin spinning={loading}>
|
|
<Spin spinning={loading}>
|