wjx 1 kuukausi sitten
vanhempi
commit
facbb1e077
47 muutettua tiedostoa jossa 3140 lisäystä ja 187 poistoa
  1. 2 0
      src/layout/index.tsx
  2. 1 1
      src/pages/weComTask/components/newSteps/index.tsx
  3. 3 1
      src/pages/weComTask/page/bookLink/SelectBookLinkButton.tsx
  4. 41 0
      src/pages/weComTask/page/bookLink/components/fanqie/bookPromoLinkCreateDTO.tsx
  5. 73 0
      src/pages/weComTask/page/bookLink/components/fanqie/consumeActivityLinkDTO.tsx
  6. 84 0
      src/pages/weComTask/page/bookLink/components/fanqie/giftActivityLinkDTO.tsx
  7. 33 0
      src/pages/weComTask/page/bookLink/components/fanqie/pagePromoLinkCreateDTO.tsx
  8. 72 0
      src/pages/weComTask/page/bookLink/components/fanqie/rechargeActivityLinkDTO.tsx
  9. 83 0
      src/pages/weComTask/page/bookLink/components/huasheng/bookPromoLinkCreateDTO.tsx
  10. 135 0
      src/pages/weComTask/page/bookLink/components/huasheng/giftActivityLinkDTO.tsx
  11. 151 0
      src/pages/weComTask/page/bookLink/components/huasheng/rechargeActivityLinkDTO.tsx
  12. 96 0
      src/pages/weComTask/page/bookLink/components/wending/bookPromoLinkCreateDTO.tsx
  13. 85 0
      src/pages/weComTask/page/bookLink/components/wending/rechargeActivityLinkDTO.tsx
  14. 248 0
      src/pages/weComTask/page/bookLink/components/wending/setConfig.tsx
  15. 2 23
      src/pages/weComTask/page/bookLink/components/yuewen/bookPromoLinkCreateDTO.tsx
  16. 2 2
      src/pages/weComTask/page/bookLink/components/yuewen/consumeActivityLinkDTO.tsx
  17. 1 1
      src/pages/weComTask/page/bookLink/components/yuewen/giftActivityLinkDTO.tsx
  18. 1 1
      src/pages/weComTask/page/bookLink/components/yuewen/pagePromoLinkCreateDTO.tsx
  19. 1 1
      src/pages/weComTask/page/bookLink/components/yuewen/rechargeActivityLinkDTO.tsx
  20. 77 0
      src/pages/weComTask/page/bookLink/const.tsx
  21. 200 53
      src/pages/weComTask/page/bookLink/details.tsx
  22. 146 46
      src/pages/weComTask/page/bookLink/index.tsx
  23. 424 28
      src/pages/weComTask/page/bookLink/modalBooklink.tsx
  24. 3 2
      src/pages/weComTask/page/bookLink/selectBook.tsx
  25. 6 4
      src/pages/weComTask/page/bookLink/selectBookLink.tsx
  26. 14 10
      src/pages/weComTask/page/bookLink/tableConfig.tsx
  27. 10 2
      src/pages/weComTask/page/businessPlan/create/components/massSending/index.tsx
  28. 136 0
      src/pages/weComTask/page/businessPlan/create/components/massSending/settingsContent.tsx
  29. 1 1
      src/pages/weComTask/page/businessPlan/create/components/welcome/index.tsx
  30. 1 2
      src/pages/weComTask/page/businessPlan/create/components/welcome/settingsWelcome.tsx
  31. 2 0
      src/pages/weComTask/page/businessPlan/create/index.less
  32. 11 2
      src/pages/weComTask/page/businessPlan/create/index.tsx
  33. 6 2
      src/pages/weComTask/page/businessPlan/create/tableConfig.tsx
  34. 1 1
      src/pages/weComTask/page/businessPlan/create/typings.d.ts
  35. 1 1
      src/pages/weComTask/page/businessPlan/taskList/components/groupTask/groupTaskNotes.tsx
  36. 1 1
      src/pages/weComTask/page/businessPlan/taskList/components/groupTask/groupXfCorpTabls.tsx
  37. 1 1
      src/pages/weComTask/page/businessPlan/taskList/components/groupTask/index.tsx
  38. 1 1
      src/pages/weComTask/page/businessPlan/taskList/tableConfig.tsx
  39. 39 0
      src/pages/weComTask/page/groupChat/create/components/groupUser/addGroupObject.tsx
  40. 58 0
      src/pages/weComTask/page/groupChat/create/components/groupUser/index.tsx
  41. 333 0
      src/pages/weComTask/page/groupChat/create/components/groupUser/settingsGroupUser.tsx
  42. 60 0
      src/pages/weComTask/page/groupChat/create/components/strategy/index.tsx
  43. 86 0
      src/pages/weComTask/page/groupChat/create/components/strategy/previewStrategy.tsx
  44. 196 0
      src/pages/weComTask/page/groupChat/create/components/strategy/settingsStrategy.tsx
  45. 176 0
      src/pages/weComTask/page/groupChat/create/index.tsx
  46. 35 0
      src/pages/weComTask/page/groupChat/create/typings.d.ts
  47. 1 0
      src/public/svg/pa.svg

+ 2 - 0
src/layout/index.tsx

@@ -23,6 +23,7 @@ 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 { ReactComponent as PaSvg } from '../public/svg/pa.svg'
 import Avatar from './AvatarDropdown';
 import styles from './index.less'
 import { useNavigate } from 'react-router-dom';
@@ -86,6 +87,7 @@ const IconMap = {
     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>,
+    pa: <span role="img" aria-label="fund-view" className="anticon anticon-fund-view"><PaSvg /></span>,
     interdiction: <StopOutlined />,
     eye: <EyeOutlined />,
     log: <ContainerOutlined />

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

@@ -53,7 +53,7 @@ const NewSteps: React.FC<NewStepsProps> = ({ items = [], onChange, isLeaf }) =>
                     {i?.description && <div className={style['newSteps-item-description']}>{i.description}</div>}
                 </div>
                 {i.children && <div style={{ marginTop: 20 }}>
-                    <NewSteps items={i.children} onChange={(e, f) => onChange(e, f)} isLeaf={true} />
+                    <NewSteps items={i.children} onChange={(e, f) => onChange?.(e, f)} isLeaf={true} />
                 </div>}
             </div>
         </div>)}

+ 3 - 1
src/pages/weComTask/page/bookLink/SelectBookLinkButton.tsx

@@ -8,9 +8,10 @@ interface SelectBookLinkButtonProps {
     bookPlatForm: TASK_CREATE.BookPlatFormProps[]
     linkData: { [x: string]: any }[]
     onChange: (linkStr: string, miniprogramAppid?: string, miniprogramPage?: string) => void
+    platform: string
 }
 
-const SelectBookLinkButton: React.FC<SelectBookLinkButtonProps> = ({ mpAccountId, bookPlatForm, linkData, onChange, children = '选择' }) => {
+const SelectBookLinkButton: React.FC<SelectBookLinkButtonProps> = ({ mpAccountId, bookPlatForm, linkData, onChange, children = '选择', platform }) => {
 
     /********************************/
     const [visible, setVisible] = useState<boolean>(false)
@@ -22,6 +23,7 @@ const SelectBookLinkButton: React.FC<SelectBookLinkButtonProps> = ({ mpAccountId
         </Button>
         {visible && <SelectBookLink
             mpAccountId={mpAccountId}
+            platform={platform}
             bookPlatForm={bookPlatForm}
             visible={visible}
             linkData={linkData}

+ 41 - 0
src/pages/weComTask/page/bookLink/components/fanqie/bookPromoLinkCreateDTO.tsx

@@ -0,0 +1,41 @@
+import { Form, InputNumber } from "antd";
+import React from "react";
+import SelectBook from "../../selectBook";
+
+interface Props extends BOOKLINK.BookLinkChildProps {
+    platform: string,
+}
+/**
+ * 作品链接
+ * @returns 
+ */
+const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, platform }) => {
+
+    /**********************************/
+    /**********************************/
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'bookId']}
+            rules={[{ required: true, message: '请输入作品(书籍)ID!' }]}
+            label={<strong>作品(书籍)ID</strong>}
+        >
+            <SelectBook
+                platformKey={platform}
+                isSearchChapter={false}
+            />
+        </Form.Item>
+
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'chapterId']}
+            label={<strong>章节</strong>}
+            rules={[{ required: true, message: '请输入章节(1~19)!' }]}
+        >
+            <InputNumber style={{ width: '100%' }} min={1} max={19} placeholder="请输入章节(1~19)" />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(BookPromoLinkCreateDTO);

+ 73 - 0
src/pages/weComTask/page/bookLink/components/fanqie/consumeActivityLinkDTO.tsx

@@ -0,0 +1,73 @@
+import { DatePicker, Form, Input, InputNumber, Select } from "antd";
+import React from "react";
+
+
+/**
+ * 免费赠币活动链接
+ * @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', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'giftAmount']}
+            rules={[{ required: true, message: '请输入赠送书币!' }]}
+            label={<strong>赠送书币</strong>}
+        >
+            <InputNumber suffix="个" min={1} max={5000} placeholder="请输入(1~5000)" style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'rechargeCount']}
+            label={<strong>赠送总次数</strong>}
+            rules={[{ required: true, message: '请选择赠送总次数!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择赠送总次数"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={[{ label: '1次', value: 1 }, { label: '2次', value: 2 }, { label: '3次', value: 3 }]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'consumeActivityLinkDTO', 'activityFrequencies', 'activityFrequenciesEnum']}
+            label={<strong>频率限制</strong>}
+            rules={[{ required: true, message: '请选择频率限制!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择频率限制"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={[{ label: '每天一次', value: 2 }, { label: '每周一次', value: 3 }]}
+            />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(ConsumeActivityLinkDTO);

+ 84 - 0
src/pages/weComTask/page/bookLink/components/fanqie/giftActivityLinkDTO.tsx

@@ -0,0 +1,84 @@
+import { DatePicker, Form, Input, InputNumber, Select } from "antd";
+import React from "react";
+
+
+interface Props extends BOOKLINK.BookLinkChildProps {
+    vipDuration?: number;
+}
+/**
+ * 年卡活动链接
+ * @returns 
+ */
+const GiftActivityLinkDTO: React.FC<Props> = ({ restField, name, vipDuration = 1 }) => {
+    console.log('-------->', vipDuration)
+
+    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', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'vipDuration']}
+            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, 4, 5].map(item => ({ label: item + '年', value: item }))}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'activityPrice']}
+            rules={[{ required: true, message: `请输入活动价格(${300 * vipDuration}~5000)!` }]}
+            label={<strong>活动价格</strong>}
+        >
+            <InputNumber suffix="元" min={300 * vipDuration} max={5000} placeholder={`请输入活动价格(${300 * vipDuration}~5000)!`} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'originalPrice']}
+            rules={[{ required: true, message: '请输入原价!' }]}
+            label={<strong>原价</strong>}
+        >
+            <InputNumber suffix="元" placeholder="请输入原价" style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'rechargeCount']}
+            label={<strong>充值次数</strong>}
+            rules={[{ required: true, message: '请选择充值次数!' }]}
+        >
+            <Select
+                showSearch
+                placeholder="请选择充值次数"
+                filterOption={(input, option) =>
+                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                }
+                allowClear
+                options={[{ label: '1次', value: 1 }, { label: '2次', value: 2 }, { label: '3次', value: 3 }]}
+            />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(GiftActivityLinkDTO);

+ 33 - 0
src/pages/weComTask/page/bookLink/components/fanqie/pagePromoLinkCreateDTO.tsx

@@ -0,0 +1,33 @@
+import { Form, Input, InputNumber, Select } from "antd";
+import React from "react";
+import { FANQIEPAGETYPE, 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(FANQIEPAGETYPE).map(key => ({ label: FANQIEPAGETYPE[key], value: key }))}
+            />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(PagePromoLinkCreateDTO);

+ 72 - 0
src/pages/weComTask/page/bookLink/components/fanqie/rechargeActivityLinkDTO.tsx

@@ -0,0 +1,72 @@
+import { DatePicker, Form, Input, InputNumber, Select, Space } from "antd";
+import React from "react";
+
+
+/**
+ * 模板充值活动
+ * @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', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+
+        <Form.Item
+            label={<strong>充值档位</strong>}
+            required
+        >
+            <Space>
+                <Form.Item
+                    {...restField}
+                    name={[name, 'rechargeActivityLinkDTO', 'rechargeAmount']}
+                    rules={[{ required: true, message: '请输入充值金额(0.1~300)!' }]}
+                    noStyle
+                >
+                    <InputNumber addonBefore="价位" suffix="元" min={0.1} max={300} 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={[{label: '不限次', value: -1}, {label: '1次', value: 1}, {label: '2次', value: 2}, {label: '3次', value: 3}]}
+            />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(RechargeActivityLinkDTO);

+ 83 - 0
src/pages/weComTask/page/bookLink/components/huasheng/bookPromoLinkCreateDTO.tsx

@@ -0,0 +1,83 @@
+import { App, Form, InputNumber, Select } from "antd";
+import React from "react";
+import SelectBook from "../../selectBook";
+import { useAjax } from "@/Hook/useAjax";
+import { getFreeChapterListApi } from "@/pages/weComTask/API/bookLink";
+
+interface Props extends BOOKLINK.BookLinkChildProps {
+    huaShengCreateLinkDTO: { [x: string]: any }
+    platform: string,
+    mpAccountIds: number[]
+}
+/**
+ * 花生作品链接
+ * @returns 
+ */
+const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, huaShengCreateLinkDTO, platform, mpAccountIds }) => {
+
+    /**********************************/
+    const { message } = App.useApp()
+    const getFreeChapterList = useAjax((params) => getFreeChapterListApi(params))
+    /**********************************/
+
+    const getChapterList = () => {
+        if (platform && mpAccountIds?.length && huaShengCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId) {
+            getFreeChapterList.run({ platform, mpAccountIds, bookId: huaShengCreateLinkDTO.bookPromoLinkCreateDTO.bookId })
+        } else {
+            message.error('请先选择书城、公众号')
+        }
+    }
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'bookId']}
+            rules={[{ required: true, message: '请输入作品(书籍)ID!' }]}
+            label={<strong>作品(书籍)ID</strong>}
+        >
+            <SelectBook
+                platformKey={platform}
+                searchChapterDisabled={!huaShengCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId}
+                searchChapterLoading={getFreeChapterList.loading}
+                hanldeSearchChapter={getChapterList}
+            />
+        </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', 'forceChapter']}
+            label={<strong>强关章节序号</strong>}
+            rules={[{ required: true, message: '请输入强关章节序号!' }]}
+        >
+            <InputNumber placeholder="请输入强关章节序号" style={{ width: '100%' }} />
+        </Form.Item>
+
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'cost']}
+            label={<strong>推广成本</strong>}
+            rules={[{ required: true, message: '请输入推广成本!' }]}
+        >
+            <InputNumber placeholder="请输入推广成本" min={0} style={{ width: '100%' }} />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(BookPromoLinkCreateDTO);

+ 135 - 0
src/pages/weComTask/page/bookLink/components/huasheng/giftActivityLinkDTO.tsx

@@ -0,0 +1,135 @@
+import { Checkbox, DatePicker, Form, Input, InputNumber, Radio } from "antd";
+import React from "react";
+import { DISPLAYTYPEHUASHENG } from "../../const";
+import { RangePickerProps } from "antd/es/date-picker";
+import dayjs from "dayjs";
+
+/**
+ * 免费赠币活动
+ * @returns 
+ */
+const GiftActivityLinkDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name, itemData }) => {
+
+    const disabledDate: RangePickerProps['disabledDate'] = current => {
+        return current && current < dayjs().endOf('day');
+    };
+
+    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', 'freeAmount']}
+            label={<strong>活动挡位</strong>}
+            rules={[{ required: true, message: '请选择活动挡位!' }]}
+        >
+            <Radio.Group
+                buttonStyle="solid"
+                options={[50, 100, 200, 300, 500, 800, 1000].map(i => ({ label: i + '书币', value: i }))}
+            />
+        </Form.Item>
+
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[
+                { required: true, message: '请选择活动时间!' },
+                {
+                    validator: (_: any, value: [dayjs.Dayjs, dayjs.Dayjs]) => {
+                        if (!value || value.length < 2) {
+                            return Promise.reject('请选择完整日期范围');
+                        }
+                        if (value[0].isSame(value[1], 'day')) {
+                            return Promise.reject('开始和结束日期不能相同');
+                        }
+                        return Promise.resolve();
+                    }
+                }
+            ]}
+        >
+            <DatePicker.RangePicker disabledDate={disabledDate} />
+        </Form.Item>
+
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'status']}
+            label={<strong>活动状态</strong>}
+            rules={[{ required: true, message: '请选择活动状态!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 'normal', label: '上架' },
+                    { value: 'del', label: '下架' }
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'display']}
+            label={<strong>活动展示位</strong>}
+        >
+            <Checkbox.Group options={Object.keys(DISPLAYTYPEHUASHENG).map(key => ({ label: DISPLAYTYPEHUASHENG[key], value: key }))} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'giftActivityLinkDTO', 'userType']}
+            label={<strong>展示粉丝</strong>}
+            rules={[{ required: true, message: '请选择展示粉丝!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 1, label: '全部粉丝' },
+                    { value: 2, label: '条件粉丝' }
+                ]}
+            />
+        </Form.Item>
+        {itemData?.giftActivityLinkDTO?.userType === 2 && <>
+            <Form.Item
+                {...restField}
+                name={[name, 'giftActivityLinkDTO', 'charge']}
+                label={<strong>充值状态</strong>}
+                rules={[{ required: true, message: '请选择充值状态!' }]}
+            >
+                <Radio.Group
+                    optionType='button'
+                    buttonStyle="solid"
+                    options={[
+                        { value: 0, label: '不限' },
+                        { value: 1, label: '已充值' },
+                        { value: 2, label: '未充值' }
+                    ]}
+                />
+            </Form.Item>
+            <Form.Item
+                {...restField}
+                name={[name, 'giftActivityLinkDTO', 'commonType']}
+                label={<strong>关注时间</strong>}
+                rules={[{ required: true, message: '请选择关注时间!' }]}
+            >
+                <Radio.Group
+                    optionType='button'
+                    buttonStyle="solid"
+                    options={[
+                        { value: 0, label: '不限' },
+                        { value: 1, label: '24小时以上' },
+                        { value: 2, label: '48小时以上' },
+                        { value: 3, label: '72小时以上' }
+                    ]}
+                />
+            </Form.Item>
+        </>}
+    </>
+}
+
+export default React.memo(GiftActivityLinkDTO);

+ 151 - 0
src/pages/weComTask/page/bookLink/components/huasheng/rechargeActivityLinkDTO.tsx

@@ -0,0 +1,151 @@
+import { Checkbox, DatePicker, Form, Input, InputNumber, Radio, Space } from "antd";
+import React from "react";
+import { DISPLAYTYPEHUASHENG } from "../../const";
+
+
+/**
+ * 花生充值活动
+ * @returns 
+ */
+const RechargeActivityLinkDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name, itemData }) => {
+
+    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
+            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', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'status']}
+            label={<strong>活动状态</strong>}
+            rules={[{ required: true, message: '请选择活动状态!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 'normal', label: '上架' },
+                    { value: 'del', label: '下架' }
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'chargeType']}
+            label={<strong>限购类型</strong>}
+            rules={[{ required: true, message: '请选择限购类型!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 0, label: '整体限购' },
+                    { value: 1, label: '每天限购' }
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'display']}
+            label={<strong>活动展示位</strong>}
+        >
+            <Checkbox.Group options={Object.keys(DISPLAYTYPEHUASHENG).map(key => ({ label: DISPLAYTYPEHUASHENG[key], value: key }))} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'chargeCount']}
+            label={<strong>限购次数</strong>}
+            rules={[{ required: true, message: '请选择充值次数!' }]}
+        >
+            <InputNumber placeholder="请输入" min={0} style={{ width: '100%' }} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'userType']}
+            label={<strong>展示粉丝</strong>}
+            rules={[{ required: true, message: '请选择展示粉丝!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 1, label: '全部粉丝' },
+                    { value: 2, label: '条件粉丝' }
+                ]}
+            />
+        </Form.Item>
+        {itemData?.rechargeActivityLinkDTO?.userType === 2 && <>
+            <Form.Item
+                {...restField}
+                name={[name, 'rechargeActivityLinkDTO', 'charge']}
+                label={<strong>充值状态</strong>}
+                rules={[{ required: true, message: '请选择充值状态!' }]}
+            >
+                <Radio.Group
+                    optionType='button'
+                    buttonStyle="solid"
+                    options={[
+                        { value: 0, label: '不限' },
+                        { value: 1, label: '已充值' },
+                        { value: 2, label: '未充值' }
+                    ]}
+                />
+            </Form.Item>
+            <Form.Item
+                {...restField}
+                name={[name, 'rechargeActivityLinkDTO', 'commonType']}
+                label={<strong>关注时间</strong>}
+                rules={[{ required: true, message: '请选择关注时间!' }]}
+            >
+                <Radio.Group
+                    optionType='button'
+                    buttonStyle="solid"
+                    options={[
+                        { value: 0, label: '不限' },
+                        { value: 1, label: '24小时以上' },
+                        { value: 2, label: '48小时以上' },
+                        { value: 3, label: '72小时以上' }
+                    ]}
+                />
+            </Form.Item>
+        </>}
+    </>
+}
+
+export default React.memo(RechargeActivityLinkDTO);

+ 96 - 0
src/pages/weComTask/page/bookLink/components/wending/bookPromoLinkCreateDTO.tsx

@@ -0,0 +1,96 @@
+import { useAjax } from "@/Hook/useAjax";
+import { getFreeChapterListApi } from "@/pages/weComTask/API/bookLink";
+import { App, Form, InputNumber, Radio, Select, Switch } from "antd";
+import React from "react";
+import SelectBook from "../../selectBook";
+import { LINKCLASSIFY } from "../../const";
+
+interface Props extends BOOKLINK.BookLinkChildProps {
+    wenDingCreateLinkDTO: { [x: string]: any }
+    platform: string,
+    mpAccountIds: number[]
+}
+/**
+ * 文鼎作品链接
+ * @returns 
+ */
+const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, wenDingCreateLinkDTO, platform, mpAccountIds }) => {
+
+    /**********************************/
+    const { message } = App.useApp()
+    const getFreeChapterList = useAjax((params) => getFreeChapterListApi(params))
+    /**********************************/
+
+    const getChapterList = () => {
+        if (platform && mpAccountIds?.length && wenDingCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId) {
+            getFreeChapterList.run({ platform, mpAccountIds, bookId: wenDingCreateLinkDTO.bookPromoLinkCreateDTO.bookId })
+        } else {
+            message.error('请先选择书城、公众号')
+        }
+    }
+
+    return <>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'bookId']}
+            rules={[{ required: true, message: '请输入作品(书籍)ID!' }]}
+            label={<strong>作品(书籍)ID</strong>}
+        >
+            <SelectBook
+                platformKey={platform}
+                searchChapterDisabled={!wenDingCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId}
+                searchChapterLoading={getFreeChapterList.loading}
+                hanldeSearchChapter={getChapterList}
+
+            />
+        </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', 'qrcodeOpenStatus']}
+            label={<strong>二维码展示</strong>}
+            rules={[{ required: true, message: '请选择二维码展示!' }]}
+        >
+            <Radio.Group
+                buttonStyle="solid"
+                options={[
+                    { value: 0, label: '关闭' },
+                    { value: 1, label: '开启' },
+                ]}
+            />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'bookPromoLinkCreateDTO', 'linkClassify']}
+            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(LINKCLASSIFY)?.map(key => ({ value: key, label: LINKCLASSIFY[key] }))}
+            />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(BookPromoLinkCreateDTO);

+ 85 - 0
src/pages/weComTask/page/bookLink/components/wending/rechargeActivityLinkDTO.tsx

@@ -0,0 +1,85 @@
+import { DatePicker, Form, Input, Radio } from "antd";
+import React from "react";
+import SetConfig from "./setConfig";
+import { RangePickerProps } from "antd/es/date-picker";
+import dayjs from 'dayjs';
+
+
+/**
+ * 文鼎充值活动
+ * @returns 
+ */
+const RechargeActivityLinkDTO: React.FC<BOOKLINK.BookLinkChildProps> = ({ restField, name }) => {
+
+    const disabledDate: RangePickerProps['disabledDate'] = current => {
+        // Can not select days before today and today
+        return current && current < dayjs().endOf('day');
+    };
+
+    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', 'viewTitle']}
+            label={<strong>活动页标题</strong>}
+            rules={[{ required: true, message: '请输入活动页标题!' }]}
+        >
+            <Input placeholder="请输入活动页标题" style={{ width: '100%' }} allowClear />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'configs']}
+            label={<strong>活动充值项</strong>}
+            rules={[{ required: true, message: '请添加活动充值项!' }]}
+        >
+            <SetConfig />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'activityTime']}
+            label={<strong>活动时间</strong>}
+            rules={[{ required: true, message: '请选择活动时间!' }]}
+        >
+            <DatePicker.RangePicker disabledDate={disabledDate} />
+        </Form.Item>
+        <Form.Item
+            {...restField}
+            name={[name, 'rechargeActivityLinkDTO', 'hideCountDown']}
+            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', 'userGroup']}
+            label={<strong>目标用户</strong>}
+            rules={[{ required: true, message: '请选择目标用户!' }]}
+        >
+            <Radio.Group
+                optionType='button'
+                buttonStyle="solid"
+                options={[
+                    { value: 0, label: '全部用户' },
+                    { value: 10, label: '标签用户' }
+                ]}
+            />
+        </Form.Item>
+    </>
+}
+
+export default React.memo(RechargeActivityLinkDTO);

+ 248 - 0
src/pages/weComTask/page/bookLink/components/wending/setConfig.tsx

@@ -0,0 +1,248 @@
+import { App, Button, Form, InputNumber, Modal, Popconfirm, Radio, Select, Table } from 'antd';
+import React, { useState } from 'react';
+import { RECHARGETYPE } from '../../const';
+
+interface valueProps {
+    hongbao: number;
+    price: number;
+    rechargeFrequency: 0 | 1;
+    rechargeTimes: number;
+    rechargeType: number;
+    vipConfigId: string
+}
+
+interface SetConfigProps {
+    value?: valueProps[]
+    onChange?: (value: valueProps[]) => void
+}
+
+const SetConfig: React.FC<SetConfigProps> = ({ value = [], onChange }) => {
+
+    /*************************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    /*************************************/
+
+    return <div>
+        <Button type="primary" onClick={() => setVisible(true)}>添加充值项</Button>
+        {value?.length > 0 && <Table
+            style={{ marginTop: 10 }}
+            dataSource={value.map((item, index) => ({ ...item, id: index + 1 }))}
+            columns={[
+                {
+                    title: '充值类型',
+                    dataIndex: 'rechargeType',
+                    key: 'rechargeType',
+                    align: 'center',
+                    render(value) {
+                        return RECHARGETYPE[value]
+                    },
+                },
+                {
+                    title: '充值金额',
+                    dataIndex: 'price',
+                    key: 'price',
+                    render(value) {
+                        return (value || value === 0) ? value + '元' : '--'
+                    },
+                },
+                {
+                    title: '赠送金额',
+                    dataIndex: 'hongbao',
+                    key: 'hongbao',
+                    render(value) {
+                        return (value || value === 0) ? value + '元' : '--'
+                    },
+                },
+                {
+                    title: '限购次数',
+                    dataIndex: 'rechargeFrequency',
+                    key: 'rechargeFrequency',
+                    render(value, record) {
+                        return value === 0 ? record.rechargeTimes === -1 ? '不限' : (record.rechargeTimes + '次') : record.rechargeTimes === -1 ? '不限' : ('每天' + record.rechargeTimes + '次')
+                    },
+                },
+                {
+                    title: '操作',
+                    dataIndex: 'cz',
+                    key: 'cz',
+                    align: 'center',
+                    render(_, record) {
+                        return <Popconfirm
+                            title="确定删除该项?"
+                            onConfirm={() => {
+                                onChange?.(value?.filter((_, index) => record.id !== (index + 1)))
+                            }}
+                        >
+                            <a>删除</a>
+                        </Popconfirm>
+                    },
+                },
+            ]}
+            rowKey={'id'}
+            size='small'
+            bordered
+            pagination={false}
+        />}
+        {visible && <SetConfigModal
+            visible={visible}
+            onClose={() => setVisible(false)}
+            onChange={(newValue) => {
+                setVisible(false)
+                const oldValue = JSON.parse(JSON.stringify(value || []))
+                oldValue.push(newValue)
+                onChange?.(oldValue)
+            }}
+        />}
+    </div>
+};
+
+interface SetConfigModalProps {
+    onChange?: (value: valueProps) => void
+    visible?: boolean;
+    onClose?: () => void;
+}
+const SetConfigModal: React.FC<SetConfigModalProps> = ({ visible, onChange, onClose }) => {
+
+    /***********************************/
+    const { message } = App.useApp()
+    const [form] = Form.useForm();
+    const rechargeType = Form.useWatch('rechargeType', form)
+    const price = Form.useWatch('price', form)
+    /***********************************/
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+            console.log(values)
+            onChange?.(values)
+        })
+    }
+
+    return <Modal
+        title={<strong>添加充值项</strong>}
+        open={visible}
+        onCancel={onClose}
+        width={600}
+        onOk={handleOk}
+    >
+        <Form
+            form={form}
+            name="newConfig"
+            labelAlign='left'
+            labelCol={{ span: 5 }}
+            colon={false}
+            scrollToFirstError={{
+                behavior: 'smooth',
+                block: 'center'
+            }}
+            onFinishFailed={({ errorFields }) => {
+                message.error(errorFields?.[0]?.errors?.[0])
+            }}
+            onFinish={handleOk}
+            initialValues={{ rechargeType: 0, rechargeFrequency: 0 }}
+        >
+            <Form.Item label={<strong>充值类型</strong>} name="rechargeType" rules={[{ required: true, message: '请选择充值类型!' }]}>
+                <Select
+                    showSearch
+                    allowClear
+                    placeholder="请选择充值类型"
+                    filterOption={(input, option) =>
+                        ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                    }
+                    options={Object.keys(RECHARGETYPE).map(key => ({ label: RECHARGETYPE[key], value: Number(key) }))}
+                />
+            </Form.Item>
+            {rechargeType === 0 ? <>
+                <Form.Item
+                    label={<strong>充值金额</strong>}
+                    name="price"
+                    rules={[
+                        { required: true, message: '请输入充值金额!' },
+                        {
+                            validator: (_: any, value: number) => {
+                                if (value && value.toString().split('.')[1]?.length > 2) {
+                                    return Promise.reject('最多输入两位小数');
+                                }
+                                return Promise.resolve();
+                            }
+                        }
+                    ]}
+                >
+                    <InputNumber suffix="元" placeholder="请输入" min={1} max={300} precision={2} style={{ width: '100%' }} />
+                </Form.Item>
+                <Form.Item
+                    label={<strong>赠送金额</strong>}
+                    name="hongbao"
+                    rules={[
+                        { required: true, message: '请输入赠送金额!' },
+                        {
+                            validator: (_: any, value: number) => {
+                                if (!value) return Promise.resolve();
+                                // 小数位数校验
+                                if (value.toString().split('.')[1]?.length > 2) {
+                                    return Promise.reject('最多输入两位小数');
+                                }
+                                // 动态倍数校验
+                                const maxRatio = price <= 9 ? 2.5 : 1.5;
+                                const maxAmount = Math.min(price * maxRatio, 20);
+                                if (value > maxAmount) {
+                                    return Promise.reject(
+                                        price <= 9
+                                            ? `不能超过${maxRatio}倍(最大20元)`
+                                            : `不能超过${maxRatio}倍`
+                                    );
+                                }
+                                return Promise.resolve();
+                            }
+                        }
+                    ]}
+                >
+                    <InputNumber suffix="元" placeholder="请输入" precision={2} style={{ width: '100%' }} />
+                </Form.Item>
+            </> : <>
+                <Form.Item label={<strong>充值项</strong>} name="vipConfigId" rules={[{ required: true, message: '请选择充值项!' }]}>
+                    <Select
+                        showSearch
+                        allowClear
+                        placeholder="请选择充值项"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                        }
+                        options={[
+                            { label: '365元包一年', value: '365元包一年' },
+                            { label: '399元包一年', value: '399元包一年' },
+                            { label: '666元包一年', value: '666元包一年' },
+                            { label: '499元包一年', value: '499元包一年' },
+                            { label: '499元买一年送一年', value: '499元买一年送一年' },
+                            { label: '666买一年送一年', value: '666买一年送一年' },
+                            { label: '888元包一年', value: '888元包一年' },
+                            { label: '288元包一年', value: '288元包一年' },
+                            { label: '199元包一个月', value: '199元包一个月' }
+                        ]}
+                    />
+                </Form.Item>
+            </>}
+            <Form.Item label={<strong>限购频次</strong>} name="rechargeFrequency" rules={[{ required: true, message: '请选择限购频次!' }]}>
+                <Radio.Group
+                    buttonStyle="solid"
+                    options={[
+                        { value: 0, label: '按次数' },
+                        { value: 1, label: '每天' },
+                    ]}
+                />
+            </Form.Item>
+            <Form.Item label={<strong>限购次数</strong>} name="rechargeTimes" rules={[{ required: true, message: '请选择限购次数!' }]}>
+                <Select
+                    showSearch
+                    allowClear
+                    placeholder="请选择限购次数"
+                    filterOption={(input, option) =>
+                        ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                    }
+                    options={[-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map(item => ({ label: item === -1 ? '不限' : item + '次', value: item }))}
+                />
+            </Form.Item>
+        </Form>
+    </Modal>
+};
+
+export default React.memo(SetConfig);

+ 2 - 23
src/pages/weComTask/page/bookLink/bookPromoLinkCreateDTO.tsx → src/pages/weComTask/page/bookLink/components/yuewen/bookPromoLinkCreateDTO.tsx

@@ -1,8 +1,8 @@
 import { useAjax } from "@/Hook/useAjax";
+import { getFreeChapterListApi } from "@/pages/weComTask/API/bookLink";
 import { App, Button, Form, Input, InputNumber, Radio, Select, Space, Switch } from "antd";
 import React from "react";
-import { getFreeChapterListApi } from "../../API/bookLink";
-import SelectBook from "./selectBook";
+import SelectBook from "../../selectBook";
 
 interface Props extends BOOKLINK.BookLinkChildProps {
     yueWenCreateLinkDTO: { [x: string]: any }
@@ -29,27 +29,6 @@ const BookPromoLinkCreateDTO: React.FC<Props> = ({ restField, name, yueWenCreate
     }
 
     return <>
-        {/* <Form.Item
-            label={<strong>作品(书籍)ID</strong>}
-            required
-        >
-            <Space.Compact style={{ width: '100%' }}>
-                <Form.Item
-                    {...restField}
-                    name={[name, 'bookPromoLinkCreateDTO', 'bookId']}
-                    rules={[{ required: true, message: '请输入作品(书籍)ID!' }]}
-                    noStyle
-                >
-                    <Input
-                        placeholder="请输入作品(书籍)ID"
-                        style={{ width: '100%' }}
-                        onChange={(e) => getFreeChapterList.mutate({ data: undefined })}
-                    />
-                </Form.Item>
-                <Button type="primary" onClick={getChapterList} disabled={!yueWenCreateLinkDTO?.bookPromoLinkCreateDTO?.bookId} loading={getFreeChapterList.loading}>查询章节列表</Button>
-            </Space.Compact>
-        </Form.Item> */}
-
         <Form.Item
             {...restField}
             name={[name, 'bookPromoLinkCreateDTO', 'bookId']}

+ 2 - 2
src/pages/weComTask/page/bookLink/consumeActivityLinkDTO.tsx → src/pages/weComTask/page/bookLink/components/yuewen/consumeActivityLinkDTO.tsx

@@ -1,6 +1,6 @@
-import { Checkbox, DatePicker, Form, Input, InputNumber, Radio, Select, Space } from "antd";
+import { Checkbox, DatePicker, Form, Input, InputNumber, Select } from "antd";
 import React from "react";
-import { ACTICITYTHEME, ACTICITYTHEMEXH, DISPLAYTYPE } from "./const";
+import { ACTICITYTHEMEXH, DISPLAYTYPE } from "../../const";
 
 
 /**

+ 1 - 1
src/pages/weComTask/page/bookLink/giftActivityLinkDTO.tsx → src/pages/weComTask/page/bookLink/components/yuewen/giftActivityLinkDTO.tsx

@@ -1,6 +1,6 @@
 import { Checkbox, DatePicker, Form, Input, InputNumber, Select } from "antd";
 import React from "react";
-import { DISPLAYTYPE, RESOURCETTYPE } from "./const";
+import { DISPLAYTYPE, RESOURCETTYPE } from "../../const";
 
 /**
  * 模板直赠活动

+ 1 - 1
src/pages/weComTask/page/bookLink/pagePromoLinkCreateDTO.tsx → src/pages/weComTask/page/bookLink/components/yuewen/pagePromoLinkCreateDTO.tsx

@@ -1,6 +1,6 @@
 import { Form, Input, InputNumber, Select } from "antd";
 import React from "react";
-import { PAGETYPE } from "./const";
+import { PAGETYPE } from "../../const";
 
 
 /**

+ 1 - 1
src/pages/weComTask/page/bookLink/rechargeActivityLinkDTO.tsx → src/pages/weComTask/page/bookLink/components/yuewen/rechargeActivityLinkDTO.tsx

@@ -1,6 +1,6 @@
 import { Checkbox, DatePicker, Form, Input, InputNumber, Radio, Select, Space } from "antd";
 import React from "react";
-import { ACTICITYTHEME, DISPLAYTYPE } from "./const";
+import { ACTICITYTHEME, DISPLAYTYPE } from "../../const";
 
 
 /**

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

@@ -8,6 +8,25 @@ export const LINKTYPE = {
     4: '模版直赠活动链接',
     5: '模板消耗活动链接'
 }
+/** 番茄 链接类型 */
+export const FANQIELINKTYPE = {
+    1: '页面链接',
+    2: '作品链接',
+    3: '充值活动链接',
+    4: '年卡活动链接',
+    5: '免费赠币活动链接'
+}
+/** 花生 链接类型 */
+export const HUASHENGLINKTYPE = {
+    1: '作品链接',
+    2: '充值活动链接',
+    3: '免费赠币活动链接'
+}
+/** 文鼎 链接类型 */
+export const WENDINGLINKTYPE = {
+    1: '作品链接',
+    2: '活动链接',
+}
 
 export const LINKTYPEEle = {
     1: <Tag color="magenta">页面链接</Tag>,
@@ -17,6 +36,28 @@ export const LINKTYPEEle = {
     5: <Tag color="gold">模板消耗活动链接</Tag>
 }
 
+// 番茄
+export const FANQIELINKTYPEEle = {
+    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>
+}
+
+// 花生
+export const HUASHENGLINKTYPEEle = {
+    1: <Tag color="red">作品链接</Tag>,
+    2: <Tag color="volcano">充值活动链接</Tag>,
+    3: <Tag color="gold">免费赠币活动链接</Tag>
+}
+
+// 文鼎
+export const WENDINGLINKTYPEELE = {
+    1: <Tag color="red">作品链接</Tag>,
+    2: <Tag color="volcano">活动链接</Tag>,
+}
+
 // 1=书城首页2=排行榜(自动)3=排行榜(男生)4=排行榜(女生)5=充值页6=最近阅读(列表)7=限免专区8=签到页面9=个人中心10=置顶公众号引导11=新用户充值活动页12=最近阅读(最近阅读作品)13=意见反馈
 export const PAGETYPE = {
     1: '书城首页',
@@ -34,6 +75,17 @@ export const PAGETYPE = {
     13: '意见反馈'
 }
 
+// 1=继续阅读,2=书城主页,3=签到活动,4=个人中心,5=充值记录,6=阅读历史,7=充值页面
+export const FANQIEPAGETYPE = {
+    1: '继续阅读',
+    2: '书城主页',
+    3: '签到活动',
+    4: '个人中心',
+    5: '充值记录',
+    6: '阅读历史',
+    7: '充值页面'
+}
+
 // 1 默认风格,2 男生风格,3 女生风格,4 教师节,5 中秋节,6 周末风格,7 国庆节,8 重阳节,9 万圣节,10 双十一,11 双十二,12 圣诞节,13 元旦,16 春节,
 // 17 元宵节,18 情人节,19 春季踏青,20 劳动节,21 端午节,23 女神节,24 七夕
 /**活动主题 */
@@ -80,7 +132,32 @@ export const DISPLAYTYPE = {
     '4': '活动中心'
 }
 
+// 花生活动展示位
+export const DISPLAYTYPEHUASHENG = {
+    'readlog': '书架弹窗',
+    'home': '首页弹窗',
+    'stack': '分类弹窗',
+    'mine': '个人中心弹窗',
+    'read_footer_text': '阅读页底部文字',
+    'read_footer_banner': '阅读页底部banner'
+}
+
 // 赠送道具类型:1 书券
 export const RESOURCETTYPE = {
     1: '书卷'
+}
+
+// 关注类型
+// 1-常规二维码2-非强制二维码3-强制二维码,默认3,仅当二维码展示开启时生效
+export const LINKCLASSIFY = {
+    1: '常规二维码',
+    2: '非强制二维码',
+    3: '强制二维码'
+}
+
+
+// 文鼎充值类型
+export const RECHARGETYPE= {
+    0: '普通充值',
+    1: 'VIP会员'
 }

+ 200 - 53
src/pages/weComTask/page/bookLink/details.tsx

@@ -1,65 +1,212 @@
 import React from "react";
-import { ACTICITYTHEME, ACTICITYTHEMEXH, DISPLAYTYPE, LINKTYPE, LINKTYPEEle, PAGETYPE, RESOURCETTYPE } from "./const";
+import { ACTICITYTHEME, ACTICITYTHEMEXH, DISPLAYTYPE, DISPLAYTYPEHUASHENG, FANQIELINKTYPEEle, FANQIEPAGETYPE, HUASHENGLINKTYPEEle, LINKCLASSIFY, LINKTYPE, LINKTYPEEle, PAGETYPE, RECHARGETYPE, RESOURCETTYPE, WENDINGLINKTYPEELE } from "./const";
+import { Table } from "antd";
 
 interface Props {
     linkType: keyof typeof LINKTYPE,
+    platform: string,
     linkContent: { [x: string]: any }
 }
 
-const Details: React.FC<Props> = ({ linkType, linkContent }) => {
+const Details: React.FC<Props> = ({ linkType, linkContent, platform }) => {
 
-    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' }}>{ACTICITYTHEMEXH[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>
+    if (platform === 'YUE_WEN') {
+        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' }}>{ACTICITYTHEMEXH[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>
+        }
+    } else if (platform === 'FAN_QIE') { // f番茄
+        if (linkType === 1) {
+            return <div>
+                <div>链接类型:{FANQIELINKTYPEEle[linkType]}</div>
+                <div>页面类型:<span style={{ color: '#1890ff' }}>{FANQIEPAGETYPE[linkContent?.pageType] || linkContent?.pageType}</span></div>
+            </div>
+        } else if (linkType === 2) {
+            return <div>
+                <div>链接类型:{FANQIELINKTYPEEle[linkType]}</div>
+                <div>作品(书籍)ID:<span style={{ color: '#1890ff' }}>{linkContent?.bookId}</span></div>
+                <div>章节ID:<span style={{ color: '#1890ff' }}>{linkContent?.chapterId}</span></div>
+            </div>
+        } else if (linkType === 3) {
+            return <div>
+                <div>链接类型:{FANQIELINKTYPEEle[linkType]}</div>
+                <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+                <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+                <div>充值挡位:<span style={{ color: '#1890ff' }}>充值{linkContent?.rechargeAmount}元,送{linkContent?.giftAmount}元</span></div>
+                <div>充值次数:<span style={{ color: '#1890ff' }}>{linkContent?.rechargeCount === -1 ? '不限次' : linkContent?.rechargeCount + '次'}</span></div>
+            </div>
+        } else if (linkType === 4) {
+            return <div>
+                <div>链接类型:{FANQIELINKTYPEEle[linkType]}</div>
+                <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+                <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+                <div>会员时长:<span style={{ color: '#1890ff' }}>{linkContent?.vipDuration}年</span></div>
+                <div>活动价格:<span style={{ color: '#1890ff' }}>{linkContent?.activityPrice}元</span></div>
+                <div>原价:<span style={{ color: '#1890ff' }}>{linkContent?.originalPrice}元</span></div>
+                <div>充值次数:<span style={{ color: '#1890ff' }}>{linkContent?.rechargeCount}次</span></div>
+            </div>
+        } else if (linkType === 5) {
+            return <div>
+                <div>链接类型:{FANQIELINKTYPEEle[linkType]}</div>
+                <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+                <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+                <div>赠送书币:<span style={{ color: '#1890ff' }}>{linkContent?.giftAmount}个</span></div>
+                <div>赠送总次数:<span style={{ color: '#1890ff' }}>{linkContent?.rechargeCount}次</span></div>
+                <div>频率限制:<span style={{ color: '#1890ff' }}>{linkContent?.activityFrequencies?.activityFrequenciesEnum == 2 ? '每天一次' : '每周一次'}</span></div>
+            </div>
+        }
+    } else if (platform === 'HUA_SHENG') {
+        if (linkType === 1) {
+            return <div>
+                <div>链接类型:{HUASHENGLINKTYPEEle[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?.forceChapter}</span></div>
+                <div>消耗:<span style={{ color: '#1890ff' }}>{linkContent?.cost}</span></div>
+            </div>
+        } else if (linkType === 2) {
+            return <div>
+                <div>链接类型:{HUASHENGLINKTYPEEle[linkType]}</div>
+                <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+                <div>充值挡位:<span style={{ color: '#1890ff' }}>{linkContent?.productName}</span></div>
+                <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+                <div>活动状态:<span style={{ color: '#1890ff' }}>{linkContent?.status === 'normal' ? '上架' : '下架'}</span></div>
+                <div>限购类型:<span style={{ color: '#1890ff' }}>{linkContent?.chargeType === 0 ? '整体限购' : '每天限购'}</span></div>
+                {linkContent?.display && <div>活动展示位:<span style={{ color: '#1890ff' }}>{linkContent.display.split(',').map(item => DISPLAYTYPEHUASHENG[item]).join('、')}</span></div>}
+                <div>限购次数:<span style={{ color: '#1890ff' }}>{linkContent?.chargeCount}次</span></div>
+                <div>展示粉丝:<span style={{ color: '#1890ff' }}>{linkContent?.userType === 1 ? '全部粉丝' : '条件粉丝'}</span></div>
+                {linkContent?.userType === 2 && <>
+                    <div>充值状态:<span style={{ color: '#1890ff' }}>{linkContent?.charge === 0 ? '不限' : linkContent?.charge === 1 ? '已充值' : '未充值'}</span></div>
+                    <div>关注时间:<span style={{ color: '#1890ff' }}>{linkContent?.commonType === 0 ? '不限' : linkContent?.charge === 1 ? '24小时以上' : linkContent?.charge === 1 ? '48小时以上' : '72小时以上'}</span></div>
+                </>}
+            </div>
+        } else if (linkType === 3) {
+            return <div>
+                <div>链接类型:{HUASHENGLINKTYPEEle[linkType]}</div>
+                <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+                <div>活动挡位:<span style={{ color: '#1890ff' }}>{linkContent?.freeAmount}书币</span></div>
+                <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+                <div>活动状态:<span style={{ color: '#1890ff' }}>{linkContent?.status === 'normal' ? '上架' : '下架'}</span></div>
+                {linkContent?.display && <div>活动展示位:<span style={{ color: '#1890ff' }}>{linkContent.display.split(',').map(item => DISPLAYTYPEHUASHENG[item]).join('、')}</span></div>}
+                <div>展示粉丝:<span style={{ color: '#1890ff' }}>{linkContent?.userType === 1 ? '全部粉丝' : '条件粉丝'}</span></div>
+                {linkContent?.userType === 2 && <>
+                    <div>充值状态:<span style={{ color: '#1890ff' }}>{linkContent?.charge === 0 ? '不限' : linkContent?.charge === 1 ? '已充值' : '未充值'}</span></div>
+                    <div>关注时间:<span style={{ color: '#1890ff' }}>{linkContent?.commonType === 0 ? '不限' : linkContent?.charge === 1 ? '24小时以上' : linkContent?.charge === 1 ? '48小时以上' : '72小时以上'}</span></div>
+                </>}
+            </div>
+        }
+    } else if (platform === 'WEN_DING') {
+        if (linkType === 1) {
+            return <div>
+                <div>链接类型:{WENDINGLINKTYPEELE[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?.qrcodeOpenStatus === 1 ? '开启' : '关闭'}</span></div>
+                <div>关注类型:<span style={{ color: '#1890ff' }}>{LINKCLASSIFY[linkContent?.linkClassify]}</span></div>
+            </div>
+        } else if (linkType === 2) {
+            return <div>
+                <div>链接类型:{WENDINGLINKTYPEELE[linkType]}</div>
+                <div>活动名称:<span style={{ color: '#1890ff' }}>{linkContent?.activityName}</span></div>
+                <div>活动页标题:<span style={{ color: '#1890ff' }}>{linkContent?.viewTitle}</span></div>
+                <div>活动充值项<Table
+                    style={{ marginTop: 10 }}
+                    dataSource={linkContent?.configs.map((item, index) => ({ ...item, id: index + 1 }))}
+                    columns={[
+                        {
+                            title: '充值类型',
+                            dataIndex: 'rechargeType',
+                            key: 'rechargeType',
+                            align: 'center',
+                            render(value) {
+                                return RECHARGETYPE[value]
+                            },
+                        },
+                        {
+                            title: '充值金额',
+                            dataIndex: 'price',
+                            key: 'price',
+                            render(value) {
+                                return (value || value === 0) ? value + '元' : '--'
+                            },
+                        },
+                        {
+                            title: '赠送金额',
+                            dataIndex: 'hongbao',
+                            key: 'hongbao',
+                            render(value) {
+                                return (value || value === 0) ? value + '元' : '--'
+                            },
+                        },
+                        {
+                            title: '限购次数',
+                            dataIndex: 'rechargeFrequency',
+                            key: 'rechargeFrequency',
+                            render(value, record: any) {
+                                return value === 0 ? record.rechargeTimes === -1 ? '不限' : (record.rechargeTimes + '次') : record.rechargeTimes === -1 ? '不限' : ('每天' + record.rechargeTimes + '次')
+                            },
+                        }
+                    ]}
+                    rowKey={'id'}
+                    size='small'
+                    bordered
+                    pagination={false}
+                /></div>
+                <div>活动时间:<span style={{ color: '#1890ff' }}>{linkContent?.startTime}~{linkContent?.endTime}</span></div>
+                <div>活动倒计时:<span style={{ color: '#1890ff' }}>{linkContent?.hideCountDown === 1 ? '隐藏' : '显示'}</span></div>
+                <div>目标用户:<span style={{ color: '#1890ff' }}>{linkContent?.userGroup === 10 ? '标签用户' : '全部用户'}</span></div>
+            </div>
+        }
     }
+
     return null
 }
 

+ 146 - 46
src/pages/weComTask/page/bookLink/index.tsx

@@ -51,52 +51,152 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
 
     const handleCopy = (value: any) => {
         const { linkType, linkContext, channelName, channelType, platform, mpAccountId } = value
-        const yueWenCreateLinkDTO: { [x: string]: any } = {
-            linkType: linkType + '',
-            channelName,
-            channelType: channelType + ''
-        }
-        switch (linkType) {
-            case 1:
-                yueWenCreateLinkDTO.pagePromoLinkCreateDTO = {
-                    ...linkContext,
-                    pageType: linkContext.pageType + ''
-                }
-                break
-            case 2:
-                yueWenCreateLinkDTO.bookPromoLinkCreateDTO = { ...linkContext, forceStyle: Number(linkContext.forceStyle) }
-                break
-            case 3:
-                yueWenCreateLinkDTO.rechargeActivityLinkDTO = {
-                    ...linkContext,
-                    activityTheme: linkContext.activityTheme + '',
-                    activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
-                    display: linkContext?.display ? linkContext?.display?.split(',') : []
-                }
-                break
-            case 4:
-                yueWenCreateLinkDTO.giftActivityLinkDTO = {
-                    ...linkContext,
-                    // activityTheme: Number(linkContext.activityTheme), 
-                    activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
-                    display: linkContext?.display ? linkContext?.display?.split(',') : [],
-                    resourceType: linkContext.resourceType + ''
-                }
-                break
-            case 5:
-                yueWenCreateLinkDTO.consumeActivityLinkDTO = {
-                    ...linkContext,
-                    activityTheme: linkContext.activityTheme + '',
-                    activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
-                    display: linkContext?.display ? linkContext?.display?.split(',') : [],
-                }
-                break
+        if (platform === 'YUE_WEN') {  // 阅文
+            const yueWenCreateLinkDTO: { [x: string]: any } = {
+                linkType: linkType + '',
+                channelName,
+                channelType: channelType + ''
+            }
+            switch (linkType) {
+                case 1:
+                    yueWenCreateLinkDTO.pagePromoLinkCreateDTO = {
+                        ...linkContext,
+                        pageType: linkContext.pageType + ''
+                    }
+                    break
+                case 2:
+                    yueWenCreateLinkDTO.bookPromoLinkCreateDTO = { ...linkContext, forceStyle: Number(linkContext.forceStyle) }
+                    break
+                case 3:
+                    yueWenCreateLinkDTO.rechargeActivityLinkDTO = {
+                        ...linkContext,
+                        activityTheme: linkContext.activityTheme + '',
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                        display: linkContext?.display ? linkContext?.display?.split(',') : []
+                    }
+                    break
+                case 4:
+                    yueWenCreateLinkDTO.giftActivityLinkDTO = {
+                        ...linkContext,
+                        // activityTheme: Number(linkContext.activityTheme), 
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                        display: linkContext?.display ? linkContext?.display?.split(',') : [],
+                        resourceType: linkContext.resourceType + ''
+                    }
+                    break
+                case 5:
+                    yueWenCreateLinkDTO.consumeActivityLinkDTO = {
+                        ...linkContext,
+                        activityTheme: linkContext.activityTheme + '',
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                        display: linkContext?.display ? linkContext?.display?.split(',') : [],
+                    }
+                    break
+            }
+            setInitialValues({
+                platform,
+                mpAccountIds: [mpAccountId],
+                yueWenCreateLinkDTOList: [yueWenCreateLinkDTO]
+            })
+        } else if (platform === 'FAN_QIE') { // 番茄
+            const fanQieCreateLinkDTO: { [x: string]: any } = {
+                linkType: linkType + '',
+                channelName
+            }
+            switch (linkType) {
+                case 1:
+                    fanQieCreateLinkDTO.pagePromoLinkCreateDTO = {
+                        ...linkContext,
+                        pageType: linkContext.pageType + ''
+                    }
+                    break
+                case 2:
+                    fanQieCreateLinkDTO.bookPromoLinkCreateDTO = { ...linkContext }
+                    break
+                case 3:
+                    fanQieCreateLinkDTO.rechargeActivityLinkDTO = {
+                        ...linkContext,
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)]
+                    }
+                    break
+                case 4:
+                    fanQieCreateLinkDTO.giftActivityLinkDTO = {
+                        ...linkContext,
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)]
+                    }
+                    break
+                case 5:
+                    fanQieCreateLinkDTO.consumeActivityLinkDTO = {
+                        ...linkContext,
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                    }
+                    break
+            }
+            setInitialValues({
+                platform,
+                mpAccountIds: [mpAccountId],
+                fanQieCreateLinkDTOList: [fanQieCreateLinkDTO]
+            })
+        } else if (platform === 'HUA_SHENG') { // 花生
+            const huaShengCreateLinkDTO: { [x: string]: any } = {
+                linkType: linkType + '',
+                channelName,
+                channelType: channelType + ''
+            }
+
+            switch (linkType) {
+                case 1:
+                    huaShengCreateLinkDTO.bookPromoLinkCreateDTO = { ...linkContext }
+                    break;
+                case 2:
+                    const [rechargeAmount, giftAmount] = linkContext.productName.split('-')
+                    huaShengCreateLinkDTO.rechargeActivityLinkDTO = {
+                        ...linkContext,
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                        display: linkContext?.display ? linkContext?.display?.split(',') : [],
+                        rechargeAmount,
+                        giftAmount
+                    }
+                    break;
+                case 3:
+                    huaShengCreateLinkDTO.giftActivityLinkDTO = {
+                        ...linkContext,
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                        display: linkContext?.display ? linkContext?.display?.split(',') : []
+                    }
+                    break
+            }
+            setInitialValues({
+                platform,
+                mpAccountIds: [mpAccountId],
+                huaShengCreateLinkDTOList: [huaShengCreateLinkDTO]
+            })
+        } else if (platform === 'WEN_DING') { // 文鼎
+            const wenDingCreateLinkDTO: { [x: string]: any } = {
+                linkType: linkType + '',
+                channelName,
+                channelType: channelType
+            }
+
+            switch (linkType) {
+                case 1:
+                    wenDingCreateLinkDTO.bookPromoLinkCreateDTO = { ...linkContext, linkClassify: linkContext.linkClassify + '' }
+                    break;
+                case 2:
+                    wenDingCreateLinkDTO.rechargeActivityLinkDTO = {
+                        ...linkContext,
+                        activityTime: [dayJs(linkContext.startTime), dayJs(linkContext.endTime)],
+                    }
+                    break;
+            }
+            console.log('wenDingCreateLinkDTO--->', wenDingCreateLinkDTO)
+            setInitialValues({
+                platform,
+                mpAccountIds: [mpAccountId],
+                wenDingCreateLinkDTOList: [wenDingCreateLinkDTO]
+            })
         }
-        setInitialValues({
-            platform,
-            mpAccountIds: [mpAccountId],
-            yueWenCreateLinkDTOList: [yueWenCreateLinkDTO]
-        })
+
         setVisible(true)
     }
 
@@ -127,7 +227,7 @@ const BookLink: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookL
                     <Button type="primary" icon={<PlusOutlined />} onClick={() => setVisible(true)}>链接生成</Button>
                     <Popconfirm
                         title="确定删除?"
-                        onConfirm={() => { handleDel({ linkIds : selectedRows.map(i => i.id) }) }}
+                        onConfirm={() => { handleDel({ linkIds: selectedRows.map(i => i.id) }) }}
                         disabled={selectedRows.length === 0}
                     >
                         <Button type='primary' danger icon={<DeleteOutlined />} loading={delAutoLink.loading} disabled={selectedRows.length === 0}>删除</Button>

+ 424 - 28
src/pages/weComTask/page/bookLink/modalBooklink.tsx

@@ -1,14 +1,24 @@
 import { App, Button, Card, Form, Input, Modal, Select } from "antd";
 import React from "react";
-import { LINKTYPE } from "./const";
+import { FANQIELINKTYPE, HUASHENGLINKTYPE, LINKTYPE, WENDINGLINKTYPE } 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 PagePromoLinkCreateDTO from "./components/yuewen/pagePromoLinkCreateDTO";
+import BookPromoLinkCreateDTO from "./components/yuewen/bookPromoLinkCreateDTO";
+import RechargeActivityLinkDTO from "./components/yuewen/rechargeActivityLinkDTO";
+import GiftActivityLinkDTO from "./components/yuewen/giftActivityLinkDTO";
+import ConsumeActivityLinkDTO from "./components/yuewen/consumeActivityLinkDTO";
+import PagePromoLinkCreateDTOFanQie from "./components/fanqie/pagePromoLinkCreateDTO";
+import BookPromoLinkCreateDTOFanqie from "./components/fanqie/bookPromoLinkCreateDTO";
+import RechargeActivityLinkDTOFanqie from "./components/fanqie/rechargeActivityLinkDTO";
+import GiftActivityLinkDTOFanQie from "./components/fanqie/giftActivityLinkDTO";
+import ConsumeActivityLinkDTOFanQie from "./components/fanqie/consumeActivityLinkDTO";
+import BookPromoLinkCreateDTOHuaSheng from './components/huasheng/bookPromoLinkCreateDTO'
+import RechargeActivityLinkDTOHuaSheng from './components/huasheng/rechargeActivityLinkDTO'
+import GiftActivityLinkDTOHuaSheng from './components/huasheng/giftActivityLinkDTO'
+import BookPromoLinkCreateDTOWenDing from './components/wending/bookPromoLinkCreateDTO'
+import RechargeActivityLinkDTOWenDing from './components/wending/rechargeActivityLinkDTO'
 import dayJs from "dayjs";
 
 interface Props {
@@ -33,6 +43,9 @@ const ModalBookLink: React.FC<Props> = ({ mpList, bookPlatForm, visible, onChang
     const { message } = App.useApp()
     const [form] = Form.useForm();
     const yueWenCreateLinkDTOList = Form.useWatch('yueWenCreateLinkDTOList', form)
+    const fanQieCreateLinkDTOList = Form.useWatch('fanQieCreateLinkDTOList', form)
+    const huaShengCreateLinkDTOList = Form.useWatch('huaShengCreateLinkDTOList', form)
+    const wenDingCreateLinkDTOList = Form.useWatch('wenDingCreateLinkDTOList', form)
     const platform = Form.useWatch('platform', form)
     const mpAccountIds = Form.useWatch('mpAccountIds', form)
 
@@ -42,26 +55,85 @@ const ModalBookLink: React.FC<Props> = ({ mpList, bookPlatForm, visible, onChang
     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, isDayRepeat, rechargeCount, ...ralDto } = rechargeActivityLinkDTO
-                        return { ...rest, rechargeActivityLinkDTO: { ...ralDto, rechargeCount, isDayRepeat: rechargeCount == 1 ? isDayRepeat : false, 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 }
-                    }
-                })
+            let params: { [x: string]: any } = {}
+            if (values?.platform === 'YUE_WEN') {
+                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, isDayRepeat, rechargeCount, ...ralDto } = rechargeActivityLinkDTO
+                            return { ...rest, rechargeActivityLinkDTO: { ...ralDto, rechargeCount, isDayRepeat: rechargeCount == 1 ? isDayRepeat : false, 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 }
+                        }
+                    })
+                }
+            } else if (values?.platform === 'FAN_QIE') {
+                params = {
+                    mpAccountIds: values.mpAccountIds,
+                    platform: values.platform,
+                    fanQieCreateLinkDTOList: values.fanQieCreateLinkDTOList.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, ...ralDto } = rechargeActivityLinkDTO
+                            return { ...rest, rechargeActivityLinkDTO: { ...ralDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD') }, linkType }
+                        } else if (linkType === '4') {
+                            const { activityTime, ...calDto } = giftActivityLinkDTO
+                            return { ...rest, giftActivityLinkDTO: { ...calDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD') }, linkType }
+                        } else if (linkType === '5') {
+                            const { activityTime, ...galDto } = consumeActivityLinkDTO
+                            return { ...rest, consumeActivityLinkDTO: { ...galDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD') }, linkType }
+                        }
+                    })
+                }
+            } else if (values?.platform === 'HUA_SHENG') {
+                params = {
+                    mpAccountIds: values.mpAccountIds,
+                    platform: values.platform,
+                    huaShengCreateLinkDTOList: values.huaShengCreateLinkDTOList.map(item => {
+                        const { linkType, bookPromoLinkCreateDTO, rechargeActivityLinkDTO, giftActivityLinkDTO, ...rest } = item
+                        if (linkType === '1') {
+                            return { ...rest, bookPromoLinkCreateDTO, linkType }
+                        } else if (linkType === '2') {
+                            const { activityTime, display, rechargeAmount, giftAmount, ...ralDto } = rechargeActivityLinkDTO
+                            return { ...rest, rechargeActivityLinkDTO: { ...ralDto, productName: rechargeAmount + '-' + giftAmount, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD'), display: display?.join(',') }, linkType }
+                        } else if (linkType === '3') {
+                            const { activityTime, display, rechargeAmount, giftAmount, ...ralDto } = giftActivityLinkDTO
+                            return { ...rest, giftActivityLinkDTO: { ...ralDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD'), display: display?.join(',') }, linkType }
+                        }
+                    })
+                }
+            } else if (values?.platform === 'WEN_DING') {
+                params = {
+                    mpAccountIds: values.mpAccountIds,
+                    platform: values.platform,
+                    wenDingCreateLinkDTOList: values.wenDingCreateLinkDTOList.map(item => {
+                        const { linkType, bookPromoLinkCreateDTO, rechargeActivityLinkDTO, giftActivityLinkDTO, ...rest } = item
+                        if (linkType === '1') {
+                            return { ...rest, bookPromoLinkCreateDTO, linkType }
+                        } else if (linkType === '2') {
+                            const { activityTime, ...ralDto } = rechargeActivityLinkDTO
+                            return { ...rest, rechargeActivityLinkDTO: { ...ralDto, startTime: dayJs(activityTime[0]).format('YYYY-MM-DD'), endTime: dayJs(activityTime[1]).format('YYYY-MM-DD') }, linkType }
+                        }
+                    })
+                }
+            } else {
+                message.error('当前书城占不支持')
+                return
             }
             addCorpAutoLink.run(params).then(res => {
                 if (res?.data) {
@@ -108,6 +180,17 @@ const ModalBookLink: React.FC<Props> = ({ mpList, bookPlatForm, visible, onChang
                         }
                         allowClear
                         options={bookPlatForm.map(item => ({ value: item.platformKey, label: item.platformName }))}
+                        onChange={(e) => {
+                            if (e === 'YUE_WEN') {
+                                form.setFieldsValue({ yueWenCreateLinkDTOList: [{}] })
+                            } else if (e === 'FAN_QIE') {
+                                form.setFieldsValue({ fanQieCreateLinkDTOList: [{}] })
+                            } else if (e === 'HUA_SHENG') {
+                                form.setFieldsValue({ huaShengCreateLinkDTOList: [{}] })
+                            } else if (e === 'WEN_DING') {
+                                form.setFieldsValue({ wenDingCreateLinkDTOList: [{}] })
+                            }
+                        }}
                     />
                 </Form.Item>
                 <Form.Item label={<strong>公众号</strong>} name="mpAccountIds" rules={[{ required: true, message: '请选择公众号!' }]}>
@@ -124,7 +207,7 @@ const ModalBookLink: React.FC<Props> = ({ mpList, bookPlatForm, visible, onChang
                 </Form.Item>
             </Card>
             <DispatchBookLink.Provider value={{ form }}>
-                <Form.List name="yueWenCreateLinkDTOList">
+                {platform === 'YUE_WEN' ? <Form.List name="yueWenCreateLinkDTOList">
                     {(fields, { add, remove }) => (
                         <>
                             {fields.map(({ key, name, ...restField }, index) => {
@@ -257,7 +340,320 @@ const ModalBookLink: React.FC<Props> = ({ mpList, bookPlatForm, visible, onChang
                             </Form.Item>
                         </>
                     )}
-                </Form.List>
+                </Form.List> : platform === "FAN_QIE" ? <Form.List name="fanQieCreateLinkDTOList">
+                    {(fields, { add, remove }) => (
+                        <>
+                            {fields.map(({ key, name, ...restField }, index) => {
+                                const fanQieCreateLinkDTO = fanQieCreateLinkDTOList?.[index]
+                                return <Card
+                                    title={<strong>链接信息配置{index + 1}</strong>}
+                                    style={{ background: '#fff', marginBottom: 10 }}
+                                    key={key}
+                                    extra={fanQieCreateLinkDTOList?.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(FANQIELINKTYPE).map(key => ({ label: FANQIELINKTYPE[key], value: key }))}
+                                            onChange={(e) => {
+                                                if (e === '1') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            fanQieCreateLinkDTOList: fanQieCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName } = item
+                                                                    return { channelName, linkType: '1', pagePromoLinkCreateDTO: {} }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '2') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            fanQieCreateLinkDTOList: fanQieCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName } = item
+                                                                    return { channelName, linkType: '2', bookPromoLinkCreateDTO: {} }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '3') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            fanQieCreateLinkDTOList: fanQieCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName } = item
+                                                                    return { channelName, linkType: '3', rechargeActivityLinkDTO: { rechargeCount: -1 } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '4') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            fanQieCreateLinkDTOList: fanQieCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName } = item
+                                                                    return { channelName, linkType: '4', giftActivityLinkDTO: { rechargeCount: 1 } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '5') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            fanQieCreateLinkDTOList: fanQieCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName } = item
+                                                                    return { channelName, linkType: '5', consumeActivityLinkDTO: { rechargeCount: 1, activityFrequencies: 2 } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                }
+                                            }}
+                                        />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelName']}
+                                        label={<strong>渠道名称</strong>}
+                                        rules={[{ required: true, message: '请输入渠道名称!' }]}
+                                    >
+                                        <Input placeholder="请输入渠道名称" allowClear />
+                                    </Form.Item>
+                                    {fanQieCreateLinkDTO?.linkType === '1' ? <PagePromoLinkCreateDTOFanQie restField={restField} name={name} /> :
+                                        fanQieCreateLinkDTO?.linkType === '2' ? <BookPromoLinkCreateDTOFanqie restField={restField} name={name} platform={platform} /> :
+                                            fanQieCreateLinkDTO?.linkType === '3' ? <RechargeActivityLinkDTOFanqie restField={restField} name={name} /> :
+                                                fanQieCreateLinkDTO?.linkType === '4' ? <GiftActivityLinkDTOFanQie restField={restField} name={name} vipDuration={fanQieCreateLinkDTO?.giftActivityLinkDTO?.vipDuration} /> :
+                                                    fanQieCreateLinkDTO?.linkType === '5' ? <ConsumeActivityLinkDTOFanQie restField={restField} name={name} /> :
+                                                        undefined}
+                                </Card>
+                            })}
+                            <Form.Item>
+                                <Button type="dashed" onClick={() => add({})} block icon={<PlusOutlined />}>
+                                    新增链接信息配置
+                                </Button>
+                            </Form.Item>
+                        </>
+                    )}
+                </Form.List> : platform === 'HUA_SHENG' ? <Form.List name="huaShengCreateLinkDTOList">
+                    {(fields, { add, remove }) => (
+                        <>
+                            {fields.map(({ key, name, ...restField }, index) => {
+                                const huaShengCreateLinkDTO = huaShengCreateLinkDTOList?.[index]
+                                return <Card
+                                    title={<strong>链接信息配置{index + 1}</strong>}
+                                    style={{ background: '#fff', marginBottom: 10 }}
+                                    key={key}
+                                    extra={huaShengCreateLinkDTOList?.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(HUASHENGLINKTYPE).map(key => ({ label: HUASHENGLINKTYPE[key], value: key }))}
+                                            onChange={(e) => {
+                                                if (e === '1') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            huaShengCreateLinkDTOList: huaShengCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '1', bookPromoLinkCreateDTO: { cost: 0 } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '2') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            huaShengCreateLinkDTOList: huaShengCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '2', rechargeActivityLinkDTO: { status: 'normal', chargeType: 0, userType: 1, charge: 0, commonType: 0, display: ['stack', 'read_footer_text'] } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '3') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            huaShengCreateLinkDTOList: huaShengCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName } = item
+                                                                    return { channelName, linkType: '3', giftActivityLinkDTO: { status: 'normal', freeAmount: 50, userType: 1, charge: 0, commonType: 0, display: ['stack', 'read_footer_text'] } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                }
+                                            }}
+                                        />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelName']}
+                                        label={<strong>渠道名称</strong>}
+                                        rules={[{ required: true, message: '请输入渠道名称!' }]}
+                                    >
+                                        <Input placeholder="请输入渠道名称" allowClear />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelType']}
+                                        label={<strong>推广类型</strong>}
+                                        rules={[{ required: huaShengCreateLinkDTO?.linkType == 1 ? true : false, 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>
+                                    {huaShengCreateLinkDTO?.linkType === '1' ? <BookPromoLinkCreateDTOHuaSheng restField={restField} name={name} platform={platform} mpAccountIds={mpAccountIds} huaShengCreateLinkDTO={huaShengCreateLinkDTO} /> :
+                                        huaShengCreateLinkDTO?.linkType === '2' ? <RechargeActivityLinkDTOHuaSheng restField={restField} name={name} itemData={huaShengCreateLinkDTO} /> :
+                                            huaShengCreateLinkDTO?.linkType === '3' ? <GiftActivityLinkDTOHuaSheng restField={restField} name={name} itemData={huaShengCreateLinkDTO} /> :
+                                                undefined}
+                                </Card>
+                            })}
+                            <Form.Item>
+                                <Button type="dashed" onClick={() => add({})} block icon={<PlusOutlined />}>
+                                    新增链接信息配置
+                                </Button>
+                            </Form.Item>
+                        </>
+                    )}
+                </Form.List> : platform === 'WEN_DING' ? <Form.List name="wenDingCreateLinkDTOList">
+                    {(fields, { add, remove }) => (
+                        <>
+                            {fields.map(({ key, name, ...restField }, index) => {
+                                const wenDingCreateLinkDTO = wenDingCreateLinkDTOList?.[index]
+                                return <Card
+                                    title={<strong>链接信息配置{index + 1}</strong>}
+                                    style={{ background: '#fff', marginBottom: 10 }}
+                                    key={key}
+                                    extra={wenDingCreateLinkDTOList?.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(WENDINGLINKTYPE).map(key => ({ label: WENDINGLINKTYPE[key], value: key }))}
+                                            onChange={(e) => {
+                                                if (e === '1') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            wenDingCreateLinkDTOList: wenDingCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '1', bookPromoLinkCreateDTO: { qrcodeOpenStatus: 0, linkClassify: '3' } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                } else if (e === '2') {
+                                                    setTimeout(() => {
+                                                        form.setFieldsValue({
+                                                            wenDingCreateLinkDTOList: wenDingCreateLinkDTOList.map((item, i) => {
+                                                                if (index === i) {
+                                                                    const { channelName, channelType } = item
+                                                                    return { channelName, channelType, linkType: '2', rechargeActivityLinkDTO: { userGroup: 0, hideCountDown: 0 } }
+                                                                }
+                                                                return item
+                                                            })
+                                                        })
+                                                    }, 0)
+                                                }
+                                            }}
+                                        />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelName']}
+                                        label={<strong>渠道名称</strong>}
+                                        rules={[{ required: true, message: '请输入渠道名称!' }]}
+                                    >
+                                        <Input placeholder="请输入渠道名称" allowClear />
+                                    </Form.Item>
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'channelType']}
+                                        label={<strong>推广类型</strong>}
+                                        rules={[{ required: true, message: '请选择推广类型!' }]}
+                                    >
+                                        <Select
+                                            showSearch
+                                            placeholder="推广类型"
+                                            filterOption={(input, option) =>
+                                                ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                                            }
+                                            allowClear
+                                            options={[{ label: '内推', value: 0 }, { label: '派单', value: 1 }]}
+                                        />
+                                    </Form.Item>
+                                    {wenDingCreateLinkDTO?.linkType === '1' ? <BookPromoLinkCreateDTOWenDing restField={restField} name={name} platform={platform} mpAccountIds={mpAccountIds} wenDingCreateLinkDTO={wenDingCreateLinkDTO} /> :
+                                        wenDingCreateLinkDTO?.linkType === '2' ? <RechargeActivityLinkDTOWenDing restField={restField} name={name} /> :
+                                            undefined}
+                                </Card>
+                            })}
+                            <Form.Item>
+                                <Button type="dashed" onClick={() => add({})} block icon={<PlusOutlined />}>
+                                    新增链接信息配置
+                                </Button>
+                            </Form.Item>
+                        </>
+                    )}
+                </Form.List> : undefined}
+
             </DispatchBookLink.Provider>
         </Form>
     </Modal>

+ 3 - 2
src/pages/weComTask/page/bookLink/selectBook.tsx

@@ -9,6 +9,7 @@ interface SelectBookProps extends InputProps {
     hanldeSearchChapter?: () => void;
     searchChapterLoading?: boolean;
     searchChapterDisabled?: boolean;
+    isSearchChapter?: boolean;
 }
 
 /**
@@ -16,7 +17,7 @@ interface SelectBookProps extends InputProps {
  * @param param0 
  * @returns 
  */
-const SelectBook: React.FC<SelectBookProps> = ({ platformKey, value, onChange, hanldeSearchChapter, searchChapterLoading, searchChapterDisabled, ...rest }) => {
+const SelectBook: React.FC<SelectBookProps> = ({ platformKey, value, onChange, hanldeSearchChapter, searchChapterLoading, searchChapterDisabled, isSearchChapter = true, ...rest }) => {
 
     /*******************************************/
     const { message } = App.useApp()
@@ -56,7 +57,7 @@ const SelectBook: React.FC<SelectBookProps> = ({ platformKey, value, onChange, h
                 />
                 <Button type="primary" disabled={!platformKey} onClick={() => setVisible(true)}>选择书</Button>
             </Space.Compact>
-            <Button type="primary" loading={searchChapterLoading} disabled={searchChapterDisabled} onClick={() => hanldeSearchChapter?.()}>查询章节列表</Button>
+            {isSearchChapter && <Button type="primary" loading={searchChapterLoading} disabled={searchChapterDisabled} onClick={() => hanldeSearchChapter?.()}>查询章节列表</Button>}
         </Flex>
         {visible && <Modal
             title={<strong>选择书籍</strong>}

+ 6 - 4
src/pages/weComTask/page/bookLink/selectBookLink.tsx

@@ -14,6 +14,7 @@ interface Props {
     bookPlatForm: TASK_CREATE.BookPlatFormProps[]
     linkData: { [x: string]: any }[]
     mpAccountId: number | null
+    platform: string
     visible?: boolean;
     onClose?: () => void;
     onChange?: (linkStr: string, miniprogramAppid?: string, miniprogramPage?: string) => void;
@@ -24,15 +25,15 @@ interface Props {
  * @param param0 
  * @returns 
  */
-const SelectBookLink: React.FC<Props> = ({ bookPlatForm, linkData, mpAccountId, visible, onClose, onChange }) => {
+const SelectBookLink: React.FC<Props> = ({ bookPlatForm, linkData, mpAccountId, visible, onClose, onChange, platform }) => {
 
     /*******************************************/
     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 [queryParams, setQueryParams] = useState<GetCorpAutoLinkListProps>({ pageNum: 1, pageSize: 20, mpAccountId, platform })
+    const [queryParamsNew, setQueryParamsNew] = useState<GetCorpAutoLinkListProps>({ pageNum: 1, pageSize: 20, mpAccountId, platform })
 
     const getCorpAutoLinkList = useAjax((params) => getCorpAutoLinkListApi(params))
     const getBindMpList = useAjax(() => getBindMpListApi())
@@ -40,7 +41,7 @@ const SelectBookLink: React.FC<Props> = ({ bookPlatForm, linkData, mpAccountId,
 
     useEffect(() => {
         getCorpAutoLinkList.run({ ...queryParamsNew, mpAccountId })
-    }, [queryParamsNew, mpAccountId])
+    }, [queryParamsNew, mpAccountId, platform])
 
     useEffect(() => {
         getBindMpList.run().then(res => {
@@ -99,6 +100,7 @@ const SelectBookLink: React.FC<Props> = ({ bookPlatForm, linkData, mpAccountId,
                         onChange={(e) => setQueryParams({ ...queryParams, platform: e })}
                         showSearch
                         style={{ width: 110 }}
+                        disabled={!!platform}
                         placeholder="书城"
                         filterOption={(input, option) =>
                             ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())

+ 14 - 10
src/pages/weComTask/page/bookLink/tableConfig.tsx

@@ -1,7 +1,7 @@
 import { copy } from "@/utils/utils"
 import { ColumnsType } from "antd/es/table"
-import { LINKTYPEEle } from "./const"
-import { Button, Flex, Popconfirm, Popover } from "antd"
+import { FANQIELINKTYPEEle, HUASHENGLINKTYPEEle, LINKTYPEEle, WENDINGLINKTYPEELE } from "./const"
+import { Button, Flex, Popconfirm, Popover, Tag } from "antd"
 import Details from "./details"
 
 
@@ -16,8 +16,8 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             width: 70,
             ellipsis: true,
             fixed: 'left',
-            render: (value) => {
-                return <span style={{ fontSize: 12 }}>{value}</span>
+            render: (value, records) => {
+                return <Tag color={records.platform === 'YUE_WEN' ? '#f50' : records.platform === 'FAN_QIE' ? '#2db7f5' : records.platform === 'HUA_SHENG' ? '#87d068' : '#108ee9'}><span style={{ fontSize: 12 }}>{value}</span></Tag>
             }
         },
         {
@@ -47,8 +47,8 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             key: 'channelType',
             align: 'center',
             width: 80,
-            render: (value) => {
-                return <span style={{ fontSize: 12 }}>{value === 1 ? '外部' : value === 2 ? '内部' : '--'}</span>
+            render: (value, records) => {
+                return records.platform === 'WEN_DING' ? <span style={{ fontSize: 12 }}>{value === 0 ? '内推' : value === 1 ? '派单' : '--'}</span> : <span style={{ fontSize: 12 }}>{value === 1 ? '外部' : value === 2 ? '内部' : '--'}</span>
             }
         },
         {
@@ -57,8 +57,12 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             key: 'linkType',
             align: 'center',
             width: 120,
-            render: (value) => {
-                return LINKTYPEEle[value] || '--'
+            render: (value, records) => {
+                return records.platform === 'YUE_WEN' ? LINKTYPEEle[value] :
+                    records.platform === 'FAN_QIE' ? FANQIELINKTYPEEle[value] :
+                        records.platform === 'HUA_SHENG' ? HUASHENGLINKTYPEEle[value] :
+                            records.platform === 'WEN_DING' ? WENDINGLINKTYPEELE[value] :
+                                '--'
             }
         },
         {
@@ -116,13 +120,13 @@ export function bookLinkTableConfig(isSelect: boolean, handleCopy?: (value: any)
             dataIndex: 'cz',
             key: 'cz',
             align: 'center',
-            width: 90,
+            width: 100,
             fixed: 'right',
             render: (_, records) => {
                 return <Flex gap={4} justify='center'>
                     <Popover
                         placement="left"
-                        content={<Details linkType={records.linkType} linkContent={records.linkContext} />}
+                        content={<Details linkType={records.linkType} platform={records.platform} linkContent={records.linkContext} />}
                         styles={{ body: { width: 300, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
                     >
                         <Button type="link" style={{ padding: 0, height: 'auto' }}>详情</Button>

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

@@ -368,7 +368,15 @@ const MassSending: React.FC = () => {
                     </div>
                 </div>
                 <div className={style.detail_footer}>
-                    <Button type="link" style={{ padding: 0, fontSize: 12, color: token.colorPrimary }} size='small' onClick={() => { setNewVisible(true); setCreateType('STRATEGY') }}>编辑</Button>
+                    <Button
+                        type="link"
+                        style={{ padding: 0, fontSize: 12, color: token.colorPrimary }}
+                        size='small'
+                        onClick={() => {
+                            setNewVisible(true);
+                            setCreateType('STRATEGY')
+                        }}
+                    >编辑</Button>
                 </div>
             </div>
             <div className={`${style.settingsBody_content_col}`} style={{ width: '50%' }}>
@@ -450,7 +458,7 @@ const MassSending: React.FC = () => {
         {newVisible && <SettingsMassSending
             visible={newVisible}
             createType={createType}
-            bookCityList={bookPlatForm?.map(item => ({ label: item.platformName, value: item.platformKey }))}
+            bookCityList={bookPlatForm?.map(item => ({ label: item.platformName, value: item.platformKey, id: item.id }))}
             value={{
                 massSendingContent: settings?.massSendingContent,
                 massSendingStrategy: settings?.massSendingStrategy

+ 136 - 0
src/pages/weComTask/page/businessPlan/create/components/massSending/settingsContent.tsx

@@ -0,0 +1,136 @@
+import { Button, Input, Modal, Typography } from 'antd';
+import React, { useEffect, useState } from 'react';
+import style from '../../../../../components/selectExternalAccount/index.less'
+import { CheckOutlined } from '@ant-design/icons';
+import SelectBookLinkButton from '@/pages/weComTask/page/bookLink/SelectBookLinkButton';
+const { Paragraph, Title } = Typography;
+
+
+interface Props {
+    corpUserGroups: TASK_CREATE.CorpUserGroupProps[]
+    content: Array<{ msgType: "TASK_CONTENT_LINK", link: { title: string, picUrl: string, desc: string } } | { msgType: "TASK_STATUS_MINIPROGRAM", miniprogram: { title: string, picUrl: string } }>
+    bookPlatForm: TASK_CREATE.BookPlatFormProps[]
+    value?: any[];
+    onChange?: (value?: any) => void;
+}
+const SettingsContent: React.FC<Props> = ({ value, onChange, content, bookPlatForm, corpUserGroups }) => {
+
+    /*******************************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    const [data, setData] = useState<any>([])
+    /*******************************************/
+
+    useEffect(() => {
+        if (visible) {
+            setData(value || corpUserGroups.map(() => {
+                return {
+                    content
+                }
+            }))
+        }
+    }, [visible, corpUserGroups, value])
+
+
+
+    return <>
+        <Button onClick={() => setVisible(true)}>设置链接、小程序</Button>
+        {visible && <SettingsContentModal
+            corpUserGroups={corpUserGroups}
+            visible={visible}
+            value={data}
+            bookPlatForm={bookPlatForm}
+            onChange={(value) => {
+                setData(value)
+                onChange(value)
+            }}
+            onClose={() => {
+                setVisible(false)
+            }}
+        />}
+    </>
+};
+
+const SettingsContentModal: React.FC<{
+    value: any[],
+    onChange: (value: any) => void
+    onClose: () => void
+    corpUserGroups: TASK_CREATE.CorpUserGroupProps[]
+    bookPlatForm: TASK_CREATE.BookPlatFormProps[]
+    visible?: boolean
+}> = ({ visible, onClose, onChange, value, corpUserGroups, bookPlatForm }) => {
+
+    /***************************************/
+    const [data, setData] = useState<any>([])
+    const [selectAdz, setSelectAdz] = useState<number>(1)
+    /***************************************/
+
+    useEffect(() => {
+        if (visible) {
+            setData(value)
+        }
+    }, [visible, value])
+
+    const handleSelectAdz = (value: number) => {
+        if (value === selectAdz) {
+            return
+        }
+        setSelectAdz(value)
+    }
+
+    return <Modal
+        title={<strong>群发内容链接、小程序配置</strong>}
+        open={visible}
+        onCancel={onClose}
+        width={800}
+        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) => {
+                        // const bookLink = item?.bookLink
+                        return <div style={{ height: 'auto', lineHeight: 'normal', }} key={index} onClick={() => { handleSelectAdz(index + 1) }} className={`${style.accItem} ${selectAdz === index + 1 && style.select} `}>
+                            <div style={{ flexDirection: 'column', alignItems: 'flex-start', padding: '2px 0', flex: 1, overflow: 'hidden' }}>
+                                <Title ellipsis={{ tooltip: true }} level={5} style={{ margin: 0 }}>客服组{index + 1}</Title>
+                                <Paragraph ellipsis={{ tooltip: true }} style={{ margin: 0, width: '100%' }}>{corpUserGroups[index]?.corpUsers?.map(i => i.name).join('、')}</Paragraph>
+                            </div>
+                            {/* {bookLink?.length > 0 && <CheckOutlined style={{ color: '#1890ff' }} />} */}
+                            <CheckOutlined style={{ color: '#1890ff' }} />
+                        </div>
+                    })}
+                </div>
+            </div>
+            <div className={style.right}>
+                {data?.[selectAdz - 1]?.content?.map((item, index) => {
+                    return <div key={index}>
+                        {item.msgType === 'TASK_CONTENT_LINK' ? <div style={{ marginBottom: 10 }}>
+                            <Title level={5} style={{ margin: 0 }}>链接:{item?.link?.title || ''}</Title>
+                            <div style={{ display: 'flex', gap: 4, alignItems: 'flex-end' }}>
+                                <Input.TextArea placeholder="请输入链接" />
+                                {/* <SelectBookLinkButton
+                                    bookPlatForm={bookPlatForm}
+                                    mpAccountId={corpUserGroups[index]?.corpUsers?.[0]?.mpAccountId}
+                                    linkData={[item]}
+                                    onChange={(linkStr, miniprogramAppid, miniprogramPage) => {
+                                        
+                                    }}
+                                /> */}
+                            </div>
+                        </div> : <>
+                            <Title level={5} style={{ margin: 0 }}>所有小程序</Title>
+                            <Input.TextArea placeholder="请输入链接" />
+                        </>}
+                    </div>
+                })}
+            </div>
+        </div>
+    </Modal>
+}
+
+export default SettingsContent;

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

@@ -23,7 +23,7 @@ const Welcome: React.FC = () => {
     const { token } = useNewToken()
     const { setSettings, settings, bookPlatForm, bookList, onPreviewReset } = useContext(DispatchTaskCreate)!;
     const { welcomeName, welcomeMsgTagDTO, sendMode, mediaContentList } = settings?.welcomeMsgTemplateDTO || {}
-    const [newVisible, setNewVisible] = React.useState(false);
+    const [newVisible, setNewVisible] = useState<boolean>(false);
     const [downloadLoading, setDownloadLoading] = useState<boolean>(false)
     /***************************************************/
 

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

@@ -43,7 +43,7 @@ const SettingsWelcome: React.FC<TASK_CREATE.WelcomeProps<any>> = ({ visible, onC
                 },
                 { title: '完成', checked: true }
             ])
-            setStep(1)
+            // setStep(1)
             form.setFieldsValue(value)
         }
     }, [value])
@@ -124,7 +124,6 @@ const SettingsWelcome: React.FC<TASK_CREATE.WelcomeProps<any>> = ({ visible, onC
                 }}
                 onFinish={handleOk}
                 initialValues={{
-                    welcomeType: 'novel',
                     mediaContentList: [undefined]
                 }}
                 onFieldsChange={() => {

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

@@ -16,6 +16,7 @@
     margin-top: 16px;
     width: 100%;
     overflow: hidden;
+    overflow-x: auto;
     --w5: 216px;
     --w100: 100%;
 
@@ -26,6 +27,7 @@
         border-radius: 6px;
         display: flex;
         box-sizing: border-box;
+        min-width: 1400px;
 
         >div {
             display: flex;

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

@@ -110,6 +110,15 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
             return
         }
 
+        if (!settings?.bizType) {
+            message.error('请选择业务类型')
+            return
+        }
+        if (!settings?.platform) {
+            message.error('请选择书城')
+            return
+        }
+
         // 欢迎语
         if (settings?.welcomeMsgTemplateDTO && Object.keys(settings?.welcomeMsgTemplateDTO).length) {
             const welcome = []
@@ -1052,7 +1061,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         </> : key === 'massSending' ? <>
                             <Table
                                 dataSource={previewData[key]}
-                                columns={massSendingColumns(setContent, bookPlatForm, bookList, previewContent)}
+                                columns={massSendingColumns(setContent, bookPlatForm, bookList, previewContent, bookPlatForm.find(item => item.id === Number(settings?.platform)).platformKey)}
                                 rowKey={'id'}
                                 bordered={true}
                                 scroll={{ y: 550 }}
@@ -1061,7 +1070,7 @@ const Create: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookLis
                         </> : key === 'welcome' ? <>
                             <Table
                                 dataSource={previewData[key]}
-                                columns={welcomeColumns(bookPlatForm, bookList, setContent, previewContent)}
+                                columns={welcomeColumns(bookPlatForm, bookList, setContent, previewContent, bookPlatForm.find(item => item.id === Number(settings?.platform)).platformKey)}
                                 rowKey={'id'}
                                 bordered={true}
                                 scroll={{ y: 550 }}

+ 6 - 2
src/pages/weComTask/page/businessPlan/create/tableConfig.tsx

@@ -125,7 +125,7 @@ export const userInheritColumns = (setContent: (data: TASK_CREATE.SetContentProp
 }
 
 /** 群发 */
-export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProps) => void, bookPlatForm: TASK_CREATE.BookPlatFormProps[], bookList: TASK_CREATE.BookListProps[], previewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] }): ColumnsType<AnyObject> => {
+export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProps) => void, bookPlatForm: TASK_CREATE.BookPlatFormProps[], bookList: TASK_CREATE.BookListProps[], previewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] }, platform: string): ColumnsType<AnyObject> => {
     return [
         {
             title: '账号',
@@ -233,6 +233,7 @@ export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProp
                     />
                     <SelectBookLinkButton
                         bookPlatForm={bookPlatForm}
+                        platform={platform}
                         mpAccountId={record.corpUserList?.[0]?.mpAccountId}
                         linkData={record.linkData}
                         onChange={(linkStr, miniprogramAppid, miniprogramPage) => {
@@ -288,6 +289,7 @@ export const massSendingColumns = (setContent: (data: TASK_CREATE.SetContentProp
                     />
                     <SelectBookLinkButton
                         bookPlatForm={bookPlatForm}
+                        platform={platform}
                         mpAccountId={record.corpUserList?.[0]?.mpAccountId}
                         linkData={[{
                             msgType: "TASK_CONTENT_LINK",
@@ -443,7 +445,7 @@ export const highMassSendingColumns = (): ColumnsType<AnyObject> => {
 }
 
 
-export const welcomeColumns = (bookPlatForm: TASK_CREATE.BookPlatFormProps[], bookList: TASK_CREATE.BookListProps[], setContent: (data: TASK_CREATE.SetContentProps) => void, previewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] }): ColumnsType<AnyObject> => {
+export const welcomeColumns = (bookPlatForm: TASK_CREATE.BookPlatFormProps[], bookList: TASK_CREATE.BookListProps[], setContent: (data: TASK_CREATE.SetContentProps) => void, previewContent: { groupMsgContent?: any[], welcomeMsgContent?: any[], externalUserTransferContent?: any[] }, platform: string): ColumnsType<AnyObject> => {
     return [
         {
             title: '账号',
@@ -540,6 +542,7 @@ export const welcomeColumns = (bookPlatForm: TASK_CREATE.BookPlatFormProps[], bo
                     />
                     <SelectBookLinkButton
                         bookPlatForm={bookPlatForm}
+                        platform={platform}
                         mpAccountId={record.corpUserList?.[0]?.mpAccountId}
                         linkData={record.linkData.map(item => ({
                             msgType: "TASK_CONTENT_LINK",
@@ -602,6 +605,7 @@ export const welcomeColumns = (bookPlatForm: TASK_CREATE.BookPlatFormProps[], bo
                     />
                     <SelectBookLinkButton
                         bookPlatForm={bookPlatForm}
+                        platform={platform}
                         mpAccountId={record.corpUserList?.[0]?.mpAccountId}
                         linkData={[{
                             msgType: "TASK_CONTENT_LINK",

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

@@ -37,7 +37,7 @@ declare namespace TASK_CREATE {
             massSendingContent?: { massSendingContentDTO: any };
         };
         onChange?: (value?: { [x: string]: any }, type?: string) => void;
-        createType?: 'STRATEGY' | 'CONTENT'
+        createType?: 'STRATEGY' | 'CONTENT';
     }
     interface HighMassSendingProps<T> extends DefaultProps, DefaultChangeProps<T> {
         value?: {

+ 1 - 1
src/pages/weComTask/page/businessPlan/taskList/components/groupTask/groupTaskNotes.tsx

@@ -51,7 +51,7 @@ const GroupTaskNotes: React.FC<Props> = ({ corpId, taskId }) => {
             dataSource={getSendTaskMsgList?.data?.data?.records}
             loading={getSendTaskMsgList?.loading}
             columns={groupTaskNotesTableConfig(() => getSendTaskMsgList.refresh())}
-            scroll={{ x: 400, y: 350 }}
+            scroll={{ x: 400, y: 320 }}
             rowKey={(s) => {
                 return s.id
             }}

+ 1 - 1
src/pages/weComTask/page/businessPlan/taskList/components/groupTask/groupXfCorpTabls.tsx

@@ -116,7 +116,7 @@ const GroupXfCorpTabls: React.FC<Props> = ({ corpId, taskId }) => {
             dataSource={getSendTaskuserList?.data?.data?.records}
             loading={getSendTaskuserList?.loading}
             columns={groupMsgCorpUserListConfig(changeHandle)}
-            scroll={{ x: 400, y: 350 }}
+            scroll={{ x: 400, y: 320 }}
             rowKey={(s) => {
                 return s.id
             }}

+ 1 - 1
src/pages/weComTask/page/businessPlan/taskList/components/groupTask/index.tsx

@@ -190,7 +190,7 @@ export const ExpandedRow: React.FC<{ record: any }> = ({ record }) => {
                     {
                         key: '4',
                         label: '群发记录',
-                        children: <Card styles={{ body: { minHeight: 185 } }}>
+                        children: <Card styles={{ body: { minHeight: 400 } }}>
                             {activeKey == '4' && <GroupTaskNotes corpId={corpId} taskId={id} />}
                         </Card>
                     }

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

@@ -25,7 +25,7 @@ const taskListColumns = (
             title: '操作',
             dataIndex: 'cz',
             key: 'cz',
-            width: 140,
+            width: 150,
             render(_, record) {
                 return <Space>
                     <Popconfirm

+ 39 - 0
src/pages/weComTask/page/groupChat/create/components/groupUser/addGroupObject.tsx

@@ -0,0 +1,39 @@
+import { Button, Modal } from 'antd';
+import React, { useState } from 'react';
+import { PlusOutlined } from '@ant-design/icons';
+
+/**
+ * 进群对象新建组件
+ * @param param0 
+ * @returns 
+ */
+const AddGroupObject: React.FC<GROUP_CHAT_CREATE.AddGroupObjectProps> = ({ value, onChange }) => {
+
+    /******************************************/
+    const [visible, setVisible] = useState<boolean>(false)
+    /******************************************/
+
+    return <>
+        <Button type="dashed" style={{ width: '100%' }} block icon={<PlusOutlined />} onClick={() => setVisible(true)}>新建进群对象</Button>
+    </>
+};
+
+const AddGroupObjectModal: React.FC<GROUP_CHAT_CREATE.AddGroupObjectModalProps> = React.memo(({visible, onChange, onClose, value}) => {
+    
+
+    const handleOk = () => {
+        
+    }
+
+    return <Modal 
+        title={<strong>新建进群对象</strong>} 
+        open={visible} 
+        onCancel={onClose}
+        width={660}
+        onOk={handleOk}
+    > 
+
+    </Modal>
+})
+
+export default React.memo(AddGroupObject);

+ 58 - 0
src/pages/weComTask/page/groupChat/create/components/groupUser/index.tsx

@@ -0,0 +1,58 @@
+import React, { useContext, useState } from 'react';
+import style from '../../../../businessPlan/create/index.less'
+import useNewToken from '@/Hook/useNewToken';
+import { App, Button, Empty } from 'antd';
+import { DispatchGroupChatCreate } from '../..';
+import SettingsGroupUser from './settingsGroupUser';
+
+
+/**
+ * 进群对象
+ * @returns 
+ */
+const GroupUser: React.FC = () => {
+
+    /*********************************/
+    const { message } = App.useApp()
+    const { token } = useNewToken()
+    const { setSettings, settings, onPreviewReset } = useContext(DispatchGroupChatCreate)!;
+    const [newVisible, setNewVisible] = useState<boolean>(false);
+    /*********************************/
+
+
+    return <>
+        <div className={`${style.settingsBody_content_row}`} style={{width: '50%'}}>
+            <div className={`${style.settingsBody_content_col}`} style={{ width: '100%' }}>
+                <div className={style.title}>
+                    <span>群聊创建进群对象</span>
+                </div>
+                <div className={style.detail}>
+                    <div className={style.detail_title}>群聊创建进群对象配置</div>
+                    <div className={style.detail_body}>
+                        {settings?.groupUsersDTO && Object.keys(settings?.groupUsersDTO).length > 0 ? <>
+                            
+                        </> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
+                    </div>
+                </div>
+                <div className={style.detail_footer}>
+                    {settings?.strategyDTO && Object.keys(settings?.strategyDTO).length > 0 ? 
+                        <Button type="link" style={{ padding: 0, fontSize: 12, color: token.colorPrimary }} size="small" onClick={() => setNewVisible(true)}>编辑</Button> : 
+                        <Button type="link" style={{ padding: 0, fontSize: 12, color: token.colorPrimary }} size="small" onClick={() => message.error('请先编辑群聊创建策略')}>编辑</Button>}
+                </div>
+            </div>
+        </div>
+        
+        {/* 配置群聊创建进群对象 */}
+        {newVisible && <SettingsGroupUser 
+            visible={newVisible} 
+            onClose={() => setNewVisible(false)} 
+            onChange={(values) => {
+                setNewVisible(false)
+            }}
+            value={settings?.groupUsersDTO}
+            strategyDTO={settings?.strategyDTO}
+        />}
+    </>
+};
+
+export default React.memo(GroupUser);

+ 333 - 0
src/pages/weComTask/page/groupChat/create/components/groupUser/settingsGroupUser.tsx

@@ -0,0 +1,333 @@
+import { App, Button, Card, Form, Input, InputNumber, Modal, Popover, Radio, Select, Space } from "antd";
+import React, { useEffect, useState } from "react";
+import '../../../../businessPlan/create/global.less'
+import { PlusOutlined, MinusCircleOutlined, QuestionCircleFilled, RightOutlined, DownOutlined, VerticalLeftOutlined } from '@ant-design/icons';
+import PreviewTime from "@/pages/weComTask/components/previewTime";
+import FilterUser from "@/pages/weComTask/components/filterUser";
+import { getAllWxListApi } from "@/pages/weComTask/API/corpUserAssign";
+import { useAjax } from "@/Hook/useAjax";
+import MindTags from "@/pages/weComTask/components/mindTags";
+
+interface Props extends GROUP_CHAT_CREATE.FoundationProps<any> {
+    strategyDTO: { [x: string]: any }
+}
+
+// 默认进群对象
+const defaultGroupObject = { externalUserType: 'all', groupIndex: 1, groupUserCount: 37, autoOutGroup: false, excludeInGroup: true, deleteGroupTag: true }
+
+/**
+ * 群聊创建进群对象配置
+ * @param param0 
+ * @returns 
+ */
+const SettingsGroupUser: React.FC<Props> = ({ strategyDTO, visible, onClose, value, onChange }) => {
+
+
+    /***************************************/
+    const { message } = App.useApp();
+    const [form] = Form.useForm();
+    const strategyList = Form.useWatch('strategyList', form)
+    const [activeKey, setActiveKey] = useState<number[]>([])
+    const [groupObjectActiveKey, setGroupObjectActiveKey] = useState<string[]>([])
+
+    const getAccountList = useAjax(() => getAllWxListApi())
+    /***************************************/
+
+    useEffect(() => {
+        getAccountList.run()
+    }, [])
+
+    useEffect(() => {
+        form.setFieldsValue({
+            strategyList: strategyDTO?.strategyList?.map(item => {
+                return {
+                    ...item,
+                    groupObjectList: item?.groupObjectList || [defaultGroupObject]
+                }
+            })
+        })
+    }, [strategyDTO])
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+            console.log(values)
+            // onChange(data)
+        }).catch(() => {
+            form.submit()
+        });
+    };
+
+    return <Modal
+        title={<strong>群聊创建进群对象配置</strong>}
+        open={visible}
+        onCancel={onClose}
+        width={850}
+        onOk={handleOk}
+        className={`settingsModal`}
+    >
+        <div className={`body_steps`}>
+
+        </div>
+        <div className={`body_content`}>
+            <Form
+                form={form}
+                name="newGroupUser"
+                labelAlign='left'
+                labelCol={{ span: 6 }}
+                colon={false}
+                labelWrap
+                scrollToFirstError={{
+                    behavior: 'smooth',
+                    block: 'center'
+                }}
+                onFinishFailed={({ errorFields }) => {
+                    console.log('errorFields--->', errorFields)
+                    setActiveKey(data => data?.filter(item => item != errorFields?.[0]?.name?.[1]))
+                    setGroupObjectActiveKey(data => data?.filter(item => item != (errorFields?.[0]?.name?.[1] + '_' + errorFields?.[0]?.name?.[3])))
+                    message.error(errorFields?.[0]?.errors?.[0])
+                }}
+                onFinish={handleOk}
+                initialValues={{
+                    // strategyList: [{ id: Date.now() }]
+                }}
+                onFieldsChange={() => {
+                    // filedUpdateChange(form.getFieldsValue())
+                }}
+                preserve={true}
+            >
+                <Form.List name="strategyList">
+                    {(fields) => (
+                        <>
+                            {fields.map(({ key, name }, index) => {
+                                const strategyItem = strategyList[index]
+                                return <Card
+                                    key={key}
+                                    title={<Space>
+                                        <strong>策略{index + 1} {strategyItem?.strategyName}</strong>
+                                        <Popover
+                                            placement="right"
+                                            content={<div>
+                                                <PreviewTime
+                                                    {...strategyItem}
+                                                />
+                                            </div>}
+                                            styles={{ body: { width: 300, overflow: 'hidden', overflowY: 'auto', maxHeight: 400 } }}
+                                        >
+                                            <a style={{ color: '#000' }}><QuestionCircleFilled /></a>
+                                        </Popover>
+                                    </Space>}
+                                    style={{ background: '#fff', marginBottom: 10 }}
+                                    hoverable
+                                    id={`strategy_${index + 1}`}
+                                    extra={<Space>
+                                        <a
+                                            style={{ padding: 2 }}
+                                            onClick={() => {
+                                                const allKey = strategyItem?.groupObjectList?.map((_, i) => `${index}_${i}`)
+                                                setGroupObjectActiveKey(data => [...new Set([...data, ...allKey])])
+                                            }}
+                                        >
+                                            <VerticalLeftOutlined />
+                                        </a>
+                                        <a
+                                            style={{ padding: 2 }}
+                                            onClick={() => setActiveKey(data => {
+                                                if (data.includes(index)) {
+                                                    return data.filter(item => item !== index)
+                                                }
+                                                return [...new Set([...data, index])]
+                                            })}
+                                        >{activeKey.includes(index) ? <RightOutlined /> : <DownOutlined />}</a>
+                                    </Space>}
+                                    styles={{
+                                        body: {
+                                            transition: 'height 0.3s ease-in-out',
+                                            overflow: 'hidden',
+                                            height: !activeKey.includes(index) ? 'auto' : 0,
+                                            padding: !activeKey.includes(index) ? '16px' : 0
+                                        }
+                                    }}
+                                >
+                                    <Form.List name={[name, 'groupObjectList']}>
+                                        {(fields, { add, remove }) => (
+                                            <>
+                                                {fields.map(({ key, name, ...restField }, index1) => {
+                                                    const groupObjectItem = strategyItem?.groupObjectList?.[index1]
+
+                                                    return <Card
+                                                        key={key}
+                                                        title={<strong>进群对象{index1 + 1} 配置</strong>}
+                                                        style={{ background: '#fff', marginBottom: 10 }}
+                                                        id={`strategy_${index + 1}_groupObject_${index1 + 1}`}
+                                                        extra={<Space>
+                                                            {strategyItem?.groupObjectList?.length > 1 && <div
+                                                                style={{ color: 'red', cursor: 'pointer', padding: 2 }}
+                                                                onClick={() => {
+                                                                    remove(name)
+                                                                }}
+                                                            >
+                                                                <MinusCircleOutlined />
+                                                            </div>}
+                                                            <a
+                                                                style={{ padding: 2 }}
+                                                                onClick={() => setGroupObjectActiveKey(data => {
+                                                                    if (data.includes(index + '_' + index1)) {
+                                                                        return data.filter(item => item !== (index + '_' + index1))
+                                                                    }
+                                                                    return [...new Set([...data, index + '_' + index1])]
+                                                                })}
+                                                            >{groupObjectActiveKey.includes(index + '_' + index1) ? <RightOutlined /> : <DownOutlined />}</a>
+                                                        </Space>}
+                                                        styles={{
+                                                            body: {
+                                                                transition: 'height 0.3s ease-in-out',
+                                                                overflow: 'hidden',
+                                                                height: !groupObjectActiveKey.includes(index + '_' + index1) ? 'auto' : 0,
+                                                                padding: !groupObjectActiveKey.includes(index + '_' + index1) ? '16px' : 0
+                                                            }
+                                                        }}
+                                                    >
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'groupObjectName']}
+                                                            label={<strong>进群对象名称</strong>}
+                                                            rules={[{ required: true, message: '请输入进群对象名称!' }]}
+                                                        >
+                                                            <Input placeholder='请输入进群对象名称' allowClear style={{ width: 358 }} />
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            label={<strong>进群对象配置</strong>}
+                                                            required
+                                                        >
+                                                            <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'flex-start' }}>
+                                                                <Form.Item
+                                                                    {...restField}
+                                                                    name={[name, 'externalUserType']}
+                                                                    rules={[{ required: true, message: '请选择转移对象!' }]}
+                                                                    noStyle
+                                                                >
+                                                                    <Radio.Group options={[{ label: '全部', value: 'all' }, { label: '指定', value: 'specify' }]} />
+                                                                </Form.Item>
+                                                                {groupObjectItem?.externalUserType === 'specify' && <div style={{ marginTop: 8, width: '100%' }}>
+                                                                    <Form.Item
+                                                                        {...restField}
+                                                                        name={[name, 'externalUserFilter']}
+                                                                        rules={[{ required: true, message: '请选择人群包!' }]}
+                                                                        noStyle
+                                                                    >
+                                                                        <FilterUser configType={'USER_GROUP'} />
+                                                                    </Form.Item>
+                                                                </div>}
+                                                            </div>
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'groupIndex']}
+                                                            tooltip={{ title: `例如:起始编号为'1'群名为'测试群',再建群后群名为'测试群1'超出群人数的用户将分配到'测试群2'依次递增`, placement: 'top' }}
+                                                            label={<strong>群递增起始编号</strong>}
+                                                            rules={[{ required: true, message: '请输入群递增起始编号!' }]}
+                                                        >
+                                                            <InputNumber placeholder='请输入群递增起始编号' min={1} style={{ width: 358 }} />
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'groupUserCount']}
+                                                            tooltip={{ title: `不包括建群人和固定企微号,最大上限数量38`, placement: 'top' }}
+                                                            label={<strong>群固定人数</strong>}
+                                                            rules={[{ required: true, message: '请输入群固定人数!' }]}
+                                                        >
+                                                            <InputNumber placeholder='请输入群固定人数' max={38} min={1} style={{ width: 358 }} />
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'autoOutGroup']}
+                                                            label={<strong>邀请客户进群完毕后客服号是否退群</strong>}
+                                                            rules={[{ required: true, message: '请选择是否退群!' }]}
+                                                        >
+                                                            <Radio.Group>
+                                                                <Radio value={true}>是</Radio>
+                                                                <Radio value={false}>否</Radio>
+                                                            </Radio.Group>
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'excludeInGroup']}
+                                                            label={<strong>是否排除已在群的客户</strong>}
+                                                            rules={[{ required: true, message: '请选择是否排除已在群的客户!' }]}
+                                                        >
+                                                            <Radio.Group>
+                                                                <Radio value={true}>是</Radio>
+                                                            </Radio.Group>
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'deleteGroupTag']}
+                                                            label={<strong>拉群完成后自动删除拉群标签</strong>}
+                                                            rules={[{ required: true, message: '请选择拉群完成后自动删除拉群标签!' }]}
+                                                        >
+                                                            <Radio.Group>
+                                                                <Radio value={true}>是</Radio>
+                                                            </Radio.Group>
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'weChatAppid']}
+                                                            label={<strong>群聊关联公众号</strong>}
+                                                        >
+                                                            <Select
+                                                                showSearch
+                                                                style={{ width: 358 }}
+                                                                allowClear
+                                                                placeholder="选择公众号"
+                                                                filterOption={(input, option) =>
+                                                                    (option?.label as any)?.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                                                                }
+                                                                options={getAccountList?.data?.data?.map(item => ({ label: item.name, value: item.appId }))}
+                                                            />
+                                                        </Form.Item>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'remark']}
+                                                            label={<strong>拉群完成后群聊备注</strong>}
+                                                        >
+                                                            <Input.TextArea placeholder="请输入群聊备注" style={{ width: 358 }} />
+                                                        </Form.Item>
+
+                                                        <Card title={<strong>拉群完成后群聊智能标签</strong>} style={{ background: '#fff', marginBottom: 10 }} styles={{ body: { padding: '6px 0 6px 16px' } }}>
+                                                            <Form.Item
+                                                                {...restField}
+                                                                name={[name, 'tagDTO']}
+                                                                style={{ marginBottom: 0 }}
+                                                            >
+                                                                <MindTags />
+                                                            </Form.Item>
+                                                        </Card>
+                                                        <Form.Item
+                                                            {...restField}
+                                                            name={[name, 'groupSendMsg']}
+                                                            label={<strong>建群成功发送内容</strong>}
+                                                            rules={[{ required: true, message: '请输入建群成功发送内容!' }]}
+                                                        >
+                                                            <Input.TextArea placeholder="请输入建群成功发送内容" style={{ width: 358 }} />
+                                                        </Form.Item>
+                                                    </Card>
+                                                })}
+                                                <Form.Item>
+                                                    <Button type="dashed" onClick={() => add(defaultGroupObject)} block icon={<PlusOutlined />}>
+                                                        新增进群对象
+                                                    </Button>
+                                                </Form.Item>
+                                            </>
+                                        )}
+                                    </Form.List>
+                                </Card>
+                            })}
+                        </>
+                    )}
+                </Form.List>
+            </Form>
+        </div>
+    </Modal>
+}
+
+export default React.memo(SettingsGroupUser);

+ 60 - 0
src/pages/weComTask/page/groupChat/create/components/strategy/index.tsx

@@ -0,0 +1,60 @@
+import React, { useContext, useState } from 'react';
+import style from '../../../../businessPlan/create/index.less'
+import useNewToken from '@/Hook/useNewToken';
+import { App, Button, Empty } from 'antd';
+import { DispatchGroupChatCreate } from '../..';
+import SettingsStrategy from './settingsStrategy';
+import PreviewStrategy from './previewStrategy';
+
+
+/** 基础执行时间配置 */
+const Strategy: React.FC = () => {
+
+    /*********************************/
+    const { message } = App.useApp()
+    const { token } = useNewToken()
+    const { setSettings, settings, onPreviewReset } = useContext(DispatchGroupChatCreate)!;
+    const [newVisible, setNewVisible] = useState<boolean>(false);
+    /*********************************/
+
+
+    return <>
+        <div className={`${style.settingsBody_content_row}`} style={{ width: '50%' }}>
+            <div className={`${style.settingsBody_content_col}`} style={{ width: '100%' }}>
+                <div className={style.title}>
+                    <span>群聊创建策略</span>
+                </div>
+                <div className={style.detail}>
+                    <div className={style.detail_title}>群聊创建策略配置</div>
+                    <div className={style.detail_body}>
+                        {settings?.strategyDTO && Object.keys(settings?.strategyDTO).length > 0 ? <>
+                            <PreviewStrategy strategyDTO={settings?.strategyDTO}/>
+                        </> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />}
+                    </div>
+                </div>
+                <div className={style.detail_footer}>
+                    <Button type="link" style={{ padding: 0, fontSize: 12, color: token.colorPrimary }} size="small" onClick={() => setNewVisible(true)}>编辑</Button>
+                </div>
+            </div>
+        </div>
+
+        {/* 配置基础信息 */}
+        {newVisible && <SettingsStrategy
+            visible={newVisible}
+            value={settings?.strategyDTO}
+            onClose={() => {
+                setNewVisible(false);
+            }}
+            onChange={(values) => {
+                setSettings({
+                    ...settings,
+                    strategyDTO: values
+                });
+                onPreviewReset();
+                setNewVisible(false);
+            }}
+        />}
+    </>
+};
+
+export default React.memo(Strategy);

+ 86 - 0
src/pages/weComTask/page/groupChat/create/components/strategy/previewStrategy.tsx

@@ -0,0 +1,86 @@
+import React, { useEffect } from 'react';
+import dayjs from 'dayjs';
+import { Card, Form, Input } from 'antd';
+import SendTimeSet from '@/pages/weComTask/components/sendTimeSet';
+import '../../../../businessPlan/create/global.less'
+
+interface Props {
+    strategyDTO: { [x: string]: any }
+}
+
+const PreviewStrategy: React.FC<Props> = ({ strategyDTO }) => {
+
+    /**************************************/
+    const [form] = Form.useForm();
+    const strategyList = Form.useWatch('strategyList', form)
+    /**************************************/
+
+    useEffect(() => {
+        if (strategyDTO && Object.keys(strategyDTO).length) {
+            const data = {
+                ...strategyDTO, strategyList: strategyDTO?.strategyList?.map(item => {
+                    const { sendTime, startTime, endTime, sendDay, timeRepeatType } = item
+                    if (timeRepeatType === 'TIME_TYPE_SINGLE_PLACE') {
+                        return {
+                            ...item,
+                            timeRepeatType,
+                            sendDay: sendDay ? dayjs(sendDay + ' ' + sendTime) : undefined
+                        }
+                    }
+                    return {
+                        ...item,
+                        timeRepeatType,
+                        sendTime: sendTime ? dayjs('2025-04-25 ' + sendTime) : undefined,
+                        startTime: startTime ? dayjs(startTime) : undefined,
+                        endTime: endTime ? dayjs(endTime) : undefined,
+                        sendDay: sendDay ? dayjs(sendDay) : undefined
+                    }
+                })
+            }
+            form.setFieldsValue(data)
+        }
+    }, [strategyDTO])
+
+    return <Form
+        form={form}
+        name="newGroupChatStrategyShow"
+        labelAlign='left'
+        labelCol={{ span: 5 }}
+        colon={false}
+        preserve={true}
+    >
+        <Card title={<strong>基础信息配置</strong>} style={{ background: '#fff', marginBottom: 10 }} id='basicInfo'>
+            <Form.Item label={<strong>任务名称</strong>} name="taskName">
+                <Input placeholder="请输入任务名称" />
+            </Form.Item>
+        </Card>
+        <Form.List name="strategyList">
+            {(fields) => (
+                <>
+                    {fields.map(({ key, name, ...restField }, index) => {
+                        const timeRepeatType = strategyList?.[index]?.timeRepeatType
+                        return <Card
+                            key={key}
+                            title={<strong>策略{index + 1} 配置</strong>}
+                            style={{ background: '#fff', marginBottom: 10 }}
+                            id={`strategy_${index + 1}`}
+                        >
+                            <div className='block_tm'>
+                                <Form.Item
+                                    {...restField}
+                                    name={[name, 'strategyName']}
+                                    label={<strong>策略名称</strong>}
+                                >
+                                    <Input placeholder='请输入策略名称' allowClear />
+                                </Form.Item>
+                                <SendTimeSet isShow active='all' form={form} restField={restField} name={name} timeRepeatType={timeRepeatType} />
+                            </div>
+                        </Card>
+                    })}
+                </>
+            )}
+        </Form.List>
+    </Form>
+};
+
+export default React.memo(PreviewStrategy);

+ 196 - 0
src/pages/weComTask/page/groupChat/create/components/strategy/settingsStrategy.tsx

@@ -0,0 +1,196 @@
+import { App, Button, Card, Form, Input, Modal } from 'antd';
+import React, { useEffect, useRef, useState } from 'react';
+import '../../../../businessPlan/create/global.less'
+import NewSteps from '@/pages/weComTask/components/newSteps';
+import { PlusOutlined, MinusCircleOutlined } from '@ant-design/icons';
+import SendTimeSet from '@/pages/weComTask/components/sendTimeSet';
+import dayjs from 'dayjs';
+
+/**
+ * 群聊创建策略配置
+ * @param param0 
+ * @returns 
+ */
+const SettingsStrategy: React.FC<GROUP_CHAT_CREATE.FoundationProps<any>> = ({ visible, onClose, value, onChange }) => {
+
+    /************************************/
+    const { message } = App.useApp()
+    const ref1 = useRef<HTMLDivElement>(null)
+    const [form] = Form.useForm();
+    const strategyList = Form.useWatch('strategyList', form)
+
+    const [stepsList, setStepsList] = useState<any>([
+        { title: '群聊创建配置', description: '任务名称', id: 'basicInfo' },
+        { title: '策略配置', children: [{ title: `策略${1}`, id: 'strategy_1' }] },
+        { title: '完成' }
+    ])
+    /************************************/
+
+    // 回填
+    useEffect(() => {
+        if (value && Object.keys(value).length) {
+            const data = {
+                ...value, strategyList: value?.strategyList?.map(item => {
+                    const { sendTime, startTime, endTime, sendDay, timeRepeatType } = item
+                    if (timeRepeatType === 'TIME_TYPE_SINGLE_PLACE') {
+                        return {
+                            ...item,
+                            timeRepeatType,
+                            sendDay: sendDay ? dayjs(sendDay + ' ' + sendTime) : undefined
+                        }
+                    }
+                    return {
+                        ...item,
+                        timeRepeatType,
+                        sendTime: sendTime ? dayjs('2025-04-25 ' + sendTime) : undefined,
+                        startTime: startTime ? dayjs(startTime) : undefined,
+                        endTime: endTime ? dayjs(endTime) : undefined,
+                        sendDay: sendDay ? dayjs(sendDay) : undefined
+                    }
+                })
+            }
+            filedUpdateChange(data)
+            form.setFieldsValue(data)
+        }
+    }, [value])
+
+    const handleOk = () => {
+        form.validateFields().then((values) => {
+            const data = {
+                ...values,
+                strategyList: values?.strategyList?.map(item => {
+                    const { startTime, endTime, sendDay, sendTime, timeRepeatType, repeatArray, ...rest } = item
+                    const data = { ...rest, timeRepeatType }
+                    if (timeRepeatType === 'TIME_TYPE_SINGLE_PLACE') {
+                        // 定时发送
+                        data.sendDay = dayjs(sendDay).format('YYYY-MM-DD')
+                        data.sendTime = dayjs(sendDay).format('HH:mm:ss')
+                    } else if (timeRepeatType === 'TIME_TYPE_REPEAT_DAY') {
+                        // 每日循环
+                        data.startTime = dayjs(startTime).format('YYYY-MM-DD')
+                        if (endTime) {
+                            data.endTime = dayjs(endTime).format('YYYY-MM-DD')
+                        }
+                        data.sendTime = dayjs(sendTime).format('HH:mm:ss')
+                    } else if (timeRepeatType === 'TIME_TYPE_REPEAT_WEEK' || timeRepeatType === 'TIME_TYPE_REPEAT_MONTH') {
+                        // 每周循环、每月循环
+                        data.startTime = dayjs(startTime).format('YYYY-MM-DD')
+                        data.sendTime = dayjs(sendTime).format('HH:mm:ss')
+                        if (endTime) {
+                            data.endTime = dayjs(endTime).format('YYYY-MM-DD')
+                        }
+                        data.repeatArray = repeatArray
+                    }
+                    return data
+                })
+            }
+            onChange(data)
+        }).catch(() => {
+            form.submit()
+        });
+    };
+
+    const filedUpdateChange = ({ taskName, strategyList }: any) => {
+        const strategyChildren = strategyList?.map((item, index) => {
+            const { strategyName, timeRepeatType, sendDay, startTime, sendTime, repeatArray } = item
+            const sendTimeChecked =
+                timeRepeatType === "TIME_TYPE_SINGLE_TIMELY" ||
+                (timeRepeatType === "TIME_TYPE_SINGLE_PLACE" && sendDay) ||
+                (timeRepeatType === "TIME_TYPE_REPEAT_DAY" && startTime && sendTime) ||
+                ((timeRepeatType === "TIME_TYPE_REPEAT_WEEK" || timeRepeatType === "TIME_TYPE_REPEAT_MONTH") && startTime && sendTime && repeatArray)
+            return { title: `策略${index + 1}`, description: `策略名称、执行时间`, id: `strategy_${index + 1}`, checked: sendTimeChecked && strategyName }
+        })
+        const stepsData = [
+            { title: '群聊创建配置', description: '任务名称', id: 'basicInfo', checked: taskName },
+            { title: '策略配置', children: strategyChildren, checked: strategyChildren.some(item => item.checked) },
+            {
+                title: '完成', checked: strategyChildren.some(item => item.checked) && taskName
+            }
+        ]
+        setStepsList(stepsData)
+    }
+
+    return <Modal
+        title={<strong>群聊创建策略配置  &nbsp;&nbsp;&nbsp;<span style={{ color: 'red' }}>对于执行时间冲突的策略,按照策略的排序执行</span></strong>}
+        open={visible}
+        onCancel={onClose}
+        width={850}
+        onOk={handleOk}
+        className={`settingsModal`}
+    >
+        <div className={`body_steps`}>
+            <NewSteps
+                items={stepsList}
+                onChange={(e) => {
+                    if (e?.id)
+                        ref1.current?.querySelector('#' + e?.id)?.scrollIntoView({ behavior: 'smooth' })
+                }}
+            />
+        </div>
+        <div className={`body_content`} ref={ref1}>
+            <Form
+                form={form}
+                name="newGroupChatStrategy"
+                labelAlign='left'
+                labelCol={{ span: 5 }}
+                colon={false}
+                scrollToFirstError={{
+                    behavior: 'smooth',
+                    block: 'center'
+                }}
+                onFinishFailed={({ errorFields }) => {
+                    message.error(errorFields?.[0]?.errors?.[0])
+                }}
+                onFinish={handleOk}
+                initialValues={{
+                    strategyList: [{ id: Date.now() }]
+                }}
+                onFieldsChange={() => {
+                    filedUpdateChange(form.getFieldsValue())
+                }}
+                preserve={true}
+            >
+                <Card title={<strong>基础信息配置</strong>} style={{ background: '#fff', marginBottom: 10 }} id='basicInfo'>
+                    <Form.Item label={<strong>任务名称</strong>} name="taskName" rules={[{ required: true, message: '请输入任务名称!' }]}>
+                        <Input placeholder="请输入任务名称" style={{ width: 358 }} allowClear />
+                    </Form.Item>
+                </Card>
+                <Form.List name="strategyList">
+                    {(fields, { add, remove }) => (
+                        <>
+                            {fields.map(({ key, name, ...restField }, index) => {
+                                const timeRepeatType = strategyList?.[index]?.timeRepeatType
+                                return <Card
+                                    key={key}
+                                    title={<strong>策略{index + 1} 配置</strong>}
+                                    style={{ background: '#fff', marginBottom: 10 }}
+                                    extra={strategyList?.length > 1 && <div style={{ color: 'red', cursor: 'pointer' }} onClick={() => remove(name)}>
+                                        <MinusCircleOutlined />
+                                    </div>}
+                                    id={`strategy_${index + 1}`}
+                                >
+                                    <Form.Item
+                                        {...restField}
+                                        name={[name, 'strategyName']}
+                                        label={<strong>策略名称</strong>}
+                                        rules={[{ required: true, message: '请输入策略名称!' }]}
+                                    >
+                                        <Input placeholder='请输入策略名称' allowClear style={{ width: 358 }} />
+                                    </Form.Item>
+                                    <SendTimeSet active='all' form={form} restField={restField} name={name} timeRepeatType={timeRepeatType} />
+                                </Card>
+                            })}
+                            <Form.Item>
+                                <Button type="dashed" onClick={() => add({ id: Date.now() })} block icon={<PlusOutlined />}>
+                                    新增策略
+                                </Button>
+                            </Form.Item>
+                        </>
+                    )}
+                </Form.List>
+            </Form>
+        </div>
+    </Modal>
+};
+
+export default React.memo(SettingsStrategy);

+ 176 - 0
src/pages/weComTask/page/groupChat/create/index.tsx

@@ -0,0 +1,176 @@
+import React, { useEffect, useState } from 'react';
+import style from '../../businessPlan/create/index.less'
+import { App, Button, Card, Input, Popconfirm, Select, Space, Spin } from 'antd';
+import { welcomeMsgJobTypeApi } from '@/pages/weComTask/API/weMaterial/weMaterial';
+import { useAjax } from '@/Hook/useAjax';
+import { inject, observer } from 'mobx-react';
+import { toJS } from 'mobx';
+import Strategy from './components/strategy';
+import GroupUser from './components/groupUser';
+import { SaveOutlined, RedoOutlined, SearchOutlined } from '@ant-design/icons';
+
+export const DispatchGroupChatCreate = React.createContext<GROUP_CHAT_CREATE.DispatchGroupChatCreate | null>(null);
+
+/**
+ * 群聊任务创建组件
+ * @returns 
+ */
+const GroupChatCreate: React.FC<{ weComTaskStore: { data: { bookList: TASK_CREATE.BookListProps[], bookPlatForm: TASK_CREATE.BookPlatFormProps[] } } }> = ({ weComTaskStore }) => {
+
+    /***********************************************/
+    const { bookList, bookPlatForm } = toJS(weComTaskStore.data)
+    const { message } = App.useApp()
+
+    const [settings, setSettings] = useState<GROUP_CHAT_CREATE.SettingsProps>();
+    const [msgJobTypeList, setMsgJobTypeList] = useState<{ value: string, label: string }[]>([])
+    const [previewData, setPreviewData] = useState<any>({})
+    const [previewDataOld, setPreviewDataOld] = useState<any>({})
+
+    const welcomeMsgJobType = useAjax(() => welcomeMsgJobTypeApi())//获取业务类型
+    /***********************************************/
+    console.log('settings--->', settings)
+
+    useEffect(() => {
+        const projectId = undefined //sessionStorage.getItem('OFFICIALTASKID')
+        if (projectId) {
+            
+        } else {
+            const task = localStorage.getItem('TASK_GROUP_CHAT_CREATE')
+            if (task) {
+                setSettings(JSON.parse(task).settings)
+            }
+        }
+    }, [])
+
+    useEffect(() => {
+        welcomeMsgJobType.run().then(res => {
+            if (res?.data) {
+                setMsgJobTypeList(Object.keys(res.data).map(key => ({ value: key, label: res.data[key] })))
+            }
+        })
+    }, [])
+
+
+    const severBd = () => {
+        localStorage.setItem('TASK_GROUP_CHAT_CREATE', JSON.stringify({ settings }))
+        message.success('存储成功')
+    }
+
+    // 重置表格
+    const onPreviewReset = () => {
+
+    }
+
+
+    return <div className={style.create}>
+        <Spin spinning={false}>
+            <Card title={<strong>配置区</strong>} className={`${style.card} ${style.config}`}>
+                <Space wrap>
+                    <Space.Compact>
+                        <Button>业务类型</Button>
+                        <Select
+                            showSearch
+                            style={{ width: 120 }}
+                            allowClear
+                            placeholder="请选择类型"
+                            filterOption={(input, option) =>
+                                ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                            }
+                            value={settings?.bizType}
+                            onChange={(e) => {
+                                setSettings({ ...settings, bizType: e })
+                                onPreviewReset()
+                            }}
+                            options={msgJobTypeList.filter(item => item.value === 'novel')}
+                        />
+                    </Space.Compact>
+
+                    {settings?.bizType === 'novel' ? <>
+                        <Space.Compact>
+                            <Button>书城</Button>
+                            <Select
+                                showSearch
+                                allowClear
+                                placeholder="请选择书城"
+                                style={{ width: 120 }}
+                                filterOption={(input, option) =>
+                                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                                }
+                                value={settings?.platform}
+                                onChange={(e) => {
+                                    setSettings({ ...settings, platform: e })
+                                    onPreviewReset()
+                                }}
+                                options={bookPlatForm.map(item => ({ value: item.id, label: item.platformName }))}
+                            />
+                        </Space.Compact>
+                        <Space.Compact>
+                            <Button>适用产品</Button>
+                            <Select
+                                showSearch
+                                style={{ width: 150 }}
+                                allowClear
+                                placeholder="请选择模板适用产品"
+                                filterOption={(input, option) =>
+                                    ((option?.label ?? '') as string).toLowerCase().includes(input.toLowerCase())
+                                }
+                                value={settings?.templateProductId}
+                                onChange={(e) => {
+                                    setSettings({ ...settings, templateProductId: e })
+                                    onPreviewReset()
+                                }}
+                                options={bookList.map(item => ({ value: item.id, label: item.bookName }))}
+                            />
+                        </Space.Compact>
+                    </> : settings?.bizType === 'game' ? <Space.Compact>
+                        <Button>游戏渠道</Button>
+                        <Input
+                            style={{ width: 200 }}
+                            allowClear
+                            placeholder="请输入游戏渠道"
+                            value={settings.channel}
+                            onChange={(e) => {
+                                setSettings({ ...settings, channel: e.target.value })
+                                onPreviewReset()
+                            }}
+                        />
+                    </Space.Compact> : undefined}
+                </Space>
+
+                <div className={style.settingsBody}>
+                    <div className={style.settingsBody_content}>
+                        <DispatchGroupChatCreate.Provider
+                            value={{
+                                settings, setSettings,
+                                onPreviewReset
+                            }}
+                        >
+                            {/* 策略配置 */}
+                            <Strategy />
+                            {/* 进群对象 */}
+                            <GroupUser />
+                        </DispatchGroupChatCreate.Provider>
+                    </div>
+                </div>
+
+                <Space className={style.bts} wrap>
+                    <Button icon={<SaveOutlined />} onClick={severBd}>存为预设</Button>
+                    <Popconfirm
+                        title="确定清空?"
+                        onConfirm={() => {
+                            setSettings(undefined)
+                            setPreviewData({})
+                            setPreviewDataOld({})
+                            localStorage.removeItem('TASK_GROUP_CHAT_CREATE')
+                        }}
+                    >
+                        <Button icon={<RedoOutlined />} danger>清空配置/预设</Button>
+                    </Popconfirm>
+                    {/* <Button type='primary' onClick={preview}><SearchOutlined />预览任务/配置内容</Button> */}
+                </Space>
+            </Card>
+        </Spin>
+    </div>
+};
+
+export default inject('store')(observer((props: any) => GroupChatCreate(props.store)))

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

@@ -0,0 +1,35 @@
+declare namespace GROUP_CHAT_CREATE {
+    interface corpUsersProps {
+        corpUserId: string,
+        name: string,
+        corpName: string,
+        corpId: string,
+    }
+    interface SettingsProps {
+        corpUsers?: corpUsersProps[]; // 企微号列表
+        bizType?: string; // 业务类型
+        platform?: string; // 书城
+        channel?: string;   // 渠道
+        templateProductId?: string; // 适用产品
+        strategyDTO?: { [x: string]: any };
+        groupUsersDTO?: { [x: string]: any };
+    }
+    interface DispatchGroupChatCreate {
+        settings: SettingsProps
+        setSettings: React.Dispatch<React.SetStateAction<SettingsProps>>
+        onPreviewReset: () => void
+    }
+    interface FoundationProps<T> extends TASK_CREATE.DefaultProps, TASK_CREATE.DefaultChangeProps<T> {
+        value?: { [x: string]: any };
+    }
+    interface AddGroupObjectProps {
+        value?: { [x: string]: any };
+        onChange?: (value: any) => void;
+    }
+    interface AddGroupObjectModalProps {
+        value?: { [x: string]: any };
+        onChange?: (value: any) => void;
+        visible?: boolean;
+        onClose?: () => void;
+    }
+}

+ 1 - 0
src/public/svg/pa.svg

@@ -0,0 +1 @@
+<svg viewBox="64 64 896 896" focusable="false" data-icon="fund-view" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M832 736v-64a80 80 0 0 0-160 0v64a64.19 64.19 0 0 0-64 64v96a64.19 64.19 0 0 0 64 64h160a64.19 64.19 0 0 0 64-64v-96a64.19 64.19 0 0 0-64-64z m-32 0h-96v-64a48 48 0 0 1 96 0z" fill="currentColor" p-id="5332"></path><path d="M934.28 442.85l-97.59-19.52a32.13 32.13 0 0 1-23.86-20.62Q808 389.37 802 376.59a32.15 32.15 0 0 1 2.28-31.48l55.21-82.81a32 32 0 0 0-4-40.38l-53.41-53.41a32 32 0 0 0-40.38-4l-82.81 55.21a32.15 32.15 0 0 1-31.48 2.28q-12.77-6-26.13-10.82a32.13 32.13 0 0 1-20.62-23.86l-19.52-97.6A32 32 0 0 0 549.77 64h-75.54a32 32 0 0 0-31.38 25.72l-19.52 97.59a32.13 32.13 0 0 1-20.62 23.86Q389.37 216 376.59 222a32.15 32.15 0 0 1-31.48-2.28l-82.81-55.21a32 32 0 0 0-40.38 4l-53.41 53.41a32 32 0 0 0-4 40.38l55.21 82.81a32.15 32.15 0 0 1 2.28 31.48q-6 12.77-10.82 26.13a32.13 32.13 0 0 1-23.86 20.62l-97.6 19.51A32 32 0 0 0 64 474.23v75.53a32 32 0 0 0 25.72 31.38l97.59 19.52a32.13 32.13 0 0 1 23.86 20.62Q216 634.63 222 647.41a32.15 32.15 0 0 1-2.28 31.48l-55.21 82.81a32 32 0 0 0 4 40.38l53.41 53.41a32 32 0 0 0 40.38 4l82.81-55.21a32.15 32.15 0 0 1 31.48-2.28q12.77 6 26.13 10.82a32.13 32.13 0 0 1 20.62 23.86l19.52 97.59A32 32 0 0 0 474.23 960h75.53A32 32 0 0 0 576 946.32v-253.2a191.7 191.7 0 1 1 124.24-143A219.59 219.59 0 0 1 752 544c52.64 0 99.88 18.25 132.13 47.17l50.15-10a32 32 0 0 0 25.72-31.4v-75.54a32 32 0 0 0-25.72-31.38z" fill="currentColor" p-id="5333"></path></svg>