wjx 2 nedēļas atpakaļ
vecāks
revīzija
34acd0f098

+ 54 - 3
src/pages/weComTask/API/groupChat/index.ts

@@ -14,6 +14,31 @@ export async function addPullGroupTaskApi(data: GROUP_CHAT_API.AddPullGroupTaskP
     });
 }
 
+/**
+ * 计划修改
+ * @param param0 
+ * @returns 
+ */
+export async function updateGroupTaskApi({ projectId, ...data }: GROUP_CHAT_API.AddPullGroupTaskProps) {
+    return request({
+        url: api + `/corpOperation/corp/pullGroup/project/task/edit/${projectId}`,
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 详情
+ * @param data 
+ * @returns 
+ */
+export async function getCreateDetailsApi(projectId: number) {
+    return request({
+        url: api + `/corpOperation/corp/pullGroup/project/selectById/${projectId}`,
+        method: 'POST'
+    });
+}
+
 
 /**
  * 计划列表
@@ -29,7 +54,7 @@ export async function getProjectListApi(data: GROUP_CHAT_API.GetProjectListProps
 }
 
 /**
- * 任务日志
+ * 计划列表
  * @param projectId 
  * @returns 
  */
@@ -41,6 +66,32 @@ export async function getProjectLogListApi(projectId: number) {
 }
 
 
+/**
+ * 任务日志列表
+ * @param data 
+ * @returns 
+ */
+export async function getProjectTaskLogListApi(data: { pageNum: number, pageSize: number, taskId: number }) {
+    return request({
+        url: api + `/corpOperation/corp/pullGroup/project/logListOfPage`,
+        method: 'POST',
+        data
+    });
+}
+
+/**
+ * 任务日志详情列表
+ * @param data 
+ * @returns 
+ */
+export async function getProjectLogDetailsListApi(taskLogId: number) {
+    return request({
+        url: api + `/corpOperation/corp/pullGroup/project/logChatList/${taskLogId}`,
+        method: 'GET'
+    });
+}
+
+
 /**
  * 删除计划
  * @param params 
@@ -69,8 +120,8 @@ export async function cancelProjectApi(data: { projectIds: number[] }) {
 
 /**
  * 获取计划详情
- * @param projectId 
- * @returns 
+ * @param projectId
+ * @returns
  */
 // export async function getCreateDetailsApi(projectId: string) {
 //     return request({

+ 1 - 0
src/pages/weComTask/API/groupChat/typings.d.ts

@@ -3,6 +3,7 @@ declare namespace GROUP_CHAT_API {
         groupSendName: string; // 任务名称
         corpUsers: { [x: string]: any }[];
         strategyList: { [x: string]: any }[];
+        projectId?: number;
     }
     interface GetProjectListProps {
         pageNum: number,

+ 40 - 5
src/pages/weComTask/page/groupChat/create/components/groupUser/addGroupObject.tsx

@@ -3,7 +3,7 @@ import React, { useEffect, useState } from 'react';
 import { PlusOutlined, QuestionCircleFilled } from '@ant-design/icons';
 import FilterUser from '@/pages/weComTask/components/filterUser';
 import MindTags from '@/pages/weComTask/components/mindTags';
-import { getAllWxListApi, getBindMpListApi } from '@/pages/weComTask/API/corpUserAssign';
+import { getBindMpListApi } from '@/pages/weComTask/API/corpUserAssign';
 import { useAjax } from '@/Hook/useAjax';
 import FilterUserTooltip from '@/pages/weComTask/components/filterUser/filterUserTooltip';
 import { businessPlanData } from '@/pages/weComTask/page/businessPlan/create/const';
@@ -15,11 +15,14 @@ const { Text, Paragraph } = Typography;
  * @param param0 
  * @returns 
  */
-const AddGroupObject: React.FC<GROUP_CHAT_CREATE.AddGroupObjectProps> = ({ value = [], onChange, bookPlatForm, bookList }) => {
+const AddGroupObject: React.FC<GROUP_CHAT_CREATE.AddGroupObjectProps> = ({ value = [], onChange, onCopy, bookPlatForm, index, strategyList, bookList }) => {
 
     /******************************************/
+    const { message } = App.useApp();
     const [visible, setVisible] = useState<boolean>(false)
     const [initialValues, setInitialValues] = useState<any>(undefined)
+    const [copyData, setCopyData] = useState<{ visible?: boolean, data?: any }>()
+    const [copyIndex, setCopyIndex] = useState<number>()
     /******************************************/
 
     return <>
@@ -35,6 +38,10 @@ const AddGroupObject: React.FC<GROUP_CHAT_CREATE.AddGroupObjectProps> = ({ value
                 setInitialValues(record)
                 setVisible(true)
             }}
+            handleCopy={(record) => {
+                const newValue = { ...record, groupObjectName: `copy策略${index + 1}_` + record.groupObjectName }
+                setCopyData({ visible: true, data: newValue })
+            }}
         /> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} description='暂无群配置' />}
         <Button type="dashed" style={{ width: '100%' }} block icon={<PlusOutlined />} onClick={() => setVisible(true)}>新建群配置</Button>
         {visible && <AddGroupObjectModal
@@ -56,10 +63,35 @@ const AddGroupObject: React.FC<GROUP_CHAT_CREATE.AddGroupObjectProps> = ({ value
                 setInitialValues(undefined)
             }}
         />}
+        {copyData?.visible && <Modal
+            title={<strong>复制至</strong>}
+            open={copyData?.visible}
+            onCancel={() => setCopyData(undefined)}
+            onOk={() => {
+                if (copyIndex) {
+                    onCopy?.(copyData.data, copyIndex)
+                    setCopyData(undefined)
+                    setCopyIndex(undefined)
+                    setVisible(false)
+                } else {
+                    message.error('清选择复制到哪')
+                }
+            }}
+        >
+            <Select
+                style={{ width: '100%' }}
+                onChange={(e) => {
+                    setCopyIndex(e)
+                }}
+                placeholder="请选择复制到哪"
+                value={copyIndex}
+                options={strategyList.map((item, index) => ({ value: index + 1, label: item.strategyName }))}
+            />
+        </Modal>}
     </>
 };
 
-export const ShowGroupUserTable: React.FC<GROUP_CHAT_CREATE.ShowGroupUserTableProps> = React.memo(({ bookList, bookPlatForm, value, handleEdit, handleDelete, isPreview }) => {
+export const ShowGroupUserTable: React.FC<GROUP_CHAT_CREATE.ShowGroupUserTableProps> = React.memo(({ bookList, bookPlatForm, value, handleEdit, handleDelete, handleCopy, isPreview }) => {
 
     const columns: ColumnsType<any> = [
         {
@@ -80,7 +112,7 @@ export const ShowGroupUserTable: React.FC<GROUP_CHAT_CREATE.ShowGroupUserTablePr
                 return value ? <Space>
                     <Badge status="success" text="开启" />
                     <span>近{record.repairTimes}天</span>
-                </Space>: <Badge status="error" text="关闭" />
+                </Space> : <Badge status="error" text="关闭" />
             },
         },
         {
@@ -205,11 +237,14 @@ export const ShowGroupUserTable: React.FC<GROUP_CHAT_CREATE.ShowGroupUserTablePr
             title: '操作',
             dataIndex: 'cz',
             key: 'cz',
-            width: 75,
+            width: 100,
             fixed: 'right',
             align: 'center',
             render(_, record) {
                 return <Space>
+                    <a onClick={() => {
+                        handleCopy?.(record)
+                    }}>复制</a>
                     <a onClick={() => {
                         handleEdit?.(record)
                     }}>修改</a>

+ 21 - 1
src/pages/weComTask/page/groupChat/create/components/groupUser/settingsGroupUser.tsx

@@ -154,7 +154,27 @@ const SettingsGroupUser: React.FC<GROUP_CHAT_CREATE.FoundationProps<any>> = ({ v
                                         name={[name, 'groupObjectList']}
                                         rules={[{ required: true, message: '请新增群配置!' }]}
                                     >
-                                        <AddGroupObject bookPlatForm={bookPlatForm} bookList={bookList} />
+                                        <AddGroupObject
+                                            bookPlatForm={bookPlatForm}
+                                            bookList={bookList}
+                                            strategyList={strategyList}
+                                            index={index}
+                                            onCopy={(data, index) => {
+                                                form.setFieldsValue({
+                                                    strategyList: strategyList.map((item, i) => {
+                                                        if (i === index - 1) {
+                                                            const groupObjectList = item?.groupObjectList || []
+                                                            groupObjectList.push(data)
+                                                            return {
+                                                                ...item,
+                                                                groupObjectList
+                                                            }
+                                                        }
+                                                        return item
+                                                    })
+                                                })
+                                            }}
+                                        />
                                     </Form.Item>
                                 </Card>
                             })}

+ 79 - 26
src/pages/weComTask/page/groupChat/create/index.tsx

@@ -16,8 +16,9 @@ import { getBindMpListApi } from '@/pages/weComTask/API/corpUserAssign';
 import { getCorpAllListApi } from '@/API/global';
 import { removeEmptyValues } from '@/utils/utils';
 import SubmitModal from '../../businessPlan/create/submitModal';
-import { addPullGroupTaskApi } from '@/pages/weComTask/API/groupChat';
+import { addPullGroupTaskApi, getCreateDetailsApi, updateGroupTaskApi } from '@/pages/weComTask/API/groupChat';
 import { useNavigate } from 'react-router-dom';
+import { getPullGroupData } from './const';
 
 export const DispatchGroupChatCreate = React.createContext<GROUP_CHAT_CREATE.DispatchGroupChatCreate | null>(null);
 
@@ -46,6 +47,8 @@ const GroupChatCreate: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREAT
     const getBindMpList = useAjax(() => getBindMpListApi())
     const getCorpAllList = useAjax((params) => getCorpAllListApi(params))
     const addPullGroupTask = useAjax((params) => addPullGroupTaskApi(params))
+    const updateGroupTask = useAjax((params) => updateGroupTaskApi(params))
+    const getCreateDetails = useAjax((params) => getCreateDetailsApi(params))
     /***********************************************/
     console.log('settings--->', settings)
 
@@ -56,12 +59,48 @@ const GroupChatCreate: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREAT
             if (!isCopy) {
                 setProjectId(id)
             }
-            // getCreateDetails.run(id).then(res => {
-            //     sessionStorage.removeItem('OFFICIALTASKID')
-            //     if (res?.data) {
-
-            //     }
-            // })
+            getCreateDetails.run(id).then(res => {
+                sessionStorage.removeItem('PG_OFFICIALTASKID')
+                if (res?.data) {
+                    const { bizType, platform, templateProductId, corpUsers, corpChatUserList, corpRobots, strategyList } = res.data
+                    const data = getPullGroupData(strategyList || [])
+                    let newSettings: GROUP_CHAT_CREATE.SettingsProps = {
+                        bizType,
+                        platform: Number(platform) as any,
+                        templateProductId,
+                        corpUserChat: corpChatUserList.map(item => {
+                            return {
+                                label: `${item.name}(${item.corpName})`,
+                                value: item.id,
+                                name: item.name,
+                                corpName: item.corpName,
+                                corpId: item.corpId,
+                                corpUserId: item.corpUserId
+                            }
+                        }),
+                        corpUsers: corpUsers?.map(item => {
+                            return {
+                                name: item.corpUserName,
+                                corpUserId: item.corpUserId,
+                                corpName: item.corpName,
+                                corpId: item.corpId
+                            }
+                        }),
+                        robotCorpUsers: corpRobots?.map(item => {
+                            return {
+                                name: item.corpUserName,
+                                corpUserId: item.corpUserId,
+                                corpName: item.corpName,
+                                corpId: item.corpId
+                            }
+                        }),
+                        strategyDTO: {
+                            ...data
+                        }
+                    }
+                    setSettings(newSettings)
+                }
+            })
         } else {
             const task = localStorage.getItem('TASK_GROUP_CHAT_CREATE')
             if (task) {
@@ -226,29 +265,42 @@ const GroupChatCreate: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREAT
             })
         }
         console.log('提交参数--->', params)
-        addPullGroupTask.run(params).then(res => {
-            console.log(res)
-            if (res?.data) {
-                modal.success({
-                    content: '任务提交成功',
-                    styles: { body: { fontWeight: 700 } },
-                    okText: '跳转任务列表',
-                    closable: true,
-                    onOk: () => {
-                        sessionStorage.setItem('CAMPCORP_PG', values?.projectName)
-                        navigate('/weComTask/groupChat/taskList')
-                    },
-                    onCancel: () => {
-                        setSubVisible(false)
-                    }
-                })
-            }
-        })
+        if (projectId) {
+            params.projectId = projectId
+            updateGroupTask.run(params).then(res => {
+                console.log(res)
+                if (res?.data) {
+                    message.success('修改提交成功')
+                    setProjectId(undefined)
+                    sessionStorage.setItem('CAMPCORP_PG', values?.projectName)
+                    navigate('/weComTask/groupChat/taskList')
+                }
+            })
+        } else {
+            addPullGroupTask.run(params).then(res => {
+                console.log(res)
+                if (res?.data) {
+                    modal.success({
+                        content: '任务提交成功',
+                        styles: { body: { fontWeight: 700 } },
+                        okText: '跳转任务列表',
+                        closable: true,
+                        onOk: () => {
+                            sessionStorage.setItem('CAMPCORP_PG', values?.projectName)
+                            navigate('/weComTask/groupChat/taskList')
+                        },
+                        onCancel: () => {
+                            setSubVisible(false)
+                        }
+                    })
+                }
+            })
+        }
     }
 
     return <div className={style.create}>
         <Spin spinning={false}>
-            <Card title={<strong>配置区</strong>} className={`${style.card} ${style.config}`}>
+            <Card title={<strong>{projectId ? getCreateDetails?.data?.data?.taskName + '任务编辑' : ''}配置区</strong>} className={`${style.card} ${style.config}`}>
                 <Space wrap>
                     <Space.Compact>
                         <Button>群主号</Button>
@@ -514,6 +566,7 @@ const GroupChatCreate: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREAT
         {subVisible && <SubmitModal
             visible={subVisible}
             loading={addPullGroupTask.loading}
+            projectName={projectId ? getCreateDetails?.data?.data?.taskName : undefined}
             onChange={(values) => {
                 onSubmit(values)
             }}

+ 4 - 0
src/pages/weComTask/page/groupChat/create/typings.d.ts

@@ -32,8 +32,11 @@ declare namespace GROUP_CHAT_CREATE {
     interface AddGroupObjectProps {
         bookPlatForm: TASK_CREATE.BookPlatFormProps[]
         bookList: TASK_CREATE.BookListProps[]
+        strategyList: any
+        index: number
         value?: { [x: string]: any }[];
         onChange?: (value: { [x: string]: any }[]) => void;
+        onCopy?: (data: any, copyIndex: number) => void
     }
     interface ShowGroupUserTableProps {
         bookPlatForm: TASK_CREATE.BookPlatFormProps[]
@@ -42,6 +45,7 @@ declare namespace GROUP_CHAT_CREATE {
         handleEdit?: (data: { [x: string]: any }) => void
         handleDelete?: (id: number) => void
         isPreview?: boolean
+        handleCopy?: (data: any) => void
     }
     interface AddGroupObjectModalProps {
         initialValues?: any;

+ 163 - 16
src/pages/weComTask/page/groupChat/taskList/details.tsx

@@ -1,12 +1,12 @@
 import { useAjax } from "@/Hook/useAjax"
-import { getProjectLogListApi } from "@/pages/weComTask/API/groupChat"
+import { getProjectLogDetailsListApi, getProjectLogListApi, getProjectTaskLogListApi } from "@/pages/weComTask/API/groupChat"
 import FilterUserTooltip from "@/pages/weComTask/components/filterUser/filterUserTooltip";
-import { Badge, Drawer, Popover, Space, Table, Typography } from "antd"
-import React, { useEffect } from "react"
+import { Badge, Button, Drawer, Flex, Modal, Popover, Space, Table, Typography } from "antd"
+import React, { useEffect, useState } from "react"
 import { QuestionCircleFilled } from "@ant-design/icons"
 import { businessPlanData, TIME_TYPE_ZJ } from "../../businessPlan/create/const";
 import PreviewTime from "@/pages/weComTask/components/previewTime";
-const { Text, Paragraph } = Typography;
+const { Text, Paragraph, Title } = Typography;
 
 interface Props {
     data: any,
@@ -23,12 +23,14 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
     /*******************************************/
 
     useEffect(() => {
-        console.log(data.id)
         getProjectLogList.run(data.id)
     }, [])
 
     return <Drawer
-        title={<strong>{data.taskName} 任务详情</strong>}
+        title={<Space>
+            <strong>{data.taskName} 运营计划</strong>
+            <Button type="link" onClick={() => getProjectLogList.refresh()}>刷新</Button>
+        </Space>}
         onClose={onClose}
         open={visible}
         width={1400}
@@ -73,6 +75,7 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
                                 content={<div>
                                     <PreviewTime
                                         {...records}
+                                        sendTime={records?.sendTime || records?.repeatSendTime}
                                     />
                                 </div>}
                                 styles={{ body: { width: 300, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
@@ -97,12 +100,12 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
                 },
                 {
                     title: '进群对象',
-                    dataIndex: 'externalUserFilter',
-                    key: 'externalUserFilter',
+                    dataIndex: 'corpCondition',
+                    key: 'corpCondition',
                     width: 90,
                     align: 'center',
                     render(value) {
-                        return value ? <div style={{ display: 'flex', alignItems: 'center' }}>
+                        return !value?.[0]?.allCorpUser ? <div style={{ display: 'flex', alignItems: 'center' }}>
                             <div style={{ flex: '1 0', overflow: 'hidden' }}>
                                 <Text ellipsis>指定</Text>
                             </div>
@@ -112,8 +115,8 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
                                 mouseEnterDelay={0.5}
                                 content={<FilterUserTooltip
                                     bookCityList={bookPlatForm?.map(item => ({ label: item.platformName, value: item.platformKey }))}
-                                    configName={value?.configName}
-                                    data={value?.configContent}
+                                    configName={'进群对象'}
+                                    data={value?.[0]}
                                 />}
                             >
                                 <a style={{ color: '#000' }}><QuestionCircleFilled /></a>
@@ -167,13 +170,13 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
                 },
                 {
                     title: '群聊关联公众号',
-                    dataIndex: 'weChatAppid',
-                    key: 'weChatAppid',
+                    dataIndex: 'mpAccountInfo',
+                    key: 'mpAccountInfo',
                     width: 100,
                     align: 'center',
                     ellipsis: true,
                     render(value) {
-                        return value || '--'
+                        return value?.name || '--'
                     },
                 },
                 {
@@ -188,8 +191,8 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
                 },
                 {
                     title: '拉群完成后群聊智能标签',
-                    dataIndex: 'tagDTO',
-                    key: 'tagDTO',
+                    dataIndex: 'msgTagDTO',
+                    key: 'msgTagDTO',
                     width: 200,
                     ellipsis: true,
                     render(value) {
@@ -225,8 +228,152 @@ const Details: React.FC<Props> = ({ data, bookPlatForm, bookList, visible, onClo
                     }
                 }
             ]}
+            expandable={{
+                fixed: 'left',
+                expandRowByClick: true,
+                expandedRowRender: (record) => <ExpandedRow record={record} />
+            }}
         />
     </Drawer>
 }
 
+const ExpandedRow: React.FC<{ record: any }> = ({ record }) => {
+
+    /*****************************************/
+    const [detalisData, setDetalisData] = useState<{visible?: boolean, taskLogId?: number}>()
+    const [queryForm, setQueryForm] = useState<{ pageNum: number, pageSize: number }>({ pageNum: 1, pageSize: 20 })
+    const getProjectTaskLogList = useAjax((params) => getProjectTaskLogListApi(params))
+    /*****************************************/
+
+    useEffect(() => {
+        getProjectTaskLogList.run({ ...queryForm, taskId: record.id })
+    }, [record.id, queryForm])
+
+    return <div style={{ maxHeight: 450 }}>
+        <Flex gap={20} align="center" style={{ marginBottom: 10, marginTop: 5 }}>
+            <Title level={4} style={{ margin: 0 }}>{record?.taskName} 任务列表</Title>
+            <Button type="link" onClick={() => getProjectTaskLogList.refresh()}>刷新</Button>
+        </Flex>
+        <Table
+            size='small'
+            bordered
+            rowKey={'id'}
+            dataSource={getProjectTaskLogList?.data?.data?.records}
+            loading={getProjectTaskLogList.loading}
+            scroll={{ x: 400, y: 350 }}
+            columns={[
+                {
+                    title: '操作',
+                    dataIndex: 'cz',
+                    key: 'cz',
+                    width: 80,
+                    align: 'center',
+                    render(_, record: any) {
+                        return <a onClick={() => setDetalisData({ visible: true, taskLogId: record.id })}>详情</a>
+                    }
+                },
+                {
+                    title: '预计拉群数',
+                    dataIndex: 'pullGroupCount',
+                    key: 'pullGroupCount',
+                    width: 120
+                },
+                {
+                    title: '预计拉群客户数',
+                    dataIndex: 'pullGroupUserCount',
+                    key: 'pullGroupUserCount',
+                    width: 120
+                },
+                {
+                    title: '执行时间',
+                    dataIndex: 'createTime',
+                    key: 'createTime'
+                }
+            ]}
+            pagination={{
+                total: getProjectTaskLogList?.data?.data?.total || 0,
+                current: queryForm.pageNum,
+                pageSize: queryForm.pageSize,
+                showTotal: (total) => `共 ${total} 条数据`,
+                onChange: (pageNum, pageSize) => setQueryForm({ pageNum, pageSize })
+            }}
+        />
+
+        {/* 详情 */}
+        {detalisData?.visible && <TaskDetails 
+            {...detalisData}
+            onClose={() => setDetalisData(undefined)}
+        />}
+    </div>
+}
+
+
+const TaskDetails: React.FC<{
+    visible?: boolean,
+    taskLogId?: number,
+    onClose?: () => void
+}> = ({visible, taskLogId, onClose}) => {
+
+    /*******************************************/
+    const getProjectLogDetailsList = useAjax((params) => getProjectLogDetailsListApi(params))
+    /*******************************************/
+
+    useEffect(() => {
+        getProjectLogDetailsList.run(taskLogId)
+    }, [taskLogId])
+
+    return <Modal
+        title={<strong>任务详情</strong>}
+        open={visible}
+        onCancel={onClose}
+        width={900}
+        footer={null}
+    >
+        <Table
+            size='small'
+            bordered
+            rowKey={'id'}
+            dataSource={getProjectLogDetailsList?.data?.data || []}
+            scroll={{ y: 1000 }}
+            columns={[
+                {
+                    title: '群名称',
+                    dataIndex: 'chatName',
+                    key: 'chatName',
+                    width: 120,
+                    ellipsis: true,
+                },
+                {
+                    title: '群主号名称',
+                    dataIndex: 'corpUserName',
+                    key: 'corpUserName',
+                    width: 120,
+                    ellipsis: true,
+                },
+                {
+                    title: '预计拉群客户数',
+                    dataIndex: 'pullGroupUserCount',
+                    key: 'pullGroupUserCount',
+                    width: 80,
+                    align: 'center'
+                },
+                {
+                    title: '实际拉群客户数',
+                    dataIndex: 'actualPullGroupUserCount',
+                    key: 'actualPullGroupUserCount',
+                    width: 80,
+                    align: 'center'
+                },
+                {
+                    title: '删除或拉黑客户数',
+                    dataIndex: 'deleteOrBlockUserCount',
+                    key: 'deleteOrBlockUserCount',
+                    width: 80,
+                    align: 'center'
+                }
+            ]}
+        />
+    </Modal>
+}
+
 export default React.memo(Details)