wjx 2 dias atrás
pai
commit
398aba7f55

+ 34 - 0
src/pages/weComTask/API/bookLink/index.ts

@@ -62,4 +62,38 @@ export function getFreeChapterListApi(data: GetFreeChapterListProps) {
         method: 'POST',
         data
     })
+}
+
+export interface GetAutoLinkBookListProps {
+    pageNum: number
+    pageSize: number
+    bookName?: string,
+    bookId?: string,
+    platformKey?: string
+}
+
+/**
+ * 书籍列表
+ * @param data 
+ * @returns 
+ */
+export function getAutoLinkBookListApi(data: GetAutoLinkBookListProps) {
+    return request({
+        url: api + `/corpOperation/corp/autoLink/bookList`,
+        method: 'POST',
+        data
+    })
+}
+
+/**
+ * 删除链接
+ * @param data 
+ * @returns 
+ */
+export function delAutoLinkApi(data: { linkIds: number[] }) {
+    return request({
+        url: api + `/corpOperation/corp/autoLink/batchDelByIds`,
+        method: 'POST',
+        data: data.linkIds
+    })
 }

+ 46 - 7
src/pages/weComTask/API/businessPlan/create.ts

@@ -9,8 +9,8 @@ const { api } = process.env.CONFIG;
 export async function addTaskApi(data: BUSINES_SPLAN_API.AddTaskProps) {
     return request({
         url: api + `/corpOperation/corp/create/project/task/add`,
-        method: 'POST', 
-        data 
+        method: 'POST',
+        data
     });
 }
 
@@ -22,8 +22,8 @@ export async function addTaskApi(data: BUSINES_SPLAN_API.AddTaskProps) {
 export async function getProjectListApi(data: BUSINES_SPLAN_API.GetProjectListProps) {
     return request({
         url: api + `/corpOperation/corp/create/project/listOfPage`,
-        method: 'POST', 
-        data 
+        method: 'POST',
+        data
     });
 }
 
@@ -34,8 +34,47 @@ export async function getProjectListApi(data: BUSINES_SPLAN_API.GetProjectListPr
  */
 export async function getProjectDetailsApi(projectId: string) {
     return request({
-        url: api + `/corpOperation/corp/create/project/getDetail/${projectId}}`,
-        method: 'GET', 
+        url: api + `/corpOperation/corp/create/project/getDetail/${projectId}`,
+        method: 'GET',
+    });
+}
+
+/**
+ * 获取计划详情
+ * @param projectId 
+ * @returns 
+ */
+export async function getCreateDetailsApi(projectId: string) {
+    return request({
+        url: api + `/corpOperation/corp/create/project/selectById/${projectId}`,
+        method: 'POST',
+    });
+}
+
+
+/**
+ * 删除计划
+ * @param params 
+ * @returns 
+ */
+export async function delProjectApi(data: { projectIds: number[] }) {
+    return request({
+        url: api + `/corpOperation/corp/create/project/batchDelByIds`,
+        method: 'POST',
+        data: data.projectIds
+    });
+}
+
+/**
+ * 停止计划
+ * @param data 
+ * @returns 
+ */
+export async function cancelProjectApi(data: { projectIds: number[] }) {
+    return request({
+        url: api + `/corpOperation/corp/create/project/cancel`,
+        method: 'POST',
+        data: data.projectIds
     });
 }
 
@@ -122,7 +161,7 @@ export async function getMessageSendTaskuserListApi(data: GetSendTaskGroupuserLi
  * 高级群发消息重试
  * @returns 
  */
-export async function putMessageUpdateApi(id:any) {
+export async function putMessageUpdateApi(id: any) {
     return request({
         url: `/corp/message/send/taskLog/status/update/${id}`,
         method: 'PUT',

+ 17 - 1
src/pages/weComTask/page/bookLink/bookPromoLinkCreateDTO.tsx

@@ -2,6 +2,7 @@ import { useAjax } from "@/Hook/useAjax";
 import { App, Button, Form, Input, InputNumber, Radio, Select, Space, Switch } from "antd";
 import React from "react";
 import { getFreeChapterListApi } from "../../API/bookLink";
+import SelectBook from "./selectBook";
 
 interface Props extends BOOKLINK.BookLinkChildProps {
     yueWenCreateLinkDTO: { [x: string]: any }
@@ -28,7 +29,7 @@ const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, yueWenCreate
     }
 
     return <>
-        <Form.Item
+        {/* <Form.Item
             label={<strong>作品(书籍)ID</strong>}
             required
         >
@@ -47,6 +48,21 @@ const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, yueWenCreate
                 </Form.Item>
                 <Button type="primary" onClick={getChapterList} disabled={!yueWenCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId} loading={getFreeChapterList.loading}>查询章节列表</Button>
             </Space.Compact>
+        </Form.Item> */}
+
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'bookId']}
+            rules={[{ required: true, message: '请输入作品(书籍)ID!' }]}
+            label={<strong>作品(书籍)ID</strong>}
+        >
+            <SelectBook 
+                platformKey={platform}
+                searchChapterDisabled={!yueWenCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId}
+                searchChapterLoading={getFreeChapterList.loading}
+                hanldeSearchChapter={getChapterList}
+
+            />
         </Form.Item>
 
         <Form.Item

+ 63 - 5
src/pages/weComTask/page/bookLink/index.tsx

@@ -1,11 +1,11 @@
-import { Button, DatePicker, Input, Pagination, Select, Table } from 'antd';
+import { App, Button, DatePicker, Input, Pagination, Popconfirm, Select, Table } from 'antd';
 import Card from 'antd/es/card/Card';
 import React, { useEffect, useRef, useState } from 'react';
-import { getCorpAutoLinkListApi, GetCorpAutoLinkListProps } from '../../API/bookLink';
+import { delAutoLinkApi, getCorpAutoLinkListApi, GetCorpAutoLinkListProps } from '../../API/bookLink';
 import style from './index.less'
 import { useAjax } from '@/Hook/useAjax';
 import SearchBox from '../../components/searchBox';
-import { SearchOutlined, PlusOutlined } from '@ant-design/icons';
+import { SearchOutlined, PlusOutlined, DeleteOutlined } from '@ant-design/icons';
 import { getBindMpListApi } from '../../API/corpUserAssign';
 import { inject, observer } from 'mobx-react';
 import { toJS } from 'mobx';
@@ -22,6 +22,7 @@ import dayJs from 'dayjs';
 const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookListProps[], bookPlatForm: TASK_CREATE.BookPlatFormProps[] } } }> = ({ weComTaskStore }) => {
 
     /******************************************/
+    const { message } = App.useApp()
     const { bookPlatForm } = toJS(weComTaskStore.data)
     const ref = useRef<HTMLDivElement>(null)
     const size = useSize(ref)
@@ -31,8 +32,10 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
     const [mpList, setMplist] = useState<{ label: string, value: number }[]>([])
     const [visible, setVisible] = useState<boolean>(false)
     const [initialValues, setInitialValues] = useState<any>()
+    const [selectedRows, setselectedRows] = useState<any[]>([])
 
     const getCorpAutoLinkList = useAjax((params) => getCorpAutoLinkListApi(params))
+    const delAutoLink = useAjax((params) => delAutoLinkApi(params))
     const getBindMpList = useAjax(() => getBindMpListApi())
     /******************************************/
 
@@ -83,7 +86,7 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
             case 5:
                 yueWenCreateLinkDTO.consumeActivityLinkDTO = {
                     ...linkContext,
-                    activityTheme: linkContext.activityTheme + '', 
+                    activityTheme: linkContext.activityTheme + '',
                     activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
                     display: linkContext?.display ? linkContext?.display?.split(',') : [],
                 }
@@ -97,6 +100,20 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
         setVisible(true)
     }
 
+    const handleDel = (value: { linkIds: number[] }) => {
+        const hide = message.loading('正在删除...', 0)
+        delAutoLink.run(value).then(res => {
+            hide()
+            setselectedRows([])
+            if (res?.data) {
+                message.success('删除成功')
+                getCorpAutoLinkList.refresh()
+            } else {
+                message.error('删除失败')
+            }
+        }).catch(() => hide())
+    }
+
     return <Card
         styles={{ body: { padding: 0, display: 'flex', flexDirection: 'column', height: 'calc(100vh - 74px)', overflow: 'hidden' } }}
     >
@@ -108,6 +125,13 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
                         setQueryParamsNew({ ...queryParams, pageNum: 1 })
                     }} loading={getCorpAutoLinkList.loading} icon={<SearchOutlined />}>搜索</Button>
                     <Button type="primary" icon={<PlusOutlined />} onClick={() => setVisible(true)}>链接生成</Button>
+                    <Popconfirm
+                        title="确定删除?"
+                        onConfirm={() => { handleDel({ linkIds : selectedRows.map(i => i.id) }) }}
+                        disabled={selectedRows.length === 0}
+                    >
+                        <Button type='primary' danger icon={<DeleteOutlined />} loading={delAutoLink.loading} disabled={selectedRows.length === 0}>删除</Button>
+                    </Popconfirm>
                 </>}
             >
                 <>
@@ -172,13 +196,47 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
         <div className={style.bookLinkTable} ref={ref}>
             <Table
                 dataSource={getCorpAutoLinkList?.data?.data?.records}
-                columns={bookLinkTableConfig(false, handleCopy)}
+                columns={bookLinkTableConfig(false, handleCopy, handleDel)}
                 bordered
                 pagination={false}
                 rowKey={'id'}
                 size='small'
                 loading={getCorpAutoLinkList?.loading}
                 scroll={{ y: size?.height && ref.current ? size?.height - ref.current.querySelector('.ant-table-thead').clientHeight : 300 }}
+                rowSelection={{
+                    selectedRowKeys: selectedRows?.map((item: any) => item?.id),
+                    onSelect: (record: { id: string }, selected: boolean) => {
+                        let newData = JSON.parse(JSON.stringify(selectedRows))
+                        if (selected) {
+                            newData.push({ ...record })
+                        } else {
+                            newData = newData.filter((item: { id: string }) => item.id !== record.id)
+                        }
+                        setselectedRows(newData)
+                    },
+                    onSelectAll: (selected: boolean, _: { id: string }[], changeRows: { id: string }[]) => {
+                        let newData = JSON.parse(JSON.stringify(selectedRows || '[]'))
+                        if (selected) {
+                            changeRows.forEach((item: { id: string }) => {
+                                let index = newData.findIndex((ite: { id: string }) => ite.id === item.id)
+                                if (index === -1) {
+                                    newData.push(item)
+                                }
+                            })
+                        } else {
+                            let newSelectAccData = newData.filter((item: { id: string }) => {
+                                let index = changeRows.findIndex((ite: { id: string }) => ite.id === item.id)
+                                if (index !== -1) {
+                                    return false
+                                } else {
+                                    return true
+                                }
+                            })
+                            newData = newSelectAccData
+                        }
+                        setselectedRows(newData)
+                    }
+                }}
             />
         </div>
         <div className={style.bookLinkPagination}>

+ 121 - 0
src/pages/weComTask/page/bookLink/selectBook.tsx

@@ -0,0 +1,121 @@
+import { useAjax } from '@/Hook/useAjax';
+import { App, Button, Flex, Input, InputProps, Modal, Space, Table, Tag } from 'antd';
+import React, { useCallback, useEffect, useState } from 'react';
+import { getAutoLinkBookListApi, GetAutoLinkBookListProps } from '../../API/bookLink';
+import { SearchOutlined } from '@ant-design/icons';
+
+interface SelectBookProps extends InputProps {
+    platformKey: string,
+    hanldeSearchChapter?: () => void;
+    searchChapterLoading?: boolean;
+    searchChapterDisabled?: boolean;
+}
+
+/**
+ * 书籍选择
+ * @param param0 
+ * @returns 
+ */
+const SelectBook: React.FC<SelectBookProps> = ({ platformKey, value, onChange, hanldeSearchChapter, searchChapterLoading, searchChapterDisabled, ...rest }) => {
+
+    /*******************************************/
+    const { message } = App.useApp()
+    const [visible, setVisible] = useState<boolean>(false)
+    const [queryForm, setQueryForm] = useState<GetAutoLinkBookListProps>({ pageNum: 1, pageSize: 20 })
+    const [queryFormNew, setQueryFormNew] = useState<GetAutoLinkBookListProps>({ pageNum: 1, pageSize: 20 })
+    const [selectedRows, setSelectedRows] = useState<any[]>([])
+
+    const getAutoLinkBookList = useAjax((params) => getAutoLinkBookListApi(params))
+    /*******************************************/
+
+    useEffect(() => {
+        if (visible && platformKey) {
+            getAutoLinkBookList.run({ ...queryFormNew, platformKey })
+        }
+    }, [visible, queryFormNew, platformKey])
+
+    const handleOk = useCallback(() => {
+        if (selectedRows.length) {
+            onChange?.(selectedRows[0])
+            setVisible(false)
+            setSelectedRows([])
+        } else {
+            message.warning('请选择书籍')
+        }
+    }, [selectedRows])
+
+    return <>
+        <Flex gap={10}>
+            <Space.Compact style={{ width: '100%' }}>
+                <Input
+                    placeholder="请输入作品(书籍)ID"
+                    style={{ width: '100%' }}
+                    {...rest}
+                    value={value}
+                    onChange={onChange}
+                />
+                <Button type="primary" disabled={!platformKey} onClick={() => setVisible(true)}>选择书</Button>
+            </Space.Compact>
+            <Button type="primary" loading={searchChapterLoading} disabled={searchChapterDisabled} onClick={() => hanldeSearchChapter?.()}>查询章节列表</Button>
+        </Flex>
+        {visible && <Modal
+            title={<strong>选择书籍</strong>}
+            open={visible}
+            onCancel={() => {
+                setVisible(false)
+                setSelectedRows([]);
+            }}
+            onOk={handleOk}
+            width={600}
+        >
+            <Flex gap={6} style={{ marginBottom: 10 }}>
+                <Input placeholder='书籍名称' allowClear value={queryForm.bookName} onChange={(e) => setQueryForm({ ...queryForm, bookName: e.target.value, pageNum: 1 })} />
+                <Input placeholder='书籍ID' allowClear value={queryForm.bookId} onChange={(e) => setQueryForm({ ...queryForm, bookId: e.target.value, pageNum: 1 })} />
+                <Button type="primary" onClick={() => {
+                    setQueryFormNew({ ...queryForm })
+                }} loading={getAutoLinkBookList.loading} icon={<SearchOutlined />}>搜索</Button>
+            </Flex>
+            <Table
+                dataSource={getAutoLinkBookList?.data?.data?.records}
+                columns={[
+                    {
+                        title: '书籍',
+                        dataIndex: 'bookName',
+                        key: 'bookName',
+                        render: (value, records: any) => {
+                            return <span style={{ fontSize: 12 }}>{value}({records.bookId})</span>
+                        }
+                    },
+                ]}
+                bordered
+                pagination={{
+                    total: getAutoLinkBookList.data?.data?.total,
+                    showTotal: (total) => <Tag color="cyan">总共{total}数据</Tag>,
+                    showSizeChanger: true,
+                    showLessItems: true,
+                    defaultCurrent: 1,
+                    defaultPageSize: 20,//默认初始的每页条数
+                    current: getAutoLinkBookList?.data?.data?.current || 1,
+                    pageSize: getAutoLinkBookList?.data?.data?.size || 20,
+                    onChange: (page, pageSize) => {
+                        setQueryForm({ ...queryForm, pageNum: page, pageSize })
+                        setQueryFormNew({ ...queryFormNew, pageNum: page, pageSize })
+                    }
+                }}
+                rowKey={'bookId'}
+                size='small'
+                loading={getAutoLinkBookList?.loading}
+                scroll={{ y: 400 }}
+                rowSelection={{
+                    selectedRowKeys: selectedRows,
+                    type: 'radio',
+                    onChange(selectedRowKeys) {
+                        setSelectedRows(selectedRowKeys)
+                    },
+                }}
+            />
+        </Modal>}
+    </>
+};
+
+export default React.memo(SelectBook);

+ 12 - 6
src/pages/weComTask/page/bookLink/tableConfig.tsx

@@ -1,11 +1,11 @@
 import { copy } from "@/utils/utils"
 import { ColumnsType } from "antd/es/table"
 import { LINKTYPEEle } from "./const"
-import { Button, Flex, Popover } from "antd"
+import { Button, Flex, Popconfirm, Popover } from "antd"
 import Details from "./details"
 
 
-export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any) => void): ColumnsType<any> {
+export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any) => void, handleDel?: (data: { linkIds: number[] }) => void): ColumnsType<any> {
 
     const arr: ColumnsType<any> = [
         {
@@ -13,7 +13,7 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             dataIndex: 'platformName',
             key: 'platformName',
             align: 'center',
-            width: 80,
+            width: 70,
             ellipsis: true,
             fixed: 'left',
             render: (value) => {
@@ -96,7 +96,7 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             dataIndex: 'createByInfo',
             key: 'createByInfo',
             align: 'center',
-            width: 80,
+            width: 70,
             render: (value) => {
                 return <span style={{ fontSize: 12 }}>{value?.nickname}</span>
             }
@@ -112,11 +112,11 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             }
         },
         {
-            title: '详情',
+            title: '操作',
             dataIndex: 'cz',
             key: 'cz',
             align: 'center',
-            width: 60,
+            width: 90,
             fixed: 'right',
             render: (_, records) => {
                 return <Flex gap={4} justify='center'>
@@ -128,6 +128,12 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
                         <Button type="link" style={{ padding: 0, height: 'auto' }}>详情</Button>
                     </Popover>
                     {!isSelect && <Button type="link" style={{ padding: 0, height: 'auto' }} onClick={() => handleCopy(records)}>复制</Button>}
+                    <Popconfirm
+                        title="确定删除?"
+                        onConfirm={() => { handleDel?.({ linkIds: [records.id] }) }}
+                    >
+                        <a style={{ color: 'red' }}>删除</a>
+                    </Popconfirm>
                 </Flex>
             }
         },

+ 1 - 23
src/pages/weComTask/page/businessPlan/create/components/welcome/index.tsx

@@ -288,29 +288,7 @@ const Welcome: React.FC = () => {
                 <div className={style.title}>
                     <span>欢迎语</span>
 
-                    {(mediaContentList?.some(item => item?.some(i => i?.mediaType === 'link' || i?.mediaType === 'miniprogram')) && settings?.corpUsers?.length) && <Space>
-                        <Button
-                            type="link"
-                            style={{ padding: 0, fontSize: 12 }}
-                            loading={downloadLoading}
-                            onClick={() => { exportExcel() }}
-                        >下载</Button>
-                        <Upload
-                            accept={'.xlsx'}
-                            action="#"
-                            showUploadList={false}
-                            customRequest={() => { }}
-                            beforeUpload={async (file: RcFile): Promise<any> => {
-                                readExcelContent(file)
-                                onPreviewReset()
-                            }}
-                        >
-                            <Button
-                                type="link"
-                                style={{ padding: 0, fontSize: 12 }}
-                            >{settings?.corpUsers?.every(item => item?.welcomeMsgContent && Object.keys(item.welcomeMsgContent).length) ? 'Excel内容已上传,重新上传' : '上传Excel'}</Button>
-                        </Upload>
-
+                    {(settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length > 0) && <Space>
                         <Button
                             type="link"
                             danger

+ 5 - 3
src/pages/weComTask/page/businessPlan/create/const.tsx

@@ -297,7 +297,7 @@ export const restoreGroupData = (groupSendTaskAddDTO: { [x: string]: any }, conf
 
         const sendContentDto = []
         const sendData = taskDetail.map(item1 => {
-            const { sendMode, contentDTO, externalUserFilter } = item1
+            const { sendMode, externalUserFilterName, contentDTO, externalUserFilter } = item1
             sendContentDto.push({
                 sendMode,
                 contentDTO: type === 'USER_GROUP' ? contentDTO : contentDTO.map(item2 => {
@@ -358,11 +358,13 @@ export const restoreGroupData = (groupSendTaskAddDTO: { [x: string]: any }, conf
                     externalUserFilter: {
                         configName,
                         configContent
-                    }
+                    },
+                    externalUserFilterName
                 }
             }
             return {
-                externalUserType: 'all'
+                externalUserType: 'all',
+                externalUserFilterName
             }
         })
 

+ 39 - 6
src/pages/weComTask/page/businessPlan/create/index.tsx

@@ -7,10 +7,10 @@ import { useAjax } from '@/Hook/useAjax';
 import { MediaContentProps, welcomeMsgJobTypeApi } from '@/pages/weComTask/API/weMaterial/weMaterial';
 import SelectCorpUser from '../../corpUserManage/selectCorpUser';
 import { SearchOutlined, PlusOutlined, RedoOutlined, SaveOutlined, CheckOutlined } from '@ant-design/icons';
-import { getGroupData, getHighGroupData, getUserInDataData } from './const';
+import { getGroupData, getHighGroupData, getUserInDataData, restoreGroupData, restoreUserInheritData } from './const';
 import { friendsColumns, highMassSendingColumns, massSendingColumns, userInheritColumns, welcomeColumns } from './tableConfig';
 import SubmitModal from './submitModal';
-import { addTaskApi } from '@/pages/weComTask/API/businessPlan/create';
+import { addTaskApi, getCreateDetailsApi, getProjectDetailsApi } from '@/pages/weComTask/API/businessPlan/create';
 import { useNavigate } from 'react-router-dom';
 import SelectExternalAccount from '@/pages/weComTask/components/selectExternalAccount';
 import Welcome from './components/welcome';
@@ -47,14 +47,47 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
     const welcomeMsgJobType = useAjax(() => welcomeMsgJobTypeApi())//获取欢迎语类型
 
     const addTask = useAjax((params) => addTaskApi(params))
+    const getCreateDetails = useAjax((params) => getCreateDetailsApi(params))
     const getBindMpList = useAjax(() => getBindMpListApi())
     /***********************************************/
     console.log('settings--->', settings, previewContent)
 
     useEffect(() => {
-        const task = localStorage.getItem('TASK_CORP_CREATE')
-        if (task) {
-            setSettings(JSON.parse(task).settings)
+        const projectId = sessionStorage.getItem('OFFICIALTASKID')
+        if (projectId) {
+            getCreateDetails.run(projectId).then(res => {
+                sessionStorage.removeItem('OFFICIALTASKID')
+                if (res?.data) {
+                    const { corpUsers, bizType, platform, templateProductId, welcomeMsgTemplateDTO, groupSendTaskAddDTO, externalUserTransferTasksDTO } = res.data
+                    let newSettings: TASK_CREATE.SettingsProps = {
+                        bizType,
+                        platform: Number(platform) as any,
+                        templateProductId,
+                        corpUserGroups: corpUsers.map(item => {
+                            return {
+                                corpUsers: item.corpUserList.map(({ corpUserId, name, corpId, mpAccountId, mpAccountInfo }) => {
+                                    return { corpUserId, name, corpName: item.corpName, corpId, mpAccountId, mpAccountName: mpAccountInfo?.name }
+                                })
+                            }
+                        }),
+                        welcomeMsgTemplateDTO
+                    }
+                    if (groupSendTaskAddDTO && Object.keys(groupSendTaskAddDTO).length > 0) {
+                        const data = restoreGroupData(groupSendTaskAddDTO)
+                        newSettings = { ...newSettings, ...data }
+                    }
+                    if (externalUserTransferTasksDTO && Object.keys(externalUserTransferTasksDTO)?.length > 0) {
+                        const data = restoreUserInheritData(externalUserTransferTasksDTO)
+                        newSettings.userInherit = data
+                    }
+                    setSettings(newSettings)
+                }
+            })
+        } else {
+            const task = localStorage.getItem('TASK_CORP_CREATE')
+            if (task) {
+                setSettings(JSON.parse(task).settings)
+            }
         }
     }, [])
 
@@ -807,7 +840,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
     }, [previewDataOld, previewData])
 
     return <div className={style.create}>
-        <Spin spinning={false}>
+        <Spin spinning={getCreateDetails.loading}>
             <Card title={<strong>配置区</strong>} className={`${style.card} ${style.config}`}>
                 <Space wrap>
                     <Space.Compact>

+ 94 - 4
src/pages/weComTask/page/businessPlan/taskList/index.tsx

@@ -1,10 +1,10 @@
 import { useAjax } from '@/Hook/useAjax';
-import { getProjectListApi } from '@/pages/weComTask/API/businessPlan/create';
-import { Button, Card, DatePicker, Input, Space, Table } from 'antd';
+import { cancelProjectApi, delProjectApi, getProjectListApi } from '@/pages/weComTask/API/businessPlan/create';
+import { Button, Card, DatePicker, Input, message, Popconfirm, Space, Table } from 'antd';
 import React, { useEffect, useState } from 'react';
 import taskListColumns from './tableConfig';
 import dayjs from 'dayjs';
-import { SearchOutlined } from '@ant-design/icons';
+import { SearchOutlined, DeleteOutlined, PauseCircleOutlined } from '@ant-design/icons';
 import Log from './log';
 import { inject, observer } from 'mobx-react';
 import { toJS } from 'mobx';
@@ -21,8 +21,11 @@ const TaskList: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
     const [queryForm, setQueryForm] = useState<BUSINES_SPLAN_API.GetProjectListProps>({ pageNum: 1, pageSize: 20, projectName })
     const [queryFormNew, setQueryFormNew] = useState<BUSINES_SPLAN_API.GetProjectListProps>({ pageNum: 1, pageSize: 20, projectName })
     const [logOpenData, setLogOpenData] = useState<{ visible: boolean, data: any }>({ visible: false, data: {} })
+    const [selectedRows, setselectedRows] = useState<any[]>([])
 
     const getProjectList = useAjax((params) => getProjectListApi(params))
+    const delProject = useAjax((params) => delProjectApi(params))
+    const cancelProject = useAjax((params) => cancelProjectApi(params))
     /***********************************************/
 
     useEffect(() => {
@@ -36,10 +39,49 @@ const TaskList: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
         getProjectList.run(queryFormNew)
     }, [queryFormNew])
 
+    // 日志
     const handleLog = (data: any) => {
         setLogOpenData({ visible: true, data })
     }
 
+    // 复制
+    const handleCopy = (data: any) => {
+        sessionStorage.setItem('OFFICIALTASKID', data.id)
+        window.location.href = '/weComTask#/weComTask/businessPlan/create'
+    }
+
+    // 删除
+    const handleDel = (data: { projectIds: number[] }, type: 'del' | 'cancel') => {
+        const hide = message.loading(type === 'del' ? '正在删除...' : '正在取消...', 0)
+        switch (type) {
+            case 'del':
+                delProject.run(data).then(res => {
+                    hide()
+                    setselectedRows([])
+                    if (res?.data) {
+                        message.success('删除成功')
+                        getProjectList.refresh()
+                    } else {
+                        message.error('删除失败')
+                    }
+                }).catch(() => hide())
+                break
+            case 'cancel':
+                cancelProject.run(data).then(res => {
+                    hide()
+                    setselectedRows([])
+                    if (res?.data) {
+                        message.success('取消成功')
+                        getProjectList.refresh()
+                    } else {
+                        message.error('取消失败')
+                    }
+                }).catch(() => hide())
+                break
+        }
+
+    }
+
     return <Card>
         <div style={{ display: 'flex', gap: 10, marginBottom: 10 }}>
             <Space.Compact>
@@ -71,10 +113,24 @@ const TaskList: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
                 }}
                 icon={<SearchOutlined />}
             >搜索</Button>
+            <Popconfirm
+                title="确定删除?"
+                onConfirm={() => { handleDel({ projectIds: selectedRows.map(i => i.id) }, 'del') }}
+                disabled={selectedRows.length === 0}
+            >
+                <Button type='primary' danger icon={<DeleteOutlined />} loading={delProject.loading} disabled={selectedRows.length === 0}>删除</Button>
+            </Popconfirm>
+            <Popconfirm
+                title="确定取消?"
+                onConfirm={() => { handleDel({ projectIds: selectedRows.map(i => i.id) }, 'cancel') }}
+                disabled={selectedRows.length === 0}
+            >
+                <Button type='primary' style={{ backgroundColor: 'orange', borderColor: 'orange' }} loading={cancelProject.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0}>取消任务</Button>
+            </Popconfirm>
         </div>
         <Table
             dataSource={getProjectList?.data?.data?.records}
-            columns={taskListColumns(bookPlatForm, bookList, handleLog)}
+            columns={taskListColumns(bookPlatForm, bookList, handleLog, handleCopy, handleDel)}
             rowKey={'id'}
             bordered={true}
             size='small'
@@ -89,6 +145,40 @@ const TaskList: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
                     setQueryForm({ ...queryForm, pageNum: page, pageSize })
                 }
             }}
+            rowSelection={{
+                selectedRowKeys: selectedRows?.map((item: any) => item?.id),
+                onSelect: (record: { id: string }, selected: boolean) => {
+                    let newData = JSON.parse(JSON.stringify(selectedRows))
+                    if (selected) {
+                        newData.push({ ...record })
+                    } else {
+                        newData = newData.filter((item: { id: string }) => item.id !== record.id)
+                    }
+                    setselectedRows(newData)
+                },
+                onSelectAll: (selected: boolean, _: { id: string }[], changeRows: { id: string }[]) => {
+                    let newData = JSON.parse(JSON.stringify(selectedRows || '[]'))
+                    if (selected) {
+                        changeRows.forEach((item: { id: string }) => {
+                            let index = newData.findIndex((ite: { id: string }) => ite.id === item.id)
+                            if (index === -1) {
+                                newData.push(item)
+                            }
+                        })
+                    } else {
+                        let newSelectAccData = newData.filter((item: { id: string }) => {
+                            let index = changeRows.findIndex((ite: { id: string }) => ite.id === item.id)
+                            if (index !== -1) {
+                                return false
+                            } else {
+                                return true
+                            }
+                        })
+                        newData = newSelectAccData
+                    }
+                    setselectedRows(newData)
+                }
+            }}
         />
 
         {/* 日志 */}

+ 30 - 3
src/pages/weComTask/page/businessPlan/taskList/tableConfig.tsx

@@ -1,4 +1,4 @@
-import { Popover, Space, Typography } from "antd";
+import { Flex, Popconfirm, Popover, Space, Typography } from "antd";
 import { AnyObject } from "antd/es/_util/type";
 import { ColumnsType } from "antd/es/table";
 import style from './index.less'
@@ -16,18 +16,32 @@ const taskListColumns = (
     bookPlatForm: any[],
     bookList: any[],
     handleLog: (data: any) => void,
+    handleCopy: (data: any) => void,
+    handleDel: (data: any, type: 'del' | 'cancel') => void,
 ): ColumnsType<AnyObject> => {
 
-
     return [
         {
             title: '操作',
             dataIndex: 'cz',
             key: 'cz',
-            width: 120,
+            width: 140,
             render(_, record) {
                 return <Space>
+                    <Popconfirm
+                        title="确定取消?"
+                        onConfirm={() => { handleDel({ projectIds: [record.id] }, 'cancel') }}
+                    >
+                        <a style={{ color: 'orange' }}>取消任务</a>
+                    </Popconfirm>
+                    <a onClick={() => handleCopy(record)}>复制</a>
                     <a onClick={() => handleLog(record)}>详情</a>
+                    <Popconfirm
+                        title="确定删除?"
+                        onConfirm={() => { handleDel({ projectIds: [record.id] }, 'del') }}
+                    >
+                        <a style={{ color: 'red' }}>删除</a>
+                    </Popconfirm>
                 </Space>
             },
         },
@@ -237,6 +251,19 @@ const taskListColumns = (
             width: 125,
             ellipsis: true
         },
+        {
+            title: '任务数量',
+            dataIndex: 'taskCount',
+            key: 'taskCount',
+            width: 260,
+            render(value, record) {
+                return <Flex gap={6}>
+                    <Text type={record.welcomeMsgCount > 0 ? 'success' : 'danger'}>欢迎语:{record.welcomeMsgCount}</Text>
+                    <Text type={record.groupSendTaskCount > 0 ? 'success' : 'danger'}>群发:{record.groupSendTaskCount}</Text>
+                    <Text type={record.externalUserTransferTaskCount > 0 ? 'success' : 'danger'}>客户继承:{record.externalUserTransferTaskCount}</Text>
+                </Flex>
+            },
+        },
     ]
 }