|
@@ -1,10 +1,11 @@
|
|
|
import React, { useEffect, useState } from 'react';
|
|
import React, { useEffect, useState } from 'react';
|
|
|
-import { Space, Table, Button, Input, Select, Tabs, message, Spin, Popconfirm } from 'antd';
|
|
|
|
|
|
|
+import { Space, Table, Button, Input, Select, Tabs, message, Spin, Popconfirm, DatePicker, Modal } from 'antd';
|
|
|
import type { TableProps } from 'antd';
|
|
import type { TableProps } from 'antd';
|
|
|
|
|
+import type { Dayjs } from 'dayjs';
|
|
|
import styles from './index.module.css';
|
|
import styles from './index.module.css';
|
|
|
import { AddWeComPlanParam, WeComPlan, WeComPlanListResponse, WeComPlanType } from './type';
|
|
import { AddWeComPlanParam, WeComPlan, WeComPlanListResponse, WeComPlanType } from './type';
|
|
|
import request from '@src/http/index';
|
|
import request from '@src/http/index';
|
|
|
-import { deleteQwPlanApi, getQwPlanListApi, getShareQrLink, saveQwPlanApi } from "@src/http/api"
|
|
|
|
|
|
|
+import { deleteQwPlanApi, getQwPlanListApi, getShareQrLink, qwPlanExportApi, saveQwPlanApi } from "@src/http/api"
|
|
|
import LinkDetailModal from './components/linkDetailModal';
|
|
import LinkDetailModal from './components/linkDetailModal';
|
|
|
import PlanDetailModal from './components/planDetailModal';
|
|
import PlanDetailModal from './components/planDetailModal';
|
|
|
import http from '@src/http/index';
|
|
import http from '@src/http/index';
|
|
@@ -13,6 +14,8 @@ import VideoPlayModal from './components/videoPlayModal';
|
|
|
import modal from 'antd/es/modal';
|
|
import modal from 'antd/es/modal';
|
|
|
import AddPlanModal from './components/addPlanModal';
|
|
import AddPlanModal from './components/addPlanModal';
|
|
|
import { QRCodeSVG } from 'qrcode.react';
|
|
import { QRCodeSVG } from 'qrcode.react';
|
|
|
|
|
+
|
|
|
|
|
+const { RangePicker } = DatePicker;
|
|
|
// Define a type for the expected API response (adjust if needed based on actual API)
|
|
// Define a type for the expected API response (adjust if needed based on actual API)
|
|
|
const TableHeight = window.innerHeight - 380;
|
|
const TableHeight = window.innerHeight - 380;
|
|
|
const WeGZHContent: React.FC = () => {
|
|
const WeGZHContent: React.FC = () => {
|
|
@@ -39,6 +42,11 @@ const WeGZHContent: React.FC = () => {
|
|
|
const [isVideoPlayModalVisible, setIsVideoPlayModalVisible] = useState<boolean>(false);
|
|
const [isVideoPlayModalVisible, setIsVideoPlayModalVisible] = useState<boolean>(false);
|
|
|
const [isAddPlanLoading, setIsAddPlanLoading] = useState<boolean>(false);
|
|
const [isAddPlanLoading, setIsAddPlanLoading] = useState<boolean>(false);
|
|
|
|
|
|
|
|
|
|
+ // 已选视频导出 modal
|
|
|
|
|
+ const [isExportModalVisible, setIsExportModalVisible] = useState<boolean>(false);
|
|
|
|
|
+ const [exportDateRange, setExportDateRange] = useState<[Dayjs, Dayjs] | undefined>(undefined);
|
|
|
|
|
+ const [isExporting, setIsExporting] = useState<boolean>(false);
|
|
|
|
|
+
|
|
|
const getTableData = (_pageNum?: number, _pageSize?: number) => {
|
|
const getTableData = (_pageNum?: number, _pageSize?: number) => {
|
|
|
if (_pageNum) {
|
|
if (_pageNum) {
|
|
|
setPageNum(_pageNum);
|
|
setPageNum(_pageNum);
|
|
@@ -191,6 +199,37 @@ const WeGZHContent: React.FC = () => {
|
|
|
setIsShowAddPunlishPlan(true);
|
|
setIsShowAddPunlishPlan(true);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ const handleExport = () => {
|
|
|
|
|
+ setIsExporting(true);
|
|
|
|
|
+ request.post<string>(qwPlanExportApi, {
|
|
|
|
|
+ type: +activeKey,
|
|
|
|
|
+ scene: selectedPublisher,
|
|
|
|
|
+ subChannel,
|
|
|
|
|
+ title: videoTitle,
|
|
|
|
|
+ startDate: exportDateRange?.[0]?.format('YYYY-MM-DD'),
|
|
|
|
|
+ endDate: exportDateRange?.[1]?.format('YYYY-MM-DD'),
|
|
|
|
|
+ }).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 handleAddPlan = (param: AddWeComPlanParam) => {
|
|
const handleAddPlan = (param: AddWeComPlanParam) => {
|
|
|
setIsAddPlanLoading(true);
|
|
setIsAddPlanLoading(true);
|
|
|
const { type, subChannel, videoList } = param;
|
|
const { type, subChannel, videoList } = param;
|
|
@@ -279,7 +318,14 @@ const WeGZHContent: React.FC = () => {
|
|
|
activeKey={activeKey}
|
|
activeKey={activeKey}
|
|
|
onChange={(key: string) => setActiveKey(key as WeComPlanType)}
|
|
onChange={(key: string) => setActiveKey(key as WeComPlanType)}
|
|
|
tabBarExtraContent={
|
|
tabBarExtraContent={
|
|
|
- { right: <Button type="primary" onClick={addPunlishPlan}>+ 创建发布</Button> }}
|
|
|
|
|
|
|
+ {
|
|
|
|
|
+ right: (
|
|
|
|
|
+ <Space>
|
|
|
|
|
+ <Button onClick={() => setIsExportModalVisible(true)}>已选视频导出</Button>
|
|
|
|
|
+ <Button type="primary" onClick={addPunlishPlan}>+ 创建发布</Button>
|
|
|
|
|
+ </Space>
|
|
|
|
|
+ )
|
|
|
|
|
+ }}
|
|
|
/>
|
|
/>
|
|
|
{/* 表格区域 */}
|
|
{/* 表格区域 */}
|
|
|
<Table
|
|
<Table
|
|
@@ -328,6 +374,28 @@ const WeGZHContent: React.FC = () => {
|
|
|
videoUrl={editPlanData?.video || ''}
|
|
videoUrl={editPlanData?.video || ''}
|
|
|
title={editPlanData?.title || ''}
|
|
title={editPlanData?.title || ''}
|
|
|
/>
|
|
/>
|
|
|
|
|
+ <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>
|
|
</div>
|
|
|
</Spin>
|
|
</Spin>
|
|
|
);
|
|
);
|