|
@@ -8,6 +8,7 @@ import {
|
|
|
Typography,
|
|
Typography,
|
|
|
Space,
|
|
Space,
|
|
|
Spin,
|
|
Spin,
|
|
|
|
|
+ Switch,
|
|
|
Pagination,
|
|
Pagination,
|
|
|
message,
|
|
message,
|
|
|
Modal,
|
|
Modal,
|
|
@@ -15,11 +16,12 @@ import {
|
|
|
import { CheckCircleFilled, CaretRightFilled } from '@ant-design/icons';
|
|
import { CheckCircleFilled, CaretRightFilled } from '@ant-design/icons';
|
|
|
import { VideoListResponse } from '@src/views/publishContent/weGZH/components/types';
|
|
import { VideoListResponse } from '@src/views/publishContent/weGZH/components/types';
|
|
|
import http from '@src/http';
|
|
import http from '@src/http';
|
|
|
-import { getVideoContentListApi } from '@src/http/api';
|
|
|
|
|
|
|
+import { getVideoContentListApi, getDemandVideoContentListApi } from '@src/http/api';
|
|
|
import { useVideoCategoryOptions } from '@src/views/publishContent/weGZH/hooks/useVideoCategoryOptions';
|
|
import { useVideoCategoryOptions } from '@src/views/publishContent/weGZH/hooks/useVideoCategoryOptions';
|
|
|
import { WeComPlanType, WeVideoItem, VideoSearchPlanType } from '@src/views/publishContent/weCom/type'
|
|
import { WeComPlanType, WeVideoItem, VideoSearchPlanType } from '@src/views/publishContent/weCom/type'
|
|
|
|
|
|
|
|
const { Text, Paragraph } = Typography;
|
|
const { Text, Paragraph } = Typography;
|
|
|
|
|
+const IS_NON_PROD = !import.meta.env.PROD;
|
|
|
|
|
|
|
|
type LoadMode = 'replace' | 'append' | 'jump';
|
|
type LoadMode = 'replace' | 'append' | 'jump';
|
|
|
|
|
|
|
@@ -55,6 +57,7 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ visible, onClose, o
|
|
|
const [playingVideo, setPlayingVideo] = useState<WeVideoItem | null>(null);
|
|
const [playingVideo, setPlayingVideo] = useState<WeVideoItem | null>(null);
|
|
|
const [viewingPage, setViewingPage] = useState(1);
|
|
const [viewingPage, setViewingPage] = useState(1);
|
|
|
const [pageAnchors, setPageAnchors] = useState<Map<number, number>>(new Map()); // videoId -> page
|
|
const [pageAnchors, setPageAnchors] = useState<Map<number, number>>(new Map()); // videoId -> page
|
|
|
|
|
+ const [useDemandRecall, setUseDemandRecall] = useState(false); // 测试入口:群体特征召回
|
|
|
const observerRef = useRef<IntersectionObserver | null>(null);
|
|
const observerRef = useRef<IntersectionObserver | null>(null);
|
|
|
const pageObserverRef = useRef<IntersectionObserver | null>(null);
|
|
const pageObserverRef = useRef<IntersectionObserver | null>(null);
|
|
|
const passedPagesRef = useRef<Set<number>>(new Set());
|
|
const passedPagesRef = useRef<Set<number>>(new Set());
|
|
@@ -82,16 +85,13 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ visible, onClose, o
|
|
|
}
|
|
}
|
|
|
setCurrentPage(pageNum);
|
|
setCurrentPage(pageNum);
|
|
|
|
|
|
|
|
- const requestParams = {
|
|
|
|
|
- category,
|
|
|
|
|
- title: searchTerm,
|
|
|
|
|
- sort,
|
|
|
|
|
- type: planType === WeComPlanType.社群 ? VideoSearchPlanType.企微社群 : VideoSearchPlanType.企微自动回复,
|
|
|
|
|
- pageNum,
|
|
|
|
|
- pageSize: PAGE_SIZE,
|
|
|
|
|
- };
|
|
|
|
|
|
|
+ const type = planType === WeComPlanType.社群 ? VideoSearchPlanType.企微社群 : VideoSearchPlanType.企微自动回复;
|
|
|
|
|
+ const apiUrl = useDemandRecall ? getDemandVideoContentListApi : getVideoContentListApi;
|
|
|
|
|
+ const requestParams = useDemandRecall
|
|
|
|
|
+ ? { title: searchTerm, sort, type, pageNum, pageSize: PAGE_SIZE }
|
|
|
|
|
+ : { category, title: searchTerm, sort, type, pageNum, pageSize: PAGE_SIZE };
|
|
|
|
|
|
|
|
- const res = await http.post<VideoListResponse>(getVideoContentListApi, requestParams).catch(() => {
|
|
|
|
|
|
|
+ const res = await http.post<VideoListResponse>(apiUrl, requestParams).catch(() => {
|
|
|
message.error('获取视频列表失败');
|
|
message.error('获取视频列表失败');
|
|
|
}).finally(() => {
|
|
}).finally(() => {
|
|
|
if (isAppend) {
|
|
if (isAppend) {
|
|
@@ -210,6 +210,18 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ visible, onClose, o
|
|
|
getVideoList(1, 'replace');
|
|
getVideoList(1, 'replace');
|
|
|
};
|
|
};
|
|
|
|
|
|
|
|
|
|
+ const handleToggleDemandRecall = (checked: boolean) => {
|
|
|
|
|
+ setUseDemandRecall(checked);
|
|
|
|
|
+ setHasMore(true);
|
|
|
|
|
+ setVideoList([]);
|
|
|
|
|
+ setViewingPage(1);
|
|
|
|
|
+ setPageAnchors(new Map());
|
|
|
|
|
+ passedPagesRef.current.clear();
|
|
|
|
|
+ drawerBodyRef.current?.scrollTo({ top: 0 });
|
|
|
|
|
+ // 切换后重新请求(用最新 state 值)
|
|
|
|
|
+ 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);
|
|
@@ -321,6 +333,12 @@ const VideoSelectModal: React.FC<VideoSelectModalProps> = ({ visible, onClose, o
|
|
|
/>
|
|
/>
|
|
|
</div>
|
|
</div>
|
|
|
<Button type="primary" loading={loading} onClick={handleSearch}>搜索</Button>
|
|
<Button type="primary" loading={loading} onClick={handleSearch}>搜索</Button>
|
|
|
|
|
+ {IS_NON_PROD && (
|
|
|
|
|
+ <div className="flex items-center gap-2 ml-auto">
|
|
|
|
|
+ <span className="text-gray-600">群体召回(测试):</span>
|
|
|
|
|
+ <Switch checked={useDemandRecall} onChange={handleToggleDemandRecall} />
|
|
|
|
|
+ </div>
|
|
|
|
|
+ )}
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<Spin spinning={loading}>
|
|
<Spin spinning={loading}>
|