123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348 |
- import React, { useEffect, useState } from 'react';
- import { Space, Table, Button, Input, Select, DatePicker, Tabs, message, Typography, Spin } from 'antd';
- import type { TableProps } from 'antd';
- import dayjs, { Dayjs } from 'dayjs';
- import styles from './index.module.css';
- import PunlishPlanModal from './components/publishPlanModal';
- const { RangePicker } = DatePicker;
- import { useAccountOptions } from '@src/views/publishContent/weGZH/hooks/useAccountOptions';
- import { useGzhPlanList, GzhPlanDataType, GzhPlanType } from '@src/views/publishContent/weGZH/hooks/useGzhPlanList';
- import http from '@src/http';
- import { deleteGzhPlanApi, saveGzhPlanApi } from '@src/http/api';
- import PunlishPlanDetailModal from './components/PunlishPlanDetailModal';
- const TableHeight = window.innerHeight - 380;
- const WeGZHContent: React.FC = () => {
- const [planType, setPlanType] = useState<GzhPlanType>(GzhPlanType.自动回复);
- // 状态管理
- const [selectedAccount, setSelectedAccount] = useState<string>();
- const [videoTitle, setVideoTitle] = useState<string>('');
- const [selectedPublisher, setSelectedPublisher] = useState<number>();
- const [dateRange, setDateRange] = useState<[Dayjs | null, Dayjs | null]>();
- const [isShowAddPunlishPlan, setIsShowAddPunlishPlan] = useState<boolean>(false);
- const [actionType, setActionType] = useState<'add' | 'edit'>('add');
- const [editPlanData, setEditPlanData] = useState<GzhPlanDataType>();
- const [selectVideoType, setSelectVideoType] = useState<number>();
- const [isSubmiting, setIsSubmiting] = useState<boolean>(false);
- const [isLoading, setIsLoading] = useState<boolean>(false);
- const { accountOptions, getAccountList } = useAccountOptions();
- const { gzhPlanList, getGzhPlanList, totalSize } = useGzhPlanList();
- const [pageNum, setPageNum] = useState<number>(1);
- const [isShowAddPunlishDetailPlan, setIsShowAddPunlishDetailPlan] = useState<boolean>(false);
- // 表格列配置
- const columns: TableProps<GzhPlanDataType>['columns'] = [
- {
- title: '公众号名称',
- dataIndex: 'accountName',
- key: 'accountName',
- width: 160,
- },
- {
- title: '发布方式',
- dataIndex: 'publishStage',
- key: 'publishStage',
- width: 120,
- render: (_, record) => {
- return record.publishStage === 0 ? '平台发布' : '用户获取路径';
- }
- },
- {
- title: '视频选取方式',
- dataIndex: 'selectVideoType',
- key: 'selectVideoType',
- width: 120,
- render: (_, record) => {
- return record.selectVideoType === 0 ? '手动选取' : '自动选取';
- }
- },
- {
- title: '发布场景',
- dataIndex: 'scene',
- key: 'scene',
- width: 120,
- render: (_, record) => {
- return record.scene === 0 ? '关注回复' : '自动回复';
- }
- },
- {
- title: '视频数量',
- dataIndex: 'videoCount',
- key: 'videoCount',
- width: 100,
- },
- {
- title: '视频标题',
- dataIndex: 'title',
- key: 'title',
- ellipsis: true,
- render: (_, record) => {
- return record?.videoList?.map(video => {
- return <Typography.Paragraph style={{ maxWidth: '300px' }} ellipsis={{ rows: 1, tooltip: true }} key={video.videoId}>{video.customTitle || video.title}</Typography.Paragraph>
- })
- }
- },
- {
- title: '计划创建时间',
- dataIndex: 'createTimestamp',
- key: 'createTimestamp',
- width: 200,
- render: (_, record) => {
- return record.createTimestamp ? dayjs(record.createTimestamp).format('YYYY-MM-DD HH:mm:ss') : '';
- }
- },
-
- {
- title: '操作',
- key: 'action',
- fixed: 'right',
- render: (_, record) => (
- <Space size="middle">
- <Button type="link" onClick={() => editPlan(record)}>编辑</Button>
- <Button type="link" onClick={() => editPlanDetail(record)}>详情</Button>
- <Button type="link" onClick={() => deletePlan(record)}>删除</Button>
- </Space>
- ),
- },
- ];
- const cloumns2: TableProps<GzhPlanDataType>['columns'] = columns.filter(item => item.title !== '发布场景');
- const deletePlan = async (record: GzhPlanDataType) => {
- setIsLoading(true);
- const res = await http.post(deleteGzhPlanApi, {
- id: record.id,
- }).catch(err => {
- message.error(err?.msg || '删除失败');
- })
- if (res?.code === 0) {
- message.success('删除成功');
- getGzhPlanList({
- type: planType,
- pageNum: 1,
- pageSize: 10,
- selectVideoType: selectVideoType,
- });
- } else {
- message.error(res?.msg || '删除失败');
- }
- setIsLoading(false);
- }
- const editPlan = (record: GzhPlanDataType) => {
- setEditPlanData(record);
- setActionType('edit');
- setIsShowAddPunlishPlan(true);
- };
- const editPlanDetail = (record: GzhPlanDataType) => {
- setEditPlanData(record);
- setActionType('edit');
- setIsShowAddPunlishDetailPlan(true);
- }
- const addPunlishPlan = () => {
- setActionType('add');
- setEditPlanData(undefined);
- setIsShowAddPunlishPlan(true);
- }
- const handleAddPunlishPlan = async (params: GzhPlanDataType) => {
- setIsSubmiting(true);
- if (params.type !== planType) {
- setPlanType(params.type as GzhPlanType);
- }
- const res = await http.post<GzhPlanDataType>(saveGzhPlanApi, params)
- .catch(err => {
- message.error(err.msg);
- })
- .finally(() => {
- setIsSubmiting(false);
- });
- if (res?.code === 0) {
- message.success('发布计划创建成功');
-
- getGzhPlanList({
- type: params.type,
- pageNum: 1,
- pageSize: 10,
- });
- setIsShowAddPunlishPlan(false);
- } else {
- message.error(res?.msg);
- }
- }
- useEffect(() => {
- setSelectedAccount(undefined);
- setVideoTitle('');
- setSelectedPublisher(undefined);
- setSelectVideoType(undefined);
- setDateRange(undefined);
- setPageNum(1);
- getAccountList({ accountType: planType });
- getGzhPlanList({
- type: planType,
- pageNum: 1,
- pageSize: 10,
- });
- }, [planType]);
- const handleSearch = () => {
- getGzhPlanList({
- pageNum: 1,
- pageSize: 10,
- title: videoTitle,
- type: planType,
- accountId: selectedAccount ? parseInt(selectedAccount) : undefined,
- publishStage: selectedPublisher,
- selectVideoType: selectVideoType,
- createTimestampStart: dateRange?.[0]?.unix() ? dateRange[0].unix() * 1000 : undefined,
- createTimestampEnd: dateRange?.[1]?.unix() ? dateRange[1].unix() * 1000 : undefined,
- });
- }
- return (
- <Spin spinning={isLoading || isSubmiting}>
- <div className="rounded-lg">
- <div className="text-lg font-medium mb-3">公众号内容</div>
-
- {/* 搜索区域 */}
- <div className="flex flex-wrap gap-4 mb-3">
- <div className="flex items-center gap-2">
- <span className="text-gray-600">{ planType === GzhPlanType.自动回复 ? '公众号名称' : '服务号名称' }:</span>
- <Select
- placeholder={planType === GzhPlanType.自动回复 ? '选择公众号' : '选择服务号'}
- style={{ width: 150 }}
- value={selectedAccount}
- onChange={setSelectedAccount}
- allowClear
- showSearch
- filterOption={(input, option) =>
- (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
- }
- options={accountOptions?.map(item => ({ label: item.name, value: item.id })) || []}
- />
- </div>
- <div className="flex items-center gap-2">
- <span className="text-gray-600">视频标题:</span>
- <Input
- placeholder="搜索视频标题"
- style={{ width: 200 }}
- value={videoTitle}
- allowClear
- onPressEnter={handleSearch}
- onChange={e => setVideoTitle(e.target.value)}
- />
- </div>
- <div className="flex items-center gap-2">
- <span className="text-gray-600">发布方式:</span>
- <Select
- placeholder="选择发布方式"
- style={{ width: 140 }}
- value={selectedPublisher}
- onChange={setSelectedPublisher}
- allowClear
- options={[
- { label: '平台发布', value: 0 },
- { label: '用户获取路径', value: 1 },
- ]}
- />
- </div>
- <div className="flex items-center gap-2">
- <span className="text-gray-600">视频选取方式:</span>
- <Select
- placeholder="视频选取方式"
- style={{ width: 130 }}
- value={selectVideoType}
- onChange={setSelectVideoType}
- allowClear
- options={[
- { label: '手动选取', value: 0 },
- { label: '自动选取', value: 1 },
- ]}
- />
- </div>
- <div className="flex items-center gap-2">
- <RangePicker
- placeholder={['开始时间', '结束时间']}
- style={{ width: 270 }}
- allowClear
- value={dateRange}
- onChange={(dates) => {
- setDateRange(dates || undefined);
- }}
- />
- </div>
- <Button type="primary" className="ml-2" onClick={ handleSearch}>搜索</Button>
- </div>
- <Tabs
- defaultActiveKey={ GzhPlanType.自动回复}
- type="card"
- size="large"
- className={styles.antTableTab}
- items={[
- { label: '自动回复', key: GzhPlanType.自动回复 },
- { label: '服务号推送', key: GzhPlanType.服务号推送 },
- ]}
- activeKey={planType}
- onChange={(key) => setPlanType(key as GzhPlanType)}
- tabBarExtraContent={
- { right: <Button type="primary" onClick={addPunlishPlan}>+ 创建发布</Button> }}
- />
- {/* 表格区域 */}
- <Table
- rowKey={(record) => record.id}
- className={styles.antTable}
- columns={planType === GzhPlanType.自动回复 ? columns : cloumns2}
- dataSource={gzhPlanList}
- scroll={{ x: 'max-content', y: TableHeight }}
- pagination={{
- total: totalSize,
- pageSize: 10,
- current: pageNum,
- showTotal: (total) => `共 ${total} 条`,
- onChange: (page) => getGzhPlanList({
- pageNum: page,
- pageSize: 10,
- title: videoTitle,
- type: planType,
- selectVideoType: selectVideoType,
- accountId: selectedAccount ? parseInt(selectedAccount) : undefined,
- publishStage: selectedPublisher,
- createTimestampStart: dateRange?.[0]?.unix() ? dateRange[0].unix() * 1000 : undefined,
- createTimestampEnd: dateRange?.[1]?.unix() ? dateRange[1].unix() * 1000 : undefined,
- }),
- }}
- />
- <PunlishPlanModal
- visible={isShowAddPunlishPlan}
- onCancel={() => {
- setEditPlanData(undefined);
- setIsShowAddPunlishPlan(false);
- }}
- onOk={handleAddPunlishPlan}
- actionType={actionType}
- editPlanData={editPlanData}
- isSubmiting={isSubmiting}
- planType={ planType}
- />
- <PunlishPlanDetailModal
- visible={isShowAddPunlishDetailPlan}
- onCancel={() => {
- setEditPlanData(undefined);
- setIsShowAddPunlishDetailPlan(false);
- }}
- planData={editPlanData as GzhPlanDataType}
- />
- </div>
- </Spin>
- );
- };
- export default WeGZHContent;
|