wjx 3 日 前
コミット
d79487d26b
34 ファイル変更2052 行追加341 行削除
  1. 2 1
      src/Hook/useNewToken.tsx
  2. 3 1
      src/layout/index.tsx
  3. 65 0
      src/pages/weComTask/API/bookLink/index.ts
  4. 11 0
      src/pages/weComTask/API/corpUserAssign/index.ts
  5. 1 0
      src/pages/weComTask/API/corpUserManage/typings.d.ts
  6. 1 1
      src/pages/weComTask/components/sendTimeSet/index.tsx
  7. 48 0
      src/pages/weComTask/page/bookLink/SelectBookLinkButton.tsx
  8. 104 0
      src/pages/weComTask/page/bookLink/bookPromoLinkCreateDTO.tsx
  9. 75 0
      src/pages/weComTask/page/bookLink/const.tsx
  10. 88 0
      src/pages/weComTask/page/bookLink/consumeActivityLinkDTO.tsx
  11. 66 0
      src/pages/weComTask/page/bookLink/details.tsx
  12. 79 0
      src/pages/weComTask/page/bookLink/giftActivityLinkDTO.tsx
  13. 13 0
      src/pages/weComTask/page/bookLink/index.less
  14. 168 0
      src/pages/weComTask/page/bookLink/index.tsx
  15. 267 0
      src/pages/weComTask/page/bookLink/modalBooklink.tsx
  16. 40 0
      src/pages/weComTask/page/bookLink/pagePromoLinkCreateDTO.tsx
  17. 126 0
      src/pages/weComTask/page/bookLink/rechargeActivityLinkDTO.tsx
  18. 209 0
      src/pages/weComTask/page/bookLink/selectBookLink.tsx
  19. 113 0
      src/pages/weComTask/page/bookLink/tableConfig.tsx
  20. 11 0
      src/pages/weComTask/page/bookLink/typings.d.ts
  21. 1 1
      src/pages/weComTask/page/businessPlan/create/components/massSending/index.tsx
  22. 2 2
      src/pages/weComTask/page/businessPlan/create/components/userInherit/index.tsx
  23. 1 1
      src/pages/weComTask/page/businessPlan/create/components/welcome/index.tsx
  24. 3 2
      src/pages/weComTask/page/businessPlan/create/const.tsx
  25. 6 2
      src/pages/weComTask/page/businessPlan/create/index.less
  26. 256 205
      src/pages/weComTask/page/businessPlan/create/index.tsx
  27. 94 29
      src/pages/weComTask/page/businessPlan/create/tableConfig.tsx
  28. 8 3
      src/pages/weComTask/page/businessPlan/create/typings.d.ts
  29. 83 83
      src/pages/weComTask/page/businessPlan/taskList/tableConfig.tsx
  30. 1 1
      src/pages/weComTask/page/corpUserManage/global.less
  31. 16 1
      src/pages/weComTask/page/corpUserManage/index.tsx
  32. 50 8
      src/pages/weComTask/page/corpUserManage/selectCorpUserGroupModal.tsx
  33. 41 0
      src/pages/weComTask/page/corpUserManage/tableConfig.tsx
  34. 0 0
      src/public/svg/book.svg

+ 2 - 1
src/Hook/useNewToken.tsx

@@ -109,7 +109,8 @@ let themeConfig = {
         token: {
             'colorTextWhite': '#FFFFFF',
             colorPrimary: '#1677FF',
-            colorBgContainer: 'rgba(247, 247, 247, 0.6)',//容器背景
+            // colorBgContainer: 'rgba(247, 247, 247, 0.6)',//容器背景
+            colorBgContainer: '#FFFFFF',//容器背景
             colorBgLayout: 'rgba(247, 247, 247, 0.5)',//路由背景
             colorTextBase: '#000',//基础文字色
             "wireframe": true,

+ 3 - 1
src/layout/index.tsx

@@ -22,6 +22,7 @@ import { ReactComponent as MsgSvg } from '../public/svg/msg.svg'
 import { ReactComponent as WeComSvg } from '../public/svg/weCom.svg'
 import { ReactComponent as BusinessPlanSvg } from '../public/svg/businessPlan.svg'
 import { ReactComponent as ImageSvg } from '../public/svg/image.svg'
+import { ReactComponent as BooKSvg } from '../public/svg/book.svg'
 import Avatar from './AvatarDropdown';
 import styles from './index.less'
 import { useNavigate } from 'react-router-dom';
@@ -56,7 +57,7 @@ const IconMap = {
     radarChart: <RadarChartOutlined />,
     barChart: <BarChartOutlined />,
     wechat: <WechatOutlined />,
-    book: <BookOutlined />,
+    // book: <BookOutlined />,
     peoples: <UserOutlined />,
     'file-image': <FileImageOutlined />,
     pay: <AlipayCircleOutlined />,
@@ -84,6 +85,7 @@ const IconMap = {
     weCom: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><WeComSvg /></span>,
     businessPlan: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><BusinessPlanSvg /></span>,
     image: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><ImageSvg /></span>,
+    book: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><BooKSvg /></span>,
     interdiction: <StopOutlined />,
     eye: <EyeOutlined />,
     log: <ContainerOutlined />

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

@@ -0,0 +1,65 @@
+
+import request from "@/utils/request";
+const { api } = process.env.CONFIG;
+
+export interface GetCorpAutoLinkListProps {
+    pageNum: number,
+    pageSize: number,
+    platform?: string,
+    mpAccountId?: number
+    linkType?: number
+    channelName?: string
+    channelType?: number
+    createTimeStart?: string
+    createTimeEnd?: string
+}
+
+/**
+ * 书城链接列表
+ * @param data 
+ * @returns 
+ */
+export function getCorpAutoLinkListApi(data: GetCorpAutoLinkListProps) {
+    return request({
+        url: api + `/corpOperation/corp/autoLink/listOfPage`,
+        method: 'POST',
+        data
+    })
+}
+
+export interface AddCorpAutoLinkProps {
+    mpAccountIds: number[],
+    platform: string,
+    yueWenCreateLinkDTOList: { [x: string]: any }
+}
+
+/**
+ * 新增书城链接生成
+ * @param data 
+ * @returns 
+ */
+export function addCorpAutoLinkApi(data: AddCorpAutoLinkProps) {
+    return request({
+        url: api + `/corpOperation/corp/autoLink/add`,
+        method: 'POST',
+        data
+    })
+}
+
+interface GetFreeChapterListProps {
+    bookId: number
+    mpAccountIds: number[]
+    platform: string
+}
+/**
+ * 获取免费章节
+ * @param data 
+ * @returns 
+ */
+export function getFreeChapterListApi(data: GetFreeChapterListProps) {
+    return request({
+        url: api + `/corpOperation/corp/autoLink/freeChapterList`,
+        method: 'POST',
+        data
+    })
+}

+ 11 - 0
src/pages/weComTask/API/corpUserAssign/index.ts

@@ -154,6 +154,17 @@ export function getAllWxListApi() {
         method: 'GET',
     })
 }
+
+/**
+ * 获取已绑定书城公众号列表
+ * @returns 
+ */
+export function getBindMpListApi() {
+    return request({
+        url:api+ `/corpOperation/corpUser/getBindMpList`,
+        method: 'GET',
+    })
+}
 /**
  * 获取公众号变更记录
  * */ 

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

@@ -13,6 +13,7 @@ declare namespace CORP_USER_ASSIGN_API {
         stopUse?: boolean,
         sysUserId?: number
         corpUserName?: string
+        mpAccountId?: number
     }
 
     interface PutCorpUserTOProps {

+ 1 - 1
src/pages/weComTask/components/sendTimeSet/index.tsx

@@ -198,7 +198,7 @@ const SendTimeSet: React.FC<Props> = ({ active, form, timeRepeatType, disabled,
                 mode="multiple"
                 placeholder="每月执行天数"
                 maxLength={8}
-                style={{ width: 358 }}
+                style={{ width: isShow ? '100%' : 358 }}
                 options={Array(31).fill('').map((item, index) => ({ label: index + 1 + '号', value: index + 1 }))}
             />
         </Form.Item>}

+ 48 - 0
src/pages/weComTask/page/bookLink/SelectBookLinkButton.tsx

@@ -0,0 +1,48 @@
+import React, { useState } from 'react';
+import { Button, Input } from 'antd';
+import SelectBookLink from './selectBookLink';
+
+interface SelectBookLinkButtonProps {
+    mpAccountId: number | null
+    bookPlatForm: TASK_CREATE.BookPlatFormProps[]
+    linkData: { [x: string]: any }[]
+    onChange: (linkStr: string) => void
+}
+
+const SelectBookLinkButton: React.FC<SelectBookLinkButtonProps> = ({ mpAccountId, bookPlatForm, linkData, onChange }) => {
+
+    /********************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    const [linkStr, setLinkStr] = useState<string>()
+    /********************************/
+
+    return <div style={{ display: 'flex', gap: 4, alignItems: 'flex-end' }}>
+        <Input.TextArea
+            placeholder="请输入链接"
+            allowClear
+            value={linkStr}
+            onChange={e => {
+                setLinkStr(e.target.value)
+                onChange(e.target.value)
+            }}
+        />
+        <Button type="link" style={{ padding: 0 }} onClick={() => setVisible(true)}>
+            选择链接
+        </Button>
+        {visible && <SelectBookLink
+            mpAccountId={mpAccountId}
+            bookPlatForm={bookPlatForm}
+            visible={visible}
+            linkData={linkData}
+            onClose={() => setVisible(false)}
+            onChange={(linkStr) => {
+                console.log('linkStr', linkStr)
+                setLinkStr(linkStr)
+                onChange(linkStr)
+                setVisible(false)
+            }}
+        />}
+    </div>
+};
+
+export default SelectBookLinkButton;

+ 104 - 0
src/pages/weComTask/page/bookLink/bookPromoLinkCreateDTO.tsx

@@ -0,0 +1,104 @@
+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";
+
+interface Props extends BOOKLINK.BookLinkChildProps {
+    yueWenCreateLinkDTO: { [x: string]: any }
+    platform: string,
+    mpAccountIds: number[]
+}
+/**
+ * 作品链接
+ * @returns 
+ */
+const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, yueWenCreateLinkDTO, platform, mpAccountIds }) => {
+
+    /**********************************/
+    const { message } = App.useApp()
+    const getFreeChapterList = useAjax((params) => getFreeChapterListApi(params))
+    /**********************************/
+
+    const getChapterList = () => {
+        if (platform && mpAccountIds?.length && yueWenCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId) {
+            getFreeChapterList.run({ platform, mpAccountIds, bookId: yueWenCreateLinkDTO.bookPromoLinkCreateDTO.bookId })
+        } else {
+            message.error('请先选择书城、公众号')
+        }
+    }
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'bookId']}
+            label={<strong>作品(书籍)ID</strong>}
+            rules={[{ required: true, message: '请输入作品(书籍)ID!' }]}
+        >
+            <Space.Compact style={{ width: '100%' }}>
+                <Input
+                    placeholder="请输入作品(书籍)ID"
+                    style={{ width: '100%' }}
+                    onChange={(e) => getFreeChapterList.mutate({ data: undefined })}
+                />
+                <Button type="primary" onClick={getChapterList} disabled={!yueWenCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId} loading={getFreeChapterList.loading}>查询章节列表</Button>
+            </Space.Compact>
+        </Form.Item>
+
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'chapterId']}
+            label={<strong>章节</strong>}
+            rules={[{ required: true, message: '请选择章节!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择章节"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={getFreeChapterList?.data?.data?.chapterList?.map(item => ({ value: item.chapterId, label: item.chapterName }))}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'forceStyle']}
+            label={<strong>强关设置</strong>}
+            rules={[{ required: true, message: '请选择强关设置!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 1, label: '不设置强关' },
+                    { value: 2, label: '主动关注' },
+                    { value: 3, label: '强制关注' },
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'forceChapter']}
+            label={<strong>强关章节序号</strong>}
+        >
+            <InputNumber placeholder="请输入强关章节序号" style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'isOpenBottom']}
+            label={<strong>是否添加底部关注引导</strong>}
+            valuePropName="checked"
+        >
+            <Switch checkedChildren="开启" unCheckedChildren="关闭" />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'cost']}
+            label={<strong>推广成本</strong>}
+        >
+            <InputNumber placeholder="请输入推广成本" style={{ width: '100%' }} />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(BookPromoLinkCreateDTO);

+ 75 - 0
src/pages/weComTask/page/bookLink/const.tsx

@@ -0,0 +1,75 @@
+import { Tag } from "antd"
+
+/** 阅文  链接类型 */
+export const LINKTYPE = {
+    1: '页面链接',
+    2: '作品链接',
+    3: '模板充值活动链接',
+    4: '模版直赠活动链接',
+    5: '模板消耗活动链接'
+}
+
+export const LINKTYPEEle = {
+    1: <Tag color="magenta">页面链接</Tag>,
+    2: <Tag color="red">作品链接</Tag>,
+    3: <Tag color="volcano">模板充值活动链接</Tag>,
+    4: <Tag color="orange">模版直赠活动链接</Tag>,
+    5: <Tag color="gold">模板消耗活动链接</Tag>
+}
+
+// 1=书城首页2=排行榜(自动)3=排行榜(男生)4=排行榜(女生)5=充值页6=最近阅读(列表)7=限免专区8=签到页面9=个人中心10=置顶公众号引导11=新用户充值活动页12=最近阅读(最近阅读作品)13=意见反馈
+export const PAGETYPE = {
+    1: '书城首页',
+    2: '排行榜(自动)',
+    3: '排行榜(男生)',
+    4: '排行榜(女生)',
+    5: '充值页',
+    6: '最近阅读(列表)',
+    7: '限免专区',
+    8: '签到页面',
+    9: '个人中心',
+    10: '置顶公众号引导',
+    11: '新用户充值活动页',
+    12: '最近阅读(最近阅读作品)',
+    13: '意见反馈'
+}
+
+// 1 默认风格,2 男生风格,3 女生风格,4 教师节,5 中秋节,6 周末风格,7 国庆节,8 重阳节,9 万圣节,10 双十一,11 双十二,12 圣诞节,13 元旦,16 春节,
+// 17 元宵节,18 情人节,19 春季踏青,20 劳动节,21 端午节,23 女神节,24 七夕
+/**活动主题 */
+export const ACTICITYTHEME = {
+    1: '默认风格',
+    2: '男生风格',
+    3: '女生风格',
+    4: '教师节',
+    5: '中秋节',
+    6: '周末风格',
+    7: '国庆节',
+    8: '重阳节',
+    9: '万圣节',
+    10: '双十一',
+    11: '双十二',
+    12: '圣诞节',
+    13: '元旦',
+    16: '春节',
+    17: '元宵节',
+    18: '情人节',
+    19: '春季踏青',
+    20: '劳动节',
+    21: '端午节',
+    23: '女神节',
+    24: '七夕'
+}
+
+// 活动展示位(可选,多个用逗号分隔):1=阅读页 banner2=客服消息3=首页 banner4=活动中心
+export const DISPLAYTYPE = {
+    '1': '阅读页banner',
+    '2': '客服消息',
+    '3': '首页banner',
+    '4': '活动中心'
+}
+
+// 赠送道具类型:1 书券
+export const RESOURCETTYPE = {
+    1: '书卷'
+}

+ 88 - 0
src/pages/weComTask/page/bookLink/consumeActivityLinkDTO.tsx

@@ -0,0 +1,88 @@
+import { Checkbox, DatePicker, Form, Input, InputNumber, Radio, Select, Space } from "antd";
+import React from "react";
+import { ACTICITYTHEME, DISPLAYTYPE } from "./const";
+
+
+/**
+ * 模板消耗活动
+ * @returns 
+ */
+const ConsumeActivityLinkDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name }) => {
+
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'activityName']}
+            label={<strong>活动名称</strong>}
+            rules={[{ required: true, message: '请输入活动名称!' }]}
+        >
+            <Input placeholder="请输入活动名称" style={{ width: '100%' }} allowClear />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'activityTheme']}
+            label={<strong>活动主题</strong>}
+            rules={[{ required: true, message: '请选择活动主题!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择活动主题"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={Object.keys(ACTICITYTHEME).map(key => ({ label: ACTICITYTHEME[key], value: key }))}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'unlockChapter']}
+            label={<strong>购买章节数量</strong>}
+            rules={[{ required: true, message: '请输入购买章节数量!' }]}
+        >
+            <InputNumber placeholder="请输入购买章节数量1-200" min={1} max={200} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'bookId']}
+            label={<strong>书籍ID</strong>}
+        >
+            <Input placeholder="请输入书籍ID,不输入默认任意书籍" style={{ width: '100%' }} allowClear />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'giftAmount']}
+            label={<strong>赠送书券数量</strong>}
+            rules={[{ required: true, message: '请输入赠送书券数量!' }]}
+        >
+            <InputNumber placeholder="请输入赠送书券数量1-2000" min={1} max={2000} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'totalGift']}
+            label={<strong>赠送名额</strong>}
+            rules={[{ required: true, message: '请输入赠送名额!' }]}
+        >
+            <InputNumber placeholder="请输入赠送名额1-10000" min={1} max={10000} style={{ width: '100%' }} />
+        </Form.Item>
+
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'display']}
+            label={<strong>活动展示位</strong>}
+        >
+            <Checkbox.Group options={Object.keys(DISPLAYTYPE).map(key => ({ label: DISPLAYTYPE[key], value: key }))} />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(ConsumeActivityLinkDTO);

+ 66 - 0
src/pages/weComTask/page/bookLink/details.tsx

@@ -0,0 +1,66 @@
+import React from "react";
+import { ACTICITYTHEME, DISPLAYTYPE, LINKTYPE, LINKTYPEEle, PAGETYPE, RESOURCETTYPE } from "./const";
+
+interface Props {
+    linkType: keyof typeof LINKTYPE,
+    linkContent: { [x: string]: any }
+}
+
+const Details: React.FC<Props> = ({ linkType, linkContent }) => {
+
+    if (linkType === 1) {
+        return <div>
+            <div>链接类型:{LINKTYPEEle[linkType]}</div>
+            <div>页面类型:<span style={{ color: '#1890ff' }}>{PAGETYPE[linkContent?.pageType] || linkContent?.pageType}</span></div>
+            {linkContent?.cost && <div>消耗:<span style={{ color: '#1890ff' }}>{linkContent?.cost}</span></div>}
+        </div>
+    } else if (linkType === 2) {
+        return <div>
+            <div>链接类型:{LINKTYPEEle[linkType]}</div>
+            <div>作品(书籍)ID:<span style={{ color: '#1890ff' }}>{linkContent?.bookId}</span></div>
+            <div>章节ID:<span style={{ color: '#1890ff' }}>{linkContent?.chapterId}</span></div>
+            <div>强关设置:<span style={{ color: '#1890ff' }}>{linkContent?.forceStyle === '1' ? '不设置强关' : linkContent?.forceStyle === '2' ? '主动强关' : '强制关注'}</span></div>
+            {linkContent?.forceChapter && <div>强关章节序号:<span style={{ color: '#1890ff' }}>{linkContent?.forceChapter}</span></div>}
+            <div>是否添加底部关注引导:<span style={{ color: '#1890ff' }}>{linkContent?.isOpenBottom ? '是' : '否'}</span></div>
+            {linkContent?.cost && <div>消耗:<span style={{ color: '#1890ff' }}>{linkContent?.cost}</span></div>}
+        </div>
+    } else if (linkType === 3) {
+        return <div>
+            <div>链接类型:{LINKTYPEEle[linkType]}</div>
+            <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+            <div>活动主题:<span style={{ color: '#1890ff' }}>{ACTICITYTHEME[linkContent?.activityTheme]}</span></div>
+            <div>充值挡位:<span style={{ color: '#1890ff' }}>充值{linkContent?.rechargeAmount}元,送{linkContent?.giftAmount}书卷</span></div>
+            <div>活动次数:<span style={{ color: '#1890ff' }}>{linkContent?.rechargeCount}</span></div>
+            <div>是否每日充值活动:<span style={{ color: '#1890ff' }}>{linkContent?.isDayRepeat ? '是' : '否'}</span></div>
+            <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+            <div>活动时间状态:<span style={{ color: '#1890ff' }}>{linkContent?.timeIsShow ? '开启' : '关闭'}</span></div>
+            {linkContent?.display && <div>活动展示位:<span style={{ color: '#1890ff' }}>{linkContent.display.split(',').map(item => DISPLAYTYPE[item]).join('、')}</span></div>}
+        </div>
+    } else if (linkType === 4) {
+        return <div>
+            <div>链接类型:{LINKTYPEEle[linkType]}</div>
+            <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+            <div>赠送道具:<span style={{ color: '#1890ff' }}>{RESOURCETTYPE[linkContent?.resourceType]}</span></div>
+            <div>赠送书卷量:<span style={{ color: '#1890ff' }}>{linkContent?.freeAmount}</span></div>
+            <div>书卷有效期:<span style={{ color: '#1890ff' }}>{linkContent?.expire}天</span></div>
+            <div>赠送名额:<span style={{ color: '#1890ff' }}>{linkContent?.totalGift}</span></div>
+            <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+            {linkContent?.display && <div>活动展示位:<span style={{ color: '#1890ff' }}>{linkContent.display.split(',').map(item => DISPLAYTYPE[item]).join('、')}</span></div>}
+        </div>
+    } else if (linkType === 5) {
+        return <div>
+            <div>链接类型:{LINKTYPEEle[linkType]}</div>
+            <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+            <div>活动主题:<span style={{ color: '#1890ff' }}>{ACTICITYTHEME[linkContent?.activityTheme]}</span></div>
+            <div>购买章节数量:<span style={{ color: '#1890ff' }}>{linkContent?.unlockChapter}</span></div>
+            <div>生效书籍:<span style={{ color: '#1890ff' }}>{linkContent?.bookId || '全部'}</span></div>
+            <div>赠送书卷数量:<span style={{ color: '#1890ff' }}>{linkContent?.giftAmount}</span></div>
+            <div>赠送名额:<span style={{ color: '#1890ff' }}>{linkContent?.totalGift}</span></div>
+            <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+            {linkContent?.display && <div>活动展示位:<span style={{ color: '#1890ff' }}>{linkContent.display.split(',').map(item => DISPLAYTYPE[item]).join('、')}</span></div>}
+        </div>
+    }
+    return null
+}
+
+export default React.memo(Details);

+ 79 - 0
src/pages/weComTask/page/bookLink/giftActivityLinkDTO.tsx

@@ -0,0 +1,79 @@
+import { Checkbox, DatePicker, Form, Input, InputNumber, Select } from "antd";
+import React from "react";
+import { DISPLAYTYPE, RESOURCETTYPE } from "./const";
+
+/**
+ * 模板直赠活动
+ * @returns 
+ */
+const GiftActivityLinkDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name }) => {
+
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'activityName']}
+            label={<strong>活动名称</strong>}
+            rules={[{ required: true, message: '请输入活动名称!' }]}
+        >
+            <Input placeholder="请输入活动名称" style={{ width: '100%' }} allowClear />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'resourceType']}
+            label={<strong>赠送道具</strong>}
+            rules={[{ required: true, message: '请选择赠送道具!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择赠送道具"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={Object.keys(RESOURCETTYPE).map(key => ({ label: RESOURCETTYPE[key], value: key }))}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'freeAmount']}
+            label={<strong>赠送书券量</strong>}
+            rules={[{ required: true, message: '请输入赠送书券量!' }]}
+        >
+            <InputNumber placeholder="请输入" min={1} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'expire']}
+            label={<strong>书券有效期</strong>}
+            rules={[{ required: true, message: '请输入书券有效期1-7天!' }]}
+        >
+            <InputNumber placeholder="请输入书券有效期1-7天" suffix="天" precision={0} max={7} min={1} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'totalGift']}
+            label={<strong>赠送名额</strong>}
+            rules={[{ required: true, message: '请输入赠送名额!' }]}
+        >
+            <InputNumber placeholder="请输入" min={0} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'display']}
+            label={<strong>活动展示位</strong>}
+        >
+            <Checkbox.Group options={Object.keys(DISPLAYTYPE).filter(key => key === '1').map(key => ({ label: DISPLAYTYPE[key], value: key }))} />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(GiftActivityLinkDTO);

+ 13 - 0
src/pages/weComTask/page/bookLink/index.less

@@ -0,0 +1,13 @@
+.bookLinkTable {
+    flex: 1 0;
+    overflow: hidden;
+}
+
+.bookLinkPagination {
+    padding: 10px 16px;
+    border-top: 1px solid #d5d5d5;
+}
+
+.content_col {
+    
+}

+ 168 - 0
src/pages/weComTask/page/bookLink/index.tsx

@@ -0,0 +1,168 @@
+import { Button, DatePicker, Input, Pagination, 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 style from './index.less'
+import { useAjax } from '@/Hook/useAjax';
+import SearchBox from '../../components/searchBox';
+import { SearchOutlined, PlusOutlined } from '@ant-design/icons';
+import { getBindMpListApi } from '../../API/corpUserAssign';
+import { inject, observer } from 'mobx-react';
+import { toJS } from 'mobx';
+import { LINKTYPE } from './const';
+import ModalBookLink from './modalBooklink';
+import { useSize } from 'ahooks';
+import { bookLinkTableConfig } from './tableConfig';
+import dayJs from 'dayjs';
+
+/**
+ * 书城自动链接管理
+ * @returns 
+ */
+const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookListProps[], bookPlatForm: TASK_CREATE.BookPlatFormProps[] } } }> = ({ weComTaskStore }) => {
+
+    /******************************************/
+    const { bookPlatForm } = toJS(weComTaskStore.data)
+    const ref = useRef<HTMLDivElement>(null)
+    const size = useSize(ref)
+
+    const [queryParams, setQueryParams] = useState<GetCorpAutoLinkListProps>({ pageNum: 1, pageSize: 20 })
+    const [queryParamsNew, setQueryParamsNew] = useState<GetCorpAutoLinkListProps>({ pageNum: 1, pageSize: 20 })
+    const [mpList, setMplist] = useState<{ label: string, value: number }[]>([])
+    const [visible, setVisible] = useState<boolean>(false)
+
+    const getCorpAutoLinkList = useAjax((params) => getCorpAutoLinkListApi(params))
+    const getBindMpList = useAjax(() => getBindMpListApi())
+    /******************************************/
+
+    useEffect(() => {
+        getCorpAutoLinkList.run(queryParamsNew)
+    }, [queryParamsNew])
+
+    useEffect(() => {
+        getBindMpList.run().then(res => {
+            setMplist(res?.data?.map((item: any) => ({ label: item.name, value: item.id })))
+        })
+    }, [])
+
+
+    return <Card
+        styles={{ body: { padding: 0, display: 'flex', flexDirection: 'column', height: 'calc(100vh - 74px)', overflow: 'hidden' } }}
+    >
+        <div>
+            <SearchBox
+                bodyPadding={`10px 16px 4px`}
+                buttons={<>
+                    <Button type="primary" onClick={() => {
+                        setQueryParamsNew({ ...queryParams, pageNum: 1 })
+                    }} loading={getCorpAutoLinkList.loading} icon={<SearchOutlined />}>搜索</Button>
+                    <Button type="primary" icon={<PlusOutlined />} onClick={() => setVisible(true)}>链接生成</Button>
+                </>}
+            >
+                <>
+                    <Select
+                        value={queryParams?.platform}
+                        onChange={(e) => setQueryParams({ ...queryParams, platform: e })}
+                        showSearch
+                        style={{ width: 110 }}
+                        placeholder="书城"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={bookPlatForm.map(item => ({ value: item.platformKey, label: item.platformName }))}
+                    />
+                    <Select
+                        value={queryParams?.mpAccountId}
+                        onChange={(e) => setQueryParams({ ...queryParams, mpAccountId: e })}
+                        showSearch
+                        style={{ width: 110 }}
+                        placeholder="公众号"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={mpList}
+                    />
+                    <Select
+                        value={queryParams?.linkType}
+                        onChange={(e) => setQueryParams({ ...queryParams, linkType: e })}
+                        showSearch
+                        style={{ width: 110 }}
+                        placeholder="链接类型"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={Object.keys(LINKTYPE).map(key => ({ label: LINKTYPE[key], value: key }))}
+                    />
+                    <Input placeholder='请输入渠道名称' style={{ width: 150 }} allowClear value={queryParams?.channelName} onChange={(e) => setQueryParams({ ...queryParams, channelName: e.target.value })} />
+                    <Select
+                        style={{ width: 110 }}
+                        showSearch
+                        placeholder="推广类型"
+                        value={queryParams?.channelType}
+                        onChange={(value) => setQueryParams({ ...queryParams, channelType: value })}
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={[{ label: '外部', value: '1' }, { label: '内部', value: '2' }]}
+                    />
+                    <DatePicker.RangePicker 
+                        placeholder={['创建时间开始', '创建时间结束']}
+                        allowClear
+                        value={queryParams?.createTimeStart ? [dayJs(queryParams?.createTimeStart), dayJs(queryParams?.createTimeEnd)] : undefined} 
+                        onChange={(_, options) => setQueryParams({ ...queryParams, createTimeStart: options?.[0], createTimeEnd: options?.[1] })}
+                    />
+                </>
+            </SearchBox>
+        </div>
+        <div className={style.bookLinkTable} ref={ref}>
+            <Table
+                dataSource={getCorpAutoLinkList?.data?.data?.records}
+                columns={bookLinkTableConfig()}
+                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 }}
+            />
+        </div>
+        <div className={style.bookLinkPagination}>
+            <Pagination
+                size="small"
+                total={getCorpAutoLinkList?.data?.data?.total || 0}
+                showSizeChanger
+                showQuickJumper
+                pageSize={getCorpAutoLinkList?.data?.data?.size || 20}
+                current={getCorpAutoLinkList?.data?.data?.current || 1}
+                onChange={(page: number, pageSize: number) => {
+                    // ref.current?.scrollTo({ top: 0 })
+                    setTimeout(() => {
+                        setQueryParams({ ...queryParams, pageNum: page, pageSize })
+                        setQueryParamsNew({ ...queryParamsNew, pageNum: page, pageSize })
+                    }, 50)
+                }}
+                showTotal={(total: number) => <span style={{ fontSize: 12 }}>共 {total} 条</span>}
+            />
+        </div>
+
+        {/* 链接生成 模态框 */}
+        {visible && <ModalBookLink
+            mpList={mpList}
+            bookPlatForm={bookPlatForm}
+            visible={visible}
+            onChange={() => {
+                setVisible(false)
+                getCorpAutoLinkList.refresh()
+            }}
+            onClose={() => {
+                setVisible(false)
+            }}
+        />}
+    </Card>
+};
+
+export default inject('store')(observer((props: any) => BookLink(props.store)));

+ 267 - 0
src/pages/weComTask/page/bookLink/modalBooklink.tsx

@@ -0,0 +1,267 @@
+import { App, Button, Card, Form, Input, Modal, Select } from "antd";
+import React from "react";
+import { LINKTYPE } from "./const";
+import { PlusOutlined, MinusCircleOutlined } from "@ant-design/icons";
+import RechargeActivityLinkDTO from "./rechargeActivityLinkDTO";
+import BookPromoLinkCreateDTO from "./bookPromoLinkCreateDTO";
+import PagePromoLinkCreateDTO from "./pagePromoLinkCreateDTO";
+import ConsumeActivityLinkDTO from "./consumeActivityLinkDTO";
+import GiftActivityLinkDTO from "./giftActivityLinkDTO";
+import { useAjax } from "@/Hook/useAjax";
+import { addCorpAutoLinkApi } from "../../API/bookLink";
+import dayJs from "dayjs";
+
+interface Props {
+    mpList: { label: string, value: number }[]
+    bookPlatForm: TASK_CREATE.BookPlatFormProps[]
+    visible?: boolean;
+    onChange?: () => void
+    onClose?: () => void
+}
+
+export const DispatchBookLink = React.createContext<BOOKLINK.DispatchBookLink | null>(null);
+
+/**
+ * 书城链接生成
+ * @param param0 
+ * @returns 
+ */
+const ModalBookLink: React.FC<Props> = ({ mpList, bookPlatForm, visible, onChange, onClose }) => {
+
+    /********************************************/
+    const { message } = App.useApp()
+    const [form] = Form.useForm();
+    const yueWenCreateLinkDTOList = Form.useWatch('yueWenCreateLinkDTOList', form)
+    const platform = Form.useWatch('platform', form)
+    const mpAccountIds = Form.useWatch('mpAccountIds', form)
+
+    const addCorpAutoLink = useAjax((params) => addCorpAutoLinkApi(params))
+    /********************************************/
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+            console.log(values)
+            const params = {
+                mpAccountIds: values.mpAccountIds,
+                platform: values.platform,
+                yueWenCreateLinkDTOList: values.yueWenCreateLinkDTOList.map(item => {
+                    const { linkType, pagePromoLinkCreateDTO, bookPromoLinkCreateDTO, rechargeActivityLinkDTO, consumeActivityLinkDTO, giftActivityLinkDTO, ...rest } = item
+                    if (linkType === '1') {
+                        return { ...rest, pagePromoLinkCreateDTO, linkType }
+                    } else if (linkType === '2') {
+                        return { ...rest, bookPromoLinkCreateDTO, linkType }
+                    } else if (linkType === '3') {
+                        const { activityTime, display, ...ralDto } = rechargeActivityLinkDTO
+                        return { ...rest, rechargeActivityLinkDTO: { ...ralDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD'), display: display?.join(',') }, linkType }
+                    } else if (linkType === '4') {
+                        const { activityTime, display, ...calDto } = giftActivityLinkDTO
+                        return { ...rest, giftActivityLinkDTO: { ...calDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD'), display: display?.join(',') }, linkType }
+                    } else if (linkType === '5') {
+                        const { activityTime, display, ...galDto } = consumeActivityLinkDTO
+                        return { ...rest, consumeActivityLinkDTO: { ...galDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD'), display: display?.join(',') }, linkType }
+                    }
+                })
+            }
+            addCorpAutoLink.run(params).then(res => {
+                if (res?.data) {
+                    message.success('添加成功')
+                    onChange?.()
+                }
+            })
+        }).catch(() => {
+            form.submit()
+        });
+    }
+
+    return <Modal
+        title={<strong>书城链接生成</strong>}
+        open={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        width={650}
+        confirmLoading={addCorpAutoLink.loading}
+    >
+        <Form
+            form={form}
+            name="newBookLink"
+            labelAlign='left'
+            labelCol={{ span: 5 }}
+            colon={false}
+            scrollToFirstError={{
+                behavior: 'smooth',
+                block: 'center'
+            }}
+            onFinishFailed={({ errorFields }) => {
+                message.error(errorFields?.[0]?.errors?.[0])
+            }}
+            onFinish={handleOk}
+            initialValues={{
+                yueWenCreateLinkDTOList: [{}]
+            }}
+        >
+            <Card title={<strong>基础信息配置</strong>} style={{ background: '#fff', marginBottom: 10 }}>
+                <Form.Item label={<strong>书城</strong>} name="platform" rules={[{ required: true, message: '请选择书城!' }]}>
+                    <Select
+                        showSearch
+                        placeholder="书城"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={bookPlatForm.map(item => ({ value: item.platformKey, label: item.platformName }))}
+                    />
+                </Form.Item>
+                <Form.Item label={<strong>公众号</strong>} name="mpAccountIds" rules={[{ required: true, message: '请选择公众号!' }]}>
+                    <Select
+                        showSearch
+                        mode="multiple"
+                        allowClear
+                        placeholder="公众号"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        options={mpList}
+                    />
+                </Form.Item>
+            </Card>
+            <DispatchBookLink.Provider value={{ form }}>
+                <Form.List name="yueWenCreateLinkDTOList">
+                    {(fields, { add, remove }) => (
+                        <>
+                            {fields.map(({ key, name, ...restField }, index) => {
+
+                                const yueWenCreateLinkDTO = yueWenCreateLinkDTOList?.[index]
+
+                                return <Card
+                                    title={<strong>链接信息配置{index + 1}</strong>}
+                                    style={{ background: '#fff', marginBottom: 10 }}
+                                    key={key}
+                                    extra={yueWenCreateLinkDTOList?.length > 1 ? <div style={{ color: 'red' }} onClick={() => remove(name)}>
+                                        <MinusCircleOutlined />
+                                    </div> : undefined}
+                                >
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'linkType']}
+                                        label={<strong>链接类型</strong>}
+                                        rules={[{ required: true, message: '请选择链接类型!' }]}
+                                    >
+                                        <Select
+                                            showSearch
+                                            placeholder="链接类型"
+                                            filterOption={(input, option) =>
+                                                ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                                            }
+                                            allowClear
+                                            options={Object.keys(LINKTYPE).map(key => ({ label: LINKTYPE[key], value: key }))}
+                                            onChange={(e) => {
+                                                if (e === '1') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            yueWenCreateLinkDTOList: yueWenCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '1', pagePromoLinkCreateDTO: {} }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '2') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            yueWenCreateLinkDTOList: yueWenCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '2', bookPromoLinkCreateDTO: { forceStyle: 1, isOpenBottom: false } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '3') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            yueWenCreateLinkDTOList: yueWenCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '3', rechargeActivityLinkDTO: { rechargeCount: 1, timeIsShow: 1, isDayRepeat: 0 } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '4') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            yueWenCreateLinkDTOList: yueWenCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '4', giftActivityLinkDTO: { expire: 7, resourceType: '1' } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '5') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            yueWenCreateLinkDTOList: yueWenCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '5', consumeActivityLinkDTO: {} }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                }
+                                            }}
+                                        />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelName']}
+                                        label={<strong>渠道名称</strong>}
+                                        rules={[{ required: ['1', '2'].includes(yueWenCreateLinkDTO?.linkType), message: '请输入渠道名称!' }]}
+                                    >
+                                        <Input placeholder="请输入渠道名称" allowClear />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelType']}
+                                        label={<strong>推广类型</strong>}
+                                        rules={[{ required: ['1', '2'].includes(yueWenCreateLinkDTO?.linkType), message: '请选择推广类型!' }]}
+                                    >
+                                        <Select
+                                            showSearch
+                                            placeholder="推广类型"
+                                            filterOption={(input, option) =>
+                                                ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                                            }
+                                            allowClear
+                                            options={[{ label: '外部', value: '1' }, { label: '内部', value: '2' }]}
+                                        />
+                                    </Form.Item>
+                                    {yueWenCreateLinkDTO?.linkType === '1' ? <PagePromoLinkCreateDTO restField={restField} name={name} /> :
+                                        yueWenCreateLinkDTO?.linkType === '2' ? <BookPromoLinkCreateDTO restField={restField} name={name} platform={platform} mpAccountIds={mpAccountIds} yueWenCreateLinkDTO={yueWenCreateLinkDTO} /> :
+                                            yueWenCreateLinkDTO?.linkType === '3' ? <RechargeActivityLinkDTO restField={restField} name={name} /> :
+                                                yueWenCreateLinkDTO?.linkType === '4' ? <GiftActivityLinkDTO restField={restField} name={name} /> :
+                                                    yueWenCreateLinkDTO?.linkType === '5' ? <ConsumeActivityLinkDTO restField={restField} name={name} /> :
+                                                        undefined}
+                                </Card>
+                            })}
+                            <Form.Item>
+                                <Button type="dashed" onClick={() => add({})} block icon={<PlusOutlined />}>
+                                    新增链接信息配置
+                                </Button>
+                            </Form.Item>
+                        </>
+                    )}
+                </Form.List>
+            </DispatchBookLink.Provider>
+        </Form>
+    </Modal>
+};
+
+export default React.memo(ModalBookLink);

+ 40 - 0
src/pages/weComTask/page/bookLink/pagePromoLinkCreateDTO.tsx

@@ -0,0 +1,40 @@
+import { Form, Input, InputNumber, Select } from "antd";
+import React from "react";
+import { PAGETYPE } from "./const";
+
+
+/**
+ * 页面链接
+ * @returns 
+ */
+const PagePromoLinkCreateDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name }) => {
+
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'pagePromoLinkCreateDTO', 'pageType']}
+            label={<strong>页面类型</strong>}
+            rules={[{ required: true, message: '请选择页面类型!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="页面类型"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={Object.keys(PAGETYPE).map(key => ({ label: PAGETYPE[key], value: key }))}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'pagePromoLinkCreateDTO', 'cost']}
+            label={<strong>推广成本</strong>}
+        >
+            <InputNumber placeholder="请输入推广成本" style={{ width: '100%' }} />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(PagePromoLinkCreateDTO);

+ 126 - 0
src/pages/weComTask/page/bookLink/rechargeActivityLinkDTO.tsx

@@ -0,0 +1,126 @@
+import { Checkbox, DatePicker, Form, Input, InputNumber, Radio, Select, Space } from "antd";
+import React from "react";
+import { ACTICITYTHEME, DISPLAYTYPE } from "./const";
+
+
+/**
+ * 模板充值活动
+ * @returns 
+ */
+const RechargeActivityLinkDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name }) => {
+
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'activityName']}
+            label={<strong>活动名称</strong>}
+            rules={[{ required: true, message: '请输入活动名称!' }]}
+        >
+            <Input placeholder="请输入活动名称" style={{ width: '100%' }} allowClear />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'activityTheme']}
+            label={<strong>活动主题</strong>}
+            rules={[{ required: true, message: '请选择活动主题!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择活动主题"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={Object.keys(ACTICITYTHEME).map(key => ({ label: ACTICITYTHEME[key], value: key }))}
+            />
+        </Form.Item>
+        <Form.Item
+            label={<strong>充值档位</strong>}
+            required
+        >
+            <Space>
+                <Form.Item
+                    {...restField}
+                    name={[name, 'rechargeActivityLinkDTO', 'rechargeAmount']}
+                    rules={[{ required: true, message: '请输入价位!' }]}
+                    noStyle
+                >
+                    <InputNumber addonBefore="价位" suffix="元" placeholder="请输入" style={{ width: '100%' }} />
+                </Form.Item>
+                <Form.Item
+                    {...restField}
+                    name={[name, 'rechargeActivityLinkDTO', 'giftAmount']}
+                    rules={[{ required: true, message: '请输入送券数量!' }]}
+                    noStyle
+                >
+                    <InputNumber addonBefore="赠送" suffix="书卷" placeholder="请输入" style={{ width: '100%' }} />
+                </Form.Item>
+            </Space>
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'rechargeCount']}
+            label={<strong>充值次数</strong>}
+            rules={[{ required: true, message: '请选择充值次数!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择充值次数"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={[1, 2, 3].map(key => ({ label: key + '次', value: key }))}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'isDayRepeat']}
+            label={<strong>是否每日充值活动</strong>}
+            rules={[{ required: true, message: '请选择是否每日充值活动!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 1, label: '是' },
+                    { value: 0, label: '否' }
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'timeIsShow']}
+            label={<strong>活动时间状态</strong>}
+            rules={[{ required: true, message: '请选择活动时间状态!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 1, label: '开启' },
+                    { value: 0, label: '关闭' }
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'display']}
+            label={<strong>活动展示位</strong>}
+        >
+            <Checkbox.Group options={Object.keys(DISPLAYTYPE).map(key => ({ label: DISPLAYTYPE[key], value: key }))} />
+        </Form.Item>
+        
+    </>
+}
+
+export default React.memo(RechargeActivityLinkDTO);

+ 209 - 0
src/pages/weComTask/page/bookLink/selectBookLink.tsx

@@ -0,0 +1,209 @@
+import { App, Button, DatePicker, Input, Modal, Select, Space, Table, Tag, Typography } from "antd";
+import style from '../../components/selectExternalAccount/index.less'
+import { useEffect, useState } from "react";
+import { getCorpAutoLinkListApi, GetCorpAutoLinkListProps } from "../../API/bookLink";
+import { useAjax } from "@/Hook/useAjax";
+import { getBindMpListApi } from "../../API/corpUserAssign";
+import { LINKTYPE } from "./const";
+const { Text, Title } = Typography;
+import dayJs from 'dayjs';
+import { SearchOutlined, CloseOutlined } from '@ant-design/icons'
+import { bookLinkTableConfig } from "./tableConfig";
+
+interface Props {
+    bookPlatForm: TASK_CREATE.BookPlatFormProps[]
+    linkData: { [x: string]: any }[]
+    mpAccountId: number | null
+    visible?: boolean;
+    onClose?: () => void;
+    onChange?: (linkStr: string) => void;
+}
+
+/**
+ * 选择链接
+ * @param param0 
+ * @returns 
+ */
+const SelectBookLink: React.FC<Props> = ({ bookPlatForm, linkData, mpAccountId, visible, onClose, onChange }) => {
+
+    /*******************************************/
+    const { message } = App.useApp()
+    const [data, setData] = useState<{ [x: string]: any }[]>(linkData)
+    const [selectAdz, setSelectAdz] = useState<number>(1)   // 选择广告主
+    const [mpList, setMplist] = useState<{ label: string, value: number }[]>([])
+    const [queryParams, setQueryParams] = useState<GetCorpAutoLinkListProps>({ pageNum: 1, pageSize: 20, mpAccountId })
+    const [queryParamsNew, setQueryParamsNew] = useState<GetCorpAutoLinkListProps>({ pageNum: 1, pageSize: 20, mpAccountId })
+
+    const getCorpAutoLinkList = useAjax((params) => getCorpAutoLinkListApi(params))
+    const getBindMpList = useAjax(() => getBindMpListApi())
+    /*******************************************/
+
+    useEffect(() => {
+        getCorpAutoLinkList.run({ ...queryParamsNew, isLink: true, mpAccountId })
+    }, [queryParamsNew, mpAccountId])
+
+    useEffect(() => {
+        getBindMpList.run().then(res => {
+            setMplist(res?.data?.map((item: any) => ({ label: item.name, value: item.id })))
+        })
+    }, [])
+
+    const handleOk = () => {
+        if (data?.every(item => item?.bookLink?.length)) {
+            onChange?.(data.map(item => item.bookLink?.[0].link).join(','))
+        } else {
+            message.error('请选择链接')
+        }
+    }
+
+    const handleSelectAdz = (value: number) => {
+        if (value === selectAdz) {
+            return
+        }
+        setSelectAdz(value)
+    }
+
+    return <Modal
+        title={<strong>选择链接</strong>}
+        open={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        width={1200}
+        className={`${style.SelectPackage}`}
+        styles={{
+            body: {
+                padding: '0 10px 0 10px'
+            }
+        }}
+    >
+        <div className={style.content}>
+            <div className={style.left}>
+                <h4 className={style.title}>链接</h4>
+                <div className={style.accountIdList}>
+                    {data?.map((item, index) => {
+                        return <div key={index} onClick={() => { handleSelectAdz(index + 1) }} className={`${style.accItem} ${selectAdz === index + 1 && style.select} `}>
+                            <div><Text ellipsis={{ tooltip: true }}>{item?.link?.title}({item?.link?.desc})</Text></div>
+                            {/* {bookLink?.length > 0 && <CheckOutlined style={{ color: '#1890ff' }} />} */}
+                        </div>
+                    })}
+                </div>
+            </div>
+            <div className={style.right}>
+                <Space style={{ marginBottom: 10 }} align="end" size={5} wrap>
+                    <Select
+                        value={queryParams?.platform}
+                        onChange={(e) => setQueryParams({ ...queryParams, platform: e })}
+                        showSearch
+                        style={{ width: 110 }}
+                        placeholder="书城"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={bookPlatForm.map(item => ({ value: item.platformKey, label: item.platformName }))}
+                    />
+                    <Select
+                        value={queryParams?.mpAccountId}
+                        onChange={(e) => setQueryParams({ ...queryParams, mpAccountId: e })}
+                        showSearch
+                        style={{ width: 110 }}
+                        placeholder="公众号"
+                        disabled={!!mpAccountId}
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={mpList}
+                    />
+                    <Select
+                        value={queryParams?.linkType}
+                        onChange={(e) => setQueryParams({ ...queryParams, linkType: e })}
+                        showSearch
+                        style={{ width: 110 }}
+                        placeholder="链接类型"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={Object.keys(LINKTYPE).filter(key => ['1', '2'].includes(key)).map(key => ({ label: LINKTYPE[key], value: key }))}
+                    />
+                    <DatePicker.RangePicker
+                        placeholder={['创建时间开始', '创建时间结束']}
+                        allowClear
+                        value={queryParams?.createTimeStart ? [dayJs(queryParams?.createTimeStart), dayJs(queryParams?.createTimeEnd)] : undefined}
+                        onChange={(_, options) => setQueryParams({ ...queryParams, createTimeStart: options?.[0], createTimeEnd: options?.[1] })}
+                    />
+                    <Input placeholder='请输入渠道名称' style={{ width: 150 }} allowClear value={queryParams?.channelName} onChange={(e) => setQueryParams({ ...queryParams, channelName: e.target.value })} />
+                    <Select
+                        style={{ width: 110 }}
+                        showSearch
+                        placeholder="推广类型"
+                        value={queryParams?.channelType}
+                        onChange={(value) => setQueryParams({ ...queryParams, channelType: value })}
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={[{ label: '外部', value: '1' }, { label: '内部', value: '2' }]}
+                    />
+                    <Button type="primary" onClick={() => {
+                        setQueryParamsNew({ ...queryParams, pageNum: 1 })
+                    }} loading={getCorpAutoLinkList.loading} icon={<SearchOutlined />}>搜索</Button>
+                </Space>
+
+                <Table
+                    tableLayout='fixed'
+                    dataSource={getCorpAutoLinkList?.data?.data?.records}
+                    columns={bookLinkTableConfig()}
+                    loading={getCorpAutoLinkList.loading}
+                    scroll={{ y: 400 }}
+                    rowKey={'id'}
+                    size='small'
+                    bordered
+                    rowSelection={{
+                        selectedRowKeys: data[selectAdz - 1]?.bookLink?.map((item: any) => item?.id),
+                        type: 'radio',
+                        getCheckboxProps: (record: any) => ({
+                            name: record.name,
+                        }),
+                        onChange(_, selectedRows) {
+                            let newData = JSON.parse(JSON.stringify(data))
+                            newData[selectAdz - 1].bookLink = selectedRows
+                            setData(newData)
+                        },
+                    }}
+                    pagination={{
+                        total: getCorpAutoLinkList.data?.data?.total,
+                        showTotal: (total) => <Tag color="cyan">总共{total}数据</Tag>,
+                        showSizeChanger: true,
+                        showLessItems: true,
+                        defaultCurrent: 1,
+                        defaultPageSize: 20,//默认初始的每页条数
+                        current: getCorpAutoLinkList?.data?.data?.current || 1,
+                        pageSize: getCorpAutoLinkList?.data?.data?.size || 20,
+                        onChange: (page, pageSize) => {
+                            setQueryParams({ ...queryParams, pageNum: page, pageSize })
+                            setQueryParamsNew({ ...queryParamsNew, pageNum: page, pageSize })
+                        }
+                    }}
+                />
+            </div>
+            <div className={style.center}>
+                <Title level={5}>已选:{data[selectAdz - 1]?.bookLink?.length || 0}</Title>
+                <div className={style.select_content}>
+                    {data[selectAdz - 1]?.bookLink?.map(item => <div key={item.id}>
+                        <Text ellipsis={{ tooltip: true }} className={style.marketingAssetName}>{item.channelName}</Text>
+                        <CloseOutlined className={style.close} onClick={() => {
+                            let newData = JSON.parse(JSON.stringify(data))
+                            newData[selectAdz - 1].bookLink = newData[selectAdz - 1]?.bookLink?.filter((i: any) => i?.id !== item.id)
+                            setData(newData)
+                        }} />
+                    </div>)}
+                </div>
+            </div>
+        </div>
+    </Modal>
+}
+
+
+export default SelectBookLink;

+ 113 - 0
src/pages/weComTask/page/bookLink/tableConfig.tsx

@@ -0,0 +1,113 @@
+import { copy } from "@/utils/utils"
+import { ColumnsType } from "antd/es/table"
+import { LINKTYPEEle } from "./const"
+import { Button, Popover } from "antd"
+import Details from "./details"
+
+
+export function bookLinkTableConfig(): ColumnsType<any> {
+
+    const arr: ColumnsType<any> = [
+        {
+            title: '书城',
+            dataIndex: 'platformName',
+            key: 'platformName',
+            align: 'center',
+            width: 80,
+            ellipsis: true,
+            fixed: 'left',
+            render: (value) => {
+                return <span style={{ fontSize: 12 }}>{value}</span>
+            }
+        },
+        {
+            title: '公众号',
+            dataIndex: 'mpAccountName',
+            key: 'mpAccountName',
+            align: 'center',
+            width: 80,
+            fixed: 'left',
+            render: (value) => {
+                return <span style={{ fontSize: 12 }}>{value}</span>
+            }
+        },
+        {
+            title: '渠道名称',
+            dataIndex: 'channelName',
+            key: 'channelName',
+            width: 110,
+            ellipsis: true,
+            render: (value) => {
+                return <span style={{ fontSize: 12 }}>{value || '--'}</span>
+            }
+        },
+        {
+            title: '推广类型',
+            dataIndex: 'channelType',
+            key: 'channelType',
+            align: 'center',
+            width: 80,
+            render: (value) => {
+                return <span style={{ fontSize: 12 }}>{value === 1 ? '外部' : value === 2 ? '内部' : '--'}</span>
+            }
+        },
+        {
+            title: '链接类型',
+            dataIndex: 'linkType',
+            key: 'linkType',
+            align: 'center',
+            width: 120,
+            render: (value) => {
+                return LINKTYPEEle[value] || '--'
+            }
+        },
+        {
+            title: '生成链接',
+            dataIndex: 'link',
+            key: 'link',
+            width: 200,
+            ellipsis: true,
+            render: (value) => {
+                return value ? <a style={{ fontSize: 12 }} onClick={() => copy(value)}>{value}</a> : '--'
+            }
+        },
+        {
+            title: '创建人',
+            dataIndex: 'createBy',
+            key: 'createBy',
+            align: 'center',
+            width: 80,
+            render: (value) => {
+                return <span style={{ fontSize: 12 }}>{value}</span>
+            }
+        },
+        {
+            title: '创建时间',
+            dataIndex: 'createTime',
+            key: 'createTime',
+            align: 'center',
+            width: 140,
+            render: (value) => {
+                return <span style={{ fontSize: 12 }}>{value}</span>
+            }
+        },
+        {
+            title: '详情',
+            dataIndex: 'cz',
+            key: 'cz',
+            align: 'center',
+            width: 60,
+            fixed: 'right',
+            render: (_, records) => {
+                return <Popover
+                    placement="left"
+                    content={<Details linkType={records.linkType} linkContent={records.linkContext} />}
+                    styles={{ body: { width: 300, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
+                >
+                    <Button type="link" style={{ padding: 0, height: 'auto' }}>详情</Button>
+                </Popover>
+            }
+        },
+    ]
+    return arr
+}

+ 11 - 0
src/pages/weComTask/page/bookLink/typings.d.ts

@@ -0,0 +1,11 @@
+declare namespace BOOKLINK {
+    interface DispatchBookLink {
+        form: FormInstance<any>
+    }
+    interface BookLinkChildProps {
+        restField: {
+            fieldKey?: number;
+        }
+        name: number
+    }
+}

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

@@ -354,7 +354,7 @@ const MassSending: React.FC = () => {
     }
 
     return <>
-        <div className={`${style.settingsBody_content_row}`} style={{ width: 'calc(100% / 3 * 2)' }}>
+        <div className={`${style.settingsBody_content_row}`} style={{ width: 'calc(100% / 2)' }}>
             <div className={`${style.settingsBody_content_col}`} style={{ width: '50%' }}>
                 <div className={style.title}>
                     <span>群发</span>

+ 2 - 2
src/pages/weComTask/page/businessPlan/create/components/userInherit/index.tsx

@@ -263,7 +263,7 @@ const UserInherit: React.FC = () => {
                 <div className={style.title}>
                     <span>客户继承</span>
                     {(settings?.userInherit && Object.keys(settings?.userInherit)?.length) && <Space>
-                        <Button
+                        {/* <Button
                             type="link"
                             style={{ padding: 0, fontSize: 12 }}
                             loading={downloadLoading}
@@ -283,7 +283,7 @@ const UserInherit: React.FC = () => {
                                 type="link"
                                 style={{ padding: 0, fontSize: 12 }}
                             >{settings?.corpUsers?.every(item => item?.externalUserTransferContent?.length) ? 'Excel内容已上传,重新上传' : '上传Excel'}</Button>
-                        </Upload>
+                        </Upload> */}
                         <Button
                             type="link"
                             danger

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

@@ -283,7 +283,7 @@ const Welcome: React.FC = () => {
     }
 
     return <>
-        <div className={`${style.settingsBody_content_row}`} style={{ width: 'calc(100% / 3)' }}>
+        <div className={`${style.settingsBody_content_row}`}>
             <div className={`${style.settingsBody_content_col}`} style={{ width: '100%' }}>
                 <div className={style.title}>
                     <span>欢迎语</span>

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

@@ -112,7 +112,7 @@ export const getUserInDataData = (schedulingStrategyDTO: any[], taskName?: strin
     schedulingStrategyDTO?.forEach((item, index) => {
         // 1、策略 名称 、时间、周期
         const { inheritDto, ...strategyData } = JSON.parse(JSON.stringify(item))
-        inheritDto?.forEach((item1, index1) => {
+        inheritDto?.forEach((item1, index1, row) => {
             // 2、转移对象、文本
 
             userInData.push({
@@ -120,7 +120,8 @@ export const getUserInDataData = (schedulingStrategyDTO: any[], taskName?: strin
                 strategyData,
                 inheritData: item1,
                 strategyIndex: index + 1,
-                inheritIndex: index1 + 1
+                inheritIndex: index1 + 1,
+                strategyRowSpan: index1 === 0 ? row.length : 0
             })
         })
     })

+ 6 - 2
src/pages/weComTask/page/businessPlan/create/index.less

@@ -46,6 +46,7 @@
         border-left: 1px solid #f0f0f0;
         box-sizing: border-box;
         display: flex;
+        width: calc(100% / 4);
 
         .title {
             height: 50px;
@@ -78,8 +79,11 @@
     .settingsBody_content_col {
         // width: 350px;
         // max-width: 350px;
-        min-width: 350px;
-
+        // min-width: 350px;
+        // width: var(--w100) / 4;
+        // max-width: calc(var(--w100) / 4);
+        // min-width: var(--w100) / 4;
+        width: 100%;
         
 
         .detail {

+ 256 - 205
src/pages/weComTask/page/businessPlan/create/index.tsx

@@ -1,5 +1,5 @@
 import { inject, observer } from 'mobx-react';
-import React, { useEffect, useState } from 'react';
+import React, { useCallback, useEffect, useState } from 'react';
 import style from './index.less'
 import { App, Button, Card, Empty, Input, Popconfirm, Select, Space, Spin, Table, Tabs } from 'antd';
 import MassSending from './components/massSending';
@@ -32,22 +32,20 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
     /***********************************************/
     const navigate = useNavigate();
     const { bookList, bookPlatForm } = toJS(weComTaskStore.data)
-
     const [settings, setSettings] = useState<TASK_CREATE.SettingsProps>();
-
-    console.log('settings--->', settings)
     const { message, modal } = App.useApp()
     const [msgJobTypeList, setMsgJobTypeList] = useState<{ value: string, label: string }[]>([])
     const [previewData, setPreviewData] = useState<TASK_CREATE.previewDataProps>({})
     const [subVisible, setSubVisible] = useState<boolean>(false) // 选择设置名称弹窗控制
     const [eaVisible, setEaVisible] = useState<boolean>(false)
     const [qwVisible, setQwVisible] = useState<boolean>(false)
-    const [previewContent, setPreviewContent] = useState<{ groupMsgContent?: any[], welcomeMsgContent?: any[] }>({})
+    const [previewContent, setPreviewContent] = useState<{ groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[], }>({})
 
     const welcomeMsgJobType = useAjax(() => welcomeMsgJobTypeApi())//获取欢迎语类型
 
     const addTask = useAjax((params) => addTaskApi(params))
     /***********************************************/
+    console.log('settings--->', settings, previewContent)
 
     useEffect(() => {
         const task = localStorage.getItem('TASK_CORP_CREATE')
@@ -74,23 +72,18 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
 
         // 欢迎语
         if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
-            if (settings?.welcomeMsgTemplateDTO?.mediaContentList?.some(item => item?.some(i => i?.mediaType === 'link' || i?.mediaType === 'miniprogram')) && settings?.corpUsers?.every(item => !item?.welcomeMsgContent?.length)) {
-                message.error('请先上传欢迎语Excel内容')
-                return
-            }
             const welcome = []
-            if (!settings?.corpUsers?.every((item, i) => {
+            if (!settings?.corpUserGroups?.every((item, i) => {
                 return settings?.welcomeMsgTemplateDTO?.mediaContentList?.every((mediaItem, index, row) => {
-                    const welcomeMsgContent = item.welcomeMsgContent?.[index]
-                    if (mediaItem?.some(media => media?.mediaType === 'link' ? !welcomeMsgContent?.linkUrl : media?.mediaType === 'miniprogram' ? (!welcomeMsgContent?.miniprogramAppid || !welcomeMsgContent?.miniprogramPage) : false)) {
-                        message.error('欢迎语内容配置错误,请检查')
-                        return false
-                    }
+                    const linkData = []
+                    let isMiniProgram = false
                     const contentReactNode = mediaItem.map(item => {
                         switch (item.mediaType) {
                             case 'link':
+                                linkData.push(item)
                                 return `<span style="color: red">链接</span>`
                             case 'miniprogram':
+                                isMiniProgram = true
                                 return `<span style="color: red">小程序</span>`
                             case 'file':
                                 return `<span>文件</span>`
@@ -108,10 +101,12 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         ...settings?.welcomeMsgTemplateDTO,
                         sendData: mediaItem,
                         contentReactNode,
-                        welcomeMsgContent,
+                        corpUsergroupIndex: i,
+                        corpUserGroupName: `客服组${i + 1}`,
+                        corpUserList: item.corpUsers,
+                        linkData,
+                        isMiniProgram,
                         contentIndex: index + 1,
-                        corpUserId: item.corpUserId,
-                        corpUserName: item.name,
                         bizType: settings?.bizType,
                         channel: settings?.channel,
                         platform: settings?.platform,
@@ -130,10 +125,6 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
 
         // 群发
         if ((settings?.massSendingContent && Object.keys(settings?.massSendingContent).length) && (settings?.massSendingStrategy && Object.keys(settings?.massSendingStrategy).length)) {
-            // if (settings?.massSendingContent?.massSendingContentDTO?.some(item => item?.sendContentDto?.some(si => si?.contentDTO?.some(i => i?.attachmentList?.some(a => ['TASK_CONTENT_LINK', 'TASK_STATUS_MINIPROGRAM'].includes(a?.msgType))))) && settings?.corpUsers?.every(item => !item?.groupMsgContent?.length)) {
-            //     message.error('需要配置小程序、链接,请上传配置好的群发Excel文件')
-            //     return
-            // }
             const massSendingData = getGroupData(settings)
             const massSending = []
             if (!settings?.corpUserGroups?.every((item, i) => {
@@ -149,12 +140,12 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                             textContent: dataItem?.content?.text?.content
                         })
                     }
-                    let isLink = false
+                    const linkData = []
                     let isMiniProgram = false
                     const contentReactNode = mediaItem.map(item => {
                         switch (item.msgType) {
                             case 'TASK_CONTENT_LINK':
-                                isLink = true
+                                linkData.push(item)
                                 return `<span style="color: red">链接</span>`
                             case 'TASK_STATUS_MINIPROGRAM':
                                 isMiniProgram = true
@@ -183,7 +174,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         platform: settings?.platform,
                         templateProductId: settings?.templateProductId,
                         id: i * row.length + (li + 1),
-                        isLink,
+                        linkData,
                         isMiniProgram,
                         userRowSpan: li % row.length === 0 ? row.length : 0,
                         strategyRowSpan: strategyIndex !== dataItem.strategyIndex ? dataItem.strategyDataCount : 0
@@ -199,42 +190,35 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
         }
 
         // 是否有客户继承配置
-        // if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
-        //     if (settings?.corpUsers?.every(item => !item?.externalUserTransferContent?.length)) {
-        //         message.error('请上传配置好的客户继承Excel文件')
-        //         return
-        //     }
-        //     const userInData = getUserInDataData(settings?.userInherit?.schedulingStrategyDTO, settings?.userInherit?.taskName)
+        if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
+            const userInData = getUserInDataData(settings?.userInherit?.schedulingStrategyDTO, settings?.userInherit?.taskName)
 
-        //     const userInherit = []
-        //     // 数据内容
-        //     if (!settings?.corpUsers?.every((item, i) => {
-        //         return userInData.every((dataItem, ii, row) => {
-        //             const externalUser = item.externalUserTransferContent?.[dataItem.strategyIndex - 1]?.[dataItem.inheritIndex - 1]
-        //             if (!externalUser || !externalUser?.corpUserName || !externalUser?.corpUserId) {
-        //                 message.error('Excel配置错误,' + JSON.stringify(dataItem) + ',' + JSON.stringify(item.externalUserTransferContent))
-        //                 return false
-        //             }
-        //             userInherit.push({
-        //                 ...dataItem,
-        //                 externalUser,
-        //                 taskName: dataItem?.taskName,
-        //                 corpUserId: item.corpUserId,
-        //                 corpUserName: item.name,
-        //                 bizType: settings?.bizType,
-        //                 channel: settings?.channel,
-        //                 platform: settings?.platform,
-        //                 templateProductId: settings?.templateProductId,
-        //                 id: i * row.length + (ii + 1)
-        //             })
-        //             return true
-        //         })
-        //     })) {
-        //         return
-        //     }
-        //     console.log('userInherit-->', userInherit)
-        //     newPreviewData.userInherit = userInherit
-        // }
+            const userInherit = []
+            // 数据内容
+            if (!settings?.corpUserGroups?.every((item, i) => {
+                return userInData.every((dataItem, ii, row) => {
+
+                    userInherit.push({
+                        ...dataItem,
+                        taskName: dataItem?.taskName,
+                        corpUsergroupIndex: i,
+                        corpUserGroupName: `客服组${i + 1}`,
+                        corpUserList: item.corpUsers,
+                        bizType: settings?.bizType,
+                        channel: settings?.channel,
+                        platform: settings?.platform,
+                        templateProductId: settings?.templateProductId,
+                        userRowSpan: ii === 0 ? row.length : 0,
+                        id: i * row.length + (ii + 1)
+                    })
+                    return true
+                })
+            })) {
+                return
+            }
+            console.log('userInherit-->', userInherit)
+            newPreviewData.userInherit = userInherit
+        }
 
         // 是否有高级群发
         // if ((settings?.highMassSendingContent && Object.keys(settings?.highMassSendingContent).length) && (settings?.highMassSendingStrategy && Object.keys(settings?.highMassSendingStrategy).length)) {
@@ -309,132 +293,194 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
         // }
 
         // 是否有朋友圈任务
-        if ((settings?.friendsContent && Object.keys(settings?.friendsContent).length) && (settings?.friendsStrategy && Object.keys(settings?.friendsStrategy).length)) {
-            if (settings?.friendsContent?.friendsContentDTO?.some(item => item?.contentDTO?.some(i => i?.attachmentList?.some(a => ['link', 'miniprogram'].includes(a?.mediaType)))) && settings?.corpUsers?.every(item => !item?.friendsMsgContent?.length)) {
-                message.error('朋友圈需要配置小程序、链接,请上传配置好的群发Excel文件')
-                return
-            }
-            const friends = []
-            let rowLength = 1
-            if (!settings?.corpUsers?.every((item, i) => {
-                let uIndex = 0
-                const uLength = settings?.friendsStrategy?.strategySettings?.reduce((pre, _, i) => settings?.friendsContent?.friendsContentDTO?.[i]?.contentDTO?.length + pre, 0)
-                return settings?.friendsStrategy?.strategySettings?.every((strategyItem, strategyIndex) => {
-                    const friendsContentDTO = settings?.friendsContent?.friendsContentDTO?.[strategyIndex]
-                    let sIndex = 0
-                    return friendsContentDTO.contentDTO.every((contentItem, contentIndex) => {
-                        const msgContent = item.friendsMsgContent?.[strategyIndex]?.[contentIndex]
-                        if (contentItem?.attachmentList?.length && contentItem?.attachmentList?.some(item => (item?.mediaType === 'link' ? !msgContent?.linkUrl : item?.mediaType === 'miniprogram' ? (!msgContent?.miniprogramAppid || !msgContent?.miniprogramPage) : false))) {
-                            message.error('朋友圈内容配置错误,请检查')
-                            return false
-                        }
+        // if ((settings?.friendsContent && Object.keys(settings?.friendsContent).length) && (settings?.friendsStrategy && Object.keys(settings?.friendsStrategy).length)) {
+        //     if (settings?.friendsContent?.friendsContentDTO?.some(item => item?.contentDTO?.some(i => i?.attachmentList?.some(a => ['link', 'miniprogram'].includes(a?.mediaType)))) && settings?.corpUsers?.every(item => !item?.friendsMsgContent?.length)) {
+        //         message.error('朋友圈需要配置小程序、链接,请上传配置好的群发Excel文件')
+        //         return
+        //     }
+        //     const friends = []
+        //     let rowLength = 1
+        //     if (!settings?.corpUsers?.every((item, i) => {
+        //         let uIndex = 0
+        //         const uLength = settings?.friendsStrategy?.strategySettings?.reduce((pre, _, i) => settings?.friendsContent?.friendsContentDTO?.[i]?.contentDTO?.length + pre, 0)
+        //         return settings?.friendsStrategy?.strategySettings?.every((strategyItem, strategyIndex) => {
+        //             const friendsContentDTO = settings?.friendsContent?.friendsContentDTO?.[strategyIndex]
+        //             let sIndex = 0
+        //             return friendsContentDTO.contentDTO.every((contentItem, contentIndex) => {
+        //                 const msgContent = item.friendsMsgContent?.[strategyIndex]?.[contentIndex]
+        //                 if (contentItem?.attachmentList?.length && contentItem?.attachmentList?.some(item => (item?.mediaType === 'link' ? !msgContent?.linkUrl : item?.mediaType === 'miniprogram' ? (!msgContent?.miniprogramAppid || !msgContent?.miniprogramPage) : false))) {
+        //                     message.error('朋友圈内容配置错误,请检查')
+        //                     return false
+        //                 }
 
-                        const mediaItem = JSON.parse(JSON.stringify(contentItem?.attachmentList || []))
-                        if (contentItem?.text?.content) {
-                            mediaItem.push({
-                                mediaType: 'text',
-                                textContent: contentItem?.text?.content
-                            })
-                        }
-                        const contentReactNode = mediaItem.map(item => {
-                            switch (item.mediaType) {
-                                case 'link':
-                                    return `<span style="color: red">链接</span>`
-                                case 'miniprogram':
-                                    return `<span style="color: red">小程序</span>`
-                                case 'file':
-                                    return `<span>文件</span>`
-                                case 'video':
-                                    return `<span>视频</span>`
-                                case 'image':
-                                    return `<span>图片</span>`
-                                case 'text':
-                                    return `<span>文本</span>`
-                                default:
-                                    return `<span style="color: red">请联系管理员</span>`
-                            }
-                        })
+        //                 const mediaItem = JSON.parse(JSON.stringify(contentItem?.attachmentList || []))
+        //                 if (contentItem?.text?.content) {
+        //                     mediaItem.push({
+        //                         mediaType: 'text',
+        //                         textContent: contentItem?.text?.content
+        //                     })
+        //                 }
+        //                 const contentReactNode = mediaItem.map(item => {
+        //                     switch (item.mediaType) {
+        //                         case 'link':
+        //                             return `<span style="color: red">链接</span>`
+        //                         case 'miniprogram':
+        //                             return `<span style="color: red">小程序</span>`
+        //                         case 'file':
+        //                             return `<span>文件</span>`
+        //                         case 'video':
+        //                             return `<span>视频</span>`
+        //                         case 'image':
+        //                             return `<span>图片</span>`
+        //                         case 'text':
+        //                             return `<span>文本</span>`
+        //                         default:
+        //                             return `<span style="color: red">请联系管理员</span>`
+        //                     }
+        //                 })
 
-                        friends.push({
-                            corpUserId: item.corpUserId,
-                            corpUserName: item.name,
-                            bizType: settings?.bizType,
-                            channel: settings?.channel,
-                            platform: settings?.platform,
-                            templateProductId: settings?.templateProductId,
-                            momentSendName: settings?.friendsStrategy?.momentSendName,
-                            strategyData: strategyItem,
-                            strategyIndex: strategyIndex,
-                            sendData: item?.friendsTagContent,
-                            contentReactNode,
-                            contentIndex,
-                            sendMode: friendsContentDTO?.sendMode,
-                            content: contentItem,
-                            friendsContent: msgContent,
-                            id: rowLength,
-                            userRowSpan: uIndex === 0 ? uLength : 0,
-                            strategyRowSpan: sIndex === 0 ? friendsContentDTO.contentDTO.length : 0
-                        })
-                        rowLength++;
-                        uIndex++;
-                        sIndex++;
-                        return true
-                    })
+        //                 friends.push({
+        //                     corpUserId: item.corpUserId,
+        //                     corpUserName: item.name,
+        //                     bizType: settings?.bizType,
+        //                     channel: settings?.channel,
+        //                     platform: settings?.platform,
+        //                     templateProductId: settings?.templateProductId,
+        //                     momentSendName: settings?.friendsStrategy?.momentSendName,
+        //                     strategyData: strategyItem,
+        //                     strategyIndex: strategyIndex,
+        //                     sendData: item?.friendsTagContent,
+        //                     contentReactNode,
+        //                     contentIndex,
+        //                     sendMode: friendsContentDTO?.sendMode,
+        //                     content: contentItem,
+        //                     friendsContent: msgContent,
+        //                     id: rowLength,
+        //                     userRowSpan: uIndex === 0 ? uLength : 0,
+        //                     strategyRowSpan: sIndex === 0 ? friendsContentDTO.contentDTO.length : 0
+        //                 })
+        //                 rowLength++;
+        //                 uIndex++;
+        //                 sIndex++;
+        //                 return true
+        //             })
+        //         })
+        //     })) {
+        //         return
+        //     }
+        //     newPreviewData.friends = friends
+        // }
+        if (newPreviewData && Object.keys(newPreviewData).length) {
+            setPreviewData(newPreviewData)
+        } else {
+            message.error('请填写至少填写一项内容')
+        }
+    }
+
+    // 设置任务名称
+    const setTaskName = () => {
+        // 欢迎语
+        if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
+            if (settings?.welcomeMsgTemplateDTO?.mediaContentList?.some(item => item?.some(i => i?.mediaType === 'link' || i?.mediaType === 'miniprogram')) && !(previewContent?.welcomeMsgContent?.length > 0)) {
+                message.error('请先上传欢迎语Excel内容')
+                return
+            }
+            if (!settings?.corpUserGroups?.every((_, i) => {
+                return settings?.welcomeMsgTemplateDTO?.mediaContentList?.every((mediaItem, index) => {
+                    const welcomeMsgContent = previewContent.welcomeMsgContent?.[i]?.[index]
+                    if (mediaItem?.some(media => media?.mediaType === 'link' ? !welcomeMsgContent?.linkUrl : media?.mediaType === 'miniprogram' ? (!welcomeMsgContent?.miniprogramAppid || !welcomeMsgContent?.miniprogramPage) : false)) {
+                        message.error('欢迎语内容配置错误,请检查')
+                        return false
+                    }
+                    return true
                 })
             })) {
                 return
             }
-            newPreviewData.friends = friends
         }
-        if (newPreviewData && Object.keys(newPreviewData).length) {
-            setPreviewData(newPreviewData)
-        } else {
-            message.error('请填写至少填写一项内容')
+        // 群发任务
+        if ((settings?.massSendingContent && Object.keys(settings?.massSendingContent).length) && (settings?.massSendingStrategy && Object.keys(settings?.massSendingStrategy).length)) {
+            if (settings?.massSendingContent?.massSendingContentDTO?.some(item => item?.sendContentDto?.some(si => si?.contentDTO?.some(i => i?.attachmentList?.some(a => ['TASK_CONTENT_LINK', 'TASK_STATUS_MINIPROGRAM'].includes(a?.msgType))))) && !(previewContent?.groupMsgContent?.length > 0)) {
+                message.error('需要配置小程序、链接,请认真填写')
+                return
+            }
+            const massSendingData = getGroupData(settings)
+            if (!settings?.corpUserGroups?.every((_, i) => {
+                return massSendingData.every((dataItem) => {
+                    const groupMsgContent = previewContent?.groupMsgContent?.[i]?.[dataItem.strategyIndex - 1]?.[dataItem.sendDataIndex - 1]?.[dataItem.contentIndex - 1]
+                    if (dataItem?.content?.attachmentList?.length && dataItem?.content?.attachmentList?.some(item => (item?.msgType === 'TASK_CONTENT_LINK' ? !groupMsgContent?.linkUrl : item?.msgType === 'TASK_STATUS_MINIPROGRAM' ? (!groupMsgContent?.miniprogramAppid || !groupMsgContent?.miniprogramPage) : false))) {
+                        message.error('群发内容配置错误,请检查')
+                        return false
+                    }
+                    return true
+                })
+            })) {
+                return
+            }
         }
+        // 客户继承
+        if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
+            const userInData = getUserInDataData(settings?.userInherit?.schedulingStrategyDTO, settings?.userInherit?.taskName)
+            if (!settings?.corpUserGroups?.every((item, i) => {
+                return userInData.every((dataItem) => {
+                    const externalUser = previewContent.externalUserTransferContent?.[i]?.[dataItem.strategyIndex - 1]?.[dataItem.inheritIndex - 1]
+                    if (!externalUser || !externalUser?.corpUserName || !externalUser?.corpUserId) {
+                        message.error('配置错误,' + JSON.stringify(dataItem) + ',' + JSON.stringify(item.externalUserTransferContent))
+                        return false
+                    }
+                    return true
+                })
+            })) {
+                return
+            }
+        }
+        setSubVisible(true)
     }
 
     const onSubmit = (values: any) => {
-        const { bizType, platform, templateProductId, corpUsers, welcomeMsgTemplateDTO, massSendingContent, massSendingStrategy, highMassSendingContent, highMassSendingStrategy, userInherit, friendsContent, friendsStrategy } = settings
+        const { bizType, platform, templateProductId, corpUserGroups, welcomeMsgTemplateDTO, massSendingContent, massSendingStrategy, highMassSendingContent, highMassSendingStrategy, userInherit, friendsContent, friendsStrategy } = settings
 
         const params = {
             ...values,
             bizType,
             platform,
             templateProductId,
-            corpUsers: corpUsers?.map(item => {
+            corpUsers: corpUserGroups?.map((item, index) => {
                 const params: { [x: string]: any } = {
-                    corpId: item.corpId,
-                    corpUserId: item.corpUserId
+                    corpId: item.corpUsers[0].corpId,
+                    corpUserIds: item.corpUsers.map(item => item.corpUserId)
                 }
                 // 欢迎语
-                if (item?.welcomeMsgContent) {
-                    params.welcomeMsgContent = item?.welcomeMsgContent
+                if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
+                    params.welcomeMsgContent = previewContent?.welcomeMsgContent[index]
                 }
+
                 // 群发
-                if (item?.groupMsgContent) {
-                    params.groupMsgContent = item?.groupMsgContent
+                if (massSendingStrategy && Object.keys(massSendingStrategy).length) {
+                    params.groupMsgContent = previewContent.groupMsgContent[index]
                 }
+
                 // 继承
-                if (item?.externalUserTransferContent) {
-                    params.takeoverUserIds = item?.externalUserTransferContent
-                }
-                // 高级群发
-                if (item?.highGroupMsgContent) {
-                    params.messageSendContent = item?.highGroupMsgContent
-                    // 外部成员
-                    if (item?.externalUserList) {
-                        params.corpList = item?.externalUserList.map(item => ({
-                            externalUserId: item.externalUserId,
-                            corpId: item.corpId
-                        }))
-                    }
-                }
-                if (item?.friendsMsgContent) {
-                    params.momentSendContent = item.friendsMsgContent
-                }
-                if (item?.friendsTagContent) {
-                    params.externalUserTagList = item.friendsTagContent.map(item => item.value)
+                if (settings?.userInherit && Object.keys(settings?.userInherit).length) {
+                    params.takeoverUserIds = previewContent?.externalUserTransferContent[index]
                 }
+                // // 高级群发
+                // if (item?.highGroupMsgContent) {
+                //     params.messageSendContent = item?.highGroupMsgContent
+                //     // 外部成员
+                //     if (item?.externalUserList) {
+                //         params.corpList = item?.externalUserList.map(item => ({
+                //             externalUserId: item.externalUserId,
+                //             corpId: item.corpId
+                //         }))
+                //     }
+                // }
+                // if (item?.friendsMsgContent) {
+                //     params.momentSendContent = item.friendsMsgContent
+                // }
+                // if (item?.friendsTagContent) {
+                //     params.externalUserTagList = item.friendsTagContent.map(item => item.value)
+                // }
                 return params
             })
         }
@@ -445,10 +491,6 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
         }
         // 群发
         if (massSendingStrategy && Object.keys(massSendingStrategy).length) {
-            if (massSendingContent?.massSendingContentDTO?.some(item => item?.sendContentDto?.some(si => si?.contentDTO?.some(i => i?.attachmentList?.some(a => ['TASK_CONTENT_LINK', 'TASK_STATUS_MINIPROGRAM'].includes(a?.msgType))))) && settings?.corpUsers?.every(item => !item?.groupMsgContent?.length)) {
-                message.error('需要配置小程序、链接,请上传配置好的群发Excel文件')
-                return
-            }
             params.groupSendTaskAddDTO = {
                 groupSendName: massSendingStrategy.groupSendName,
                 strategyList: massSendingStrategy?.strategySettings?.map((settingsItem, settingsIndex) => {
@@ -574,32 +616,33 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
         //         })
         //     }
         // }
-        // if (userInherit && Object.keys(userInherit).length) {
-        //     params.externalUserTransferTasksDTO = {
-        //         taskName: userInherit.taskName,
-        //         schedulingStrategyDTO: userInherit.schedulingStrategyDTO.map(strategyItem => {
-        //             const {
-        //                 inheritDto,
-        //                 ...strategy
-        //             } = strategyItem
-        //             return {
-        //                 ...strategy,
-        //                 transferStrategyContentDTOS: inheritDto.map(inheritItem => {
-        //                     const inherit: { [x: string]: any } = {
-        //                         transferSuccessMsg: inheritItem.transferSuccessMsg
-        //                     }
-        //                     if (inheritItem.transferType === 'specify') {
-        //                         inherit.externalUserFilter = {
-        //                             configName: inheritItem.transferUserDto.configName,
-        //                             ...inheritItem.transferUserDto.configContent
-        //                         }
-        //                     }
-        //                     return inherit
-        //                 })
-        //             }
-        //         })
-        //     }
-        // }
+        // 客户继承
+        if (userInherit && Object.keys(userInherit).length) {
+            params.externalUserTransferTasksDTO = {
+                taskName: userInherit.taskName,
+                schedulingStrategyDTO: userInherit.schedulingStrategyDTO.map(strategyItem => {
+                    const {
+                        inheritDto,
+                        ...strategy
+                    } = strategyItem
+                    return {
+                        ...strategy,
+                        transferStrategyContentDTOS: inheritDto.map(inheritItem => {
+                            const inherit: { [x: string]: any } = {
+                                transferSuccessMsg: inheritItem.transferSuccessMsg
+                            }
+                            if (inheritItem.transferType === 'specify') {
+                                inherit.externalUserFilter = {
+                                    configName: inheritItem.transferUserDto.configName,
+                                    ...inheritItem.transferUserDto.configContent
+                                }
+                            }
+                            return inherit
+                        })
+                    }
+                })
+            }
+        }
         // 朋友圈
         // if (friendsStrategy && Object.keys(friendsStrategy).length) {
         //     params.momentCreateDTO = {
@@ -662,7 +705,6 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
         //         })
         //     }
         // }
-
         addTask.run(params).then(res => {
             console.log(res)
             if (res?.data) {
@@ -693,25 +735,34 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
         message.success('存储成功')
     }
 
-    const setContent = (data: TASK_CREATE.SetContentProps) => {
+    const setContent = useCallback((data: TASK_CREATE.SetContentProps) => {
         const { msg, index, type } = data
-        const newPreviewContent = JSON.parse(JSON.stringify(previewContent))
-
-
+        const newPreviewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] } = JSON.parse(JSON.stringify(previewContent))
         switch (type) {
             case 'welcome':
+                newPreviewContent.welcomeMsgContent = newPreviewContent?.welcomeMsgContent || []
+                if (!newPreviewContent.welcomeMsgContent?.[index[0]]) newPreviewContent.welcomeMsgContent[index[0]] = [];
+                if (!newPreviewContent.welcomeMsgContent[index[0]][index[1]]) newPreviewContent.welcomeMsgContent[index[0]][index[1]] = {};
+                newPreviewContent.welcomeMsgContent[index[0]][index[1]] = { ...newPreviewContent.welcomeMsgContent[index[0]][index[1]], ...msg }
                 break
             case 'massSending':
-                newPreviewContent.groupMsgContent = newPreviewContent?.groupMsgContent || {}
+                newPreviewContent.groupMsgContent = newPreviewContent?.groupMsgContent || []
                 if (!newPreviewContent.groupMsgContent?.[index[0]]) newPreviewContent.groupMsgContent[index[0]] = [];
                 if (!newPreviewContent.groupMsgContent[index[0]][index[1]]) newPreviewContent.groupMsgContent[index[0]][index[1]] = [];
                 if (!newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]]) newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]] = [];
                 if (!newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]]) newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]] = {};
                 newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]] = { ...newPreviewContent.groupMsgContent[index[0]][index[1]][index[2]][index[3]], ...msg }
                 break
+            case 'userInherit':
+                newPreviewContent.externalUserTransferContent = newPreviewContent?.externalUserTransferContent || []
+                if (!newPreviewContent.externalUserTransferContent?.[index[0]]) newPreviewContent.externalUserTransferContent[index[0]] = [];
+                if (!newPreviewContent.externalUserTransferContent[index[0]][index[1]]) newPreviewContent.externalUserTransferContent[index[0]][index[1]] = [];
+                if (!newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]]) newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]] = {};
+                newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]] = { ...newPreviewContent.externalUserTransferContent[index[0]][index[1]][index[2]], ...msg }
+                break
         }
         setPreviewContent(newPreviewContent)
-    }
+    }, [previewContent])
 
     return <div className={style.create}>
         <Spin spinning={false}>
@@ -727,8 +778,8 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                                     ...settings, corpUserGroups: corpUserGroups.map(item => {
                                         return {
                                             ...item, corpUsers: item.corpUsers.map(item => {
-                                                const { corpUserId, name, corpName, corpId } = item
-                                                return { corpUserId, name, corpName, corpId }
+                                                const { corpUserId, name, corpName, corpId, mpAccountId } = item
+                                                return { corpUserId, name, corpName, corpId, mpAccountId }
                                             })
                                         }
                                     })
@@ -851,7 +902,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                                 {/* 朋友圈 */}
                                 {/* <Friends /> */}
                                 {/* 客户继承 */}
-                                {/* <UserInherit /> */}
+                                <UserInherit />
                             </div>
                         </DispatchTaskCreate.Provider>
                     </div>
@@ -884,7 +935,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         children: key === 'userInherit' ? <>
                             <Table
                                 dataSource={previewData[key]}
-                                columns={userInheritColumns()}
+                                columns={userInheritColumns(setContent)}
                                 rowKey={'id'}
                                 bordered={true}
                                 scroll={{ y: 550 }}
@@ -893,7 +944,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         </> : key === 'massSending' ? <>
                             <Table
                                 dataSource={previewData[key]}
-                                columns={massSendingColumns(setContent)}
+                                columns={massSendingColumns(setContent, bookPlatForm)}
                                 rowKey={'id'}
                                 bordered={true}
                                 scroll={{ y: 550 }}
@@ -902,7 +953,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         </> : key === 'welcome' ? <>
                             <Table
                                 dataSource={previewData[key]}
-                                columns={welcomeColumns(bookPlatForm, bookList)}
+                                columns={welcomeColumns(bookPlatForm, bookList, setContent)}
                                 rowKey={'id'}
                                 bordered={true}
                                 scroll={{ y: 550 }}
@@ -931,7 +982,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                     tabBarExtraContent={<Space size={10}>
                         {/* <Text strong>欢迎语:{previewData?.welcome?.length || 0},群发:{previewData?.massSending?.length || 0},客户继承:{previewData?.userInherit?.length || 0}</Text> */}
                         <Button type='primary' icon={<PlusOutlined />} onClick={() => {
-                            setSubVisible(true)
+                            setTaskName()
                         }}>提交</Button>
                     </Space>}
                 />

+ 94 - 29
src/pages/weComTask/page/businessPlan/create/tableConfig.tsx

@@ -6,19 +6,26 @@ import FilterUser from "@/pages/weComTask/components/filterUser";
 import ShowContentTable from "./components/massSending/showContentTable";
 import WelcomeShowTable from "./components/welcome/welcomeShowTable";
 import FriendsShowTable from "./components/friends/friendsShowTable";
+import SelectBookLinkButton from "../../bookLink/SelectBookLinkButton";
 const { Title, Text, Paragraph } = Typography;
 
-export const userInheritColumns = (): ColumnsType<AnyObject> => {
+export const userInheritColumns = (setContent: (data: TASK_CREATE.SetContentProps) => void): ColumnsType<AnyObject> => {
 
     return [
         {
-            title: '账号(原跟进企微号)',
-            dataIndex: 'corpUserName',
-            key: 'corpUserName',
+            title: '账号',
+            dataIndex: 'corpUserGroupName',
+            key: 'corpUserGroupName',
             width: 150,
             render(value, record) {
-                return <Text>{value}({record.corpUserId})</Text>
+                return <>
+                    <Title level={5} style={{ margin: 0 }}>{value}({record?.corpUserList?.[0]?.corpName})</Title>
+                    <Paragraph style={{ margin: 0 }}>客服号:{record?.corpUserList?.map(i => i.name).join('、')}</Paragraph>
+                </>
             },
+            onCell: (record) => {
+                return { rowSpan: record.userRowSpan }
+            }
         },
         {
             title: '继承信息',
@@ -33,6 +40,9 @@ export const userInheritColumns = (): ColumnsType<AnyObject> => {
                     {record?.templateProductId && <Paragraph style={{ margin: 0 }}>适用产品:{record?.templateProductId || '<空>'}</Paragraph>}
                 </>
             },
+            onCell: (record) => {
+                return { rowSpan: record.userRowSpan }
+            }
         },
         {
             title: '策略信息',
@@ -49,6 +59,9 @@ export const userInheritColumns = (): ColumnsType<AnyObject> => {
                     {value?.sendTime && <Paragraph style={{ margin: 0 }}>执行时间:{value?.sendTime}</Paragraph>}
                     {value?.repeatArray && <Paragraph style={{ margin: 0 }}>执行天数:{value?.repeatArray.join('、')}</Paragraph>}
                 </>
+            },
+            onCell: (record) => {
+                return { rowSpan: record.strategyRowSpan }
             }
         },
         {
@@ -78,8 +91,16 @@ export const userInheritColumns = (): ColumnsType<AnyObject> => {
             dataIndex: 'externalUser',
             key: 'externalUserCorpUserName',
             width: 100,
-            render(value) {
-                return <Text style={{ fontWeight: 'bold', color: '#000' }}>{value?.corpUserName || '<空>'}</Text>
+            render(_, record) {
+                return <Input.TextArea
+                    placeholder="请输入接替客户企微号"
+                    allowClear
+                    onChange={e => setContent({
+                        msg: { corpUserName: e.target.value },
+                        index: [record.corpUsergroupIndex, record.strategyIndex - 1, record.inheritIndex - 1],
+                        type: 'userInherit'
+                    })}
+                />
             },
         },
         {
@@ -87,8 +108,16 @@ export const userInheritColumns = (): ColumnsType<AnyObject> => {
             dataIndex: 'externalUser',
             key: 'externalUserCorpUserId',
             width: 100,
-            render(value) {
-                return <Text style={{ fontWeight: 'bold', color: '#000' }}>{value?.corpUserId || '<空>'}</Text>
+            render(_, record) {
+                return <Input.TextArea
+                    placeholder="请输入接替客户企微号ID"
+                    allowClear
+                    onChange={e => setContent({
+                        msg: { corpUserId: e.target.value },
+                        index: [record.corpUsergroupIndex, record.strategyIndex - 1, record.inheritIndex - 1],
+                        type: 'userInherit'
+                    })}
+                />
             },
         }
     ]
@@ -96,7 +125,7 @@ export const userInheritColumns = (): ColumnsType<AnyObject> => {
 }
 
 /** 群发 */
-export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProps) => void): ColumnsType<AnyObject> => {
+export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProps) => void, bookPlatForm: TASK_CREATE.BookPlatFormProps[]): ColumnsType<AnyObject> => {
     return [
         {
             title: '账号',
@@ -185,13 +214,14 @@ export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProp
             title: '图文链接',
             dataIndex: 'linkUrl',
             key: 'linkUrl',
-            width: 200,
+            width: 250,
             render(_, record) {
-                return record?.isLink ? <Input.TextArea
-                    placeholder="请输入链接"
-                    allowClear
-                    onChange={e => setContent({
-                        msg: { linkUrl: e.target.value },
+                return record?.linkData?.length > 0 ? <SelectBookLinkButton
+                    bookPlatForm={bookPlatForm}
+                    mpAccountId={record.corpUserList?.[0]?.mpAccountId}
+                    linkData={record.linkData}
+                    onChange={(linkStr) => setContent({
+                        msg: { linkUrl: linkStr },
                         index: [record.corpUsergroupIndex, record.strategyIndex - 1, record.sendDataIndex - 1, record.contentIndex - 1],
                         type: 'massSending'
                     })}
@@ -204,7 +234,7 @@ export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProp
             key: 'miniprogramAppid',
             width: 200,
             render(_, record) {
-                return record?.isMiniProgram ? <Input.TextArea 
+                return record?.isMiniProgram ? <Input.TextArea
                     placeholder="请输入小程序APPID"
                     allowClear
                     onChange={e => setContent({
@@ -221,7 +251,7 @@ export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProp
             key: 'miniprogramPage',
             width: 200,
             render(_, record) {
-                return record?.isMiniProgram ? <Input.TextArea 
+                return record?.isMiniProgram ? <Input.TextArea
                     placeholder="请输入小程序路径"
                     allowClear
                     onChange={e => setContent({
@@ -362,15 +392,18 @@ export const highMassSendingColumns = (): ColumnsType<AnyObject> => {
 }
 
 
-export const welcomeColumns = (bookPlatForm: { platformName: string, id: number, platformKey: string }[], bookList: { id: number, bookName: string, platformId: number }[]): ColumnsType<AnyObject> => {
+export const welcomeColumns = (bookPlatForm: { platformName: string, id: number, platformKey: string }[], bookList: { id: number, bookName: string, platformId: number }[], setContent: (data: TASK_CREATE.SetContentProps) => void): ColumnsType<AnyObject> => {
     return [
         {
             title: '账号',
-            dataIndex: 'corpUserName',
-            key: 'corpUserName',
+            dataIndex: 'corpUserGroupName',
+            key: 'corpUserGroupName',
             width: 150,
             render(value, record) {
-                return <Text>{value}({record.corpUserId})</Text>
+                return <>
+                    <Title level={5} style={{ margin: 0 }}>{value}({record?.corpUserList?.[0]?.corpName})</Title>
+                    <Paragraph style={{ margin: 0 }}>客服号:{record?.corpUserList?.map(i => i.name).join('、')}</Paragraph>
+                </>
             },
             onCell: (record) => {
                 return { rowSpan: record.rowSpan }
@@ -438,28 +471,60 @@ export const welcomeColumns = (bookPlatForm: { platformName: string, id: number,
             title: '图文链接',
             dataIndex: 'linkUrl',
             key: 'linkUrl',
-            width: 150,
+            width: 250,
             render(_, record) {
-                return <Paragraph style={{ margin: 0, color: '#000', fontWeight: !!record?.welcomeMsgContent?.linkUrl ? 'bold' : 'normal' }}>{record?.welcomeMsgContent?.linkUrl || '--'}</Paragraph>
+                return record?.linkData?.length > 0 ? <SelectBookLinkButton
+                    bookPlatForm={bookPlatForm}
+                    mpAccountId={record.corpUserList?.[0]?.mpAccountId}
+                    linkData={record.linkData.map(item => ({
+                        msgType: "TASK_CONTENT_LINK",
+                        link: {
+                            title: item.linkTitle,
+                            picUrl: item.linkPicurl,
+                            desc: item.linkDesc
+                        }
+                    }))}
+                    onChange={(linkStr) => setContent({
+                        msg: { linkUrl: linkStr },
+                        index: [record.corpUsergroupIndex, record.contentIndex - 1],
+                        type: 'welcome'
+                    })}
+                /> : '--'
             },
         },
         {
             title: '小程序APPID',
             dataIndex: 'miniprogramAppid',
             key: 'miniprogramAppid',
-            width: 150,
+            width: 200,
             render(_, record) {
-                return <Paragraph style={{ margin: 0, color: '#000', fontWeight: !!record?.welcomeMsgContent?.miniprogramAppid ? 'bold' : 'normal' }}>{record?.welcomeMsgContent?.miniprogramAppid || '--'}</Paragraph>
+                return record?.isMiniProgram ? <Input.TextArea
+                    placeholder="请输入小程序APPID"
+                    allowClear
+                    onChange={e => setContent({
+                        msg: { miniprogramAppid: e.target.value },
+                        index: [record.corpUsergroupIndex, record.contentIndex - 1],
+                        type: 'welcome'
+                    })}
+                /> : '--'
             },
         },
         {
             title: '小程序路径',
             dataIndex: 'miniprogramPage',
             key: 'miniprogramPage',
-            width: 150,
+            width: 200,
             render(_, record) {
-                return <Paragraph style={{ margin: 0, color: '#000', fontWeight: !!record?.welcomeMsgContent?.miniprogramPage ? 'bold' : 'normal' }}>{record?.welcomeMsgContent?.miniprogramPage || '--'}</Paragraph>
-            },
+                return record?.isMiniProgram ? <Input.TextArea
+                    placeholder="请输入小程序路径"
+                    allowClear
+                    onChange={e => setContent({
+                        msg: { miniprogramPage: e.target.value },
+                        index: [record.corpUsergroupIndex, record.contentIndex - 1],
+                        type: 'welcome'
+                    })}
+                /> : '--'
+            }
         }
     ]
 }

+ 8 - 3
src/pages/weComTask/page/businessPlan/create/typings.d.ts

@@ -71,8 +71,13 @@ declare namespace TASK_CREATE {
         friendsTagContent?: any[],
         friendsMsgContent?: any[],
     }
-    type CorpUserProps = { corpUserId: string, name: string, corpName: string, corpId: string }
-    type CorpUserGroupProps = { corpUsers: CorpUserProps[] }
+    type CorpUserProps = { corpUserId: string, name: string, corpName: string, corpId: string, mpAccountId?: number }
+    type CorpUserGroupProps = { 
+        corpUsers: CorpUserProps[],
+        welcomeMsgContent?: any[],
+        groupMsgContent?: any[],
+        externalUserTransferContent?: any[]
+    }
     // 配置保存字段
     interface SettingsProps {
         corpUsers?: corpUsersProps[]; // 企微号列表
@@ -200,6 +205,6 @@ declare namespace TASK_CREATE {
     interface SetContentProps {
         msg: { [x: string]: string },
         index: number[],
-        type: 'welcome' | 'massSending'
+        type: 'welcome' | 'massSending' | 'userInherit'
     }
 }

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

@@ -76,45 +76,45 @@ const taskListColumns = (
                 </div> : <Text type="danger">当前没有欢迎语配置</Text>
             }
         },
-        {
-            title: '朋友圈配置',
-            dataIndex: 'momentCreateDTO',
-            key: 'momentCreateDTO',
-            width: 150,
-            ellipsis: true,
-            render: (value) => {
-                if (value && Object.keys(value)?.length > 0) {
-                    const data = restoreMomentData(value)
-                    return <div className={style.nameBox}>
-                        <div>
-                            <Text ellipsis>{value?.momentSendName || '<空>'}</Text>
-                        </div>
-                        <Popover
-                            placement="left"
-                            content={<div>
-                                <PreviewFriendsStrategy friendsStrategy={data?.friendsStrategy} />
-                            </div>}
-                            styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
-                        >
-                            <a><QuestionCircleFilled /></a>
-                        </Popover>
-                        <Popover
-                            placement="left"
-                            content={<div>
-                                <ShowFriendsContent
-                                    strategySettings={data?.friendsStrategy?.strategySettings}
-                                    friendsContent={data?.friendsContent}
-                                />
-                            </div>}
-                            styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
-                        >
-                            <a><QuestionCircleFilled /></a>
-                        </Popover>
-                    </div>
-                }
-                return <Text type="danger">当前没有朋友圈配置</Text>
-            }
-        },
+        // {
+        //     title: '朋友圈配置',
+        //     dataIndex: 'momentCreateDTO',
+        //     key: 'momentCreateDTO',
+        //     width: 150,
+        //     ellipsis: true,
+        //     render: (value) => {
+        //         if (value && Object.keys(value)?.length > 0) {
+        //             const data = restoreMomentData(value)
+        //             return <div className={style.nameBox}>
+        //                 <div>
+        //                     <Text ellipsis>{value?.momentSendName || '<空>'}</Text>
+        //                 </div>
+        //                 <Popover
+        //                     placement="left"
+        //                     content={<div>
+        //                         <PreviewFriendsStrategy friendsStrategy={data?.friendsStrategy} />
+        //                     </div>}
+        //                     styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
+        //                 >
+        //                     <a><QuestionCircleFilled /></a>
+        //                 </Popover>
+        //                 <Popover
+        //                     placement="left"
+        //                     content={<div>
+        //                         <ShowFriendsContent
+        //                             strategySettings={data?.friendsStrategy?.strategySettings}
+        //                             friendsContent={data?.friendsContent}
+        //                         />
+        //                     </div>}
+        //                     styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
+        //                 >
+        //                     <a><QuestionCircleFilled /></a>
+        //                 </Popover>
+        //             </div>
+        //         }
+        //         return <Text type="danger">当前没有朋友圈配置</Text>
+        //     }
+        // },
         {
             title: '群发配置',
             dataIndex: 'groupSendTaskAddDTO',
@@ -156,50 +156,50 @@ const taskListColumns = (
                 return <Text type="danger">当前没有群发配置</Text>
             }
         },
-        {
-            title: '高级群发配置',
-            dataIndex: 'messageSendTaskAddDTO',
-            key: 'messageSendTaskAddDTO',
-            width: 170,
-            ellipsis: true,
-            render: (value, record) => {
-                if (value && Object.keys(value)?.length > 0) {
-                    const data = restoreGroupData(value, 'GROUP_GROUP')
-                    console.log('data', record.projectName, data)
-                    return <div className={style.nameBox}>
-                        <div>
-                            <Text ellipsis>{value?.groupSendName || '<空>'}</Text>
-                        </div>
-                        <Popover
-                            placement="left"
-                            content={<div>
-                                <PreviewMassSendingStrategy
-                                    massSendingStrategy={data.massSendingStrategy}
-                                    configType='GROUP_GROUP'
-                                />
-                            </div>}
-                            styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
-                        >
-                            <a><QuestionCircleFilled /></a>
-                        </Popover>
-                        <Popover
-                            placement="left"
-                            content={<div>
-                                <ShowContent
-                                    strategySettings={data?.massSendingStrategy?.strategySettings}
-                                    massSendingContent={data?.massSendingContent}
-                                    type="highQf"
-                                />
-                            </div>}
-                            styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
-                        >
-                            <a><QuestionCircleFilled /></a>
-                        </Popover>
-                    </div>
-                }
-                return <Text type="danger">当前没有群发配置</Text>
-            }
-        },
+        // {
+        //     title: '高级群发配置',
+        //     dataIndex: 'messageSendTaskAddDTO',
+        //     key: 'messageSendTaskAddDTO',
+        //     width: 170,
+        //     ellipsis: true,
+        //     render: (value, record) => {
+        //         if (value && Object.keys(value)?.length > 0) {
+        //             const data = restoreGroupData(value, 'GROUP_GROUP')
+        //             console.log('data', record.projectName, data)
+        //             return <div className={style.nameBox}>
+        //                 <div>
+        //                     <Text ellipsis>{value?.groupSendName || '<空>'}</Text>
+        //                 </div>
+        //                 <Popover
+        //                     placement="left"
+        //                     content={<div>
+        //                         <PreviewMassSendingStrategy
+        //                             massSendingStrategy={data.massSendingStrategy}
+        //                             configType='GROUP_GROUP'
+        //                         />
+        //                     </div>}
+        //                     styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
+        //                 >
+        //                     <a><QuestionCircleFilled /></a>
+        //                 </Popover>
+        //                 <Popover
+        //                     placement="left"
+        //                     content={<div>
+        //                         <ShowContent
+        //                             strategySettings={data?.massSendingStrategy?.strategySettings}
+        //                             massSendingContent={data?.massSendingContent}
+        //                             type="highQf"
+        //                         />
+        //                     </div>}
+        //                     styles={{ body: { width: 360, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
+        //                 >
+        //                     <a><QuestionCircleFilled /></a>
+        //                 </Popover>
+        //             </div>
+        //         }
+        //         return <Text type="danger">当前没有群发配置</Text>
+        //     }
+        // },
         {
             title: '客户继承配置',
             dataIndex: 'externalUserTransferTasksDTO',

+ 1 - 1
src/pages/weComTask/page/corpUserManage/global.less

@@ -45,7 +45,7 @@
         cursor: pointer;
     }
 
-    &:hover  .selectCorpUserIconClear{
+    &:hover .selectCorpUserIconClear {
         display: inline-block;
     }
 }

+ 16 - 1
src/pages/weComTask/page/corpUserManage/index.tsx

@@ -10,6 +10,7 @@ import { delAccountToGroupApi, getCorpUserApi } from '../../API/corpUserManage';
 import SearchBox from '../../components/searchBox';
 import { WeTableConfig } from './tableConfig';
 import { useSize } from 'ahooks';
+import { getBindMpListApi } from '../../API/corpUserAssign';
 
 /**
  * 企微号管理
@@ -27,12 +28,14 @@ const CorpUserManage: React.FC = () => {
     const [showLeft, setShowLeft] = useState<boolean>(false)
 
     const allOfMember = useAjax(() => getAdAccountAllOfMember())
+    const getBindMpList = useAjax(() => getBindMpListApi())
     const getCorpUser = useAjax((params) => getCorpUserApi(params))
     const delAccountToGroup = useAjax((params) => delAccountToGroupApi(params))
     /***************************************************/
 
     useEffect(() => {
         allOfMember.run()
+        getBindMpList.run()
     }, [])
 
     useEffect(() => {
@@ -106,7 +109,7 @@ const CorpUserManage: React.FC = () => {
                             value={queryFormNew?.operUserId}
                             onChange={(e) => setQueryFormNew({ ...queryFormNew, operUserId: e })}
                             showSearch
-                            style={{ width: 120 }}
+                            style={{ width: 110 }}
                             placeholder="运营"
                             filterOption={(input, option) =>
                                 ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
@@ -114,6 +117,18 @@ const CorpUserManage: React.FC = () => {
                             allowClear
                             options={allOfMember?.data?.data?.map((item: any) => ({ label: item.nickname, value: item.userId }))}
                         />
+                        <Select
+                            value={queryFormNew?.mpAccountId}
+                            onChange={(e) => setQueryFormNew({ ...queryFormNew, mpAccountId: e })}
+                            showSearch
+                            style={{ width: 110 }}
+                            placeholder="公众号"
+                            filterOption={(input, option) =>
+                                ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                            }
+                            allowClear
+                            options={getBindMpList?.data?.data?.map((item: any) => ({ label: item.name, value: item.id }))}
+                        />
                         <Select
                             value={queryFormNew?.groupOwner}
                             onChange={(e) => setQueryFormNew({ ...queryFormNew, groupOwner: e })}

+ 50 - 8
src/pages/weComTask/page/corpUserManage/selectCorpUserGroupModal.tsx

@@ -8,6 +8,7 @@ import { useAjax } from "@/Hook/useAjax";
 import { getAdAccountAllOfMember } from "@/API/global";
 import { getCorpUserApi, getGroupListApi } from "../../API/corpUserManage";
 import { WeTableSelectConfig } from "./tableConfig";
+import { getBindMpListApi } from "../../API/corpUserAssign";
 const { Text, Title } = Typography;
 
 
@@ -24,17 +25,19 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
     const [data, setData] = useState<TASK_CREATE.CorpUserGroupProps[]>(value)
     const [selectAdz, setSelectAdz] = useState<number>(1)   // 选择广告主
 
-    const [queryForm, setQueryForm] = useState<CORP_USER_ASSIGN_API.GetCorpUserProps>({ pageNum: 1, pageSize: 20, stopUse: false, status: 1 })
-    const [queryFormNew, setQueryFormNew] = useState<CORP_USER_ASSIGN_API.GetCorpUserProps>({ pageNum: 1, pageSize: 20, stopUse: false, status: 1 })
+    const [queryForm, setQueryForm] = useState<CORP_USER_ASSIGN_API.GetCorpUserProps>({ pageNum: 1, pageSize: 20, stopUse: false, status: 1, corpIds: value?.[0]?.corpUsers?.[0]?.corpId as any })
+    const [queryFormNew, setQueryFormNew] = useState<CORP_USER_ASSIGN_API.GetCorpUserProps>({ pageNum: 1, pageSize: 20, stopUse: false, status: 1, corpIds: value?.[0]?.corpUsers?.[0]?.corpId as any })
 
     const allOfMember = useAjax(() => getAdAccountAllOfMember())
     const getCorpUser = useAjax((params) => getCorpUserApi(params))
     const getGroupList = useAjax(() => getGroupListApi())
+    const getBindMpList = useAjax(() => getBindMpListApi())
     /*****************************************/
 
     useEffect(() => {
         allOfMember.run()
         getGroupList.run()
+        getBindMpList.run()
     }, [])
 
     useEffect(() => {
@@ -60,10 +63,25 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
         }
     }
 
-    const handleSelectAdz = (value: number) => {
-        if (value === selectAdz) {
+    const handleSelectAdz = (value: number, data: TASK_CREATE.CorpUserGroupProps[], isSd: boolean) => {
+        if (value === selectAdz && isSd) {
             return
         }
+        const nowCorpUsers = data[value - 1]?.corpUsers
+        const newQueryForm: any = { ...queryForm }
+        if (nowCorpUsers?.length > 0) {
+            newQueryForm.corpIds = nowCorpUsers[0]?.corpId
+            if (nowCorpUsers?.[0]?.mpAccountId) {
+                newQueryForm.mpAccountId = nowCorpUsers[0]?.mpAccountId
+            } else {
+                delete newQueryForm?.mpAccountId
+            }
+        } else {
+            delete newQueryForm?.corpIds
+            delete newQueryForm?.mpAccountId
+        }
+        setQueryForm(newQueryForm)
+        setQueryFormNew(newQueryForm)
         setSelectAdz(value)
     }
 
@@ -72,7 +90,7 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
         open={visible}
         onCancel={onClose}
         onOk={handleOk}
-        width={1000}
+        width={1100}
         className={`${style.SelectPackage}`}
         styles={{
             body: {
@@ -91,7 +109,7 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
                 <div className={style.accountIdList}>
                     {data?.map((item, index) => {
                         const corpUserList = data[index]?.corpUsers || []
-                        return <div key={index} onClick={() => { handleSelectAdz(index + 1) }} className={`${style.accItem} ${selectAdz === index + 1 && style.select} `}>
+                        return <div key={index} onClick={() => { handleSelectAdz(index + 1, data, true) }} className={`${style.accItem} ${selectAdz === index + 1 && style.select} `}>
                             <div><Text ellipsis={{ tooltip: true }}>客服组{index + 1}</Text></div>
                             {corpUserList?.length > 0 && <CheckOutlined style={{ color: '#1890ff' }} />}
                         </div>
@@ -127,6 +145,18 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
                         allowClear
                         options={allOfMember?.data?.data?.map((item: any) => ({ label: item.nickname, value: item.userId }))}
                     />
+                    <Select
+                        value={queryFormNew?.mpAccountId}
+                        onChange={(e) => setQueryFormNew({ ...queryFormNew, mpAccountId: e })}
+                        showSearch
+                        style={{ width: 100 }}
+                        placeholder="公众号"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        allowClear
+                        options={getBindMpList?.data?.data?.map((item: any) => ({ label: item.name, value: item.id }))}
+                    />
                     <Select
                         value={queryFormNew?.groupOwner}
                         onChange={(e) => setQueryFormNew({ ...queryFormNew, groupOwner: e })}
@@ -174,7 +204,8 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
                         type: 'checkbox',
                         selectedRowKeys: data?.[selectAdz - 1]?.corpUsers?.map(item => item.corpUserId),
                         getCheckboxProps: (record: any) => ({
-                            disabled: data.filter((_, i) => i !== selectAdz - 1)?.map(item => item.corpUsers).flat(1)?.map(item => item.corpUserId).includes(record.corpUserId)
+                            disabled: data.filter((_, i) => i !== selectAdz - 1)?.map(item => item.corpUsers).flat(1)?.map(item => item.corpUserId).includes(record.corpUserId) ||
+                                (data?.[selectAdz - 1]?.corpUsers?.length > 0 ? data?.[selectAdz - 1]?.corpUsers?.[0]?.corpId !== record.corpId || (data?.[selectAdz - 1]?.corpUsers?.[0]?.mpAccountId ? data?.[selectAdz - 1]?.corpUsers?.[0]?.mpAccountId !== record.mpAccountId : record.mpAccountId) : false)
                         }),
                         onSelect: (record: { corpUserId: string }, selected: boolean) => {
                             let newData = JSON.parse(JSON.stringify(data))
@@ -221,7 +252,18 @@ const SelectCorpUserGroupModal: React.FC<Props> = ({ visible, onClose, value, on
             </div>
 
             <div className={style.center}>
-                <Title level={5}>已选:{data[selectAdz - 1]?.corpUsers?.length || 0}</Title>
+                <div style={{ margin: '0 0 5px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
+                    <Title level={5} style={{ margin: 0 }}>已选:{data[selectAdz - 1]?.corpUsers?.length || 0}</Title>
+                    {data.length > 1 && <a style={{ color: 'red' }} onClick={() => {
+                        const newData = data.filter((_, index) => index !== selectAdz - 1)
+                        setData(newData)
+                        if (selectAdz > 1) {
+                            handleSelectAdz(selectAdz - 1, newData, false)
+                        } else {
+                            handleSelectAdz(1, newData, false)
+                        }
+                    }}>删除组</a>}
+                </div>
                 <div className={style.select_content}>
                     {data[selectAdz - 1]?.corpUsers?.map(item => <div key={item.corpUserId}>
                         <Text ellipsis={{ tooltip: true }} className={style.marketingAssetName}>{item.name}({item?.corpName})</Text>

+ 41 - 0
src/pages/weComTask/page/corpUserManage/tableConfig.tsx

@@ -71,6 +71,26 @@ export function WeTableConfig(
                 return <span>{a?.nickName || '--'}</span>
             }
         },
+        {
+            title: '公众号',
+            dataIndex: 'name',
+            key: 'name',
+            align: 'center',
+            width: 80,
+            render: (_, record) => {
+                return <span>{record?.mpAccountInfo?.name || '--'}</span>
+            }
+        },
+        {
+            title: '书城',
+            dataIndex: 'platformName',
+            key: 'platformName',
+            align: 'center',
+            width: 80,
+            render: (_, record) => {
+                return <span>{record?.mpAccountInfo?.platformName || '--'}</span>
+            }
+        },
         {
             title: '操作',
             dataIndex: 'cz',
@@ -122,6 +142,7 @@ export function WeTableSelectConfig(): ColumnsType<any> {
             key: 'name',
             align: 'center',
             width: 80,
+            fixed: 'left'
         },
         {
             title: '所属企业',
@@ -161,6 +182,26 @@ export function WeTableSelectConfig(): ColumnsType<any> {
             render: (a: { nickName: string }) => {
                 return <span>{a?.nickName || '--'}</span>
             }
+        },
+        {
+            title: '公众号',
+            dataIndex: 'name',
+            key: 'name',
+            align: 'center',
+            width: 80,
+            render: (_, record) => {
+                return <span>{record?.mpAccountInfo?.name || '--'}</span>
+            }
+        },
+        {
+            title: '书城',
+            dataIndex: 'platformName',
+            key: 'platformName',
+            align: 'center',
+            width: 80,
+            render: (_, record) => {
+                return <span>{record?.mpAccountInfo?.platformName || '--'}</span>
+            }
         }
     ]
     return tableDfixed(arr)

ファイルの差分が大きいため隠しています
+ 0 - 0
src/public/svg/book.svg


この差分においてかなりの量のファイルが変更されているため、一部のファイルを表示していません