|
|
@@ -1,5 +1,6 @@
|
|
|
import React, { useEffect, useMemo, useState } from 'react';
|
|
|
import { Space, Table, Button, Input, Select, DatePicker, message, Typography, Spin, Popconfirm, Modal, InputNumber } from 'antd';
|
|
|
+import { DownloadOutlined } from '@ant-design/icons';
|
|
|
import type { TableProps } from 'antd';
|
|
|
import dayjs, { Dayjs } from 'dayjs';
|
|
|
import copy from 'copy-to-clipboard';
|
|
|
@@ -12,7 +13,7 @@ import { useXcxPlanList, XcxPlanDataType } from './hooks/useXcxPlanList';
|
|
|
import { useAudiencePackageOptions } from './hooks/useAudiencePackageOptions';
|
|
|
import { VideoItem } from '@src/views/publishContent/weGZH/components/types';
|
|
|
import http from '@src/http';
|
|
|
-import { deleteXcxPlanApi, getShareQrLink, saveXcxPlanApi, xcxPlanMultiLinkApi } from '@src/http/api';
|
|
|
+import { deleteXcxPlanApi, getShareQrLink, saveXcxPlanApi, xcxPlanExportApi, xcxPlanMultiLinkApi } from '@src/http/api';
|
|
|
import { getUserInfo } from '@src/http/sso';
|
|
|
|
|
|
const { RangePicker } = DatePicker;
|
|
|
@@ -31,6 +32,9 @@ const XcxTouliuContent: React.FC = () => {
|
|
|
const [multiLinkPlan, setMultiLinkPlan] = useState<XcxPlanDataType | null>(null);
|
|
|
const [multiLinkCount, setMultiLinkCount] = useState<number>(10);
|
|
|
const [multiLinkLoading, setMultiLinkLoading] = useState<boolean>(false);
|
|
|
+ const [isExportModalVisible, setIsExportModalVisible] = useState<boolean>(false);
|
|
|
+ const [exportDateRange, setExportDateRange] = useState<[Dayjs, Dayjs] | undefined>();
|
|
|
+ const [isExporting, setIsExporting] = useState<boolean>(false);
|
|
|
const { xcxPlanList, getXcxPlanList, totalSize } = useXcxPlanList();
|
|
|
const { options: audiencePackageOptions } = useAudiencePackageOptions();
|
|
|
const userType = useMemo(() => getUserInfo()?.type, []);
|
|
|
@@ -67,6 +71,13 @@ const XcxTouliuContent: React.FC = () => {
|
|
|
<img src={record.cover} referrerPolicy="no-referrer" className="w-[80px] h-auto" />
|
|
|
) : '-',
|
|
|
},
|
|
|
+ {
|
|
|
+ title: '备注',
|
|
|
+ dataIndex: 'remark',
|
|
|
+ key: 'remark',
|
|
|
+ width: 180,
|
|
|
+ ellipsis: true,
|
|
|
+ },
|
|
|
{
|
|
|
title: '计划创建时间',
|
|
|
dataIndex: 'createTimestamp',
|
|
|
@@ -203,12 +214,42 @@ const XcxTouliuContent: React.FC = () => {
|
|
|
setIsShowAddPunlishPlan(true);
|
|
|
};
|
|
|
|
|
|
+ const handleExport = () => {
|
|
|
+ setIsExporting(true);
|
|
|
+ http.post<string>(xcxPlanExportApi, {
|
|
|
+ audiencePackage: audiencePackage || undefined,
|
|
|
+ title: videoTitle || undefined,
|
|
|
+ createTimestampStart: exportDateRange?.[0] ? exportDateRange[0].startOf('day').valueOf() : undefined,
|
|
|
+ createTimestampEnd: exportDateRange?.[1] ? exportDateRange[1].add(1, 'day').startOf('day').valueOf() : undefined,
|
|
|
+ }).then(res => {
|
|
|
+ if (res.code === 0 && res.data) {
|
|
|
+ const a = document.createElement('a');
|
|
|
+ a.href = res.data;
|
|
|
+ a.target = '_blank';
|
|
|
+ a.rel = 'noopener noreferrer';
|
|
|
+ document.body.appendChild(a);
|
|
|
+ a.click();
|
|
|
+ document.body.removeChild(a);
|
|
|
+ message.success('已开始下载');
|
|
|
+ setIsExportModalVisible(false);
|
|
|
+ setExportDateRange(undefined);
|
|
|
+ } else {
|
|
|
+ message.error(res.msg || '导出失败');
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ message.error(err?.msg || '导出失败');
|
|
|
+ }).finally(() => {
|
|
|
+ setIsExporting(false);
|
|
|
+ });
|
|
|
+ };
|
|
|
+
|
|
|
const handleAddPunlishPlan = async (
|
|
|
params: XcxPlanDataType & { videoList: VideoItem[] }
|
|
|
) => {
|
|
|
setIsSubmiting(true);
|
|
|
const payload = {
|
|
|
audiencePackage: params.audiencePackage,
|
|
|
+ remark: params.remark,
|
|
|
videoList: (params.videoList || []).map((v) => ({
|
|
|
videoId: v.videoId,
|
|
|
title: v.customTitle || v.title,
|
|
|
@@ -302,6 +343,7 @@ const XcxTouliuContent: React.FC = () => {
|
|
|
|
|
|
<Button type="primary" className="ml-2" onClick={handleSearch}>搜索</Button>
|
|
|
<Button type="primary" onClick={addPunlishPlan}>+ 创建发布</Button>
|
|
|
+ <Button type="primary" icon={<DownloadOutlined />} onClick={() => setIsExportModalVisible(true)}>已选视频导出</Button>
|
|
|
</div>
|
|
|
|
|
|
<Table
|
|
|
@@ -376,6 +418,29 @@ const XcxTouliuContent: React.FC = () => {
|
|
|
</div>
|
|
|
)}
|
|
|
</Modal>
|
|
|
+
|
|
|
+ <Modal
|
|
|
+ title="已选视频导出"
|
|
|
+ open={isExportModalVisible}
|
|
|
+ onCancel={() => setIsExportModalVisible(false)}
|
|
|
+ onOk={handleExport}
|
|
|
+ confirmLoading={isExporting}
|
|
|
+ okText="确认导出"
|
|
|
+ cancelText="取消"
|
|
|
+ >
|
|
|
+ <div className="flex items-center gap-2 my-4">
|
|
|
+ <span className="text-gray-600">日期范围:</span>
|
|
|
+ <RangePicker
|
|
|
+ placeholder={['开始日期', '结束日期']}
|
|
|
+ value={exportDateRange}
|
|
|
+ onChange={(dates) => setExportDateRange(dates as [Dayjs, Dayjs] | undefined)}
|
|
|
+ allowClear
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ <div className="text-gray-400 text-sm">
|
|
|
+ 不选日期默认导出当天数据;最多导出 2000 条;会沿用当前页的「人群包 / 视频标题」筛选条件。
|
|
|
+ </div>
|
|
|
+ </Modal>
|
|
|
</div>
|
|
|
</Spin>
|
|
|
);
|