wjx 1 неделя назад
Родитель
Сommit
40101b832d

+ 19 - 0
src/pages/weComTask/API/global.ts

@@ -267,4 +267,23 @@ export async function getGameListNewApi(data: { sourceSystem: string }) {
         method: 'POST',
         data
     });
+}
+
+
+// 根据书城获取书籍
+export async function getBookListApi(data: { pageNum: number, pageSize: number, platformKey: string, bookName?: string  }) {
+    return request({
+        url: `/corp/externalUser/platform/bookList`,
+        method: 'POST',
+        data
+    });
+}
+
+// 根据书城书籍获取章节
+export async function getBookChapterListListApi(data: { pageNum: number, pageSize: number, platformKey: string, bookName: string, chapterName?: string  }) {
+    return request({
+        url: `/corp/externalUser/platform/chapterList`,
+        method: 'POST',
+        data
+    });
 }

+ 136 - 0
src/pages/weComTask/components/SelectBook/index.tsx

@@ -0,0 +1,136 @@
+import { useAjax } from "@/Hook/useAjax"
+import { Button, Col, Input, Modal, Row, Space, Table, Tag, Typography } from "antd"
+import React, { useEffect, useState } from "react"
+import { getBookListApi } from "../../API/global"
+
+interface Props {
+    platformKey?: string
+    value?: string[],
+    onChange?: (value?: string[]) => void
+}
+
+/**
+ * 选择书籍
+ * @returns 
+ */
+const SelectBook: React.FC<Props> = ({ platformKey, value, onChange }) => {
+
+    /**************************************/
+    const [queryForm, setQueryForm] = useState<{ pageNum: number, pageSize: number, bookName?: string }>({ pageNum: 1, pageSize: 20 })
+    const [queryFormNew, setQueryFormNew] = useState<{ pageNum: number, pageSize: number, bookName?: string }>({ pageNum: 1, pageSize: 20 })
+    const [visible, setVisible] = useState<boolean>(false)
+    const [selectedRow, setSelectedRow] = useState<any[]>([])//选择下发企微号
+
+    const getBookList = useAjax((params) => getBookListApi(params))
+    /**************************************/
+
+    useEffect(() => {
+        if (value && value?.length > 0) {
+            setSelectedRow(value.map(item => ({ bookName: item })))
+        } else {
+            setSelectedRow([])
+        }
+    }, [value])
+
+    useEffect(() => {
+        if (platformKey) {
+            getBookList.run({ ...queryForm, platformKey })
+        }
+    }, [queryForm, platformKey])
+
+    const handleOk = () => {
+        onChange?.(selectedRow?.length > 0 ? selectedRow.map(item => item.bookName) : undefined)
+        setVisible(false)
+    }
+
+    return <div style={{ width: '100%', display: 'flex', alignItems: 'center' }}>
+        {(value && value?.length > 0) && <div style={{ maxWidth: 'calc(100% - 72px)', marginRight: 8 }}><Typography.Text ellipsis={{ tooltip: true }}>{value?.toString()}</Typography.Text></div>}
+        <Button type="primary" disabled={!platformKey} onClick={() => { setQueryForm({ ...queryForm, pageNum: 1 }); setVisible(true) }}>{(value && value?.length > 0) ? '修改书籍' : '选择书籍'}</Button>
+
+        {visible && <Modal
+            title="选择书籍"
+            open={visible}
+            onCancel={() => setVisible(false)}
+            onOk={handleOk}
+        >
+            <Space direction="vertical" style={{ width: '100%' }}>
+                <Space>
+                    <Input placeholder="请输入书名" allowClear value={queryFormNew?.bookName} onChange={(e) => setQueryFormNew({ ...queryFormNew, bookName: e.target.value, pageNum: 1 })} />
+                    <Button type="primary" onClick={() => setQueryForm({ ...queryFormNew })}>搜索</Button>
+                </Space>
+                <Row>
+                    <Col span={17}>
+                        <Table
+                            style={{ marginBottom: 1 }}
+                            dataSource={getBookList?.data?.data?.records?.map((item: any, index: number) => ({ bookName: item, id: item + '_' + index }))}
+                            columns={[{
+                                title: '书名',
+                                dataIndex: 'bookName',
+                                key: 'bookName',
+                            }]}
+                            scroll={{ y: 400 }}
+                            rowKey={'bookName'}
+                            size='small'
+                            loading={getBookList.loading}
+                            bordered
+                            rowSelection={{
+                                type: 'checkbox',
+                                onSelect: (rocord, selected, rows) => {
+                                    if (selected) {
+                                        setSelectedRow([...selectedRow, rocord])
+                                    } else {
+                                        setSelectedRow(selectedRow?.filter(item => item.bookName !== rocord?.bookName))
+                                    }
+                                },
+                                onSelectAll: (selected, _, changeRows) => {
+                                    if (selected) {
+                                        setSelectedRow([...selectedRow, ...changeRows])
+                                    } else {
+                                        let arr = selectedRow?.filter(item => changeRows?.every(i => i.bookName !== item.bookName))
+                                        setSelectedRow(arr)
+                                    }
+                                },
+                                selectedRowKeys: selectedRow?.map(item => item?.bookName),
+                                getCheckboxProps: (record: any) => ({
+                                    name: record?.bookName
+                                }),
+                            }}
+                            pagination={{
+                                total: getBookList?.data?.data?.total,
+                                showTotal: (total) => <Tag color="cyan">总共{total}数据</Tag>,
+                                showSizeChanger: true,
+                                showLessItems: true,
+                                defaultCurrent: 1,
+                                defaultPageSize: 200,//默认初始的每页条数
+                                current: getBookList?.data?.data?.current || 1,
+                                pageSize: getBookList?.data?.data?.size || 20,
+                                onChange: (page, pageSize) => {
+                                    setQueryForm({ ...queryForm, pageNum: page, pageSize })
+                                }
+                            }}
+                        />
+                    </Col>
+                    <Col span={7} style={{ paddingLeft: 6 }}>
+                        <Space style={{ width: '100%' }} direction="vertical">
+                            <div style={{ display: 'flex', justifyContent: 'space-between' }}><Typography.Text>已选:({selectedRow.length || 0})</Typography.Text><a onClick={() => { setSelectedRow([]) }}>清空选择</a></div>
+                            <div style={{ maxHeight: 430, overflow: 'hidden', overflowY: 'auto' }}>
+                                {selectedRow?.map(item => {
+                                    return <div key={item?.bookName} style={{ marginBottom: 5 }}>
+                                        <Tag closable onClose={(e) => {
+                                            e.preventDefault();
+                                            setSelectedRow([...selectedRow.filter(s => s?.bookName !== item?.bookName)])
+                                        }} style={{ padding: 5 }}>
+                                            <div style={{ maxWidth: 110, display: 'inline-block' }}><Typography.Text ellipsis={{ tooltip: true }}>{item?.bookName}</Typography.Text></div>
+                                        </Tag>
+                                    </div>
+                                })}
+                            </div>
+                        </Space>
+                    </Col>
+                </Row>
+            </Space>
+        </Modal>}
+    </div>
+}
+
+export default React.memo(SelectBook)

+ 139 - 0
src/pages/weComTask/components/SelectChapter/index.tsx

@@ -0,0 +1,139 @@
+import { useAjax } from "@/Hook/useAjax"
+import { Button, Col, Input, Modal, Row, Space, Table, Tag, Typography } from "antd"
+import React, { useEffect, useState } from "react"
+import { getBookChapterListListApi } from "../../API/global"
+
+interface Props {
+    bookName?: string
+    platformKey?: string
+    value?: string[],
+    onChange?: (value?: string[]) => void
+}
+
+/**
+ * 选择书籍
+ * @returns 
+ */
+const SelectChapter: React.FC<Props> = ({ bookName, platformKey, value, onChange }) => {
+
+    /**************************************/
+    const [queryForm, setQueryForm] = useState<{ pageNum: number, pageSize: number, chapterName?: string }>({ pageNum: 1, pageSize: 20 })
+    const [queryFormNew, setQueryFormNew] = useState<{ pageNum: number, pageSize: number, chapterName?: string }>({ pageNum: 1, pageSize: 20 })
+    const [visible, setVisible] = useState<boolean>(false)
+    const [selectedRow, setSelectedRow] = useState<any[]>([])//选择下发企微号
+
+    const getBookChapterListList = useAjax((params) => getBookChapterListListApi(params))
+    /**************************************/
+
+    useEffect(() => {
+        if (value && value?.length > 0) {
+            setSelectedRow(value.map(item => ({ chapterName: item })))
+        } else {
+            setSelectedRow([])
+        }
+    }, [value])
+
+    useEffect(() => {
+        if (bookName) {
+            getBookChapterListList.run({ ...queryForm, platformKey, bookName })
+        } else if (getBookChapterListList?.data) {
+            getBookChapterListList.mutate({ data: { records: [], size: 20, total: 0, pages: 0, current: 1 } })
+        }
+    }, [queryForm, platformKey, bookName])
+
+    const handleOk = () => {
+        onChange?.(selectedRow?.length > 0 ? selectedRow.map(item => item.chapterName) : undefined)
+        setVisible(false)
+    }
+
+    return <div style={{ width: '100%', display: 'flex', alignItems: 'center' }}>
+        {(value && value?.length > 0) && <div style={{ maxWidth: 'calc(100% - 72px)', marginRight: 8 }}><Typography.Text ellipsis={{ tooltip: true }}>{value?.toString()}</Typography.Text></div>}
+        <Button type="primary" disabled={!platformKey} onClick={() => { setQueryForm({ ...queryForm, pageNum: 1 }); setVisible(true) }}>{(value && value?.length > 0) ? '修改章节' : '选择章节'}</Button>
+
+        {visible && <Modal
+            title="选择章节"
+            open={visible}
+            onCancel={() => setVisible(false)}
+            onOk={handleOk}
+        >
+            <Space direction="vertical" style={{ width: '100%' }}>
+                <Space>
+                    <Input placeholder="请输入章节名" allowClear value={queryFormNew?.chapterName} onChange={(e) => setQueryFormNew({ ...queryFormNew, chapterName: e.target.value, pageNum: 1 })} />
+                    <Button type="primary" onClick={() => setQueryForm({ ...queryFormNew })}>搜索</Button>
+                </Space>
+                <Row>
+                    <Col span={17}>
+                        <Table
+                            style={{ marginBottom: 1 }}
+                            dataSource={getBookChapterListList?.data?.data?.records?.map((item: any, index: number) => ({ chapterName: item, id: item + '_' + index }))}
+                            columns={[{
+                                title: '章节',
+                                dataIndex: 'chapterName',
+                                key: 'chapterName',
+                            }]}
+                            scroll={{ y: 400 }}
+                            rowKey={'chapterName'}
+                            size='small'
+                            loading={getBookChapterListList.loading}
+                            bordered
+                            rowSelection={{
+                                type: 'checkbox',
+                                onSelect: (rocord, selected, rows) => {
+                                    if (selected) {
+                                        setSelectedRow([...selectedRow, rocord])
+                                    } else {
+                                        setSelectedRow(selectedRow?.filter(item => item.chapterName !== rocord?.chapterName))
+                                    }
+                                },
+                                onSelectAll: (selected, _, changeRows) => {
+                                    if (selected) {
+                                        setSelectedRow([...selectedRow, ...changeRows])
+                                    } else {
+                                        let arr = selectedRow?.filter(item => changeRows?.every(i => i.chapterName !== item.chapterName))
+                                        setSelectedRow(arr)
+                                    }
+                                },
+                                selectedRowKeys: selectedRow?.map(item => item?.chapterName),
+                                getCheckboxProps: (record: any) => ({
+                                    name: record?.chapterName
+                                }),
+                            }}
+                            pagination={{
+                                total: getBookChapterListList?.data?.data?.total,
+                                showTotal: (total) => <Tag color="cyan">总共{total}数据</Tag>,
+                                showSizeChanger: true,
+                                showLessItems: true,
+                                defaultCurrent: 1,
+                                defaultPageSize: 200,//默认初始的每页条数
+                                current: getBookChapterListList?.data?.data?.current || 1,
+                                pageSize: getBookChapterListList?.data?.data?.size || 20,
+                                onChange: (page, pageSize) => {
+                                    setQueryForm({ ...queryForm, pageNum: page, pageSize })
+                                }
+                            }}
+                        />
+                    </Col>
+                    <Col span={7} style={{ paddingLeft: 6 }}>
+                        <Space style={{ width: '100%' }} direction="vertical">
+                            <div style={{ display: 'flex', justifyContent: 'space-between' }}><Typography.Text>已选:({selectedRow.length || 0})</Typography.Text><a onClick={() => { setSelectedRow([]) }}>清空选择</a></div>
+                            <div style={{ maxHeight: 430, overflow: 'hidden', overflowY: 'auto' }}>
+                                {selectedRow?.map(item => {
+                                    return <div key={item?.chapterName} style={{ marginBottom: 5 }}>
+                                        <Tag closable onClose={(e) => {
+                                            e.preventDefault();
+                                            setSelectedRow([...selectedRow.filter(s => s?.chapterName !== item?.chapterName)])
+                                        }} style={{ padding: 5 }}>
+                                            <div style={{ maxWidth: 110, display: 'inline-block' }}><Typography.Text ellipsis={{ tooltip: true }}>{item?.chapterName}</Typography.Text></div>
+                                        </Tag>
+                                    </div>
+                                })}
+                            </div>
+                        </Space>
+                    </Col>
+                </Row>
+            </Space>
+        </Modal>}
+    </div>
+}
+
+export default React.memo(SelectChapter)

+ 27 - 2
src/pages/weComTask/components/filterUser/filterUserText.ts

@@ -5,6 +5,8 @@ const targetingData = [
     { key: 'msgTagIds', name: '智能标签' },
     { key: 'msgExcludeTagIds', name: '排除智能标签' },
     { key: 'platformKey', name: '书城' },
+    { key: 'lastBookNameList', name: '最近阅读书籍' },
+    { key: 'lastChapterNameList', name: '最近阅读章节' },
     { key: 'platformUserId', name: '书城用户ID' },
     { key: 'rechargeBook', name: '充值小说' },
     { key: 'begin', name: '关注时间' },
@@ -17,6 +19,8 @@ const targetingData = [
     { key: 'subHour', name: '关注距今时间' },
     { key: 'subDay', name: '关注距今天' },
     { key: 'lastRechargeHour', name: '最近充值时间距今(小时)' },
+    { key: 'lastReadTime', name: '最近阅读时间' },
+    { key: 'lastReadHour', name: '最近阅读至今(小时)' },
     { key: 'opers', name: '手机系统' }
 ]
 
@@ -32,6 +36,8 @@ interface ContentProps {
     msgTagIds?: { [x: string]: string }[], // 智能标签
     msgExcludeTagIds?: { [x: string]: string }[], // 排除智能标签
     platformKey?: string,   // 书城
+    lastBookNameList?: string[],
+    lastChapterNameList?: string[],
     platformUserId?: string,// 书城用户ID
     rechargeBook?: string,  // 充值小说
     begin?: {               // 关注时间
@@ -71,6 +77,14 @@ interface ContentProps {
         lastRechargeHourMin?: number
         lastRechargeHourMax?: number
     },
+    lastReadTime?: {        // 最近阅读时间
+        lastReadTimeMin?: string,
+        lastReadTimeMax?: string
+    },
+    lastReadHour?: {          // 充值距今
+        lastReadHourMin?: number
+        lastReadHourMax?: number
+    },
     opers?: string[]   // 手机系统
     // 群
     groupChatNames?: string,
@@ -93,7 +107,8 @@ export const resetFilterUserData = (data: { [x: string]: any }): ContentProps =>
     const {
         beginTime, endTime, rechargeCountMin, rechargeCountMax, rechargeMoneyMin, rechargeMoneyMax, lastRechargeTimeMin, lastRechargeTimeMax,
         firstRechargeMoneyMin, firstRechargeMoneyMax, rechargeMoneyMaxMin, rechargeMoneyMaxMax, subHourMin, subHourMax, subDayMin, subDayMax, 
-        lastRechargeHourMin, lastRechargeHourMax,groupChatNames, groupChatBeginTime, groupChatEndTime, groupChatHourMin, groupChatHourMax, groupChatUserMin, groupChatUserMax,
+        lastRechargeHourMin, lastRechargeHourMax, lastReadHourMin, lastReadHourMax, groupChatNames, groupChatBeginTime, groupChatEndTime, groupChatHourMin, groupChatHourMax, 
+        groupChatUserMin, groupChatUserMax, lastReadTimeMin, lastReadTimeMax,
         ...params
     } = data
 
@@ -110,6 +125,9 @@ export const resetFilterUserData = (data: { [x: string]: any }): ContentProps =>
     if (lastRechargeTimeMin || lastRechargeTimeMax) {
         newData.lastRechargeTime = { lastRechargeTimeMin, lastRechargeTimeMax }
     }
+    if (lastReadTimeMin || lastReadTimeMax) {
+        newData.lastReadTime = { lastReadTimeMin, lastReadTimeMax }
+    }
     if (firstRechargeMoneyMin || firstRechargeMoneyMax) {
         newData.firstRechargeMoney = { firstRechargeMoneyMin, firstRechargeMoneyMax }
     }
@@ -125,6 +143,9 @@ export const resetFilterUserData = (data: { [x: string]: any }): ContentProps =>
     if (lastRechargeHourMin || lastRechargeHourMax) {
         newData.lastRechargeHour = { lastRechargeHourMin, lastRechargeHourMax }
     }
+    if (lastReadHourMin || lastReadHourMax) {
+        newData.lastReadHour = { lastReadHourMin, lastReadHourMax }
+    }
     if (groupChatNames?.length) {
         newData.groupChatNames = groupChatNames.join('、')
     }
@@ -173,6 +194,8 @@ const FilterUserText = ({ data, configName, configType = 'USER_GROUP', bookCityL
     (content?.msgTagIds ? `智能标签:${content?.msgTagIds?.['business'] ? `业务:${businessPlanData.find(i => i.value === content?.msgTagIds['business'])?.label}` : ''}--${content?.msgTagIds?.['bookCity'] ? `书城:${bookPlatForm.find(i => i.id === content?.msgTagIds['bookCity'])?.platformName}` : ''}--${content?.msgTagIds?.['product'] ? `产品:${bookList.find(i => i.id === content?.msgTagIds['product'])?.bookName}\n` : ''}` : '') + 
     (content?.msgExcludeTagIds ? `排除智能标签:${content?.msgExcludeTagIds?.['business'] ? `业务:${businessPlanData.find(i => i.value === content?.msgExcludeTagIds['business'])?.label}` : ''}--${content?.msgExcludeTagIds?.['bookCity'] ? `书城:${bookPlatForm.find(i => i.id === content?.msgExcludeTagIds['bookCity'])?.platformName}` : ''}--${content?.msgExcludeTagIds?.['product'] ? `产品:${bookList.find(i => i.id === content?.msgExcludeTagIds['product'])?.bookName}\n` : ''}` : '') + 
     (content?.platformKey ? `书城:${bookCityList?.find(item => item.value === content?.platformKey)?.label || '--'}\n` : '') +
+    (content?.lastBookNameList ? `最近阅读书籍:${content?.lastBookNameList?.join('、') || '--'}\n` : '') +
+    (content?.lastChapterNameList ? `最近阅读章节:${content?.lastChapterNameList?.join('、') || '--'}\n` : '') +
     (content?.platformUserId ? `书城用户ID:${content?.platformUserId}\n` : '') + 
     (content?.rechargeBook ? `充值小说:${content?.rechargeBook}\n` : '') +
     (content?.begin ? `关注时间:${content?.begin?.beginTime ? content?.begin?.beginTime : '不限'} - ${content?.begin?.endTime ? content?.begin?.endTime : '不限'}\n` : '') + 
@@ -184,7 +207,9 @@ const FilterUserText = ({ data, configName, configType = 'USER_GROUP', bookCityL
     (content?.rechargeMoneyMax ? `单笔最大充值金额:${content?.rechargeMoneyMax?.rechargeMoneyMaxMin ? content?.rechargeMoneyMax?.rechargeMoneyMaxMin : '不限'} - ${content?.rechargeMoneyMax?.rechargeMoneyMaxMax ? content?.rechargeMoneyMax?.rechargeMoneyMaxMax : '不限'}\n` : '') +
     (content?.subHour ? `关注距今时间:${content?.subHour?.subHourMin ? content?.subHour?.subHourMin + '小时' : '不限'} - ${content?.subHour?.subHourMax ? content?.subHour?.subHourMax + '小时' : '不限'}\n` : '') +
     (content?.subDay ? `关注距今天:${content?.subDay?.subDayMin ? content?.subDay?.subDayMin + '天' : '不限'} - ${content?.subDay?.subDayMax ? content?.subDay?.subDayMax + '天' : '不限'}\n` : '') +
-    (content?.lastRechargeHour ? `关注距今天:${content?.lastRechargeHour?.lastRechargeHourMin ? content?.lastRechargeHour?.lastRechargeHourMin + '天' : '不限'} - ${content?.lastRechargeHour?.lastRechargeHourMax ? content?.lastRechargeHour?.lastRechargeHourMax + '小时' : '不限'}\n` : '') +
+    (content?.lastRechargeHour ? `最近一次充值距今:${content?.lastRechargeHour?.lastRechargeHourMin ? content?.lastRechargeHour?.lastRechargeHourMin + '小时' : '不限'} - ${content?.lastRechargeHour?.lastRechargeHourMax ? content?.lastRechargeHour?.lastRechargeHourMax + '小时' : '不限'}\n` : '') +
+    (content?.lastReadTime ? `最近阅读时间:${content?.lastReadTime?.lastReadTimeMin ? content?.lastReadTime?.lastReadTimeMin : '不限'} - ${content?.lastReadTime?.lastReadTimeMax ? content?.lastReadTime?.lastReadTimeMax : '不限'}\n` : '') +
+    (content?.lastRechargeHour ? `最近阅读至今:${content?.lastReadHour?.lastReadHourMin ? content?.lastReadHour?.lastReadHourMin + '小时' : '不限'} - ${content?.lastReadHour?.lastReadHourMax ? content?.lastReadHour?.lastReadHourMax + '小时' : '不限'}\n` : '') +
     (content?.opers?.length > 0 ? `手机系统:${content?.opers.map(g => ({ '0': '未知', '1': '安卓', '2': 'IOS' } as any)[g]).join('、')}\n` : '') +
     (content?.groupChatNames ? `群名称列表:${content?.groupChatNames?.toString()}` : '') +
     (content?.groupChatTime ? `群创建时间:${content?.groupChatTime?.groupChatBeginTime ? content?.groupChatTime?.groupChatBeginTime + '小时' : '不限'} - ${content?.groupChatTime?.groupChatEndTime ? content?.groupChatTime?.groupChatEndTime + '小时' : '不限'}\n` : '') +

+ 34 - 1
src/pages/weComTask/components/filterUser/filterUserTooltip.tsx

@@ -8,6 +8,8 @@ const targetingData = [
     { key: 'msgTagIds', name: '智能标签' },
     { key: 'msgExcludeTagIds', name: '排除智能标签' },
     { key: 'platformKey', name: '书城' },
+    { key: 'lastBookNameList', name: '最近阅读书籍' },
+    { key: 'lastChapterNameList', name: '最近阅读章节' },
     { key: 'platformUserId', name: '书城用户ID' },
     { key: 'rechargeBook', name: '充值小说' },
     { key: 'begin', name: '关注时间' },
@@ -15,11 +17,13 @@ const targetingData = [
     { key: 'rechargeCount', name: '充值次数' },
     { key: 'rechargeMoney', name: '充值金额' },
     { key: 'lastRechargeTime', name: '最后充值时间' },
+    { key: 'lastReadTime', name: '最近阅读时间' },
     { key: 'firstRechargeMoney', name: '首充金额' },
     { key: 'rechargeMoneyMax', name: '单笔最大充值金额' },
     { key: 'subHour', name: '关注距今时间' },
     { key: 'subDay', name: '关注距今天' },
     { key: 'lastRechargeHour', name: '最近充值时间距今(小时)' },
+    { key: 'lastReadHour', name: '最近阅读至今(小时)' },
     { key: 'opers', name: '手机系统' }
 ]
 
@@ -40,6 +44,8 @@ interface ContentProps {
     msgTagIds?: { [x: string]: string }[], // 智能标签
     msgExcludeTagIds?: { [x: string]: string }[], // 排除智能标签
     platformKey?: string,   // 书城
+    lastBookNameList?: string[],
+    lastChapterNameList?: string[],
     platformUserId?: string,// 书城用户ID
     rechargeBook?: string,  // 充值小说
     begin?: {               // 关注时间
@@ -59,6 +65,10 @@ interface ContentProps {
         lastRechargeTimeMin?: string,
         lastRechargeTimeMax?: string
     },
+    lastReadTime?: {        // 最近阅读时间
+        lastReadTimeMin?: string,
+        lastReadTimeMax?: string
+    },
     firstRechargeMoney?: { // 首充金额
         firstRechargeMoneyMin?: number,
         firstRechargeMoneyMax?: number
@@ -79,6 +89,10 @@ interface ContentProps {
         lastRechargeHourMin?: number,
         lastRechargeHourMax?: number
     },
+    lastReadHour?: {  // 最近阅读至今
+        lastReadHourMin?: number,
+        lastReadHourMax?: number
+    },
     opers?: string[]   // 手机系统
     // 群
     groupChatNames?: string,
@@ -101,7 +115,8 @@ export const resetFilterUserData = (data: { [x: string]: any }): ContentProps =>
     const {
         beginTime, endTime, rechargeCountMin, rechargeCountMax, rechargeMoneyMin, rechargeMoneyMax, lastRechargeTimeMin, lastRechargeTimeMax,
         firstRechargeMoneyMin, firstRechargeMoneyMax, rechargeMoneyMaxMin, rechargeMoneyMaxMax, subHourMin, subHourMax, subDayMin, subDayMax,
-        lastRechargeHourMin, lastRechargeHourMax, groupChatNames, groupChatBeginTime, groupChatEndTime, groupChatHourMin, groupChatHourMax, groupChatUserMin, groupChatUserMax,
+        lastRechargeHourMin, lastRechargeHourMax, groupChatNames, groupChatBeginTime, groupChatEndTime, groupChatHourMin, groupChatHourMax, 
+        groupChatUserMin, groupChatUserMax, lastReadHourMin, lastReadHourMax, lastReadTimeMin, lastReadTimeMax,
         ...params
     } = data
 
@@ -118,6 +133,9 @@ export const resetFilterUserData = (data: { [x: string]: any }): ContentProps =>
     if (lastRechargeTimeMin || lastRechargeTimeMax) {
         newData.lastRechargeTime = { lastRechargeTimeMin, lastRechargeTimeMax }
     }
+    if (lastReadTimeMin || lastReadTimeMax) {
+        newData.lastReadTime = { lastReadTimeMin, lastReadTimeMax }
+    }
     if (firstRechargeMoneyMin || firstRechargeMoneyMax) {
         newData.firstRechargeMoney = { firstRechargeMoneyMin, firstRechargeMoneyMax }
     }
@@ -133,6 +151,9 @@ export const resetFilterUserData = (data: { [x: string]: any }): ContentProps =>
     if (lastRechargeHourMin || lastRechargeHourMax) {
         newData.lastRechargeHour = { lastRechargeHourMin, lastRechargeHourMax }
     }
+    if (lastReadHourMin || lastReadHourMax) {
+        newData.lastReadHour = { lastReadHourMin, lastReadHourMax }
+    }
     if (groupChatNames?.length) {
         newData.groupChatNames = groupChatNames.join('、')
     }
@@ -201,6 +222,12 @@ const FilterUserTooltip: React.FC<Props> = (props) => {
         {content?.platformKey && <div>
             <strong>书城:</strong><span>{bookCityList?.find(item => item.value === content?.platformKey)?.label || '--'}</span>
         </div>}
+        {content?.lastBookNameList && <div>
+            <strong>最近阅读书籍:</strong><span>{content?.lastBookNameList?.join('、') || '--'}</span>
+        </div>}
+        {content?.lastChapterNameList && <div>
+            <strong>最近阅读章节:</strong><span>{content?.lastChapterNameList?.join('、') || '--'}</span>
+        </div>}
         {content?.platformUserId && <div>
             <strong>书城用户ID:</strong><span>{content?.platformUserId}</span>
         </div>}
@@ -237,6 +264,12 @@ const FilterUserTooltip: React.FC<Props> = (props) => {
         {content?.lastRechargeHour && <div>
             <strong>最近一次充值距今(小时):</strong><span>{content?.lastRechargeHour?.lastRechargeHourMin ? content?.lastRechargeHour?.lastRechargeHourMin + '小时' : '不限'} - {content?.lastRechargeHour?.lastRechargeHourMax ? content?.lastRechargeHour?.lastRechargeHourMax + '小时' : '不限'}</span>
         </div>}
+        {content?.lastReadTime && <div>
+            <strong>最近阅读时间:</strong><span>{content?.lastReadTime?.lastReadTimeMin ? content?.lastReadTime?.lastReadTimeMin : '不限'} - {content?.lastReadTime?.lastReadTimeMax ? content?.lastReadTime?.lastReadTimeMax : '不限'}</span>
+        </div>}
+        {content?.lastReadHour && <div>
+            <strong>最近阅读至今(小时):</strong><span>{content?.lastReadHour?.lastReadHourMin ? content?.lastReadHour?.lastReadHourMin + '小时' : '不限'} - {content?.lastReadHour?.lastReadHourMax ? content?.lastReadHour?.lastReadHourMax + '小时' : '不限'}</span>
+        </div>}
         {content?.opers?.length > 0 && <div>
             <strong>手机系统:</strong><span>{content?.opers.map(g => ({ '0': '未知', '1': '安卓', '2': 'IOS' } as any)[g]).toString()}</span>
         </div>}

+ 59 - 20
src/pages/weComTask/components/filterUser/newFiterUser.tsx

@@ -6,6 +6,8 @@ import { GENDER_TYPE } from '../../page/businessPlan/create/const';
 import { addSiftPopulationConfigApi, updateSiftPopulationConfigApi } from '../../API/businessPlan/filterUser';
 import dayjs from 'dayjs';
 import MindTags from '../mindTags';
+import SelectBook from '../SelectBook';
+import SelectChapter from '../SelectChapter';
 
 interface NewFilterUserProps {
     configType: BUSINES_SPLAN_API.ConfigTypeProps
@@ -27,6 +29,8 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
     /***********************************/
     const { message } = App.useApp()
     const [form] = Form.useForm();
+    const platformKey = Form.useWatch('platformKey', form)
+    const lastBookNameList = Form.useWatch('lastBookNameList', form)
     const [isSave, setIsSave] = useState<boolean>(false)
 
     const addSiftPopulationConfig = useAjax((params) => addSiftPopulationConfigApi(params))
@@ -35,7 +39,7 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
 
     useEffect(() => {
         if (value && Object.keys(value).length > 0) {
-            const { beginTime, endTime, lastRechargeTimeMin, lastRechargeTimeMax, groupChatNames, groupChatBeginTime, groupChatEndTime, ...params } = value
+            const { beginTime, endTime, lastRechargeTimeMin, lastRechargeTimeMax, groupChatNames, groupChatBeginTime, groupChatEndTime, lastReadTimeMin, lastReadTimeMax, ...params } = value
             if (beginTime) {
                 params.beginTime = dayjs(beginTime)
             }
@@ -45,6 +49,9 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
             if (lastRechargeTimeMin && lastRechargeTimeMax) {
                 params.lastRechargeTime = [dayjs(lastRechargeTimeMin), dayjs(lastRechargeTimeMax)]
             }
+            if (lastReadTimeMin && lastReadTimeMax) {
+                params.lastReadTime = [dayjs(lastReadTimeMin), dayjs(lastReadTimeMax)]
+            }
             if (groupChatBeginTime && groupChatEndTime) {
                 params.groupChatTime = [dayjs(groupChatBeginTime), dayjs(groupChatEndTime)]
             }
@@ -60,7 +67,7 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
             console.log(values)
             const { configName, ...configContent } = values
             if (configContent && Object.keys(configContent).length > 0 && Object.keys(configContent).some(key => configContent[key])) {
-                const { beginTime, endTime, lastRechargeTime, groupChatNames, groupChatTime, ...params } = configContent
+                const { beginTime, endTime, lastRechargeTime, lastReadTime, groupChatNames, groupChatTime, ...params } = configContent
                 const dta = {
                     ...params
                 }
@@ -74,6 +81,10 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     dta.lastRechargeTimeMin = dayjs(lastRechargeTime[0]).format('YYYY-MM-DD');
                     dta.lastRechargeTimeMax = dayjs(lastRechargeTime[1]).format('YYYY-MM-DD');
                 }
+                if (lastReadTime?.length > 1) {
+                    dta.lastReadTimeMin = dayjs(lastReadTime[0]).format('YYYY-MM-DD');
+                    dta.lastReadTimeMax = dayjs(lastReadTime[1]).format('YYYY-MM-DD');
+                }
                 if (groupChatNames) {
                     dta.groupChatNames = groupChatNames.split(/[,,\n\s]+/ig).filter((item: any) => item)
                 }
@@ -197,11 +208,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>群创建时长</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="groupChatHourMin" noStyle>
-                                <InputNumber placeholder="最小值小时" style={{ width: 150 }} />
+                                <InputNumber placeholder="最小值小时" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="groupChatHourMax" noStyle>
-                                <InputNumber placeholder="最大值小时" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大值小时" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -210,11 +221,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>群人数</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="groupChatUserMin" noStyle>
-                                <InputNumber placeholder="最小值" style={{ width: 150 }} />
+                                <InputNumber placeholder="最小值" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="groupChatUserMax" noStyle>
-                                <InputNumber placeholder="最大值" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大值" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -259,6 +270,16 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                         />
                     </Form.Item>
                 </div>
+                <div className={style.newSpace}>
+                    <Form.Item name="lastBookNameList" label={<strong>最近阅读书籍</strong>} style={{ marginBottom: 0 }}>
+                        <SelectBook onChange={() => form.setFieldsValue({ lastChapterNameList: undefined })} platformKey={platformKey} />
+                    </Form.Item>
+                </div>
+                {lastBookNameList?.length === 1 && <div className={style.newSpace}>
+                    <Form.Item label={<strong>最近阅读章节</strong>} name='lastChapterNameList' tooltip="选择单本书才可选择章节">
+                        <SelectChapter platformKey={platformKey} bookName={lastBookNameList?.[0]} />
+                    </Form.Item>
+                </div>}
                 <div className={style.newSpace}>
                     <Form.Item name="platformUserId" label={<strong>书城用户ID</strong>} style={{ marginBottom: 0 }}>
                         <Input placeholder="书城用户ID" allowClear />
@@ -298,11 +319,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>充值次数</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="rechargeCountMin" noStyle>
-                                <InputNumber placeholder="最小充值次数" style={{ width: 150 }} />
+                                <InputNumber placeholder="最小充值次数" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="rechargeCountMax" noStyle>
-                                <InputNumber placeholder="最大充值次数" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大充值次数" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -311,11 +332,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>充值金额</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="rechargeMoneyMin" noStyle>
-                                <InputNumber placeholder="最低充值金额" style={{ width: 150 }} />
+                                <InputNumber placeholder="最低充值金额" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="rechargeMoneyMax" noStyle>
-                                <InputNumber placeholder="最大充值金额" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大充值金额" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -329,11 +350,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>首充金额</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="firstRechargeMoneyMin" noStyle>
-                                <InputNumber placeholder="最低首充金额" style={{ width: 150 }} />
+                                <InputNumber placeholder="最低首充金额" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="firstRechargeMoneyMax" noStyle>
-                                <InputNumber placeholder="最大首充金额" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大首充金额" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -342,11 +363,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>单笔最大充值金额</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="rechargeMoneyMaxMin" noStyle>
-                                <InputNumber placeholder="最低单笔最大充值金额" style={{ width: 150 }} />
+                                <InputNumber placeholder="最低单笔最大充值金额" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="rechargeMoneyMaxMax" noStyle>
-                                <InputNumber placeholder="最大单笔最大充值金额" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大单笔最大充值金额" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -355,11 +376,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>关注距今时间</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="subHourMin" noStyle>
-                                <InputNumber placeholder="最小关注时间" style={{ width: 150 }} />
+                                <InputNumber placeholder="最小关注时间" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="subHourMax" noStyle>
-                                <InputNumber placeholder="最大关注时间" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大关注时间" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -368,11 +389,11 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>关注距今天</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="subDayMin" noStyle>
-                                <InputNumber placeholder="最小关注天" style={{ width: 150 }} />
+                                <InputNumber placeholder="最小关注天" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="subDayMax" noStyle>
-                                <InputNumber placeholder="最大关注天" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大关注天" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>
@@ -381,11 +402,29 @@ const NewFilterUser: React.FC<NewFilterUserProps> = ({ bookCityList, configType
                     <Form.Item label={<strong>最近一次充值距今(小时)</strong>} style={{ marginBottom: 0 }}>
                         <Space>
                             <Form.Item name="lastRechargeHourMin" noStyle>
-                                <InputNumber placeholder="最小充值距今" style={{ width: 150 }} />
+                                <InputNumber placeholder="最小充值距今" style={{ width: 200 }} />
                             </Form.Item>
                             <span>-</span>
                             <Form.Item name="lastRechargeHourMax" noStyle>
-                                <InputNumber placeholder="最大充值距今" style={{ width: 150 }} />
+                                <InputNumber placeholder="最大充值距今" style={{ width: 200 }} />
+                            </Form.Item>
+                        </Space>
+                    </Form.Item>
+                </div>
+                <div className={style.newSpace}>
+                    <Form.Item name="lastReadTime" label={<strong>最近阅读时间</strong>} style={{ marginBottom: 0 }}>
+                        <DatePicker.RangePicker placeholder={["最近阅读时间开始", "最近阅读时间结束"]} />
+                    </Form.Item>
+                </div>
+                <div className={style.newSpace}>
+                    <Form.Item label={<strong>最近阅读至今(小时)</strong>} style={{ marginBottom: 0 }}>
+                        <Space>
+                            <Form.Item name="lastReadHourMin" noStyle>
+                                <InputNumber placeholder="最近阅读至今小时差区间-最小" style={{ width: 200 }} />
+                            </Form.Item>
+                            <span>-</span>
+                            <Form.Item name="lastReadHourMax" noStyle>
+                                <InputNumber placeholder="最近阅读至今小时差区间-最大" style={{ width: 200 }} />
                             </Form.Item>
                         </Space>
                     </Form.Item>

+ 2 - 1
src/pages/weComTask/page/groupChat/create/const.ts

@@ -12,10 +12,11 @@ export const getPullGroupData = (strategyList: any[]) => {
             return {
                 ...item,
                 id,
-                groupObjectList: taskDetail.map(({ externalUserFilter, weChatAppid, mpAccountInfo, msgTagDTO, groupName, ...go }, i) => {
+                groupObjectList: taskDetail.map(({ externalUserFilter, weChatAppid, mpAccountInfo, msgTagDTO, groupName, isRetry, ...go }, i) => {
                     const id = go.id || nowTime_inherit + (index * 1000) + (i * 100)
                     const inherit: { [x: string]: any } = {
                         ...go,
+                        isRetry: isRetry || false,
                         id,
                         weChatAppid: mpAccountInfo?.name ? mpAccountInfo?.name + '_' + mpAccountInfo?.id : undefined,
                         tagDTO: msgTagDTO,