Przeglądaj źródła

videoSelectModal 加视频标题搜索框:仅对 user.type∈{2 自营,3 代理} 可见;小程序投流入口未选人群包时 disable+tooltip 提示「请先选人群包再搜索」;requestParams 透传 title,清空走 allowClear,后端按 demand 池白名单+向量召回交集返回。weCom 入口不显示(企微渠道不在搜索白名单)。

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
刘立冬 2 dni temu
rodzic
commit
b424a8684f

+ 40 - 3
src/views/publishContent/weGZH/components/videoSelectModal/index.tsx

@@ -14,6 +14,8 @@ import {
 	Tabs,
 	Popover,
 	Descriptions,
+	Input,
+	Tooltip,
 } from 'antd';
 import { CheckCircleFilled, CaretRightFilled, HeartOutlined, HistoryOutlined, FireOutlined } from '@ant-design/icons';
 import { VideoItem, VideoListResponse } from '../types';
@@ -123,6 +125,12 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
 	const { uploadLogVideoListQuery, uploadLogVideoPlay, uploadLogVideoPlayEnd, uploadLogVideoCollect } = useLogger();
 	const debouncedUploadLogVideoListQuery = useMemo(() => debounce(uploadLogVideoListQuery, 500), [uploadLogVideoListQuery]);
 	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 PAGE_SIZE = 10;
 	const [currentPage, setCurrentPage] = useState(1);
@@ -184,13 +192,13 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
 			planType: getVideoListType(planType),
 			subChannel: 'weGZH',
 			category: category ?? '',
-			title: '',
+			title: title ?? '',
 			sortType: sort,
 		});
 
 		const requestParams = {
 			category,
-			title: '',
+			title: title ?? '',
 			sort,
 			type: getVideoListType(planType),
 			pageNum,
@@ -355,6 +363,19 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
 		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) => {
 		setSelectedVideoIds(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 }))}
 					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">
 						<span className="text-gray-600">品类:</span>
 						<Select
@@ -468,6 +489,22 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ planType, visible,
 							options={videoCategoryOptions.map(option => ({ label: option, value: option }))}
 						/>
 					</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>
 
 				<Spin spinning={loading}>