|
@@ -1,102 +1,168 @@
|
|
|
-import React, { useState } from 'react';
|
|
|
-import { Space, Table, Button, Input, Select, Tabs } from 'antd';
|
|
|
+import React, { useEffect, useState } from 'react';
|
|
|
+import { Space, Table, Button, Input, Select, Tabs, message } from 'antd';
|
|
|
import type { TableProps } from 'antd';
|
|
|
import styles from './index.module.css';
|
|
|
-import PunlishPlanModal from '../weGZH/components/publishPlanModal';
|
|
|
-import { wxPlanType } from './type';
|
|
|
+import { WeComPlan, WeComPlanListResponse, WeComPlanType, WeVideoItem } from './type';
|
|
|
+import request from '@src/http/index';
|
|
|
+import { getQwPlanListApi, saveQwPlanApi } from "@src/http/api"
|
|
|
+import VideoSelectModal from './components/videoSelectModal';
|
|
|
+import LinkDetailModal from './components/linkDetailModal';
|
|
|
+import http from '@src/http/index';
|
|
|
+
|
|
|
+// Define a type for the expected API response (adjust if needed based on actual API)
|
|
|
+interface SaveQwPlanResponse {
|
|
|
+ // Assuming the response has a data field containing the created items
|
|
|
+ // And each item is like WeVideoItem but includes a pageUrl
|
|
|
+ createdLinks: (WeVideoItem & { pageUrl: string })[];
|
|
|
+}
|
|
|
|
|
|
const WeGZHContent: React.FC = () => {
|
|
|
// 状态管理
|
|
|
const [videoTitle, setVideoTitle] = useState<string>('');
|
|
|
const [selectedPublisher, setSelectedPublisher] = useState<string>();
|
|
|
const [isShowAddPunlishPlan, setIsShowAddPunlishPlan] = useState<boolean>(false);
|
|
|
- const [actionType, setActionType] = useState<'add' | 'edit'>('add');
|
|
|
- const [editPlanData, setEditPlanData] = useState<wxPlanType>();
|
|
|
- const [activeKey, setActiveKey] = useState<string>('1');
|
|
|
+ const [editPlanData, setEditPlanData] = useState<WeComPlan>();
|
|
|
+ const [activeKey, setActiveKey] = useState<WeComPlanType>(WeComPlanType.每日推送);
|
|
|
+
|
|
|
+ const [tableData, setTableData] = useState<WeComPlan[]>([]);
|
|
|
+ const [totalSize, setTotalSize] = useState<number>(0);
|
|
|
+ const [pageNum, setPageNum] = useState<number>(1);
|
|
|
+
|
|
|
+ // State for the new modal
|
|
|
+ const [isLinkDetailModalVisible, setIsLinkDetailModalVisible] = useState<boolean>(false);
|
|
|
+ // State to hold data for the new modal (adjust type if needed)
|
|
|
+ const [createdVideoLinks, setCreatedVideoLinks] = useState<(WeVideoItem & { pushLink?: string })[]>([]);
|
|
|
+
|
|
|
+ const getTableData = (_pageNum?: number) => {
|
|
|
+ setPageNum(_pageNum || 1);
|
|
|
+ request.post<WeComPlanListResponse>(getQwPlanListApi, {
|
|
|
+ pageNum: _pageNum || pageNum,
|
|
|
+ pageSize: 10,
|
|
|
+ scene: selectedPublisher,
|
|
|
+ title: videoTitle,
|
|
|
+ type: +activeKey,
|
|
|
+ }
|
|
|
+ ).then(res => {
|
|
|
+ setTableData(res.data.objs || []);
|
|
|
+ setTotalSize(res.data.totalSize);
|
|
|
+ }).catch(err => {
|
|
|
+ message.error(err.msg || '获取数据失败');
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ useEffect(() => {
|
|
|
+ getTableData(1);
|
|
|
+ }, [activeKey]);
|
|
|
|
|
|
// 表格列配置
|
|
|
- const columns: TableProps<wxPlanType>['columns'] = [
|
|
|
- {
|
|
|
- title: '公众号名称',
|
|
|
- dataIndex: 'officialAccount',
|
|
|
- key: 'officialAccount',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '场景',
|
|
|
- dataIndex: 'scene',
|
|
|
- key: 'scene',
|
|
|
- },
|
|
|
+ const columns: TableProps<WeComPlan>['columns'] = [
|
|
|
{
|
|
|
- title: '视频数量',
|
|
|
- dataIndex: 'videoCount',
|
|
|
- key: 'videoCount',
|
|
|
+ title: '创建时间',
|
|
|
+ dataIndex: 'createTimestamp',
|
|
|
+ key: 'createTimestamp',
|
|
|
+ render: (_, record) => {
|
|
|
+ return record.createTimestamp ? new Date(record.createTimestamp).toLocaleString() : '';
|
|
|
+ }
|
|
|
},
|
|
|
{
|
|
|
title: '视频标题',
|
|
|
- dataIndex: 'videoTitle',
|
|
|
- key: 'videoTitle',
|
|
|
+ dataIndex: 'title',
|
|
|
+ key: 'title',
|
|
|
ellipsis: true,
|
|
|
},
|
|
|
{
|
|
|
- title: '计划创建时间',
|
|
|
- dataIndex: 'planPublishTime',
|
|
|
- key: 'planPublishTime',
|
|
|
- },
|
|
|
- {
|
|
|
- title: '发布方',
|
|
|
- dataIndex: 'publisher',
|
|
|
- key: 'publisher',
|
|
|
+ title: '场景',
|
|
|
+ dataIndex: 'scene',
|
|
|
+ key: 'scene',
|
|
|
+ render: (_, record) => {
|
|
|
+ if (activeKey === WeComPlanType.每日推送) {
|
|
|
+ return record.scene === 0 ? '群发' : '单发';
|
|
|
+ } else {
|
|
|
+ return '自动回复';
|
|
|
+ }
|
|
|
+ }
|
|
|
},
|
|
|
{
|
|
|
title: '操作',
|
|
|
key: 'action',
|
|
|
render: (_, record) => (
|
|
|
- <Space size="middle">
|
|
|
- <Button type="link" onClick={() => editPlan(record)}>编辑</Button>
|
|
|
- <Button type="link">详情</Button>
|
|
|
+ <Space size="middle" wrap>
|
|
|
+ <Button type="link" onClick={() => window.open(record.video, '_blank')}>播放</Button>
|
|
|
+ <Button type="link" onClick={() => downloadFile(record.cover, record.title + '_cover')}>下载封面</Button>
|
|
|
+ <Button type="link" onClick={() => showQrCodeModal(record.pageUrl, record.title)}>二维码</Button>
|
|
|
+ <Button type="link" onClick={() => copyToClipboard(record.pageUrl)}>复制链接</Button>
|
|
|
</Space>
|
|
|
),
|
|
|
},
|
|
|
];
|
|
|
|
|
|
- const editPlan = (record: wxPlanType) => {
|
|
|
- console.log(editPlanData)
|
|
|
- setEditPlanData(record);
|
|
|
- setActionType('edit');
|
|
|
- setIsShowAddPunlishPlan(true);
|
|
|
+ const copyToClipboard = (text: string) => {
|
|
|
+ if (text && navigator.clipboard) {
|
|
|
+ navigator.clipboard.writeText(text).then(() => {
|
|
|
+ message.success('链接已复制');
|
|
|
+ }, (err) => {
|
|
|
+ message.error('复制失败: ' + err);
|
|
|
+ });
|
|
|
+ } else {
|
|
|
+ message.warning('无链接可复制或浏览器不支持');
|
|
|
+ }
|
|
|
};
|
|
|
|
|
|
- // 模拟数据
|
|
|
- const data: wxPlanType[] = [
|
|
|
- {
|
|
|
- officialAccount: '小慧爱厨房',
|
|
|
- scene: 1,
|
|
|
- videoCount: 3,
|
|
|
- videoTitle: '养老金最新规定,快来看看...',
|
|
|
- planPublishTime: '2024-08-13 13:32:07',
|
|
|
- publisher: '平台发布',
|
|
|
- videoList: [],
|
|
|
- },
|
|
|
- {
|
|
|
- officialAccount: '小阳看天下',
|
|
|
- scene: 1,
|
|
|
- videoCount: 1,
|
|
|
- videoTitle: '养老金最新规定,快来看看...',
|
|
|
- planPublishTime: '2024-08-13 13:32:07',
|
|
|
- publisher: '用户发布',
|
|
|
- videoList: [],
|
|
|
- },
|
|
|
- ];
|
|
|
+ const downloadFile = (url: string, filename: string) => {
|
|
|
+ if (!url) {
|
|
|
+ message.warning('无可用文件下载');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ const link = document.createElement('a');
|
|
|
+ link.href = url;
|
|
|
+ link.download = filename || url.substring(url.lastIndexOf('/') + 1);
|
|
|
+ link.target = '_blank';
|
|
|
+ link.rel = 'noopener noreferrer';
|
|
|
+ document.body.appendChild(link);
|
|
|
+ link.click();
|
|
|
+ document.body.removeChild(link);
|
|
|
+ message.success('开始下载...');
|
|
|
+ };
|
|
|
+
|
|
|
+ const showQrCodeModal = (url: string, title: string) => {
|
|
|
+ if (!url) {
|
|
|
+ message.warning('无链接生成二维码');
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ message.info(`显示 ${title} 的二维码 (功能待实现)`);
|
|
|
+ };
|
|
|
|
|
|
const addPunlishPlan = () => {
|
|
|
- setActionType('add');
|
|
|
setIsShowAddPunlishPlan(true);
|
|
|
}
|
|
|
|
|
|
+ const handleOk = (selectedVideos: WeVideoItem[]) => {
|
|
|
+ http.post<SaveQwPlanResponse>(saveQwPlanApi, {
|
|
|
+ type: +activeKey,
|
|
|
+ videoList: selectedVideos,
|
|
|
+ }).then(res => {
|
|
|
+ if (res.code === 0 &&res.data && Array.isArray(res.data.createdLinks) && res.data.createdLinks.length > 0) {
|
|
|
+ const linksForModal = res.data.createdLinks.map(item => ({
|
|
|
+ ...item,
|
|
|
+ pushLink: item.pageUrl
|
|
|
+ }));
|
|
|
+ message.success('创建成功');
|
|
|
+ setCreatedVideoLinks(linksForModal);
|
|
|
+ setIsLinkDetailModalVisible(true);
|
|
|
+ setIsShowAddPunlishPlan(false);
|
|
|
+ getTableData();
|
|
|
+ } else {
|
|
|
+ message.error(res.msg || '创建失败');
|
|
|
+ }
|
|
|
+ }).catch(err => {
|
|
|
+ message.error(err.msg || '创建失败');
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
return (
|
|
|
<div>
|
|
|
- <div className="rounded-lg">
|
|
|
- <div className="text-lg font-medium mb-3">公众号内容</div>
|
|
|
+ <div className="rounded-lg bg-white p-4">
|
|
|
+ <div className="text-lg font-medium mb-3">企业微信内容库</div>
|
|
|
|
|
|
{/* 搜索区域 */}
|
|
|
<div className="flex flex-wrap gap-4 mb-3">
|
|
@@ -113,72 +179,65 @@ const WeGZHContent: React.FC = () => {
|
|
|
</div>
|
|
|
|
|
|
<div className="flex items-center gap-2">
|
|
|
- <span className="text-gray-600">发布方:</span>
|
|
|
+ <span className="text-gray-600">场景:</span>
|
|
|
<Select
|
|
|
placeholder="筛选场景"
|
|
|
style={{ width: 200 }}
|
|
|
value={selectedPublisher}
|
|
|
onChange={setSelectedPublisher}
|
|
|
allowClear
|
|
|
- options={[
|
|
|
- { label: '关注回复', value: 'platform' },
|
|
|
- { label: '用户发布', value: 'user' },
|
|
|
+ options={activeKey === WeComPlanType.每日推送 ? [
|
|
|
+ { label: '群发', value: 0 },
|
|
|
+ { label: '单发', value: 1 },
|
|
|
+ ] : [
|
|
|
+ { label: '关注回复', value: 0 },
|
|
|
]}
|
|
|
/>
|
|
|
</div>
|
|
|
|
|
|
- <Button type="primary" className="ml-2">搜索</Button>
|
|
|
+ <Button type="primary" className="ml-2" onClick={() => getTableData(1)}>搜索</Button>
|
|
|
</div>
|
|
|
<Tabs
|
|
|
defaultActiveKey="1"
|
|
|
type="card"
|
|
|
size="large"
|
|
|
items={[
|
|
|
- { label: '每日推送', key: '1' },
|
|
|
- { label: '自动回复', key: '2' },
|
|
|
+ { label: '每日推送', key: WeComPlanType.每日推送 },
|
|
|
+ { label: '自动回复', key: WeComPlanType.自动回复 },
|
|
|
]}
|
|
|
activeKey={activeKey}
|
|
|
- onChange={setActiveKey}
|
|
|
+ onChange={(key: string) => setActiveKey(key as WeComPlanType)}
|
|
|
tabBarExtraContent={
|
|
|
{ right: <Button type="primary" onClick={addPunlishPlan}>+ 创建发布</Button> }}
|
|
|
/>
|
|
|
{/* 表格区域 */}
|
|
|
- {
|
|
|
- activeKey === '1' && (
|
|
|
- <Table
|
|
|
- rowKey={(record) => record.officialAccount}
|
|
|
- className={styles.antTable}
|
|
|
- columns={columns}
|
|
|
- dataSource={data}
|
|
|
- pagination={{
|
|
|
- total: data.length,
|
|
|
- pageSize: 10,
|
|
|
- showTotal: (total) => `共 ${total} 条`,
|
|
|
- }}
|
|
|
- />
|
|
|
- )
|
|
|
- }
|
|
|
- {
|
|
|
- activeKey === '2' && (
|
|
|
- <Table
|
|
|
- rowKey={(record) => record.officialAccount}
|
|
|
- className={styles.antTable}
|
|
|
- columns={columns}
|
|
|
- dataSource={data}
|
|
|
- pagination={{
|
|
|
- total: data.length,
|
|
|
- pageSize: 10,
|
|
|
- showTotal: (total) => `共 ${total} 条`,
|
|
|
- }}
|
|
|
- />
|
|
|
- )
|
|
|
- }
|
|
|
- <PunlishPlanModal
|
|
|
+ <Table
|
|
|
+ rowKey={(record) => record.id}
|
|
|
+ className={styles.antTable}
|
|
|
+ columns={columns}
|
|
|
+ dataSource={tableData}
|
|
|
+ pagination={{
|
|
|
+ current: pageNum,
|
|
|
+ total: totalSize,
|
|
|
+ pageSize: 10,
|
|
|
+ showTotal: (total) => `共 ${total} 条`,
|
|
|
+ onChange: (page) => getTableData(page),
|
|
|
+ }}
|
|
|
+ />
|
|
|
+ <VideoSelectModal
|
|
|
visible={isShowAddPunlishPlan}
|
|
|
- onCancel={() => setIsShowAddPunlishPlan(false)}
|
|
|
- onOk={() => setIsShowAddPunlishPlan(false)}
|
|
|
- actionType={actionType}
|
|
|
- editPlanData={undefined}
|
|
|
+ onClose={() => {
|
|
|
+ setIsShowAddPunlishPlan(false);
|
|
|
+ setEditPlanData(undefined);
|
|
|
+ }}
|
|
|
+ onOk={handleOk}
|
|
|
+ initialSelectedIds={editPlanData ? [editPlanData.id] : []}
|
|
|
+ planType={activeKey}
|
|
|
+ />
|
|
|
+ <LinkDetailModal
|
|
|
+ visible={isLinkDetailModalVisible}
|
|
|
+ onClose={() => setIsLinkDetailModalVisible(false)}
|
|
|
+ videos={createdVideoLinks}
|
|
|
/>
|
|
|
</div>
|
|
|
</div>
|