wjx 1 rok pred
rodič
commit
09cb0ed4c0
88 zmenil súbory, kde vykonal 50 pridanie a 13342 odobranie
  1. 0 178
      src/Hook/useIndexDB.tsx
  2. 0 30
      src/components/Alink/index.less
  3. 0 171
      src/components/Alink/index.tsx
  4. 0 59
      src/components/BatchAddLabel/index.tsx
  5. 0 26
      src/components/CityCascader/index.tsx
  6. 0 246
      src/components/Editor/AudioUploader.js
  7. 0 299
      src/components/Editor/Box/TEditor.tsx
  8. 0 32
      src/components/Editor/Box/UEditor.tsx
  9. 0 149
      src/components/Editor/Box/editorPlugin.tsx
  10. 0 25
      src/components/Editor/Box/index.less
  11. 0 526
      src/components/Editor/Box/index.tsx
  12. 0 22
      src/components/Editor/Button.js
  13. 0 25
      src/components/Editor/Input.js
  14. 0 24
      src/components/Editor/Label.js
  15. 0 101
      src/components/Editor/Link.js
  16. 0 57
      src/components/Editor/Modal.js
  17. 0 472
      src/components/Editor/ReactUeditor.js
  18. 0 22
      src/components/Editor/Select.js
  19. 0 45
      src/components/Editor/Tag.js
  20. 0 38
      src/components/Editor/Upload.js
  21. 0 247
      src/components/Editor/VideoUploader.js
  22. 0 1
      src/components/Editor/index.d.ts
  23. 0 3
      src/components/Editor/index.js
  24. 0 20
      src/components/Editor/utils.js
  25. 0 23
      src/components/FansSelect/index.less
  26. 0 681
      src/components/FansSelect/index.tsx
  27. 0 166
      src/components/Formitem/index.less
  28. 0 403
      src/components/Formitem/index.tsx
  29. 0 60
      src/components/Formitem/type.ts
  30. 0 23
      src/components/HeaderSearch/index.less
  31. 0 102
      src/components/HeaderSearch/index.tsx
  32. 0 110
      src/components/MaterialModal/db.less
  33. 0 268
      src/components/MaterialModal/graphic.less
  34. 0 81
      src/components/MaterialModal/index.less
  35. 0 182
      src/components/MaterialModal/index.tsx
  36. 0 409
      src/components/MaterialModal/modalBox.tsx
  37. 0 104
      src/components/MaterialModal/mphnews.less
  38. 0 110
      src/components/MaterialModal/mpnews.less
  39. 0 471
      src/components/MaterialModal/msgWxGraphicListModal.tsx
  40. 0 102
      src/components/MaterialModal/msgWxLeft.tsx
  41. 0 97
      src/components/MaterialModal/previewLocalModal.tsx
  42. 0 359
      src/components/MaterialModal/previewModal.tsx
  43. 0 250
      src/components/MaterialModal/smModalBox.tsx
  44. 0 136
      src/components/MaterialModal/synthetic.less
  45. 0 148
      src/components/MaterialModal/synthetic.tsx
  46. 0 334
      src/components/MaterialModal/text.less
  47. 0 443
      src/components/MaterialModal/textModal.tsx
  48. 0 6
      src/components/MaterialModal/updata.less
  49. 0 227
      src/components/MaterialModal/updata.tsx
  50. 0 291
      src/components/MaterialModal/wxGraphicListModal.tsx
  51. 0 239
      src/components/MaterialModal/wxGraphicModal.tsx
  52. 0 101
      src/components/MaterialModal/wxHistorBD.tsx
  53. 0 188
      src/components/MaterialModal/wxModalBox.tsx
  54. 0 153
      src/components/MaterialModal/wxMpnews.tsx
  55. 0 125
      src/components/NoticeIcon/NoticeIcon.tsx
  56. 0 103
      src/components/NoticeIcon/NoticeList.less
  57. 0 112
      src/components/NoticeIcon/NoticeList.tsx
  58. 0 35
      src/components/NoticeIcon/index.less
  59. 0 158
      src/components/NoticeIcon/index.tsx
  60. 0 18
      src/components/TagSelect/index.less
  61. 0 99
      src/components/TagSelect/index.tsx
  62. 0 22
      src/components/UpImg/index.less
  63. 0 62
      src/components/UpImg/index.tsx
  64. 0 31
      src/components/WeChatImgCard/index.less
  65. 0 183
      src/components/WeChatImgCard/index.tsx
  66. 0 262
      src/components/WxDetailsBox/index.less
  67. 0 378
      src/components/WxDetailsBox/index.tsx
  68. 0 35
      src/components/WxSelect/index.tsx
  69. 0 96
      src/models/useOperating/useAccountyyb.ts
  70. 0 12
      src/models/useOperating/useAdCensus.ts
  71. 0 263
      src/models/useOperating/useAservice.ts
  72. 0 65
      src/models/useOperating/useAtemplate.ts
  73. 0 30
      src/models/useOperating/useDB.tsx
  74. 0 64
      src/models/useOperating/useExamine.ts
  75. 0 124
      src/models/useOperating/useFans.ts
  76. 0 309
      src/models/useOperating/useInteract.ts
  77. 0 209
      src/models/useOperating/useMaterialContent.ts
  78. 0 218
      src/models/useOperating/useNews.ts
  79. 0 64
      src/models/useOperating/useOperate.ts
  80. 9 2
      src/pages/gameDataStatistics/allSurvey/index.tsx
  81. 0 610
      src/pages/gameDataStatistics/components/TableData/indexTab.tsx
  82. 1 1
      src/pages/gameDataStatistics/rankingList/game/index.tsx
  83. 34 0
      src/services/gameData/allSurvey.ts
  84. 6 4
      src/services/gameData/rankingList.ts
  85. 0 155
      src/services/operating/fans.ts
  86. 0 107
      src/services/operating/interact.ts
  87. 0 280
      src/services/operating/news.ts
  88. 0 21
      src/services/operating/qqAuth.ts

+ 0 - 178
src/Hook/useIndexDB.tsx

@@ -1,178 +0,0 @@
-import { message } from "antd"
-import { useCallback, useEffect, useState } from "react"
-import { useModel } from "umi"
-
-function useIndexDB() {
-    const [myDB, setMyDB] = useState<IDBDatabase>()
-    const [data, setData] = useState<any>([])
-    const [total, setTotal] = useState<any>(0)
-    const { dispatch } = useModel('useOperating.useDB')
-    /*新建或者打开数据库*/
-    const createDB = useCallback(() => {
-        let db: IDBDatabase | null = null
-        let request = window.indexedDB.open('temporaryNews', 1) //打开数据库或新建数据库
-        request.onupgradeneeded = function (event: any) {//数据库不存在和更新都会触发这个事件
-            console.log('更新')
-            db = event?.target?.result
-            let objectStore: IDBObjectStore | undefined;
-            if (!db?.objectStoreNames.contains('news')) {//假如news表不存在
-                objectStore = db?.createObjectStore('temporaryNews', { autoIncrement: true });//创建news表,自动生成主键
-                objectStore?.createIndex('knewsLink', 'knewsLink', { unique: false });//新建索引
-                objectStore?.createIndex('title', 'title', { unique: false });
-                objectStore?.createIndex('knewsThumbUrl', 'knewsThumbUrl', { unique: false });
-                objectStore?.createIndex('description', 'description', { unique: false });
-            }
-        }
-        request.onerror = function () {
-            console.log('打开数据库失败')
-        }
-        request.onsuccess = function () {
-            setMyDB(request.result)
-            console.log('数据库打开成功')
-        }
-    }, [])
-    /*新增数据*/
-    const add = useCallback((params: { data: { newsUrl: string, newsTitle: string, newsPicUrl: string, newsDescription: string }[] }) => {
-        let request: IDBRequest<IDBValidKey> | undefined = myDB?.transaction(['temporaryNews'], 'readwrite')//新建一个事务
-            .objectStore('temporaryNews')//拿到 IDBObjectStore 对象
-            .add(params);
-        if (request) {
-            request.onsuccess = function (event) {
-                readAll({})
-                console.log('数据写入成功', event.target, request);
-                message.success('添加成功!')
-            };
-            request.onerror = function (event) {
-                console.log('数据写入失败');
-            }
-        }
-    }, [myDB, total])
-    /*编辑更新数据*/
-    const updata = useCallback(() => {
-        let request: IDBRequest<IDBValidKey> | undefined = myDB?.transaction(['temporaryNews'], 'readwrite')//新建一个事务
-            .objectStore('temporaryNews')//拿到 IDBObjectStore 对象
-            .put(1);
-        if (request) {
-            request.onsuccess = function (event) {
-                console.log('数据更新成功', event);
-            };
-            request.onerror = function (event) {
-                console.log('数据更新失败');
-            }
-        }
-    }, [myDB])
-    /*删除数据*/
-    const del = useCallback((params: number) => {
-        let request: IDBRequest<undefined> | undefined = myDB?.transaction(['temporaryNews'], 'readwrite')
-            .objectStore('temporaryNews')
-            .delete(params);
-        if (request) {
-            request.onsuccess = function (event) {
-                console.log('数据删除成功');
-                message.success('删除成功!')
-                readAll({})
-            };
-        }
-    }, [myDB])
-    /*查询数据*/
-    const query = useCallback((params?: any) => {
-        if (params) {
-            readAll(params)
-        } else {
-            readAll({});
-        }
-    }, [myDB])
-    /**遍历数据 */
-    const readAll = useCallback((params: { str?: string, start?: number, end?: number }) => {
-        let { str, start = 1, end = 10 } = params
-        let objectStore = myDB?.transaction('temporaryNews').objectStore('temporaryNews');
-        let arr: any[] = []
-        if (objectStore) {
-            //倒序读取IDBKeyRange.upperBound(10000000000, true), "prev"
-            objectStore.openCursor(IDBKeyRange.upperBound(10000000000, true), "prev").onsuccess = function (event: any) {
-                let cursor = event.target.result;
-                if (str) {
-                    if (cursor) {
-                        let isOk = cursor?.value?.data?.some((item: any) => {
-                            return Object.keys(item).some(key => { return item[key].indexOf(str) !== -1 })
-                        })
-                        if (isOk) {
-                            arr.push({ ...cursor?.value, id: cursor?.key })
-                        }
-                        cursor.continue();
-                    } else {
-                        console.log('没有更多数据了!');
-                        let newArr: any[] = []
-                        arr.forEach((item: any, index: number) => {
-                            if (index >= (start - 1) * end && index < start * end) {
-                                newArr.push(item)
-                            }
-                        })
-                        setData(newArr)
-                        setTotal(arr.length)
-                    }
-                } else {
-                    if (cursor) {
-                        arr.push({ ...cursor?.value, id: cursor?.key })
-                        cursor.continue();
-                    } else {
-                        console.log('没有更多数据了!');
-                        let newArr: any[] = []
-                        arr.forEach((item: any, index: number) => {
-                            if (index >= (start - 1) * end && index < start * end) {
-                                newArr.push(item)
-                            }
-                        })
-                        setData(newArr)
-                        setTotal(arr.length)
-                    }
-                }
-            };
-        }
-    }, [myDB, data])
-    /**分页 */
-    const page = useCallback((params?: string) => {
-        let objectStore = myDB?.transaction('temporaryNews').objectStore('temporaryNews');
-        let arr: any[] = []
-        if (objectStore) {
-            objectStore.openCursor().onsuccess = function (event: any) {
-                let cursor = event.target.result;
-                console.log(cursor)
-                if (params) {
-                    if (cursor) {
-                        let isOk = cursor?.value?.data?.some((item: any) => {
-                            return Object.keys(item).some(key => { return item[key].indexOf(params) !== -1 })
-                        })
-                        if (isOk) {
-                            arr.push({ ...cursor?.value, id: cursor?.key })
-                        }
-                        cursor.continue();
-                    } else {
-                        console.log('没有更多数据了!');
-                        setData(arr)
-                        setTotal(arr.length)
-                    }
-                } else {
-                    if (cursor) {
-                        arr.push({ ...cursor?.value, id: cursor?.key })
-                        cursor.continue();
-                    } else {
-                        console.log('没有更多数据了!');
-                        setData(arr)
-                    }
-                }
-            };
-        }
-    }, [myDB, data])
-    useEffect(() => {
-        if (!myDB) {
-            createDB()
-        }
-    }, [myDB])
-    useEffect(() => {
-        dispatch({ type: 'set', params: { data: data.length > 0 ? data : [], total } })
-    }, [data, total])
-    return { add, del, updata, query, readAll }
-}
-
-export default useIndexDB

+ 0 - 30
src/components/Alink/index.less

@@ -1,30 +0,0 @@
-.row_style {
-  width: 100%;
-  > div:nth-child(1) {
-    width: 120px;
-    text-align: right;
-  }
-  > div:nth-child(2) {
-    width: 100%;
-  }
-}
-.add {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  flex-flow: column;
-  height: 100%;
-}
-.pos {
-  position: absolute;
-  top: 0;
-  left: 0;
-  height: 100%;
-  width: 100%;
-  opacity: 0;
-  color: #fff;
-}
-.pos:hover {
-  opacity: 1;
-  background: rgba(0, 0, 0, 0.6);
-}

+ 0 - 171
src/components/Alink/index.tsx

@@ -1,171 +0,0 @@
-import React, { useState } from 'react'
-import { Col, Input, message, Modal, Radio, RadioChangeEvent, Row, Space, Switch } from 'antd'
-import { useCallback } from 'react'
-import style from './index.less'
-import { PlusOutlined } from '@ant-design/icons'
-import SmMaterialModal from '@/components/MaterialModal/smModalBox';
-interface Props {
-    visible: boolean,
-    onCancel: () => void,
-    onOk: (v: any) => void,
-    title: string,
-    weCathType: 'img' | 'card',
-    defaultData?: { appid: string, appPath: string, cardTitle: string, img: string, imgInfo: any },
-    isOnUserId?: boolean
-}
-function Alink(props: Props) {
-    const { visible = false, title, onCancel, weCathType, onOk, isOnUserId = true } = props
-    const [type, setType] = useState<1 | 2>(1)
-    const [open, setOpen] = useState<boolean>(false)
-    const [imgVisible, setImgVisible] = useState<boolean>(false)
-    const [imgInfo, setImgInfo] = useState<any>(null)
-    const [img, setImg] = useState<string>('')
-    const [text, setText] = useState<string>('')
-    const [link, setLink] = useState<string>('')
-    const [size, setSize] = useState<25 | 50 | 75 | 100>(100)
-    /**确定 */
-    const handleOk = useCallback(() => {
-        let html = ''
-        if (!link) {
-            message.error('请输入连接地址')
-            return
-        }
-        if (!(text || img)) {
-            message.error('请输入文本或者选择图片')
-            return
-        }
-        if (type === 1) {
-            if (open) {
-                html = `<a data-linktype="2"  target="_blank"  tab="innerlink" data-itemshowtype="0"  href=${link}>${text}</a>`
-            } else {
-                html = ` <a data-linktype="2"  target="_blank"  tab="innerlink" data-itemshowtype="0"  href=${link} >${text}</a>`
-            }
-        } else {
-            if (open) {
-                html =`<br/><a href=${link} target="_blank" rel="noopener" data-itemshowtype="0" data-linktype="1" data-mce-href=${link}><img src=${img} style="margin: 0px;" class="rich_pages wxw-img" data-galleryid="" data-s="300,640" data-type="png" data-ratio="1" data-w="797" data-imgqrcoded="1" data-mce-style="margin: 0px;" data-mce-src=${img} ></a ><br/>`
-                // html = `<br/><a data-itemshowtype="0" data-linktype="2" href=${link}  style="display: block;background-image: url(${img});background-repeat: no-repeat;background-size: ${size}% auto;background-position: center bottom;margin-top: 0%;padding-top: 40.85714285714286%;" tab="innerlink" target="_blank" ></a><br/>`
-            } else {
-                html =`<br/><a href=${link} target="_blank" rel="noopener"  tab="innerlink" data-itemshowtype="0" data-linktype="2" data-mce-href=${link}><img src=${img} style="margin: 0px;" class="rich_pages wxw-img" data-galleryid="" data-s="300,640" data-type="png" data-ratio="1" data-w="797" data-imgqrcoded="1" data-mce-style="margin: 0px;" data-mce-src=${img} >&nbsp;</a ><br/>`
-                // html = `<br/><a href=${link} data-linktype="2"  target="_blank"  tab="innerlink" data-itemshowtype="0"  style="display: block;background-image: url(${img});background-repeat: no-repeat;background-size:${size}% auto;background-position: center bottom;margin-top: 0%;padding-top: 40.85714285714286%;">&nbsp;</a><br/>`
-            }
-        }
-        onOk(html)
-    }, [open, type, img, text, link, size])
-    //类型
-    const onChange = useCallback((e: RadioChangeEvent) => {
-        setType(e.target.value)
-    }, [])
-    return <div>
-        <Modal
-            visible={visible}
-            title={title}
-            onCancel={onCancel}
-            onOk={handleOk}
-            maskClosable={false}
-        >
-            <Row gutter={[10, 20]}>
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>链接地址</span>
-                        <Input
-                            placeholder={'请填写链接地址https://www.*****'}
-                            onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                let v = e.target.value
-                                setLink(v)
-                            }}
-                            value={link}
-                        />
-                    </Space>
-                </Col>
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>链接类型</span>
-                        <Radio.Group onChange={onChange} value={type}>
-                            <Radio value={1}>文本</Radio>
-                            <Radio value={2}>图片</Radio>
-                        </Radio.Group>
-                    </Space>
-                </Col>
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>{type === 1 ? '链接文本' : '链接图片'}</span>
-                        {
-                            type === 1 ?
-                                <Input
-                                    placeholder={'请填写链接文本'}
-                                    onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
-                                        let v = e.target.value
-                                        setText(v)
-                                    }}
-                                    value={text}
-                                /> :
-                                <div onClick={() => setImgVisible(true)} style={{ width: '100%', height: 200, border: '1px dashed #d8d8d8', position: 'relative', cursor: 'pointer' }}>
-                                    {
-                                        img ?
-                                            <>
-                                                <img src={img} style={{ width: '100%', height: '100%', objectFit: 'contain' }} />
-                                            </>
-                                            :
-                                            <span className={`${style.add} ${img ? style.pos : ''} `}>
-                                                <PlusOutlined style={{ fontSize: 32 }} />
-                                            </span>
-                                    }
-                                </div>
-                        }
-                        {
-                            imgVisible && <SmMaterialModal
-                                visible={imgVisible}
-                                onCancel={() => setImgVisible(false)}
-                                title='选择图片'
-                                onOk={(props: any) => {
-                                    console.log('props===>', props)
-                                    let obj: any = {}
-                                    if (props?.mediaId) {//微信素材
-                                        obj.wxMediaId = props?.id
-                                        obj.thumbUrl = props?.url
-                                    } else {
-                                        obj.thumbUrl = props?.url
-                                    }
-                                    setImg(obj?.thumbUrl)
-                                    setImgInfo(props)
-                                    setImgVisible(false)
-                                }}
-                                mediaType={1}
-                                isShowWx={false}
-                                isAllData
-                                noFile={true}
-                            />
-                        }
-                    </Space>
-                </Col>
-                {/* {
-                    img && <Col span={24}>
-                        <Space className={style.row_style}>
-                            <span>图片大小</span>
-                            <Radio.Group onChange={(e: RadioChangeEvent) => {
-                                let v = e.target.value
-                                setSize(v)
-                            }} value={size}>
-                                <Radio value={25}>25%</Radio>
-                                <Radio value={50}>50%</Radio>
-                                <Radio value={75}>75%</Radio>
-                                <Radio value={100}>100%</Radio>
-                            </Radio.Group>
-                        </Space>
-                    </Col>
-                } */}
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>是否开启弹窗</span>
-                        <Switch checkedChildren="开启" unCheckedChildren="关闭" onChange={(checked: boolean) => { setOpen(checked) }} checked={open} />
-                    </Space>
-                </Col>
-                <Col>
-                    <strong style={{color:'red'}}>注:公众号必须开通支付才可以正常使用A链接!</strong>
-                </Col>
-            </Row>
-        </Modal>
-    </div>
-}
-
-export default Alink

+ 0 - 59
src/components/BatchAddLabel/index.tsx

@@ -1,59 +0,0 @@
-import { message, Modal, Select, Space } from "antd";
-import { SelectValue } from "antd/lib/select";
-import React, { useCallback, useEffect, useState } from "react";
-import { useModel } from "umi";
-
-
-interface Props {
-    show?: boolean,
-    onClose?: () => void,
-    onChange?: (value: string[]) => void,
-    ajax?: any
-}
-
-function BatchAddLabel(props: Props) {
-    const { show = false, onClose, onChange, ajax } = props
-
-    /** 变量开始 */
-    const [labelIds, setLabelIds] = useState<string[] | undefined>([])
-    /** 变量结束 */
-
-    const { getLabels } = useModel('useLaunch.useMaterial')
-
-    useEffect(() => {
-        getLabels.run({ pageNum: 1, pageSize: 200 })
-    }, [])
-    
-    // 设置标签
-    const setLable = (value: any) => {
-        setLabelIds(value)
-    }
-
-    // 确定按钮
-    const handleOk = useCallback(() => {
-        if (labelIds && labelIds.length > 0) {
-            onChange && onChange(labelIds)
-        } else {
-            message.error('请选择标签')
-        }
-    }, [labelIds])
-
-    return <Modal 
-        visible={show}
-        width={460}
-        title="批量添加标签"
-        onCancel={() => {onClose && onClose()}}
-        maskClosable={false}
-        onOk={handleOk}
-        confirmLoading={ajax && ajax?.loading}
-    >
-        <Space>
-            <span>标签:</span>
-            <Select value={labelIds} style={{width: 350}} onChange={(value: SelectValue) => { setLable(value) }} placeholder="选择标签" mode="multiple">
-                {getLabels?.data?.records.map((item: any) => (<Select.Option value={item?.id?.toString()} key={item?.label + item?.id}>{item?.label}</Select.Option>))}
-            </Select>
-        </Space>
-    </Modal>
-}
-
-export default React.memo(BatchAddLabel)

+ 0 - 26
src/components/CityCascader/index.tsx

@@ -1,26 +0,0 @@
-import cityList from '@/utils/city'
-import { Cascader } from 'antd'
-import React from 'react'
-type Props = {
-    change: (v: any) => void,//回调
-    fieldNames?: { label: string, value: string, childern: string },//自定义字段名称如需地域编号vlaue改id
-    disabled?: boolean
-}
-/**
- * 地域联调 
- * @param fieldNames?:{ label: 'label', value: 'value', children: 'children' }自定义字段名称如需地域编号vlaue改id
- * @param change: (v: any[]) => void 回调函数选中后返回一个数组
- */
-const CityCascader = React.memo((props: Props) => {
-    const { change, fieldNames, disabled = false } = props
-    return <Cascader
-        options={cityList()}
-        fieldNames={fieldNames || { label: 'label', value: 'value', children: 'children' }}
-        onChange={change}
-        placeholder="选择地域"
-        style={{ minWidth: 220 }}
-        disabled={disabled}
-    />
-})
-
-export default CityCascader

+ 0 - 246
src/components/Editor/AudioUploader.js

@@ -1,246 +0,0 @@
-import Button from './Button'
-import Input from './Input'
-import Label from './Label'
-import React from 'react'
-import Select from './Select'
-import Tag from './Tag'
-import Upload from './Upload'
-
-const style = {
-  paramsConfig: {
-    paddingBottom: '10px',
-    borderBottom: '1px solid rgb(217, 217, 217)',
-    display: 'flex',
-    flexWrap: 'wrap',
-  },
-  insertTitle: {
-    fontSize: '14px',
-    paddingRight: '10px',
-    color: 'rgba(0, 0, 0, 0.65)',
-  },
-  sourceList: {
-    margin: '10px 10px 10px 0',
-    border: '1px dashed rgb(217, 217, 217)',
-    borderRadius: '4px',
-  },
-  configTitle: {
-    display: 'block',
-    fontSize: '14px',
-    margin: '10px 0',
-    paddingRight: '10px',
-    color: 'rgba(0, 0, 0, 0.65)',
-  },
-  warnInfo: {
-    display: 'inline-block',
-    width: '100%',
-    margin: '5px',
-    textAlign: 'center',
-    fontSize: '12px',
-    color: '#f04134',
-  },
-}
-
-const linkRegx = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9,_-](\?)?)*)*$/i
-
-let timeoutInstance = null
-
-class UploadModal extends React.PureComponent {
-  state = {
-    sources: [],
-    currentSource: '',
-    width: 400,
-    height: 400,
-    controls: 'true',
-    autoplay: 'false',
-    muted: 'false',
-    loop: 'false',
-    poster: '',
-    name: '',
-    author: '',
-    errorMsg: '',
-    errorMsgVisible: false,
-  }
-
-  updateCurrentSource = e => {
-    this.setState({currentSource: e.target.value})
-  }
-
-  addSource = () => {
-    let {sources, currentSource} = this.state
-    let newsources = sources.concat([currentSource])
-    if (currentSource === '') {
-      this.showErrorMsg('链接不能为空')
-    } else if (!linkRegx.test(currentSource)) {
-      this.showErrorMsg('非法的链接')
-    } else if (sources.indexOf(currentSource) !== -1) {
-      this.showErrorMsg('链接已存在')
-    } else {
-      this.setState({
-        sources: newsources,
-        currentSource: '',
-      }, () => {
-        this.props.onChange && this.props.onChange(this.generateHtml())
-      })
-    }
-  }
-
-  removeSource = index => {
-    let sourcesCopy = this.state.sources.concat([])
-    sourcesCopy.splice(index, 1)
-    this.setState({sources: sourcesCopy})
-  }
-
-  upload = e => {
-    let {upload} = this.props
-
-    if (!upload) return
-
-    upload(e).then(url => {
-      this.setState({currentSource: url})
-    }).catch(e => {
-      e.constructor === Error ? this.showErrorMsg(e.message) : this.showErrorMsg(e)
-    })
-  }
-
-  showErrorMsg = msg => {
-    this.setState({errorMsg: msg, errorMsgVisible: true})
-    clearTimeout(timeoutInstance)
-    timeoutInstance = setTimeout(() => {
-      this.setState({errorMsg: '', errorMsgVisible: false})
-    }, 4000)
-  }
-
-  getFileType = (fileUrl, mediaType) => {
-    let type = fileUrl.match(/\.(\w+)$/, 'i')
-    return type ? type[1].toLowerCase() : 'mp3'
-  }
-
-  generateHtml = () => {
-    let {sources, controls, autoplay, loop, poster, name, author} = this.state
-    let dataExtra = JSON.stringify({'poster': poster, 'name': name, 'author': author})
-    let len = sources.length
-
-    if (len > 0) {
-      let html = ''
-      let attr = ''
-
-      attr += controls === 'false' ? '' : ' controls="true" '
-      attr += autoplay === 'false' ? '' : ' autoplay="true" '
-      attr += loop === 'false' ? '' : ' loop="true" '
-
-      if (len === 1) {
-        html = `<audio src="${sources[0]}" ${attr} data-extra='${dataExtra}'>你的浏览器不支持 audio 标签</audio>`
-      } else {
-        html = `<audio ${attr} data-extra='${dataExtra}'>`
-        sources.forEach(source => {
-          html += `<source src=${source} type="audio/${this.getFileType(source, 'audio')}">`
-        })
-        html += '你的浏览器不支持 audio 标签</audio>'
-      }
-
-      return html + '<p></p>'
-    }
-  }
-
-  closeModal = () => {
-    this.props.closeModal()
-  }
-
-  changeConfig = (e, type) => {
-    let value = e.target.value
-    let boolType = ['controls', 'autoplay', 'muted', 'loop']
-    if (type === 'width' || type === 'height') {
-      if (isNaN(parseInt(value))) {
-        value = parseInt(value)
-      }
-    } else if (boolType.indexOf(type) !== -1) {
-      value = !!value
-    }
-    this.setState({[type]: value}, () => {
-      this.props.onChange && this.props.onChange(this.generateHtml())
-    })
-  }
-
-  renderSourceList = () => {
-    let {sources} = this.state
-    if (sources.length > 0) {
-      let list = sources.map((source, index) => {
-        return <Tag value={source} key={source} index={index} onRemove={this.removeSource} />
-      })
-      return list
-    } else {
-      return <span style={style.warnInfo}>至少添加一个链接</span>
-    }
-  }
-
-  renderAudioConfig = () => {
-    let {controls, autoplay, loop, poster, name, author} = this.state
-    return (
-      <form style={style.paramsConfig}>
-        <Label name='controls'>
-          <Select defaultValue={controls} onChange={e => { this.changeConfig(e, 'controls') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-        <Label name='autoplay'>
-          <Select defaultValue={autoplay} onChange={e => { this.changeConfig(e, 'autoplay') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-        <Label name='loop'>
-          <Select defaultValue={loop} onChange={e => { this.changeConfig(e, 'loop') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-        <Label name='poster'>
-          <Input type='text' defaultValue={poster} onChange={e => { this.changeConfig(e, 'poster') }} />
-        </Label>
-        <Label name='name'>
-          <Input type='text' defaultValue={name} onChange={e => { this.changeConfig(e, 'name') }} />
-        </Label>
-        <Label name='author'>
-          <Input type='text' defaultValue={author} onChange={e => { this.changeConfig(e, 'author') }} />
-        </Label>
-      </form>
-    )
-  }
-
-  render() {
-    let {currentSource, errorMsg, errorMsgVisible} = this.state
-    let {progress} = this.props
-
-    return (
-      <div>
-        <div>
-          <span style={style.insertTitle}>插入链接</span>
-          <Input style={{width: '300px'}} type='text' value={currentSource} onChange={this.updateCurrentSource} />
-          <Button onClick={this.addSource}>添加</Button>
-          <Upload onChange={this.upload} />
-        </div>
-        <div>
-          <span style={{...style.warnInfo, display: progress && progress !== -1 ? 'block' : 'none'}}>
-            {progress}%
-          </span>
-          <span style={{...style.warnInfo, display: errorMsgVisible ? 'block' : 'none'}}>{errorMsg}</span>
-        </div>
-        <div style={style.sourceList}>
-          {this.renderSourceList()}
-        </div>
-        <span style={style.configTitle}>参数配置</span>
-        {this.renderAudioConfig()}
-        <div style={{textAlign: 'center', padding: '20px 10px 0 10px'}}>
-          {
-            <audio src={currentSource} controls='controls' style={{width: '400px'}}>
-              你的浏览器不支持 audio 标签
-            </audio>
-          }
-        </div>
-      </div>
-    )
-  }
-}
-
-export default UploadModal

+ 0 - 299
src/components/Editor/Box/TEditor.tsx

@@ -1,299 +0,0 @@
-import { Editor } from '@tinymce/tinymce-react';
-import React, { useRef, useEffect, useState, useCallback } from 'react';
-import SmMaterialModal from '@/components/MaterialModal/smModalBox'
-import WeChatImgCard from "@/components/WeChatImgCard"
-import Alink from '@/components/Alink'
-// https://mmbiz.qpic.cn/mmbiz_png/Bic8GaUSeMXaRjA1qiaGAu35ssNpnPejMzyY4c0HHPrO1kjh93uWIE4F9aQUfIsEiakib5TWfHls8GLHEPXOIQiaiakg/640?wx_fmt=png
-//https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/B9B6AEB034044B5E9A7FC05227060789.jpg
-export default function TEditor(props: {
-    dispatch: (arg: any) => void,
-    setLoding: (arg: boolean) => void,
-    isOk: (arg: any) => void,
-    content: string,
-    actionId: any
-}) {
-    let { dispatch, setLoding, isOk, content, actionId } = props
-    let [value, setValue] = useState<any>(null)
-    let [imgVisible, setImgVisible] = useState(false)
-    let [wImgVisible, setWImgVisible] = useState(false)
-    let [wCardVisible, setWCardVisible] = useState(false)
-    let [wAVisible, setWAVisible] = useState(false)
-    const editorRef: any = useRef(null);
-    // console.log('传进来的content====>',content)
-
-    /**==================实时处理html===================*/
-    const disposeHtml = useCallback((html) => {
-        console.log(333333, '执行HTML处理方法')
-        // =================处理腾讯的图片,解决非法引用看不到图的问题==========================
-        // 筛选出是腾讯的图片,并查看是否带了随机数,以免加载失败
-        // let imgArr = html?.match(/(<img .*(\B>))/ig)?.filter((img: string ) => !img.includes('aliyuncs.com') && img.search(/=?\w{0,4}\?v/)!== -1)
-        // imgArr?.forEach((img: any) => {
-        //     // let src = img.match(/src=.*=png/)[0]
-        //     console.log('img====>', img)
-        //     let src = img.match(/(src=.*=\w{3,4})|(src=.*\/[0-9]{0,3}")/)[0]
-        //     console.log('src====>', src)
-        //     // 不存在no-referrer执行添加
-        //     if (!img.includes('referrerpolicy="no-referrer"')) {
-        //         console.log('修改IMG1')
-        //         html = html.replace(src, `${src + '?v' + Math.random() * 10}" referrerpolicy="no-referrer"`)
-        //     } else {
-        //         console.log('修改IMG2')
-        //         html = html.replace(src, src + '?v' + Math.random() * 10)
-        //     }
-        // })
-
-        // 处理微信背景图片
-        let bgImgArr = html?.match(/background(-image)?:\s?url\(['"].*\)/ig)
-        console.log('bgImgArr===>',bgImgArr)
-        bgImgArr?.forEach((bg: any) => {
-            if (bg?.match(/http[s]?:.*'/) && !bg?.includes(`http://api.zanxiangnet.com/system/domain/forward?url=`)) {
-                let url = bg?.match(/http[s]?:.*'/)[0]
-                let newBg = bg.replace(url, `http://api.zanxiangnet.com/system/domain/forward?url=` + bg?.match(/http[s]?:.*'/)[0])
-                console.log({bg,newBg})
-                html = html.replace(bg, newBg)
-            }
-        })
-
-        // 处理小程序卡片假如没有外层加上外层好在本地展示
-        let mp_miniprogram = html?.match(/(<mp-miniprogram .*>\s?<\/mp-miniprogram>)/ig)
-        mp_miniprogram?.forEach((mp: any) => {
-            if (!mp.includes('data-bd="true"')) {
-                let imgSrc = mp?.match(/(http.*\.\w{3,4})/)[0]
-                let newMp = mp.replace('<mp-miniprogram', `<mp-miniprogram data-bd="true"`)
-                html = html.replace(mp, `
-                <div class='mp-miniprogram'>
-                ${newMp}
-                    <img src='${imgSrc}' />
-                </div>
-                `)
-            }
-        })
-        console.log(content !== html)
-        //存放处理后的html
-        if (content !== html) {
-            // console.log('setValue=====>',html)
-            console.log(444444, '改变后的HTML和当前存放的HTML不同替换旧的HTML')
-            setValue(html)
-        }
-    }, [content])
-
-    /**====================处理保存的html=======================*/
-    const disposeSaverHtml = useCallback((html) => {
-        console.log(5555555, '焦点脱离,处理HTML并保存内容dispatch=====>')
-        /**查找小程序卡片并替换回微信的元素*/ 
-        let divStr = html?.match(/<div\s?class="mp-miniprogram">.*<img\s?src=.*\.\w{3,4}">\s?<\/div>/ig)
-        divStr?.forEach((div: any) => {
-            let mpStr = div?.match(/(<mp-miniprogram .*>\s?<\/mp-miniprogram>)/)[0]
-            mpStr = mpStr?.replace(`data-bd="true"`, '')
-            html = html?.replace(div, mpStr)
-        })
-        /**查找是否是微信的图片.是就去掉http://api.zanxiangnet.com/system/domain/forward?url=*/ 
-        let bgImgArr = html?.match(/background(-image)?:\s?url\(['"].*\)/ig)
-            bgImgArr?.forEach((bg: any)=>{
-                if (bg?.match(/http[s]?:.*'/) && bg?.includes(`http://api.zanxiangnet.com/system/domain/forward?url=`) && bg?.includes('mmbiz.qpic.cn')) {
-                    let newBg = bg?.replace('http://api.zanxiangnet.com/system/domain/forward?url=','').replace(/'/ig,'&quot;')
-                    html = html?.replace(bg, newBg)
-                    console.log(newBg)
-                }
-            })
-        // 去除display:block;
-        // html = html?.replace(/display:\s?block;/ig,'')
-        console.log('html====>', html)
-        dispatch({ type: 'pushData', params: { menuId: actionId, content: html || '<p></p>' } })
-    }, [actionId])
-    useEffect(() => {
-        // actionId的监听因为content可能一样为默认值所以监听actionId的变化来强行执行
-        console.log(1111111111, 'props.content改变')
-        setValue(content)
-    }, [content, actionId])
-    // console.log('content=======>',content)
-    // 腾讯图片出去referrer请求头
-    useEffect(() => {
-        let meta = document.createElement('meta')
-        meta.name = 'referrer'
-        meta.content = 'no-referrer'
-        document.head.appendChild(meta)
-        return () => {
-            let m = document.head.querySelector('[name="referrer"]')
-            if (m) {
-                document.head.removeChild(m)
-            }
-        }
-    }, [])
-    return <>
-        <Editor
-            // apiKey='wkn1n49be4rmnjq9h33nzp15z9n9v5jn2n4dr3kav8bx7y4y'
-            // 初始化
-            onInit={(evt, editor) => {
-                editorRef.current = editor
-                setLoding(false)
-                isOk(editor);
-                // let div:any = document.querySelector('.tox-tinymce-aux')
-                // if(div){
-                //     div.style = 'display:none'
-                // }
-                // editor.ui.registry.addButton
-            }}
-
-            // initialValue={content}
-            value={value}
-            onBlur={() => {
-                // 假如焦点丢失时最后数据与数据存放中的数据不同执行保存
-                if (value !== content || content === '') {
-                    disposeSaverHtml(value)
-                }
-            }}
-            // 编辑变化
-            onEditorChange={(html, editor) => {
-                console.log(22222222, '监听到html变化,执行处理HTML函数方法', html)
-                // console.log('html===>',html)
-                //每次html变化去处理函数处理html
-                disposeHtml(html)
-            }}
-            init={{
-                height: 730,
-                menubar: true,
-                language: 'zh-Hans',
-                language_url: 'http://test.zanxiangnet.com/aaplugin/zh-Hans.js',
-                extended_valid_elements: 'img[src|_src|referrerpolicy|style|class],mp-miniprogram[data-*]',//扩展有效元素
-                custom_elements: 'mp-miniprogram',
-                branding: false,//右下角支持关闭
-                typeahead_urls: false,//输入地址时的自动完成
-                // remove_trailing_brs: false,
-                plugins: [//头部文字插件
-                    'advlist', 'autolink', 'lists', 'link', 'charmap', 'preview',
-                    'anchor', 'searchreplace', 'visualblocks', 'code', 'fullscreen',
-                    'insertdatetime', 'emoticons', 'table', 'code', 'wordcount', 'image', 'paste', 'help'
-                ],
-                // 图标插件按钮
-                toolbar: 'undo redo  blocks fontsize  |bold italic forecolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent paste |img wImg wCard wA',//工具栏
-                toolbar_mode: 'wrap',//工具换行
-                font_size_formats: '11px 12px 14px 16px 18px 24px 36px 48px',
-                paste_webkit_styles: 'all',
-                // element_format:'html',
-                valid_children:'+span[p]',//允许span下可以存在P元素
-                content_style: `
-                body { font-family:Helvetica,Arial,sans-serif; font-size:14px ;}
-                .mp-miniprogram{
-                    width:200px;
-                    height:200px;
-                }
-                .mp-miniprogram img{
-                    width:100%;
-                }
-                `,
-                setup(ed) {
-                    // 图
-                    ed.ui.registry.addButton('img', {
-                        text: '图片',
-                        onAction: () => {
-                            setImgVisible(true)
-                        }
-                    })
-                    // 小程序图片链插件
-                    ed.ui.registry.addButton('wImg', {
-                        text: '小程序图片',
-                        onAction: () => {
-                            setWImgVisible(true)
-                        }
-                    })
-                    // 小程序卡片链插件
-                    ed.ui.registry.addButton('wCard', {
-                        text: '小程序卡片',
-                        onAction: () => {
-                            setWCardVisible(true)
-                        }
-                    })
-                    // A链接功能插件
-                    ed.ui.registry.addButton('wA', {
-                        text: 'A链接',
-                        onAction: () => {
-                            setWAVisible(true)
-                        }
-                    })
-                },
-                
-                // '' +
-                // 'alignright alignjustify | bullist numlist outdent indent | ' +
-                // 'removeformat |code| emoticons|media| image|help'
-            }}
-        />
-        {/* 图片选择 */}
-        <SmMaterialModal
-            mediaType={1}
-            onCancel={() => { setImgVisible(false) }}
-            title='选择图片'
-            visible={imgVisible}
-            onOk={(props: any) => {
-                let url = props.url
-                editorRef.current.insertContent(`<img 
-                style='max-width:100%'
-                src=\"${url}\" 
-                alt=\"\" 
-                data-w=\"auto\" 
-                data-ratio=\"0.66796875\" 
-                data-type=\"${url.replace(/http[s]?:\/\/\S*(wx_fmt=|\.)/ig, '') === 'gif' ? 'png' : url.replace(/http[s]?:\/\/\S*(wx_fmt=|\.)/ig, '')}\"
-                />`)
-                setImgVisible(false)
-            }}
-            // isShowWx={isShowWx}
-            isAllData
-            noFile={true}
-        />
-        {/* 小程序图片链 */}
-        {
-            wImgVisible && <WeChatImgCard
-                onCancel={() => {
-                    setWImgVisible(false)
-                }}
-                title='小程序图片链'
-                visible={wImgVisible}
-                onOk={(props: { img: string, appid: string, appPath: string, href?: string }) => {
-                    editorRef.current.insertContent(`<a data-miniprogram-appid=\"${props.appid}\" data-miniprogram-path=\"${props.appPath}\" href=\"${props.href}\"><img src=\"${props.img}\" alt=\"\" data-width=\"null\" data-ratio=\"NaN\"/></a>`)
-                    setWImgVisible(false)
-                }}
-                weCathType='img'
-                isOnUserId={false}
-            />
-        }
-        {/* 小程序卡片链 */}
-        {
-            wCardVisible && <WeChatImgCard
-                onCancel={() => {
-                    setWCardVisible(false)
-                }}
-                title='小程序卡片链'
-                visible={wCardVisible}
-                onOk={(props: { img: string, appid: string, appPath: string, cardTitle?: string }) => {
-                    editorRef.current.insertContent(`
-                    <div class='mp-miniprogram'>
-                        <mp-miniprogram data-bd="true" data-miniprogram-appid=\"${props?.appid}\" data-miniprogram-path=\"${props?.appPath}\" data-miniprogram-title=\"${props?.cardTitle}\" data-miniprogram-type=\"card\" data-miniprogram-servicetype=\"0\" data-miniprogram-imageurl=\"${props?.img}\"></mp-miniprogram>
-                        <img src='${props.img}' />
-                    </div>
-                    `)
-                    setWCardVisible(false)
-                }}
-                weCathType='card'
-                isOnUserId={false}
-            />
-        }
-        {/*A链 */}
-        {
-            wAVisible && <Alink
-                onCancel={() => { setWAVisible(false) }}
-                title='A链接'
-                visible={wAVisible}
-                onOk={(props: string) => {
-                    console.log(props)
-                    editorRef.current.insertContent(props.replace('&lt;','<').replace('&gt;','>'))
-                    setWAVisible(false)
-                }}
-                weCathType='card'
-                isOnUserId={false}
-            />
-        }
-    </>
-}
-
-// /**图片上传插件*/
-

+ 0 - 32
src/components/Editor/Box/UEditor.tsx

@@ -1,32 +0,0 @@
-import React from 'react'
-import ReactUeditor from '@/components/Editor/ReactUeditor'
-import { uploadImagePlugin, uploadVidioPlugin, uploadWeChatImagePlugin, uploadWeChatCardPlugin, uploadALink } from './editorPlugin'
-
-export default function UEditor(props:{dispatch: (arg: any) => void,setLoding: (arg: boolean) => void,isOk: (arg: any) => void,setContent:(arg:any)=>void,isShowWx:any}) {
-    let {dispatch,setLoding,isOk,setContent,isShowWx} = props
-    return <ReactUeditor
-        ueditorPath={`/ueditor`}
-        getRef={(ref: any) => {
-            dispatch({ type: 'setRef', params: { ueditorRef: ref } })//存放实例
-        }}
-        onReady={
-            (ueditor: any) => {
-                setLoding(false)
-                isOk(ueditor)//执行编辑的操作
-            }
-        }
-        plugins={[
-            'emotion',
-            (e: any) => { return uploadImagePlugin(e, isShowWx) },
-            uploadVidioPlugin,
-            uploadWeChatImagePlugin,
-            uploadWeChatCardPlugin,
-            uploadALink
-        ]}
-        onChange={(content: any) => {
-            if (content || '<p></p>') {
-                setContent(content)
-            }
-        }}
-    />
-}

+ 0 - 149
src/components/Editor/Box/editorPlugin.tsx

@@ -1,149 +0,0 @@
-import React from "react"
-import SmMaterialModal from '@/components/MaterialModal/smModalBox'
-import WeChatImgCard from "@/components/WeChatImgCard"
-import Alink from '@/components/Alink'
-/**图片上传插件*/
-const uploadImagePlugin = (ueditor: any, isShowWx?: boolean) => {
-    return {
-        menuText: '图片上传',
-        cssRules: `background-image: url(/ueditor/themes/default/icon/tool-0332@2x.png) !important;background-size: 20px 1340px;background-position: 0 -480px;`,
-        render: (visible: any, closeModal: any) => {
-            const handleSelectImage = (url: string) => {
-                ueditor.focus()
-                ueditor.execCommand('insertHtml', `<img 
-                style='max-width:100%'
-                src=\"${url}\" 
-                alt=\"\" 
-                data-w=\"auto\" 
-                data-ratio=\"0.66796875\" 
-                data-type=\"${url.replace(/http[s]?:\/\/\S*(wx_fmt=|\.)/ig, '') === 'gif' ? 'png' : url.replace(/http[s]?:\/\/\S*(wx_fmt=|\.)/ig, '')}\"
-                />`)
-                closeModal()
-            }
-            return visible && <SmMaterialModal
-                mediaType={1}
-                onCancel={closeModal}
-                title='选择图片'
-                visible={visible}
-                onOk={(props: any) => { handleSelectImage(props?.url) }}
-                isShowWx={isShowWx}
-                isAllData
-                noFile={true}
-            />
-        }
-    }
-}
-/**音频上传插件*/
-const uploadAudioPlugin = (ueditor: any) => {
-    return {
-        menuText: '音频上传',
-        cssRules: `background-image: url(/ueditor/themes/default/icon/tool-0332@2x.png) !important;background-size: 20px 1340px;background-position: 0 -510px;`,
-        render: (visible: any, closeModal: any) => {
-            const handleSelectImage = (url: string) => {
-                ueditor.focus()
-                ueditor.execCommand('insertparagraph')
-                ueditor.execCommand('insertHtml', `<audio src="${url}" controls="true" data-extra="{}"></audio>`)
-                ueditor.execCommand('insertparagraph')
-                closeModal()
-            }
-            return visible && <SmMaterialModal mediaType={2} onCancel={closeModal} title='公众号音频素材' visible={visible} onOk={handleSelectImage} actionKey='2' />
-        }
-    }
-}
-/**视频上传插件*/
-const uploadVidioPlugin = (ueditor: any) => {
-    return {
-        menuText: '视频上传',
-        cssRules: `background-image: url(/ueditor/themes/default/icon/tool-0332@2x.png) !important;background-size: 20px 1340px;background-position: 0 -540px;`,
-        render: (visible: any, closeModal: any) => {
-            const handleSelectImage = (url: string) => {
-                ueditor.focus()
-                ueditor.execCommand('insertparagraph')
-                ueditor.execCommand('insertHtml', `
-                <iframe
-                    data-vidtype="2" 
-                    height="310" 
-                    width="500"
-                    data-ratio="1.7666666666666666" 
-                    data-w="848"
-                    frameborder="0" 
-                    data-src=${url}
-                    allowfullscreen="" 
-                    src=${url}
-                >
-                </iframe>
-                `)
-                ueditor.execCommand('insertparagraph')
-                closeModal()
-            }
-            return visible && <SmMaterialModal mediaType={3} onCancel={closeModal} title='公众号视频素材' visible={visible} onOk={handleSelectImage} actionKey='1' />
-        }
-    }
-}
-/**小程序图片链插件*/
-const uploadWeChatImagePlugin = (ueditor: any,) => {
-    return {
-        menuText: '小程序图片链',
-        cssRules: `background-image: url(/ueditor/themes/default/icon/tool-0332@2x.png) !important;background-size: 20px 1340px;background-position: 0 -1320px;`,
-        render: (visible: any, closeModal: any) => {
-            const handleSelectImage = (obj: { img: string, appid: string, appPath: string, href?: string }) => {
-                ueditor.focus()
-                ueditor.execCommand('insertHtml', `<a data-miniprogram-appid=\"${obj.appid}\" data-miniprogram-path=\"${obj.appPath}\" href=\"${obj.href}\"><img src=\"${obj.img}\" alt=\"\" data-width=\"null\" data-ratio=\"NaN\"/></a>`)
-                closeModal()
-            }
-            return visible && <WeChatImgCard
-                onCancel={closeModal}
-                title='小程序图片链'
-                visible={visible}
-                onOk={(props: { img: string, appid: string, appPath: string, href?: string }) => { handleSelectImage(props) }}
-                weCathType='img'
-                isOnUserId={false}
-            />
-        }
-    }
-}
-/**小程序卡片链插件*/
-const uploadWeChatCardPlugin = (ueditor: any,) => {
-    return {
-        menuText: '小程序卡片',
-        cssRules: `background-image: url(/ueditor/themes/default/icon/tool-0332@2x.png) !important;background-size: 20px 1340px;background-position: 0 -1290px;`,
-        render: (visible: any, closeModal: any) => {
-            const handleSelectImage = (obj: { img: string, appid: string, appPath: string, cardTitle?: string }) => {
-                ueditor.focus()
-                ueditor.execCommand('insertHtml', `<mp-miniprogram data-miniprogram-appid=\"${obj?.appid}\" data-miniprogram-path=\"${obj?.appPath}\" data-miniprogram-title=\"${obj?.cardTitle}\" data-miniprogram-type=\"card\" data-miniprogram-servicetype=\"0\" data-miniprogram-imageurl=\"${obj?.img}\"></mp-miniprogram>`)
-                closeModal()
-            }
-            return visible && <WeChatImgCard
-                onCancel={closeModal}
-                title='小程序卡片'
-                visible={visible}
-                onOk={(props: { img: string, appid: string, appPath: string, cardTitle?: string }) => { handleSelectImage(props) }}
-                weCathType='card'
-                isOnUserId={false}
-            />
-        }
-    }
-}
-/**A链接功能插件*/
-const uploadALink = (ueditor: any,) => {
-    return {
-        menuText: 'A链接',
-        cssRules: `background-image: url(/ueditor/themes/default/icon/tool-0332@2x.png) !important;background-size: 20px 1340px;background-position: 0 -1290px;`,
-        render: (visible: any, closeModal: any) => {
-            const handleSelectImage = (html: string) => {
-                ueditor.focus()
-                ueditor.execCommand('insertHtml', `${html}`)
-                closeModal()
-            }
-            return visible && <Alink
-                onCancel={closeModal}
-                title='A链接'
-                visible={visible}
-                onOk={(props: string) => { handleSelectImage(props) }}
-                weCathType='card'
-                isOnUserId={false}
-            />
-        }
-    }
-}
-export { uploadImagePlugin, uploadAudioPlugin, uploadVidioPlugin, uploadWeChatImagePlugin, uploadWeChatCardPlugin, uploadALink }

+ 0 - 25
src/components/Editor/Box/index.less

@@ -1,25 +0,0 @@
-.ueditor_title{
-    padding: 10px 30px;
-    display: flex;
-    justify-content: left;
-    align-items: center;
-    border-top: 1px solid #efefef;
-    border-bottom: 1px solid #efefef;
-    // position: absolute;
-    // left: 0;
-    width: 100%;
-    top:175px;
-    z-index: 999;
-    >input{
-        height: 52px;
-        line-height: 52px ;
-        font-size: 25px;
-        font-weight: 500;
-    }
-}
-.btn{
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    height: 50px;
-}

+ 0 - 526
src/components/Editor/Box/index.tsx

@@ -1,526 +0,0 @@
-import React, { useState, useCallback, useMemo, useEffect, useRef } from 'react'
-
-import { Button, Input, message, Space, Spin } from 'antd'
-import style from './index.less'
-
-import { useModel, history } from 'umi'
-import ActionModal from '@/components/ActionModal'
-import TEditor from './TEditor'
-import UEditor from './UEditor'
-
-
-const Title = React.memo(() => {
-    const [titleV, setTitleV] = useState<string>('') //title值
-    const { state: { actionId, dataArr }, dispatch } = useModel('useOperating.useMaterialDrawer')
-    //获取已有Title回写入
-    const defaultTitle = useMemo(() => {
-        let title = ''
-        setTitleV('')
-        dataArr.forEach((obj: any) => {
-            if (obj.menuId === actionId) {
-                if (obj.title) {
-                    title = obj.title
-                }
-            }
-        })
-        return title
-    }, [actionId, dataArr])
-    //插入数据
-    let titleValue = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let value = e.target.value
-        console.log(3)
-        dispatch({ type: 'pushData', params: { menuId: actionId, title: value } })
-        setTitleV(value)
-    }, [actionId])
-    return <div className={style.ueditor_title}>
-        <Input placeholder='输入文章标题(请勿输入特殊字符)' bordered={false} maxLength={64} onChange={titleValue} value={titleV || defaultTitle} />
-    </div>
-})
-interface Props {
-    onClose: () => void, //关闭
-    editId: string,//编辑ID
-    editData: any, //编辑初始内容
-    syncNews?: boolean,//同步
-    isWx?: boolean //是否是微信素材用来判断不同接口逻辑
-    isShowWx?: boolean,
-    isAll?: boolean,
-    callback?: (data: any) => void //回调获取数据
-}
-// ======================== TEditor =========================
-export default function Editor(props: Props) {
-    let { syncNews = true, isWx, isShowWx, isAll = true, callback = null } = props
-    const [showActionModal, setShowActionModal] = useState<boolean>(false)//选择公众号弹窗
-    const [id, setId] = useState<string>('')
-    const [loding, setLoding] = useState<boolean>(true)
-    const { getWeData } = useModel('useOperating.useMaterialContent')
-    const { dispatchNews } = useModel('useOperating.useNews', model => ({ dispatchNews: model.dispatch }))
-    const { dispatch, state } = useModel('useOperating.useMaterialDrawer')
-    const { dispatch: contentDispatch } = useModel('useOperating.useMaterialContent')
-    const { actionId, actionIdold, dataArr, actionData, ueditorRef, sort = 0, isImport } = state
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    //
-    const { add, list, edit, syncId, addWx, state: { parentId, belongUser }, eidtWxlists } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    const { state: { selectWx }, initSelectWx } = useModel('useOperating.useWxGroupList')//公众号筛选
-    const [sid, setSid] = useState<number>(0)//已经切换设置过的ID
-    const [content, setContent] = useState<string>('<p></p>')//内容
-    const editorRef: any = useRef(null);
-    //保存
-    let seve = useCallback((isSaveNews?: boolean) => {
-        let content = ueditorRef?.getContent()
-        let menuId = actionIdold || actionId
-        console.log('保存dataArr===>', dataArr)
-        dispatch({ type: 'pushData', params: { content } })
-        let isOk = dataArr.every((item: any) => {
-            let img = item?.thumbMediaUrl || item?.thumbUrl
-            if (!item.title) {
-                message.error(`第${item.menuId}篇标题为空`)
-                return false
-            }
-            if (!img) {
-                message.error(`第${item.menuId}篇封面为空`)
-                return false
-            }
-            if (item?.digest?.length > 54) {
-                message.error(`第${item.menuId}摘要不能超过54个字`)
-                return false
-            }
-            if (item.content === '<p></p>' || !item.content) {
-                message.error(`第${item.menuId}篇内容为空`)
-                return false
-            }
-            // if (!item.contentSourceUrl) {
-            //     message.error(`第${item.menuId}原文链接为空`)
-            //     return false
-            // }
-            return true
-        })
-        if (isOk) {
-            let news = dataArr.map((item: any) => {
-                let bgImgArr = item?.content?.match(/background(-image)?:\s?url\(['"].*\)/ig)
-                bgImgArr?.forEach((bg: any) => {
-                    if (bg?.match(/http[s]?:.*'/) && bg?.includes(`http://api.zanxiangnet.com/system/domain/forward?url=`) && bg?.includes('mmbiz.qpic.cn')) {
-                        let newBg = bg?.replace('http://api.zanxiangnet.com/system/domain/forward?url=', '').replace(/'/ig, '&quot;')
-                        item.content = item.content?.replace(bg, newBg)
-                    }
-                })
-                return { ...item, showCoverPic: false, thumbUrl: item?.thumbUrl || item?.thumbMediaUrl }
-            })
-            let data: any = {
-                news,
-                folder: false,
-                fileType: 'news',
-                parentId,
-                belongUser,
-                sort
-            }
-            if (callback) {//假如有回调那么不请求接口保存直接执行回调函数
-                callback && callback(data)
-                dispatch({ type: 'initData' })
-                props.onClose()
-                return
-            }
-            if (isWx) {//执行微信接口
-                console.log('微信素材', props?.editId);
-                if (props?.editId) {//编辑走新建本地素材再同步到微信
-                    add.run({ ...data, mpIds: selectWx }).then((res: any) => {
-                        if (res) {
-                            if (isSaveNews) {//走保存去群发逻辑
-                                console.log('新建===》保存并群发', props)
-                                syncId.run({ mpIds: [actionWX?.id], sysMediaId: res }).then((syncWxres: any) => {
-                                    if (syncWxres) {
-                                        dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: syncWxres, msgType: 'mpnews' } } })
-                                        history.push(`/operatePage/news/advanced?show=true`)
-                                        dispatch({ type: 'initData' })
-                                        localStorage.setItem('collapsed', '0')
-                                    }
-                                })
-                            } else {
-                                syncId.run({ mpIds: [actionWX?.id], sysMediaId: res }).then((syncWxres: any) => {
-                                    if (syncWxres) {
-                                        console.log('新建==》保存')
-                                        dispatch({ type: 'initData' })
-                                        props.onClose()
-                                        getWeData.refresh().then((res) => {//刷新页面
-                                            contentDispatch({ type: 'initData', params: { data: res.records } })
-                                        })
-                                        localStorage.setItem('collapsed', '0')
-                                    }
-                                })
-                            }
-                        }
-                    })
-                } else {//新建
-                    addWx.run({ mpId: actionWX?.id, mediaType: 'news', news }).then((res: any) => {
-                        console.log(res)
-                        if (res) {
-                            if (isSaveNews) {//走保存去群发逻辑
-                                console.log('新建===》保存并群发', props)
-                                setId(res)
-                                setShowActionModal(true)
-                            } else {
-                                dispatch({ type: 'initData' })
-                                props.onClose()
-                                getWeData.refresh().then((res) => {//刷新页面
-                                    contentDispatch({ type: 'initData', params: { data: res.records } })
-                                })
-                                localStorage.setItem('collapsed', '0')
-                            }
-                        }
-                    })
-                }
-            } else {//执行本地
-                if (props?.editId) {//表示编辑
-                    edit.run({ belongUser, fileType: 'news', folder: false, news, sysMediaId: props?.editId, sort }).then((res: any) => {
-                        if (isSaveNews) {//走保存去群发逻辑
-                            console.log('编辑==》保存并群发', news, dataArr)
-                            setId(props?.editId)
-                            setShowActionModal(true)
-                        } else {
-                            console.log('编辑===》保存')
-                            dispatch({ type: 'initData' })
-                            props.onClose()
-                            list.refresh()
-                            localStorage.setItem('collapsed', '0')
-                        }
-                    })
-                    eidtWxlists.run({ sysMediaId: props?.editId, mpIds: selectWx || [] }).then((res) => {
-                        console.log(res, 'eidtWxlists')
-                        initSelectWx()
-                    })
-                } else {//新建
-                    add.run({ ...data, mpIds: selectWx }).then((res: any) => {
-                        if (res) {
-                            if (isSaveNews) {//走保存去群发逻辑
-                                console.log('新建===》保存并群发', props)
-                                setId(res)
-                                setShowActionModal(true)
-                                initSelectWx()
-                            } else {
-                                console.log('新建==》保存')
-                                dispatch({ type: 'initData' })
-                                props.onClose()
-                                list.refresh()
-                                localStorage.setItem('collapsed', '0')
-                                initSelectWx()
-                            }
-
-                        }
-                    })
-                }
-            }
-
-        }
-    }, [dataArr, props?.editId, ueditorRef, actionWX, getWeData, isWx, parentId, belongUser, list, selectWx, sort])
-    //保存并群发选择公众号后回调
-    const saverNews = useCallback((cancel: boolean) => {
-        setShowActionModal(false)
-        if (!cancel) {//假如cancel为false就是保持并群发
-            let news = dataArr.map((item: any) => { return { ...item, showCoverPic: false, thumbUrl: item?.thumbUrl || item?.thumbMediaUrl } })
-            console.log(news, dataArr, 'dataArr,news')
-            if (actionWX) {
-                if (isWx) {
-                    // dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: id, msgType: 'mpnews' } } })
-                    // history.push(`/operatePage/news/advanced?show=true`)
-                    // dispatch({ type: 'initData' })
-                    // localStorage.setItem('collapsed', '0')
-                } else {//本地素材先同步再群发
-                    syncId.run({ mpIds: [actionWX?.id], sysMediaId: id }).then((syncWxres: any) => {
-                        if (syncWxres) {
-                            // dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: syncWxres, msgType: 'mpnews' } } })
-                            // history.push(`/operatePage/news/advanced?show=true`)
-                            // dispatch({ type: 'initData' })
-                            // localStorage.setItem('collapsed', '0')
-                        }
-                    })
-                }
-            }
-            dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: id, msgType: 'mpnews' } } })
-            history.push(`/operatePage/news/advanced?show=true`)
-            dispatch({ type: 'initData' })
-            localStorage.setItem('collapsed', '0')
-        }
-    }, [actionWX, isWx, id, syncId, dataArr])
-    // //切换文章
-    useEffect(() => {
-        console.log('切换文章=====>', { sid, actionId, isImport })
-        if (sid !== actionId || isImport) {
-            setSid(actionId)
-            let content = dataArr?.filter((item: { menuId: any }) => item.menuId === actionId)[0]?.content
-            content = content !== '' ? content : '<p></p>'
-            console.log('切换后的content====>', content)
-            setContent(content)
-            if (isImport) {
-                dispatch({ type: 'overImport' }) //关闭导入
-            }
-        }
-    }, [actionId, dataArr, sid, isImport])
-    //编辑回填
-    const isOk = useCallback((ueditor) => {
-        console.log('props?.editData===>', props?.editData)
-        if (actionData) {
-            let dataArr = actionData.dataArr?.map((item: any, index: number) => {
-                item.menuId = index + 1
-                return item
-            })
-            // 存放到数据中心
-            dispatch({ type: 'initData', params: { data: { ...actionData, dataArr, actionId: 1 } } })
-            setContent(dataArr[0].content)
-        }
-    }, [props?.editData])
-    return <div >
-        <h3 style={{ height: 43, lineHeight: '43px', textAlign: 'center' }}>素材编辑</h3>
-        <Spin spinning={loding} tip='初始化中请稍等。。。'>
-            <Title />
-            {/* ================================ TEditor ============================== */}
-
-            <TEditor dispatch={dispatch} setLoding={setLoding} isOk={isOk} content={content} actionId={actionId} />
-
-            {/* ================================ UEditor ============================== */}
-            {/* <UEditor dispatch={dispatch}  setLoding={setLoding} isOk={isOk} setContent={setContent} isShowWx={isShowWx}/> */}
-            <Space className={style.btn}>
-                <Button onClick={() => { seve() }} type='primary' loading={add?.loading || edit?.loading || addWx?.loading}>保存素材</Button>
-                {syncNews && !callback && <Button onClick={() => { seve(true) }} type='primary' loading={add?.loading || addWx?.loading || edit?.loading || syncId?.loading}>保存并群发</Button>}
-                <Button onClick={() => { props.onClose(); initSelectWx() }} >取消</Button>
-            </Space>
-            <ActionModal visible={showActionModal} hideWx={saverNews} />
-        </Spin>
-    </div>
-}
-
-// ======================== UEditor =========================
-
-// export default function Editor(props: Props) {
-//     let { syncNews = true, isWx, isShowWx, isAll = true, callback = null } = props
-//     const [showActionModal, setShowActionModal] = useState<boolean>(false)//选择公众号弹窗
-//     const [id, setId] = useState<string>('')
-//     const [loding, setLoding] = useState<boolean>(true)
-//     const { getWeData } = useModel('useOperating.useMaterialContent')
-//     const { dispatchNews } = useModel('useOperating.useNews', model => ({ dispatchNews: model.dispatch }))
-//     const { dispatch, state } = useModel('useOperating.useMaterialDrawer')
-//     const { dispatch: contentDispatch } = useModel('useOperating.useMaterialContent')
-//     const { actionId, actionIdold, dataArr, actionData, ueditorRef, sort = 0 } = state
-//     const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-//     //
-//     const { add, list, edit, syncId, addWx, state: { parentId, belongUser }, eidtWxlists } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-//     const { state: { selectWx }, initSelectWx } = useModel('useOperating.useWxGroupList')//公众号筛选
-//     const [sid, setSid] = useState<number>(0)//已经切换设置过的ID
-//     const [content, setContent] = useState<string>('<p></p>')//内容
-//     const editorRef:any = useRef(null);
-
-//     //保存
-//     let seve = useCallback((isSaveNews?: boolean) => {
-//         let content = ueditorRef?.getContent()
-//         let menuId = actionIdold || actionId
-//         dispatch({ type: 'pushData', params: { content } })
-//         let isOk = dataArr.every((item: any) => {
-//             let img = item?.thumbMediaUrl || item?.thumbUrl
-//             if (!item.title) {
-//                 message.error(`第${item.menuId}篇标题为空`)
-//                 return false
-//             }
-//             if (!img) {
-//                 message.error(`第${item.menuId}篇封面为空`)
-//                 return false
-//             }
-//             if (item?.digest?.length > 54) {
-//                 message.error(`第${item.menuId}摘要不能超过54个字`)
-//                 return false
-//             }
-//             if (item.content === '<p></p>' || !item.content) {
-//                 message.error(`第${item.menuId}篇内容为空`)
-//                 return false
-//             }
-//             // if (!item.contentSourceUrl) {
-//             //     message.error(`第${item.menuId}原文链接为空`)
-//             //     return false
-//             // }
-//             return true
-//         })
-//         if (isOk) {
-//             let news = dataArr.map((item: any) => {
-//                 return { ...item, showCoverPic: false, thumbUrl: item?.thumbUrl || item?.thumbMediaUrl }
-//             })
-//             let data: any = {
-//                 news,
-//                 folder: false,
-//                 fileType: 'news',
-//                 parentId,
-//                 belongUser,
-//                 sort
-//             }
-//             if (callback) {//假如有回调那么不请求接口保存直接执行回调函数
-//                 callback && callback(data)
-//                 dispatch({ type: 'initData' })
-//                 props.onClose()
-//                 return
-//             }
-//             if (isWx) {//执行微信接口
-//                 console.log('微信素材', props?.editId);
-//                 if (props?.editId) {//编辑走新建本地素材再同步到微信
-//                     add.run({ ...data, mpIds: selectWx }).then((res: any) => {
-//                         if (res) {
-//                             if (isSaveNews) {//走保存去群发逻辑
-//                                 console.log('新建===》保存并群发', props)
-//                                 syncId.run({ mpIds: [actionWX?.id], sysMediaId: res }).then((syncWxres: any) => {
-//                                     if (syncWxres) {
-//                                         dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: syncWxres, msgType: 'mpnews' } } })
-//                                         history.push(`/operatePage/news/advanced?show=true`)
-//                                         dispatch({ type: 'initData' })
-//                                         localStorage.setItem('collapsed', '0')
-//                                     }
-//                                 })
-//                             } else {
-//                                 syncId.run({ mpIds: [actionWX?.id], sysMediaId: res }).then((syncWxres: any) => {
-//                                     if (syncWxres) {
-//                                         console.log('新建==》保存')
-//                                         dispatch({ type: 'initData' })
-//                                         props.onClose()
-//                                         getWeData.refresh().then((res) => {//刷新页面
-//                                             contentDispatch({ type: 'initData', params: { data: res.records } })
-//                                         })
-//                                         localStorage.setItem('collapsed', '0')
-//                                     }
-//                                 })
-//                             }
-//                         }
-//                     })
-//                 } else {//新建
-//                     addWx.run({ mpId: actionWX?.id, mediaType: 'news', news }).then((res: any) => {
-//                         console.log(res)
-//                         if (res) {
-//                             if (isSaveNews) {//走保存去群发逻辑
-//                                 console.log('新建===》保存并群发', props)
-//                                 setId(res)
-//                                 setShowActionModal(true)
-//                             } else {
-//                                 dispatch({ type: 'initData' })
-//                                 props.onClose()
-//                                 getWeData.refresh().then((res) => {//刷新页面
-//                                     contentDispatch({ type: 'initData', params: { data: res.records } })
-//                                 })
-//                                 localStorage.setItem('collapsed', '0')
-//                             }
-//                         }
-//                     })
-//                 }
-//             } else {//执行本地
-//                 if (props?.editId) {//表示编辑
-//                     edit.run({ belongUser, fileType: 'news', folder: false, news, sysMediaId: props?.editId, sort }).then((res: any) => {
-//                         if (isSaveNews) {//走保存去群发逻辑
-//                             console.log('编辑==》保存并群发', news, dataArr)
-//                             setId(props?.editId)
-//                             setShowActionModal(true)
-//                         } else {
-//                             console.log('编辑===》保存')
-//                             dispatch({ type: 'initData' })
-//                             props.onClose()
-//                             list.refresh()
-//                             localStorage.setItem('collapsed', '0')
-//                         }
-//                     })
-//                     eidtWxlists.run({ sysMediaId: props?.editId, mpIds: selectWx || [] }).then((res) => {
-//                         console.log(res, 'eidtWxlists')
-//                         initSelectWx()
-//                     })
-//                 } else {//新建
-//                     add.run({ ...data, mpIds: selectWx }).then((res: any) => {
-//                         if (res) {
-//                             if (isSaveNews) {//走保存去群发逻辑
-//                                 console.log('新建===》保存并群发', props)
-//                                 setId(res)
-//                                 setShowActionModal(true)
-//                                 initSelectWx()
-//                             } else {
-//                                 console.log('新建==》保存')
-//                                 dispatch({ type: 'initData' })
-//                                 props.onClose()
-//                                 list.refresh()
-//                                 localStorage.setItem('collapsed', '0')
-//                                 initSelectWx()
-//                             }
-
-//                         }
-//                     })
-//                 }
-//             }
-
-//         }
-//     }, [dataArr, props?.editId, ueditorRef, actionWX, getWeData, isWx, parentId, belongUser, list, selectWx, sort])
-//     //保存并群发选择公众号后回调
-//     const saverNews = useCallback((cancel: boolean) => {
-//         setShowActionModal(false)
-//         if (!cancel) {//假如cancel为false就是保持并群发
-//             let news = dataArr.map((item: any) => { return { ...item, showCoverPic: false, thumbUrl: item?.thumbUrl || item?.thumbMediaUrl } })
-//             console.log(news, dataArr, 'dataArr,news')
-//             if (actionWX) {
-//                 if (isWx) {
-//                     // dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: id, msgType: 'mpnews' } } })
-//                     // history.push(`/operatePage/news/advanced?show=true`)
-//                     // dispatch({ type: 'initData' })
-//                     // localStorage.setItem('collapsed', '0')
-//                 } else {//本地素材先同步再群发
-//                     syncId.run({ mpIds: [actionWX?.id], sysMediaId: id }).then((syncWxres: any) => {
-//                         if (syncWxres) {
-//                             // dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: syncWxres, msgType: 'mpnews' } } })
-//                             // history.push(`/operatePage/news/advanced?show=true`)
-//                             // dispatch({ type: 'initData' })
-//                             // localStorage.setItem('collapsed', '0')
-//                         }
-//                     })
-//                 }
-//             }
-//             dispatchNews({ type: 'theEdit', params: { theEdit: { content: { news }, mediaId: id, msgType: 'mpnews' } } })
-//             history.push(`/operatePage/news/advanced?show=true`)
-//             dispatch({ type: 'initData' })
-//             localStorage.setItem('collapsed', '0')
-//         }
-//     }, [actionWX, isWx, id, syncId, dataArr])
-//     // //切换文章
-//     useEffect(() => {
-//         if (!ueditorRef?.body) {
-//             return
-//         }
-//         if (sid !== actionId) {
-//             setSid(actionId)
-//             let content = dataArr?.filter((item: { menuId: any }) => item.menuId === actionId)[0]?.content || '<p></p>'
-//             ueditorRef?.setContent(content, false)
-//         }
-//     }, [actionId, dataArr, ueditorRef?.body, sid])
-//     // 内容变化设置
-//     useEffect(() => {
-//         if (ueditorRef?.body) {
-//             dispatch({ type: 'pushData', params: { menuId: actionId, content: content || '<p></p>' } })
-//         }
-
-//     }, [ueditorRef?.body, content, actionId])
-//     //编辑回填
-//     const isOk = useCallback((ueditor) => {
-//         if (actionData) {
-//             let dataArr = actionData.dataArr?.map((item: any, index: number) => {
-//                 item.menuId = index + 1
-//                 return item
-//             })
-//             dispatch({ type: 'initData', params: { data: { ...actionData, dataArr, actionId: 1 } } })
-//             ueditor?.setContent(dataArr[0].content, false)
-//         }
-//     }, [props?.editData, ueditorRef?.setContent])
-//     return <div >
-//         <h3 style={{ height: 43, lineHeight: '43px', textAlign: 'center' }}>素材编辑</h3>
-//         <Spin spinning={loding} tip='初始化中请稍等。。。'>
-//             <Title />
-//             {/* ================================ TEditor ============================== */}
-
-//             {/* <TEditor dispatch={dispatch}  setLoding={setLoding} isOk={isOk} content={content}/> */}
-
-//              {/* ================================ UEditor ============================== */}
-//             <UEditor dispatch={dispatch}  setLoding={setLoding} isOk={isOk} setContent={setContent} isShowWx={isShowWx}/>
-//             <Space className={style.btn}>
-//                 <Button onClick={() => { seve() }} type='primary' loading={add?.loading || edit?.loading || addWx?.loading}>保存素材</Button>
-//                 {syncNews && !callback && <Button onClick={() => { seve(true) }} type='primary' loading={add?.loading || addWx?.loading || edit?.loading || syncId?.loading}>保存并群发</Button>}
-//                 <Button onClick={() => { props.onClose(); initSelectWx() }} >取消</Button>
-//             </Space>
-//             <ActionModal visible={showActionModal} hideWx={saverNews} />
-//         </Spin>
-//     </div>
-// }
-

+ 0 - 22
src/components/Editor/Button.js

@@ -1,22 +0,0 @@
-import React from 'react'
-
-const buttonStyle = {
-  height: '24px',
-  fontWeight: '500',
-  cursor: 'pointer',
-  padding: '0 15px',
-  fontSize: '12px',
-  color: 'rgba(0,0,0,.65)',
-  border: '1px solid #d9d9d9',
-  marginLeft: '10px',
-}
-
-class Button extends React.PureComponent {
-  render() {
-    let {style, children, onClick} = this.props
-    let mergedStyle = {...buttonStyle, ...style}
-    return <button style={mergedStyle} onClick={onClick}>{children}</button>
-  }
-}
-
-export default Button

+ 0 - 25
src/components/Editor/Input.js

@@ -1,25 +0,0 @@
-import React from 'react'
-
-const inputStyle = {
-  height: '18px',
-  width: '72px',
-  boxSizing: 'content-box',
-  fontSize: '12px',
-  lineHeight: '18px',
-  color: 'rgba(0,0,0,.65)',
-  backgroundColor: '#fff',
-  border: '1px solid #d9d9d9',
-  borderRadius: '4px',
-  padding: '1px 3px',
-  margin: '0 10px',
-}
-
-class Input extends React.PureComponent {
-  render() {
-    let {type, value, onChange, style} = this.props
-    let mergedStyle = {...inputStyle, ...style}
-    return <input style={mergedStyle} type={type} value={value} onChange={onChange} />
-  }
-}
-
-export default Input

+ 0 - 24
src/components/Editor/Label.js

@@ -1,24 +0,0 @@
-import React from 'react'
-
-const labelStyle = {
-  display: 'block',
-  width: '165px',
-  color: 'rgba(0, 0, 0, 0.65)',
-  marginRight: '20px',
-  marginBottom: '10px',
-}
-
-const labelName = {
-  display: 'inline-block',
-  width: '50px',
-}
-
-class Label extends React.PureComponent {
-  render() {
-    let {style, children, name} = this.props
-    let mergedStyle = {...labelStyle, ...style}
-    return <label style={mergedStyle}><span style={labelName}>{name}</span>{children}</label>
-  }
-}
-
-export default Label

+ 0 - 101
src/components/Editor/Link.js

@@ -1,101 +0,0 @@
-import Input from './Input'
-import React from 'react'
-
-let inputStyle = {
-  width: '300px',
-}
-let spanStyle = {
-  fontSize: '14px',
-  color: 'rgba(0, 0, 0, 0.65)',
-  display: 'inline-block',
-  width: '80px',
-}
-let formItmeStyle = {
-  marginBottom: '10px',
-}
-
-class Link extends React.Component {
-  state = {
-    text: '',
-    link: '',
-    title: '',
-    newTab: false,
-    showTips: false,
-  }
-
-  hasProtocol = link => {
-    if (link.match(/^http:|https:/) || link.match(/^\/\//)) {
-      return true
-    }
-    return false
-  }
-
-  generateHtml = () => {
-    let {text, link, title, newTab} = this.state
-
-    if (link) {
-      let html = ''
-
-      if (!this.hasProtocol(link)) {
-        link = 'http://' + link
-      }
-
-      html += `<a href="${link}" target=${newTab ? '_blank' : '_self'} title="${title}">${text || link}</a>`
-
-      return html
-    }
-  }
-
-  changeConfig = (e, type) => {
-    let value = e.target.value
-    let boolType = ['newTab']
-    if (boolType.indexOf(type) !== -1) {
-      value = !!value
-    }
-
-    if (type == 'link') {
-      if (!this.hasProtocol(value)) {
-        this.setState({
-          showTips: true,
-        })
-      } else {
-        this.setState({
-          showTips: false,
-        })
-      }
-    }
-    if (type == 'newTab') {
-      return this.setState({newTab: !this.state.newTab})
-    }
-    this.setState({[type]: value}, () => {
-      this.props.onChange && this.props.onChange(this.generateHtml())
-    })
-  }
-
-  render() {
-    let {text, link, title, newTab, showTips} = this.state
-    return (
-      <form>
-        <div style={formItmeStyle}>
-          <span style={spanStyle}>文本内容:</span>
-          <Input type='text' style={inputStyle} value={text} onChange={e => this.changeConfig(e, 'text')} />
-        </div>
-        <div style={formItmeStyle}>
-          <span style={spanStyle}>链接地址:</span>
-          <Input type='text' style={inputStyle} value={link} onChange={e => this.changeConfig(e, 'link')} />
-        </div>
-        <div style={formItmeStyle}>
-          <span style={spanStyle}>标题:</span>
-          <Input type='text' style={inputStyle} value={title} onChange={e => this.changeConfig(e, 'title')} />
-        </div>
-        <div style={formItmeStyle}>
-          <span style={{color: 'rgba(0, 0, 0, 0.65)', fontSize: '14px'}}>是否在新窗口打开:</span>
-          <input type='checkbox' checked={newTab} onChange={e => this.changeConfig(e, 'newTab')} />
-        </div>
-        {showTips && <p style={{fontSize: '14px', color: 'red'}}>您输入的超链接中不包含http等协议名称,默认将为您添加http://前缀</p>}
-      </form>
-    )
-  }
-}
-
-export default Link

+ 0 - 57
src/components/Editor/Modal.js

@@ -1,57 +0,0 @@
-import Button from './Button'
-import Dialog from 'rc-dialog'
-import PropTypes from 'prop-types'
-import React from 'react'
-import 'rc-dialog/assets/index.css'
-
-class Modal extends React.PureComponent {
-  static propTypes = {
-    title: PropTypes.string,
-    visible: PropTypes.bool,
-    beforeClose: PropTypes.func,
-    onClose: PropTypes.func,
-    onConfirm: PropTypes.func,
-  }
-
-  static defaultProps = {
-    title: '',
-    visible: false,
-    zIndex: 1050,
-    alignStyle: 'top',
-    extendControls: [],
-    debug: false,
-  }
-
-  closeModal = () => {
-    this.props.beforeClose && this.props.beforeClose()
-    this.props.onClose()
-  }
-
-  onConfirm = () => {
-    this.props.onConfirm && this.props.onConfirm()
-    this.closeModal()
-  }
-
-  render() {
-    let {title, visible, zIndex, alignStyle} = this.props
-
-    return (
-      <Dialog
-        title={title}
-        onClose={this.closeModal}
-        visible={visible}
-        footer={[
-          <Button key='close' onClick={this.closeModal}>取消</Button>,
-          <Button key='insert' onClick={this.onConfirm}>确认</Button>,
-        ]}
-        animation='zome'
-        maskAnimation='fade'
-        zIndex={zIndex}
-        style={alignStyle === 'middle' ? {top: '50%', transform: 'translateY(-50%)'} : {}}>
-        {this.props.component}
-      </Dialog>
-    )
-  }
-}
-
-export default Modal

+ 0 - 472
src/components/Editor/ReactUeditor.js

@@ -1,472 +0,0 @@
-import Link from './Link';
-import Modal from './Modal';
-import PropTypes from 'prop-types';
-import React from 'react';
-import VideoUploader from './VideoUploader';
-import AudioUploader from './AudioUploader';
-import * as utils from './utils';
-
-const MODE = {
-  INTERNAL_MODAL: 'internal-modal',
-  MODAL: 'modal',
-  NORMAL: 'normal',
-};
-
-function isModalMode(mode) {
-  return mode === MODE.INTERNAL_MODAL || mode === MODE.MODAL;
-}
-
-const simpleInsertCodeIcon =
-  'data:img/jpg;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAB9klEQVRYR+2Wy' +
-  '23CQBCGZxwUASdKgA7IIdIukhF0QCoI6YAS6CB0EDpIOgjCEbs3nApCB+EEKFI80ToYgR/7IEhIEb4hvPN/8/jHi3DmB8+sDxeA/1GBdosNi' +
-  'TAMhHhxnamTVMDnfAEAo0CI0ckBOs1mbRKGy6LArdZtswSl+VdEDSmlAtk9prPqRW0FfMb66OGjt1o3iiB8zgcAMAiEqKfFo0p5QQSDQMpxU' +
-  'QKFAFvxJ4roQRfA52yCgOFUCAVy8NjEyAWwOaiUVImjauWTCO6KBtAUKwNgOrCfos95DxGepzNh08rcah4cdBFXID5nY0CsBTPRM01/Uewdg' +
-  'Ku4EmxztiTAoa398jRigGPEdfbTVSOthUkfTdOeDrrdfv20/UytSCeMKhAQ3HvrzY1u4WQs1mIhEk7y7GeCiN1TKc8J8R3Vj+9qWXmZvNW6a' +
-  'wOR2C+KqPsm5cQkmFlQ1corAeHVatOJZ8AVIu4jwmgqZO0v4irZnQtcIFzslwBuq7bLPKn0wR6whYjtZ9jxurLvtzmzwUwQrvYryjwBzF2hO' +
-  'ojYfgC9YCabpv6bxLWf4yII39J+NuLG+8BvkPJgOpND9TJjrH7t4Yet/VS1vNVmpLO205XsWPvpWuUGoD6/AJ1jtp/zjcg0YKf636kCpxLdj' +
-  '3MBOHsFfgBLLaBN8r49lAAAAABJRU5ErkJggg==';
-const uploadAudioIcon =
-  'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAACBUlEQVRYR+1VwXHbMBC8' +
-  'qyBxBXI6cCqwUkEOFUSuIHYFliuwUoGVCrAdWOlA6UCuIOpgPashNRQIOtJkHH2ID2eIA25vD7vndublZ85vI4CRgZGBkxmIiI9mdm9mMzNb' +
-  'AHgYknJEzM3sA4C7oZiTAEREmNmTuwvEi5lNSH4GsK4liIiFu38nuQRwU4s5CkBTtRILwAvJWzPbuvszyS8AVhFxZWbXAH50E0XE0t2/kbwB' +
-  'sCxBVAFExKW7TxRMUhfPVTVJXT4HsI2IaQHg1t0fFQNAAPcrpbQhqVZc/BWAaHb3XASq6pkqbf+XAPQ/pQQz+9qy0omdufsTyQRAMfvVYyCl' +
-  'pCSXLc1N5FpVF9QeMKA9tcrd/5D8CUCPdLc6/3vsDAGwnPP0rUFVY6BhYUVyAuBT0QYVsC7vfQ8AuzbknA/ubpjtFfYeANTCq5yzpNp9iJLq' +
-  '9n8wIKpXOWdJtguA5dvQZpUB9dDdd1pXEMnfRz5CyfW+1HyrrJoX9ADUZEhyY2YykkEZds79KmnuyPOiLGTIiNQ/GZCWTGkhTyep78OAEck/' +
-  'Zo1f7CXbUUtPgtUW1KTX6Fg2KpPR5fL1AyseONfODhnZtKz+aAAdQ1GVYkFDaOPuMqzBYdRITxZeTX4ygNbVmtkgujWONXKrqxliVqu8PXDU' +
-  'NHzLEf91bwQwMjAycHYGXgGLbI8w70amwwAAAABJRU5ErkJggg==';
-
-class ReactUeditor extends React.Component {
-  constructor(props) {
-    super(props);
-    this.content = props.value || ''; // 存储编辑器的实时数据,用于传递给父组件
-    this.ueditor = null;
-    this.isContentChangedByWillReceiveProps = false;
-    this.tempfileInput = null;
-    this.containerID = 'reactueditor' + Math.random().toString(36).substr(2);
-    this.fileInputID = 'fileinput' + Math.random().toString(36).substr(2);
-    this.pasteImageAmount = 0;
-    this.state = {
-      videoSource: '',
-      audioSource: '',
-      extendControls: this.props.extendControls ? this.props.extendControls : [],
-      videoHtml: '',
-      audioHtml: '',
-      pluginsWithCustomRender: [],
-    };
-  }
-
-  static propTypes = {
-    value: PropTypes.string,
-    ueditorPath: PropTypes.string.isRequired,
-    plugins: PropTypes.array,
-    onChange: PropTypes.func,
-    uploadImage: PropTypes.func,
-    getRef: PropTypes.func,
-    multipleImagesUpload: PropTypes.bool,
-    onReady: PropTypes.func,
-    pasteImageStart: PropTypes.func,
-    handlePasteImage: PropTypes.func,
-    pasteImageDone: PropTypes.func,
-    extendControls: PropTypes.array,
-    debug: PropTypes.bool,
-  };
-
-  static defaultProps = {
-    value: '',
-    multipleImagesUpload: false,
-    extendControls: [],
-    debug: false,
-  };
-
-  componentDidMount() {
-    let { ueditorPath } = this.props;
-    if (!window.UE && !window.UE_LOADING_PROMISE) {
-      window.UE_LOADING_PROMISE = this.createScript(ueditorPath + '/ueditor.config.js').then(() => {
-        return this.createScript(ueditorPath + '/ueditor.all.min.js')
-      });
-    }
-    window.UE_LOADING_PROMISE.then(() => {
-      this.tempfileInput = document.getElementById(this.fileInputID);
-      this.initEditor();
-    });
-  }
-
-  /**
-   * 这里存在两种情况会改变编辑器的内容:
-   * 1. 父组件初始化传递的 value。父组件 value 的获取是异步的,因此会触发一次 componentWillReceiveProps,这种情况不需要将更新再通知父组件
-   * 2. 用户对编辑器进行编辑
-   */
-  componentWillReceiveProps(nextProps) {
-    if ('value' in nextProps && this.props.value !== nextProps.value) {
-      this.isContentChangedByWillReceiveProps = true;
-      this.content = nextProps.value;
-      if (this.ueditor) {
-        this.ueditor.ready(() => {
-          this.ueditor.setContent(nextProps.value);
-        });
-      }
-    }
-  }
-
-  componentWillUnmount() {
-    if (this.ueditor) {
-      this.ueditor.destroy();
-    }
-  }
-
-  createScript = (url) => {
-    let scriptTags = window.document.querySelectorAll('script');
-    let len = scriptTags.length;
-    let i = 0;
-    let _url = window.location.origin + url;
-    return new Promise((resolve, reject) => {
-      for (i = 0; i < len; i++) {
-        var src = scriptTags[i].src;
-        if (src && src === _url) {
-          scriptTags[i].parentElement.removeChild(scriptTags[i]);
-        }
-      }
-
-      let node = document.createElement('script');
-      node.src = url;
-      node.onload = resolve;
-      document.body.appendChild(node);
-    });
-  };
-
-  registerInternalPlugin(pluginName) {
-    switch (pluginName) {
-      case 'uploadImage':
-        return this.registerImageUpload();
-      case 'insertCode':
-        return this.registerSimpleInsertCode();
-      case 'uploadVideo':
-        return this.registerUploadVideo();
-      case 'uploadAudio':
-        return this.registerUploadAudio();
-      case 'insertLink':
-        return this.registerLink();
-      default:
-        return;
-    }
-  }
-
-  registerPlugin(plugin) {
-    let name = Math.random().toString(36).slice(2);
-    if (window.UE.registerUI) {
-      window.UE.registerUI(
-        name,
-        (ueditor, uiName) => {
-          let config = plugin(ueditor);
-          if (!config.mode) {
-            config.mode = MODE.MODAL;
-          }
-          var btn = new window.UE.ui.Button({
-            name: uiName,
-            title: config.menuText,
-            cssRules: config.cssRules || '',
-            onclick: isModalMode(config.mode)
-              ? () => {
-                  this.setState({ [this.getVisibleName(name)]: true });
-                  config.onIconClick && config.onIconClick();
-                }
-              : config.onIconClick,
-          });
-          if (config.render) {
-            this.setState((prevState) => ({
-              pluginsWithCustomRender: [...prevState.pluginsWithCustomRender, { name, ...config }],
-            }));
-          }
-          return btn;
-        },
-        undefined,
-        this.containerID,
-      );
-    }
-  }
-
-  registerImageUpload = () =>
-    this.registerPlugin(() => ({
-      menuText: '图片上传',
-      cssRules: 'background-position: -726px -77px;',
-      mode: MODE.NORMAL,
-      onIconClick: () => {
-        this.tempfileInput.click();
-      },
-    }));
-
-  registerSimpleInsertCode = () =>
-    this.registerPlugin((ueditor) => ({
-      menuText: '插入代码',
-      cssRules:
-        'background: url(' +
-        simpleInsertCodeIcon +
-        ') !important; background-size: 20px 20px !important;',
-      mode: MODE.NORMAL,
-      onIconClick: () => {
-        ueditor.focus();
-        ueditor.execCommand('insertcode');
-      },
-    }));
-
-  registerUploadVideo = () => {
-    let { uploadVideo, progress } = this.props;
-    return this.registerPlugin((ueditor) => ({
-      menuText: '上传视频',
-      cssRules: 'background-position: -320px -20px;',
-      mode: MODE.INTERNAL_MODAL,
-      render: () => (
-        <VideoUploader upload={uploadVideo} progress={progress} onChange={this.videoChange} />
-      ),
-      onConfirm: () => {
-        ueditor.execCommand('insertparagraph');
-        ueditor.execCommand('inserthtml', this.state.videoHtml, true);
-        ueditor.execCommand('insertparagraph');
-        ueditor.execCommand('insertparagraph');
-      },
-    }));
-  };
-
-  registerUploadAudio = () => {
-    let { uploadAudio, progress } = this.props;
-    return this.registerPlugin((ueditor) => ({
-      menuText: '上传音频',
-      cssRules:
-        'background: url(' +
-        uploadAudioIcon +
-        ') !important; background-size: 20px 20px !important;',
-      mode: MODE.INTERNAL_MODAL,
-      render: () => (
-        <AudioUploader upload={uploadAudio} progress={progress} onChange={this.audioChange} />
-      ),
-      onConfirm: () => {
-        ueditor.execCommand('insertparagraph');
-        ueditor.execCommand('inserthtml', this.state.audioHtml, true);
-        ueditor.execCommand('insertparagraph');
-        ueditor.execCommand('insertparagraph');
-      },
-    }));
-  };
-
-  registerLink = () =>
-    this.registerPlugin((ueditor) => ({
-      menuText: '超链接',
-      cssRules: 'background-position: -504px 0px;',
-      mode: MODE.INTERNAL_MODAL,
-      render: () => <Link onChange={this.linkChange} />,
-      onConfirm: () => {
-        ueditor && ueditor.execCommand('inserthtml', this.state.linkHtml, true);
-      },
-    }));
-
-  videoChange = (videoHtml) => {
-    this.setState({ videoHtml });
-  };
-
-  audioChange = (audioHtml) => {
-    this.setState({ audioHtml });
-  };
-
-  linkChange = (linkHtml) => {
-    this.setState({ linkHtml });
-  };
-
-  uploadImage = (e) => {
-    let { uploadImage } = this.props;
-    if (uploadImage) {
-      let promise = uploadImage(e);
-      if (!!promise && typeof promise.then == 'function') {
-        promise.then((imageUrl) => {
-          if (imageUrl instanceof Array) {
-            imageUrl.forEach((url) => {
-              this.insertImage(url);
-            });
-          } else {
-            this.insertImage(imageUrl);
-          }
-        });
-      }
-    }
-    this.tempfileInput.value = '';
-  };
-
-  insertImage = (imageUrl) => {
-    if (this.ueditor) {
-      this.ueditor.focus();
-      this.ueditor.execCommand('inserthtml', '<img src="' + imageUrl + '" />');
-    }
-  };
-
-  handlePasteImage = () => {
-    let { pasteImageStart, handlePasteImage, pasteImageDone } = this.props;
-    if (!handlePasteImage) return;
-
-    let html = this.ueditor.getContent();
-    let images = utils.extractImageSource(html);
-
-    if (Object.prototype.toString.call(images) !== '[object Array]') return;
-
-    this.pasteImageAmount += images.length;
-    pasteImageStart && pasteImageStart(this.pasteImageAmount);
-    images.forEach((src) => {
-      let promise = handlePasteImage(src);
-      if (!!promise && typeof promise.then == 'function') {
-        promise.then((newSrc) => {
-          --this.pasteImageAmount;
-          if (this.pasteImageAmount === 0) {
-            pasteImageDone && pasteImageDone();
-          }
-          let newHtml = utils.replaceImageSource(this.ueditor.getContent(), src, newSrc);
-          this.ueditor.setContent(newHtml);
-        });
-      }
-    });
-  };
-
-  getVisibleName = (name) => {
-    return name + 'VisibleModal';
-  };
-
-  getRegisterUIName = (name) => {
-    return `${name}-${this.containerID}`;
-  };
-
-  initEditor = () => {
-    if (!window.UE.getEditor) {
-      return;
-    }
-    const { config, plugins, onChange, value, getRef, onReady } = this.props;
-
-    if (plugins && Array.isArray(plugins)) {
-      plugins.forEach((plugin) => {
-        if (typeof plugin === 'string') {
-          return this.registerInternalPlugin(plugin);
-        } else {
-          return this.registerPlugin(plugin);
-        }
-      });
-    }
-
-    // 即将废弃
-    this.state.extendControls.forEach((control) => {
-      window.UE.registerUI(
-        this.getRegisterUIName(control.name),
-        (editor, uiName) => {
-          var btn = new window.UE.ui.Button({
-            name: uiName,
-            title: control.menuText,
-            cssRules: control.cssRules ? control.cssRules : '',
-            onclick: () => {
-              this.setState({ [this.getVisibleName(control.name)]: true });
-            },
-          });
-          return btn;
-        },
-        undefined,
-        this.containerID,
-      );
-    });
-
-    this.ueditor = config
-      ? window.UE.getEditor(this.containerID, config)
-      : window.UE.getEditor(this.containerID);
-    this.ueditor._react_ref = this;
-    this.ueditor.ready(() => {
-      this.ueditor.addListener('contentChange', () => {
-        // 由 componentWillReceiveProps 导致的 contentChange 不需要通知父组件
-        if (this.isContentChangedByWillReceiveProps) {
-          this.isContentChangedByWillReceiveProps = false;
-        } else {
-          this.content = this.ueditor.getContent();
-          onChange && onChange(this.content);
-        }
-      });
-
-      this.ueditor.addListener('afterpaste', () => {
-        this.handlePasteImage();
-      });
-
-      if (this.isContentChangedByWillReceiveProps) {
-        this.isContentChangedByWillReceiveProps = false;
-        this.ueditor.setContent(this.content);
-      } else {
-        this.ueditor.setContent(value);
-      }
-
-      onReady && onReady(this.ueditor);
-    });
-    getRef && getRef(this.ueditor);
-  };
-
-  render() {
-    let { extendControls } = this.state;
-    let { multipleImagesUpload } = this.props;
-
-    return (
-      <div>
-        <script id={this.containerID} name={this.containerID} type="text/plain" />
-        <input
-          type="file"
-          id={this.fileInputID}
-          onChange={this.uploadImage}
-          style={{ visibility: 'hidden', width: 0, height: 0, margin: 0, padding: 0, fontSize: 0 }}
-          multiple={multipleImagesUpload}
-        />
-        {this.state.pluginsWithCustomRender.map((plugin) => {
-          const visible = !!this.state[this.getVisibleName(plugin.name)];
-          const onClose = () => {
-            if (isModalMode(plugin.mode)) {
-              this.setState({ [this.getVisibleName(plugin.name)]: false });
-            }
-            plugin.onClose && typeof plugin.onClose === 'function' && plugin.onClose();
-          };
-          if (plugin.mode === MODE.INTERNAL_MODAL) {
-            return (
-              <Modal
-                key={plugin.name}
-                title={plugin.title || plugin.menuText}
-                zIndex={plugin.zIndex}
-                alignStyle={plugin.alignStyle}
-                visible={visible}
-                beforeClose={plugin.beforeClose}
-                onClose={onClose}
-                onConfirm={plugin.onConfirm}
-                component={plugin.render()}
-              />
-            );
-          } else if (plugin.mode === MODE.MODAL) {
-            return <div key={plugin.name}>{plugin.render(visible, onClose)}</div>;
-          } else if (plugin.mode === MODE.NORMAL) {
-            return <div key={plugin.name}>{plugin.render()}</div>;
-          }
-        })}
-        {
-          // 即将废弃
-          extendControls.map((control) => (
-            <Modal
-              key={control.name + this.containerID}
-              name={control.name}
-              menuText={control.menuText}
-              title={control.title}
-              zIndex={control.zIndex}
-              alignStyle={control.alignStyle}
-              visible={
-                this.state[this.getVisibleName(control.name)]
-                  ? this.state[this.getVisibleName(control.name)]
-                  : false
-              }
-              beforeClose={control.beforeClose}
-              onClose={() => {
-                this.setState({ [this.getVisibleName(control.name)]: false });
-              }}
-              onConfirm={control.onConfirm}
-              component={control.component}
-            />
-          ))
-        }
-      </div>
-    );
-  }
-}
-
-export default ReactUeditor;

+ 0 - 22
src/components/Editor/Select.js

@@ -1,22 +0,0 @@
-import React from 'react'
-
-const selectStyle = {
-  height: '22px',
-  width: '80px',
-  fontSize: '14px',
-  color: 'rgba(0,0,0,.65)',
-  backgroundColor: '#fff',
-  border: '1px solid #d9d9d9',
-  borderRadius: '4px',
-  marginLeft: '10px',
-}
-
-class Select extends React.PureComponent {
-  render() {
-    let {style, children, defaultValue, onChange} = this.props
-    let mergedStyle = {...selectStyle, ...style}
-    return <select style={mergedStyle} defaultValue={defaultValue} onChange={onChange}>{children}</select>
-  }
-}
-
-export default Select

+ 0 - 45
src/components/Editor/Tag.js

@@ -1,45 +0,0 @@
-import React from 'react'
-
-const tagStyle = {
-  wrapper: {
-    display: 'inline-block',
-    lineHeight: '22px',
-    height: '22px',
-    padding: '0 0 0 8px',
-    borderRadius: '4px',
-    border: '1px solid #e9e9e9',
-    backgroundColor: '#f3f3f3',
-    fontSize: '13px',
-    color: 'rgba(0, 0, 0, 0.65)',
-    margin: '5px',
-  },
-  text: {
-    display: 'inline-block',
-    maxWidth: '500px',
-    overflow: 'hidden',
-    textOverflow: 'ellipsis',
-    whiteSpace: 'nowrap',
-  },
-  icon: {
-    display: 'inline-block',
-    width: '25px',
-    textAlign: 'center',
-    float: 'right',
-    cursor: 'pointer',
-  },
-}
-
-class Tag extends React.PureComponent {
-  render() {
-    let {value, index, onRemove, style, key} = this.props
-    let mergedStyle = {...tagStyle.wrapper, ...style}
-    return (
-      <span style={mergedStyle} key={key}>
-        <span style={tagStyle.text}>{value}</span>
-        <i style={tagStyle.icon} onClick={() => { onRemove(index) }}>×</i>
-      </span>
-    )
-  }
-}
-
-export default Tag

+ 0 - 38
src/components/Editor/Upload.js

@@ -1,38 +0,0 @@
-import React from 'react'
-
-const uploadStyle = {
-  height: '26px',
-  width: '80px',
-  display: 'inline-block',
-  boxSizing: 'border-box',
-  lineHeight: '25px',
-  textAlign: 'center',
-  borderRadius: '4px',
-  border: '1px solid transparent',
-  fontSize: '12px',
-  fontWeight: '500',
-  color: '#fff',
-  backgroundColor: '#108ee9',
-  cursor: 'pointer',
-  marginLeft: '10px',
-}
-
-class Upload extends React.PureComponent {
-  onInputChange = e => {
-    let props = this.props
-    if (props.onChange) {
-      props.onChange(e)
-    }
-    e.target.value = ''
-  }
-
-  render() {
-    return (
-      <label style={uploadStyle}>直接上传
-        <input type='file' onChange={this.onInputChange} style={{display: 'none'}} />
-      </label>
-    )
-  }
-}
-
-export default Upload

+ 0 - 247
src/components/Editor/VideoUploader.js

@@ -1,247 +0,0 @@
-import Button from './Button'
-import Input from './Input'
-import Label from './Label'
-import React from 'react'
-import Select from './Select'
-import Tag from './Tag'
-import Upload from './Upload'
-
-const style = {
-  paramsConfig: {
-    paddingBottom: '10px',
-    borderBottom: '1px solid rgb(217, 217, 217)',
-    display: 'flex',
-    flexWrap: 'wrap',
-  },
-  insertTitle: {
-    fontSize: '14px',
-    paddingRight: '10px',
-    color: 'rgba(0, 0, 0, 0.65)',
-  },
-  sourceList: {
-    margin: '10px 10px 10px 0',
-    border: '1px dashed rgb(217, 217, 217)',
-    borderRadius: '4px',
-  },
-  configTitle: {
-    display: 'block',
-    fontSize: '14px',
-    margin: '10px 0',
-    paddingRight: '10px',
-    color: 'rgba(0, 0, 0, 0.65)',
-  },
-  warnInfo: {
-    display: 'inline-block',
-    width: '100%',
-    margin: '5px',
-    textAlign: 'center',
-    fontSize: '12px',
-    color: '#f04134',
-  },
-}
-
-const linkRegx = /^https?:\/\/(([a-zA-Z0-9_-])+(\.)?)*(:\d+)?(\/((\.)?(\?)?=?&?[a-zA-Z0-9,_-](\?)?)*)*$/i
-
-let timeoutInstance = null
-
-class UploadModal extends React.PureComponent {
-  state = {
-    sources: [],
-    currentSource: '',
-    width: 400,
-    height: 400,
-    controls: 'true',
-    autoplay: 'false',
-    muted: 'false',
-    loop: 'false',
-    poster: '',
-    name: '',
-    author: '',
-    errorMsg: '',
-    errorMsgVisible: false,
-  }
-
-  updateCurrentSource = e => {
-    this.setState({currentSource: e.target.value})
-  }
-
-  addSource = () => {
-    let {sources, currentSource} = this.state
-    let newsources = sources.concat([currentSource])
-    if (currentSource === '') {
-      this.showErrorMsg('链接不能为空')
-    } else if (!linkRegx.test(currentSource)) {
-      this.showErrorMsg('非法的链接')
-    } else if (sources.indexOf(currentSource) !== -1) {
-      this.showErrorMsg('链接已存在')
-    } else {
-      this.setState({
-        sources: newsources,
-        currentSource: '',
-      }, () => {
-        this.props.onChange && this.props.onChange(this.generateHtml())
-      })
-    }
-  }
-
-  removeSource = index => {
-    let sourcesCopy = this.state.sources.concat([])
-    sourcesCopy.splice(index, 1)
-    this.setState({sources: sourcesCopy})
-  }
-
-  upload = e => {
-    let {upload} = this.props
-
-    if (!upload) return
-
-    upload(e).then(url => {
-      this.setState({currentSource: url})
-    }).catch(e => {
-      e.constructor === Error ? this.showErrorMsg(e.message) : this.showErrorMsg(e)
-    })
-  }
-
-  showErrorMsg = msg => {
-    this.setState({errorMsg: msg, errorMsgVisible: true})
-    clearTimeout(timeoutInstance)
-    timeoutInstance = setTimeout(() => {
-      this.setState({errorMsg: '', errorMsgVisible: false})
-    }, 4000)
-  }
-
-  getFileType = (fileUrl, mediaType) => {
-    let type = fileUrl.match(/\.(\w+)$/, 'i')
-    return type ? type[1].toLowerCase() : 'mp4'
-  }
-
-  generateHtml = () => {
-    let {sources, width, height, controls, autoplay, muted, loop} = this.state
-    let len = sources.length
-
-    if (len > 0) {
-      let html = ''
-      let attr = ''
-
-      attr += controls === 'false' ? '' : ' controls="true" '
-      attr += autoplay === 'false' ? '' : ' autoplay="true" '
-      attr += loop === 'false' ? '' : ' loop="true" '
-
-      attr += muted === 'false' ? '' : ' muted '
-      if (len === 1) {
-        html = `<video src="${sources[0]}" width="${width}" height="${height}" ${attr}>你的浏览器不支持 video 标签</video>`
-      } else {
-        html = `<video width="${width}" height="${height}" ${attr}>`
-        sources.forEach(source => {
-          html += `<source src=${source} type="video/${this.getFileType(source, 'video')}"}>`
-        })
-        html += '你的浏览器不支持 video 标签</video>'
-      }
-
-      return html + '<p></p>'
-    }
-  }
-
-  changeConfig = (e, type) => {
-    console.log('change config')
-    let value = e.target.value
-    let boolType = ['controls', 'autoplay', 'muted', 'loop']
-    if (type === 'width' || type === 'height') {
-      if (isNaN(parseInt(value))) {
-        value = parseInt(value)
-      }
-    } else if (boolType.indexOf(type) !== -1) {
-      value = !!value
-    }
-    this.setState({[type]: value}, () => {
-      this.props.onChange && this.props.onChange(this.generateHtml())
-    })
-  }
-
-  renderSourceList = () => {
-    let {sources} = this.state
-    if (sources.length > 0) {
-      let list = sources.map((source, index) => {
-        return <Tag value={source} key={source} index={index} onRemove={this.removeSource} />
-      })
-      return list
-    } else {
-      return <span style={style.warnInfo}>至少添加一个链接</span>
-    }
-  }
-
-  renderVideoConfig = () => {
-    let {width, height, controls, autoplay, muted, loop} = this.state
-    return (
-      <form style={style.paramsConfig}>
-        <Label name='width'>
-          <Input type='number' defaultValue={width} onChange={e => { this.changeConfig(e, 'width') }} />
-        </Label>
-        <Label name='height'>
-          <Input type='number' defaultValue={height} onChange={e => { this.changeConfig(e, 'height') }} />
-        </Label>
-        <Label name='controls'>
-          <Select defaultValue={controls} onChange={e => { this.changeConfig(e, 'controls') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-        <Label name='autoplay'>
-          <Select defaultValue={autoplay} onChange={e => { this.changeConfig(e, 'autoplay') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-        <Label name='muted'>
-          <Select defaultValue={muted} onChange={e => { this.changeConfig(e, 'muted') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-        <Label name='loop'>
-          <Select defaultValue={loop} onChange={e => { this.changeConfig(e, 'loop') }}>
-            <option value='true'>true</option>
-            <option value='false'>false</option>
-          </Select>
-        </Label>
-      </form>
-    )
-  }
-
-  render() {
-    let {currentSource, errorMsg, errorMsgVisible} = this.state
-    let {progress} = this.props
-
-    return (
-      <div>
-        <div>
-          <span style={style.insertTitle}>插入链接</span>
-          <Input style={{width: '300px'}} type='text' value={currentSource} onChange={this.updateCurrentSource} />
-          <Button onClick={this.addSource}>添加</Button>
-          <Upload onChange={this.upload} />
-        </div>
-        <div>
-          <span style={{...style.warnInfo, display: progress && progress !== -1 ? 'block' : 'none'}}>
-            {progress}%
-          </span>
-          <span style={{...style.warnInfo, display: errorMsgVisible ? 'block' : 'none'}}>{errorMsg}</span>
-        </div>
-        <div style={style.sourceList}>
-          {this.renderSourceList()}
-        </div>
-        <span style={style.configTitle}>参数配置</span>
-        {this.renderVideoConfig()}
-        <div style={{textAlign: 'center', padding: '20px 10px 0 10px'}}>
-          {
-            <video src={currentSource} controls='controls'
-              style={{width: '400px', height: '250px', backgroundColor: '#000'}}>
-              你的浏览器不支持 video 标签
-            </video>
-          }
-        </div>
-      </div>
-    )
-  }
-}
-
-export default UploadModal

+ 0 - 1
src/components/Editor/index.d.ts

@@ -1 +0,0 @@
-declare module 'ifanrx-react-ueditor'

+ 0 - 3
src/components/Editor/index.js

@@ -1,3 +0,0 @@
-import ReactUeditor from './ReactUeditor'
-
-export default ReactUeditor

+ 0 - 20
src/components/Editor/utils.js

@@ -1,20 +0,0 @@
-export function extractImageSource(html) {
-  let imgReg = /<img.*?(?:>|\/>)/gi
-  let srcReg = /src=['"]?([^'"]*)['"]?/i
-  let arr = html.match(imgReg)
-  let imgSrc = []
-
-  if (!arr) return html
-
-  for (let i = 0; i < arr.length; i++) {
-    let src = arr[i].match(srcReg)[1]
-    src && imgSrc.push(src)
-  }
-  return imgSrc
-}
-
-export function replaceImageSource(html, origin, target) {
-  return html.replace(/<img.*?src="(.*?)".*?\/?>/ig, function(img, src) {
-    return src === origin ? img.replace(src, target) : img
-  })
-}

+ 0 - 23
src/components/FansSelect/index.less

@@ -1,23 +0,0 @@
-.s_label{
-    >div{
-        align-self: start;
-    }
-    >div:nth-child(2){
-        label{
-            width: 120px;
-            margin-left: 0;
-        }
-        >div{
-            >span{
-                position: absolute;
-                top:42px;
-                right: 50px;
-            }
-        }
-    }
-  
-}
-.open_span{
-    cursor: pointer;
-    font-size:20px;
-}

+ 0 - 681
src/components/FansSelect/index.tsx

@@ -1,681 +0,0 @@
-import { UpCircleOutlined, DownCircleOutlined } from '@ant-design/icons'
-import { Radio, Col, DatePicker, Input, Row, Space, Checkbox, Divider } from 'antd'
-import { CheckboxValueType } from 'antd/lib/checkbox/Group'
-import { RadioChangeEvent } from 'antd/lib/radio'
-import moment from 'moment'
-import React, { useEffect, useReducer, useState } from 'react'
-import style from './index.less'
-/**粉丝选项 */
-type State = {
-    fansFilterOsType?: any[],//操作系统
-    fansFilterMember?: '' | boolean,//是否是会员
-    fansFilterSubscribeTimeType?: '' | 1 | 2 | 3,//关注时间
-    fansFilterSubscribeTimeBegin?: string | '',//关注起始时间
-    fansFilterSubscribeTimeEnd?: string | '',//关注截至时间
-    rechargeType?: '' | number,//充值情况选项
-    fansFilterRechargeCountMin?: string | '',//充值次数(最少)
-    fansFilterRechargeCountMax?: string | '',//充值次数(最多)
-    dayType?: '' | number,//天数选项
-    fansFilterRechargeTimeMin?: string | '',//上次充值时间(最少 n天内)
-    fansFilterRechargeTimeMax?: string | '',//上次充值时间(最大 n天内)
-    fansFilterRechargeMin?: string | '',//最低充值金额
-    fansFilterRechargeMax?: string | '',//最大充值金额
-    countType?: '' | number,//书币选项
-    fansFilterCoinCountMin?: string | '',//最低书币余额
-    fansFilterCoinCountMax?: string | '',//最高书币余额
-    timeType?: '' | number,//时间选项
-    fansFilterActiveTimeMin?: string | '',//上次活跃距今时间(最低)
-    fansFilterActiveTimeMax?: string | '',//上次活跃距今时间(最高)
-    fansFilterSex?: any[],//粉丝性别
-}
-type Action = {
-    type: 'setData' | 'initData',
-    params: State
-}
-function reducer(state: State, action: Action) {
-    let { type, params } = action
-    let newState = JSON.parse(JSON.stringify(state))
-    switch (type) {
-        case 'setData':
-            Object.keys(params as State).forEach((key: string) => {
-                newState[key] = (params as State)[key]
-            })
-            return newState
-        case 'initData':
-            let data: any = initialState
-            if (params) {
-                data = { ...data, ...params }
-            }
-            return data
-        default:
-            return state
-    }
-}
-const initialState = {
-    fansFilterOsType: [],//操作系统
-    fansFilterMember: '',//是否是会员
-    fansFilterSex: [],//粉丝性别
-    fansFilterSubscribeTimeType: '',//关注时间
-    fansFilterSubscribeTimeBegin: '',//关注起始时间
-    fansFilterSubscribeTimeEnd: '',//关注截至时间
-    fansFilterRechargeCountMin: '',//充值次数(最少)
-    fansFilterRechargeCountMax: '',//充值次数(最多)
-    fansFilterRechargeTimeMin: '',//上次充值时间(最少 n天内)
-    fansFilterRechargeTimeMax: '',//上次充值时间(最大 n天内)
-    fansFilterRechargeMin: '',//最低充值金额
-    fansFilterRechargeMax: '',//最大充值金额
-    fansFilterCoinCountMin: '',//最低书币余额
-    fansFilterCoinCountMax: '',//最高书币余额
-    fansFilterActiveTimeMin: '',//上次活跃距今时间(最低)
-    fansFilterActiveTimeMax: '',//上次活跃距今时间(最高)
-    rechargeType: '',//充值情况选项
-    dayType: '',//天数选项
-    countType: '',//书币选项
-    timeType: ''//时间选项
-}
-type Props = {
-    callback: (value: State) => void;//回调函数获取数据
-    defaultValue?: any;//回填数据
-    openConfig?: {
-        /**活跃时间*/
-        activeTime: boolean
-    }
-}
-function FansSelect(props: Props) {
-    const [open, setOpen] = useState<any>({ a: 1, b: 1, c: 1, d: 1 })
-    const [state, dispatch] = useReducer(reducer, initialState)
-    const { callback, defaultValue = initialState,openConfig} = props
-    let [activeTime,setActiveTime] =useState(openConfig?.activeTime !== undefined ? openConfig?.activeTime : true)
-    const {
-        fansFilterMember, fansFilterSubscribeTimeType, fansFilterSubscribeTimeBegin,
-        fansFilterSubscribeTimeEnd, fansFilterRechargeCountMin, fansFilterRechargeCountMax,
-        fansFilterRechargeTimeMin, fansFilterRechargeTimeMax, fansFilterRechargeMin, fansFilterRechargeMax,
-        fansFilterCoinCountMin, fansFilterCoinCountMax, fansFilterActiveTimeMin, fansFilterActiveTimeMax,
-        rechargeType, dayType, countType, timeType, fansFilterSex, fansFilterOsType
-    } = state
-    //数据回填
-    useEffect(() => {
-        if (defaultValue && JSON.stringify(defaultValue) !== '{}') {
-            let {
-                fansFilterMember, fansFilterSubscribeTimeType, fansFilterSubscribeTimeBegin,
-                fansFilterSubscribeTimeEnd, fansFilterRechargeCountMin, fansFilterRechargeCountMax,
-                fansFilterRechargeTimeMin, fansFilterRechargeTimeMax, fansFilterRechargeMin, fansFilterRechargeMax,
-                fansFilterCoinCountMin, fansFilterCoinCountMax, fansFilterActiveTimeMin, fansFilterActiveTimeMax, fansFilterSex, fansFilterOsType
-            } = defaultValue
-            dispatch({
-                type: 'initData', params: {
-                    fansFilterMember, fansFilterSubscribeTimeType, fansFilterSubscribeTimeBegin,
-                    fansFilterSubscribeTimeEnd, fansFilterRechargeCountMin, fansFilterRechargeCountMax,
-                    fansFilterRechargeTimeMin, fansFilterRechargeTimeMax, fansFilterRechargeMin, fansFilterRechargeMax,
-                    fansFilterCoinCountMin, fansFilterCoinCountMax, fansFilterActiveTimeMin, fansFilterActiveTimeMax, fansFilterSex, fansFilterOsType,
-                    rechargeType: fansFilterRechargeCountMin === null && fansFilterRechargeCountMax === null ? '' :
-                        fansFilterRechargeCountMin == 0 && fansFilterRechargeCountMax == 0 ? 0 :
-                            fansFilterRechargeCountMin == 1 && fansFilterRechargeCountMax == null ? -1 :
-                                fansFilterRechargeCountMin == 1 && fansFilterRechargeCountMax == 1 ? 1 :
-                                    fansFilterRechargeCountMin == 2 && fansFilterRechargeCountMax == 2 ? 2 :
-                                        fansFilterRechargeCountMin == 3 && fansFilterRechargeCountMax == 3 ? 3 :
-                                            fansFilterRechargeCountMin == 4 && fansFilterRechargeCountMax == 4 ? 4 :
-                                                fansFilterRechargeCountMin == 5 && fansFilterRechargeCountMax == 5 ? 5 :
-                                                    fansFilterRechargeCountMin == 6 && fansFilterRechargeCountMax == 6 ? 6 :
-                                                        fansFilterRechargeCountMin == 7 && fansFilterRechargeCountMax == 7 ? 7 :
-                                                            fansFilterRechargeCountMin == 8 && fansFilterRechargeCountMax == 8 ? 8 :
-                                                                fansFilterRechargeCountMin == 10 && fansFilterRechargeCountMax == 10 ? 10 :
-                                                                    fansFilterRechargeCountMin > 10 && fansFilterRechargeCountMax > 10 ? 11 : -2,
-                    dayType: fansFilterRechargeTimeMin === null && fansFilterRechargeTimeMax === null ? '' :
-                        fansFilterRechargeTimeMin == 0 && fansFilterRechargeTimeMax == 15 ? 15 :
-                            fansFilterRechargeTimeMin == 0 && fansFilterRechargeTimeMax == 30 ? 30 :
-                                fansFilterRechargeTimeMin == 30 && fansFilterRechargeTimeMax == 0 ? 31 :
-                                    fansFilterRechargeTimeMin == 0 && fansFilterRechargeTimeMax == 45 ? 45 :
-                                        fansFilterRechargeTimeMin == 0 && fansFilterRechargeTimeMax == 60 ? 60 : 61,
-                    timeType: fansFilterActiveTimeMin == null && fansFilterActiveTimeMax == null ? '' :
-                        fansFilterActiveTimeMin == 0 && fansFilterActiveTimeMax == 1 ? 1 :
-                            fansFilterActiveTimeMin == 1 && fansFilterActiveTimeMax == 3 ? 2 :
-                                fansFilterActiveTimeMin == 3 && fansFilterActiveTimeMax == 12 ? 3 :
-                                    fansFilterActiveTimeMin == 12 && fansFilterActiveTimeMax == 24 ? 4 : 5
-                }
-            })
-        }
-    }, [defaultValue])
-    useEffect(() => {
-        let { rechargeType, dayType, countType, timeType, ...obj } = state
-        callback(obj)
-    }, [state])
-
-    console.log('rechargeType--->', rechargeType);
-
-    return <Row gutter={[10, 20]}>
-        {/* <Col span={24}>
-            <Space>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>性别:</label>
-                <Checkbox.Group
-                    onChange={(checkedValue: CheckboxValueType[]) => {
-                        dispatch({ type: 'setData', params: { fansFilterSex: checkedValue } })
-                    }}
-                    value={fansFilterSex}
-                >
-                    <Checkbox value={''}>不限</Checkbox>
-                    <Checkbox value={1}>男</Checkbox>
-                    <Checkbox value={2}>女</Checkbox>
-                    <Checkbox value={0}>未知</Checkbox>
-                </Checkbox.Group>
-            </Space>
-        </Col> */}
-        <Col span={24}>
-            <Space>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>操作系统:</label>
-                <Checkbox.Group
-                    onChange={(checkedValue: CheckboxValueType[]) => {
-                        dispatch({ type: 'setData', params: { fansFilterOsType: checkedValue } })
-                    }}
-                    value={fansFilterOsType}
-                >
-                    <Checkbox value={0}>未知</Checkbox>
-                    <Checkbox value={1}>安卓</Checkbox>
-                    <Checkbox value={2}>IOS</Checkbox>
-                </Checkbox.Group>
-            </Space>
-        </Col>
-        <Divider style={{ margin: 0 }} />
-        {/* <Col span={24}>
-            <Space>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>是否VIP:</label>
-                <div>
-                    <Radio.Group onChange={(e: RadioChangeEvent) => { dispatch({ type: 'setData', params: { fansFilterMember: e.target.value } }) }} value={fansFilterMember}>
-                        <Radio value={''}>不限</Radio>
-                        <Radio value={true}>是</Radio>
-                        <Radio value={false}>否</Radio>
-                    </Radio.Group>
-                </div>
-            </Space>
-        </Col>
-        <Divider style={{padding:0}}/> */}
-        <Col span={24}>
-            <Space>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>关注时间:</label>
-                <div>
-                    <Radio.Group
-                        onChange={(e: RadioChangeEvent) => {
-                            dispatch({
-                                type: 'setData',
-                                params: {
-                                    fansFilterSubscribeTimeType: e.target.value,
-                                    fansFilterSubscribeTimeBegin: '',
-                                    fansFilterSubscribeTimeEnd: '',
-                                }
-                            })
-                        }}
-                        value={fansFilterSubscribeTimeType === null ? '' : fansFilterSubscribeTimeType}
-                    >
-                        <Radio value={''}>不限</Radio>
-                        <Radio value={0}>具体时间</Radio>
-                        <Radio value={1}>常用日期</Radio>
-                        <Radio value={2}>动态日期</Radio>
-                    </Radio.Group>
-                </div>
-            </Space>
-            {
-                fansFilterSubscribeTimeType === 0 && <div style={{ paddingLeft: 100, marginTop: 8 }}>
-                    <DatePicker.RangePicker
-                        showTime={{ format: 'HH:mm:ss' }}
-                        format="YYYY-MM-DD HH:mm:ss"
-                        onChange={(values: any, formatString: [string, string]) => {
-                            dispatch({
-                                type: 'setData', params: {
-                                    fansFilterSubscribeTimeBegin: formatString[0],
-                                    fansFilterSubscribeTimeEnd: formatString[1],
-                                }
-                            })
-                        }}
-                        value={fansFilterSubscribeTimeBegin ? [moment(fansFilterSubscribeTimeBegin), moment(fansFilterSubscribeTimeEnd)] : undefined}
-                    />
-                </div>
-            }
-            {
-                fansFilterSubscribeTimeType === 1 && <div style={{ paddingLeft: 100, marginTop: 8 }}>
-                    <Input.Group compact>
-                        <Input
-                            style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                            placeholder="起始(小时)"
-                            value={fansFilterSubscribeTimeBegin}
-                            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                let v = event.target.value
-                                dispatch({ type: 'setData', params: { fansFilterSubscribeTimeBegin: v } })
-                            }}
-                        />
-                        <Input
-                            style={{
-                                width: 30,
-                                borderLeft: 0,
-                                borderRight: 0,
-                                pointerEvents: 'none',
-                                backgroundColor: '#fff'
-                            }}
-                            placeholder="~"
-                            disabled
-                        />
-                        <Input
-                            className="site-input-right"
-                            style={{
-                                width: 100,
-                                textAlign: 'center',
-                                borderLeftWidth: 0
-                            }}
-                            value={fansFilterSubscribeTimeEnd}
-                            placeholder="结束(小时)"
-                            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                let v = event.target.value
-                                dispatch({ type: 'setData', params: { fansFilterSubscribeTimeEnd: v } })
-                            }}
-                        />
-                    </Input.Group>
-                    <Radio.Group
-                        onChange={(e: RadioChangeEvent) => {
-                            let arr = ['', ['0', '1'], ['0', '24'], ['0', '48'], ['48', '']]
-                            dispatch({
-                                type: 'setData',
-                                params: {
-                                    fansFilterSubscribeTimeBegin: arr[e.target.value][0],
-                                    fansFilterSubscribeTimeEnd: arr[e.target.value][1],
-                                }
-                            })
-                        }} value={
-                            fansFilterSubscribeTimeBegin === "48" && fansFilterSubscribeTimeEnd === '' ?
-                                4 : fansFilterSubscribeTimeBegin === "0" && fansFilterSubscribeTimeEnd === '48' ?
-                                    3 : fansFilterSubscribeTimeBegin === "0" && fansFilterSubscribeTimeEnd === '24' ?
-                                        2 :
-                                        fansFilterSubscribeTimeBegin === "0" && fansFilterSubscribeTimeEnd === '1' ?
-                                            1 : ''}>
-                        <Radio value={1}>1小时内</Radio>
-                        <Radio value={2}>24小时内</Radio>
-                        <Radio value={3}>48小时内</Radio>
-                        <Radio value={4}>48小时外</Radio>
-                    </Radio.Group>
-                </div>
-            }
-            {
-                fansFilterSubscribeTimeType === 2 && <div style={{ paddingLeft: 100, marginTop: 8 }}>
-                    <Input.Group compact>
-                        <Input
-                            style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                            placeholder="第n天"
-                            value={fansFilterSubscribeTimeBegin}
-                            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                let v = event.target.value
-                                dispatch({ type: 'setData', params: { fansFilterSubscribeTimeBegin: v } })
-                            }}
-                        />
-                        <Input
-                            style={{
-                                width: 30,
-                                borderLeft: 0,
-                                borderRight: 0,
-                                pointerEvents: 'none',
-                                backgroundColor: '#fff'
-                            }}
-                            placeholder="~"
-                            disabled
-                        />
-                        <Input
-                            className="site-input-right"
-                            style={{
-                                width: 100,
-                                textAlign: 'center',
-                                borderLeftWidth: 0
-                            }}
-                            placeholder="第n天"
-                            value={fansFilterSubscribeTimeEnd}
-                            onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                let v = event.target.value
-                                dispatch({ type: 'setData', params: { fansFilterSubscribeTimeEnd: v } })
-                            }}
-                        />
-                    </Input.Group>
-                </div>
-            }
-        </Col>
-        <Divider style={{ margin: 0 }} />
-        <Col span={24}>
-            <Space className={style.s_label}>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}> 充值情况:</label>
-                <div>
-                    <div style={{ marginBottom: 5 }}>
-                        <Input.Group compact>
-                            <Input
-                                style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                                placeholder="最小次数"
-                                value={fansFilterRechargeCountMin}
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterRechargeCountMin: v } })
-                                }}
-                            />
-                            <Input
-                                style={{
-                                    width: 30,
-                                    borderLeft: 0,
-                                    borderRight: 0,
-                                    pointerEvents: 'none',
-                                    backgroundColor: '#fff'
-                                }}
-                                placeholder="~"
-                                disabled
-                            />
-                            <Input
-                                className="site-input-right"
-                                style={{
-                                    width: 100,
-                                    textAlign: 'center',
-                                    borderLeftWidth: 0
-                                }}
-                                value={fansFilterRechargeCountMax}
-                                placeholder="最大次数"
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterRechargeCountMax: v } })
-                                }}
-                            />
-                        </Input.Group>
-                    </div>
-                    <Radio.Group
-                        style={{ width: '100%' }}
-                        onChange={(e: RadioChangeEvent) => {
-                            dispatch({
-                                type: 'setData', params: {
-                                    rechargeType: e.target.value,
-                                    fansFilterRechargeCountMin: e.target.value === '' ? '' : e.target.value === 11 ? 10 : e.target.value === -1 ? 1 : e.target.value,
-                                    fansFilterRechargeCountMax: e.target.value === 11 ? '' : e.target.value === -1 ? '' : e.target.value
-                                }
-                            })
-                        }}
-                        value={rechargeType}
-                    >
-                        <Radio value={''}>不限</Radio>
-                        <Radio value={0}>未充值</Radio>
-                        <Radio value={-1}>已充值</Radio>
-                        {
-                            !!open.a && <>
-                                <Radio value={1}>充值1次</Radio>
-                                <Radio value={2}>充值2次</Radio>
-                                <Radio value={3}>充值3次</Radio>
-                                <Radio value={5}>充值5次</Radio>
-                                <Radio value={8}>充值8次</Radio>
-                                <Radio value={10}>充值10次</Radio>
-                                <Radio value={11}>充值10次以上</Radio>
-                            </>
-                        }
-                    </Radio.Group >
-                    <span className={style.open_span} onClick={() => setOpen({ ...open, a: !open.a })}>{!!open.a ? <UpCircleOutlined style={{ color: '#1890ff' }} /> : <DownCircleOutlined style={{ color: '#1890ff' }} />}</span>
-                </div>
-            </Space>
-        </Col>
-        <Divider style={{ margin: 0 }} />
-        <Col span={24}>
-            <Space className={style.s_label}>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>上次充值距今:</label>
-                <div>
-                    <div style={{ marginBottom: 5 }}>
-                        <Input.Group compact>
-                            <Input
-                                style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                                placeholder="最小天数"
-                                value={fansFilterRechargeTimeMin}
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterRechargeTimeMin: v } })
-                                }}
-                            />
-                            <Input
-                                style={{
-                                    width: 30,
-                                    borderLeft: 0,
-                                    borderRight: 0,
-                                    pointerEvents: 'none',
-                                    backgroundColor: '#fff'
-                                }}
-                                placeholder="~"
-                                disabled
-                            />
-                            <Input
-                                className="site-input-right"
-                                style={{
-                                    width: 100,
-                                    textAlign: 'center',
-                                    borderLeftWidth: 0
-                                }}
-                                value={fansFilterRechargeTimeMax}
-                                placeholder="最大天数"
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterRechargeTimeMax: v } })
-                                }}
-                            />
-                        </Input.Group>
-                    </div>
-                    <Radio.Group
-                        style={{ width: '100%' }}
-                        onChange={(e: RadioChangeEvent) => {
-                            dispatch({
-                                type: 'setData',
-                                params: {
-                                    dayType: e.target.value,
-                                    fansFilterRechargeTimeMin: e.target.value === '' ? '' : e.target.value === 31 ? '30' : e.target.value === 61 ? '60' : '0',
-                                    fansFilterRechargeTimeMax: e.target.value === 31 ? '' : e.target.value === 61 ? '' : e.target.value
-                                }
-                            })
-                        }}
-                        value={dayType}
-                    >
-                        <Radio value="">不限</Radio>
-                        <Radio value={15}>15天之内</Radio>
-                        <Radio value={30}>30天之内</Radio>
-                        {
-                            !!open.b && <>
-                                <Radio value={31}>30天以上</Radio>
-                                <Radio value={45}>45天之内</Radio>
-                                <Radio value={60}>60天之内</Radio>
-                                <Radio value={61}>60天以上</Radio>
-                            </>
-                        }
-                    </Radio.Group>
-
-                    <span className={style.open_span} onClick={() => setOpen({ ...open, b: !open.b })}>{!!open['b'] ? <UpCircleOutlined style={{ color: '#1890ff' }} /> : <DownCircleOutlined style={{ color: '#1890ff' }} />}</span>
-                </div>
-            </Space>
-        </Col>
-        <Divider style={{ margin: 0 }} />
-        <Col span={24}>
-            <Space>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>累计充值金额:</label>
-                <Input.Group compact>
-                    <Input
-                        style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                        placeholder="最小金额"
-                        onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                            let v = event.target.value
-                            dispatch({ type: 'setData', params: { fansFilterRechargeMin: v } })
-                        }}
-                        value={fansFilterRechargeMin}
-                    />
-                    <Input
-                        style={{
-                            width: 30,
-                            borderLeft: 0,
-                            borderRight: 0,
-                            pointerEvents: 'none',
-                            backgroundColor: '#fff'
-                        }}
-                        placeholder="~"
-                        disabled
-                    />
-                    <Input
-                        className="site-input-right"
-                        style={{
-                            width: 100,
-                            textAlign: 'center',
-                            borderLeftWidth: 0
-                        }}
-                        placeholder="最大金额"
-                        onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                            let v = event.target.value
-                            dispatch({ type: 'setData', params: { fansFilterRechargeMax: v } })
-                        }}
-                        value={fansFilterRechargeMax}
-                    />
-                </Input.Group>
-            </Space>
-        </Col>
-        <Divider style={{ margin: 0 }} />
-        {/* <Col span={24}>
-            <Space className={style.s_label}>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>书币余额:</label>
-                <div>
-                    <div style={{ marginBottom: 5 }}>
-                        <Input.Group compact>
-                            <Input
-                                style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                                placeholder="最小书币"
-                                value={fansFilterCoinCountMin}
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterCoinCountMin: v } })
-                                }}
-                            />
-                            <Input
-                                style={{
-                                    width: 30,
-                                    borderLeft: 0,
-                                    borderRight: 0,
-                                    pointerEvents: 'none',
-                                    backgroundColor: '#fff'
-                                }}
-                                placeholder="~"
-                                disabled
-                            />
-                            <Input
-                                className="site-input-right"
-                                style={{
-                                    width: 100,
-                                    textAlign: 'center',
-                                    borderLeftWidth: 0
-                                }}
-                                placeholder="最大书币"
-                                value={fansFilterCoinCountMax}
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterCoinCountMax: v } })
-                                }}
-                            />
-                        </Input.Group>
-                    </div>
-                    <Radio.Group
-                        style={{ width: '100%' }}
-                        onChange={(e: RadioChangeEvent) => {
-                            let arr = [['', ''], ['0', '500'], ['501', '1000'], ['1001', '3000'], ['3001', '10000'], ['10000', '']]
-                            dispatch({
-                                type: 'setData',
-                                params: {
-                                    countType: e.target.value,
-                                    fansFilterCoinCountMin: e.target.value === '' ? arr[0][0] : arr[e.target.value][0],
-                                    fansFilterCoinCountMax: e.target.value === '' ? arr[0][1] : arr[e.target.value][1],
-                                }
-                            })
-                        }}
-                        value={countType}>
-                        <Radio value="">不限</Radio>
-                        <Radio value={1}>低于500</Radio>
-                        <Radio value={2}>501-1000</Radio>
-                        {
-                            !!open.c && <>
-                                <Radio value={3}>1001-3000</Radio>
-                                <Radio value={4}>3001-10000</Radio>
-                                <Radio value={5}>10000以上</Radio>
-                            </>
-                        }
-                    </Radio.Group>
-                    <span className={style.open_span} onClick={() => setOpen({ ...open, c: !open.c })}>{!!open['c'] ? <UpCircleOutlined style={{ color: '#1890ff' }} /> : <DownCircleOutlined style={{ color: '#1890ff' }} />}</span>
-                </div>
-            </Space>
-        </Col>
-        <Divider style={{padding:0}}/> */}
-       {activeTime && <Col span={24}>
-            <Space className={style.s_label}>
-                <label style={{ width: 100, display: 'inline-block', textAlign: 'right' }}>活跃时间:</label>
-                <div>
-                    <div style={{ marginBottom: 5 }}>
-                        <Input.Group compact>
-                            <Input
-                                style={{ width: 100, textAlign: 'center', borderRightWidth: 0 }}
-                                placeholder="最小时间"
-                                value={fansFilterActiveTimeMin}
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterActiveTimeMin: v } })
-                                }}
-                            />
-                            <Input
-                                style={{
-                                    width: 30,
-                                    borderLeft: 0,
-                                    borderRight: 0,
-                                    pointerEvents: 'none',
-                                    backgroundColor: '#fff'
-                                }}
-                                placeholder="~"
-                                disabled
-                            />
-                            <Input
-                                className="site-input-right"
-                                style={{
-                                    width: 100,
-                                    textAlign: 'center',
-                                    borderLeftWidth: 0
-                                }}
-                                placeholder="最大时间"
-                                value={fansFilterActiveTimeMax}
-                                onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                                    let v = event.target.value
-                                    dispatch({ type: 'setData', params: { fansFilterActiveTimeMax: v } })
-                                }}
-                            />
-                        </Input.Group>
-                    </div>
-                    <Radio.Group
-                        style={{ width: '100%' }}
-                        onChange={(e: RadioChangeEvent) => {
-                            let arr = [['', ''], ['0', '1'], ['1', '3'], ['3', '12'], ['12', '24'], ['24', '48']]
-                            dispatch({
-                                type: 'setData',
-                                params: {
-                                    timeType: e.target.value,
-                                    fansFilterActiveTimeMin: e.target.value === '' ? arr[0][0] : arr[e.target.value][0],
-                                    fansFilterActiveTimeMax: e.target.value === '' ? arr[0][1] : arr[e.target.value][1],
-                                }
-                            })
-                        }}
-                        value={timeType}
-                    >
-                        <Radio value="">不限</Radio>
-                        <Radio value={1}>1小时</Radio>
-                        <Radio value={2}>1-3小时</Radio>
-                        {
-                            !!open.d && <>
-                                <Radio value={3}>3-12小时</Radio>
-                                <Radio value={4}>12-24小时</Radio>
-                                <Radio value={5}>24-48小时</Radio>
-                            </>
-                        }
-                    </Radio.Group>
-                    <span className={style.open_span} onClick={() => setOpen({ ...open, d: !open.d })}>{!!open['d'] ? <UpCircleOutlined style={{ color: '#1890ff' }} /> : <DownCircleOutlined style={{ color: '#1890ff' }} />}</span>
-                </div>
-
-            </Space>
-        </Col>}
-    </Row >
-}
-
-export default React.memo(FansSelect, (a, b) => {
-    if (JSON.stringify(a) === JSON.stringify(b)) {
-        return true
-    }
-    return false
-})

+ 0 - 166
src/components/Formitem/index.less

@@ -1,166 +0,0 @@
-@w: 14px;
-.form_style {
-  width: 100%;
-  .file {
-    position: relative;
-    cursor: pointer;
-    > input {
-      opacity: 0;
-      position: absolute;
-      display: block;
-      top: 0;
-      left: 0;
-      cursor: pointer;
-      right: 0;
-      bottom: 0;
-      width: 100%;
-      font-size: 0;
-      > span {
-        display: none;
-      }
-    }
-  }
-  > h1 {
-    text-align: left;
-    padding-left: 20px;
-  }
-  > form {
-    display: flex;
-    width: 100%;
-    justify-content: space-between;
-    > div {
-      margin-left: 20px;
-      .ant-form-item-control-input-content {
-        display: flex;
-        align-items: center;
-      }
-    }
-    .form_row{
-      flex: 1;
-    }
-    .form_item2 {
-      color: red;
-      > div:nth-child(1) {
-        width: calc(@w * 4);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 4);
-      }
-    }
-    .form_item3 {
-      > div:nth-child(1) {
-        width: calc(@w * 5);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 5);
-      }
-    }
-    .form_item4 {
-      > div:nth-child(1) {
-        width: calc(@w * 6);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 6);
-      }
-    }
-    .form_item5 {
-      > div:nth-child(1) {
-        width: calc(@w * 7);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 7);
-      }
-    }
-    .form_item6 {
-      > div:nth-child(1) {
-        width: calc(@w * 8);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 8);
-      }
-    }
-    .form_item7 {
-      > div:nth-child(1) {
-        width: calc(@w * 9);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 9);
-      }
-    }
-    .form_item8 {
-      > div:nth-child(1) {
-        width: calc(@w * 10);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 10);
-      }
-    }
-    .form_item9 {
-      > div:nth-child(1) {
-        width: calc(@w * 11);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 11);
-      }
-    }
-    .form_item10 {
-      > div:nth-child(1) {
-        width: calc(@w * 12);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 12);
-      }
-    }
-    .form_item11 {
-      > div:nth-child(1) {
-        width: calc(@w * 13);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 13);
-      }
-    }
-    .form_item12 {
-      > div:nth-child(1) {
-        width: calc(@w * 14);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 14);
-      }
-    }
-    .form_item13 {
-      > div:nth-child(1) {
-        width: calc(@w * 5);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 15);
-      }
-    }
-    .form_item14 {
-      > div:nth-child(1) {
-        width: calc(@w * 16);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 16);
-      }
-    }
-    .form_item15 {
-      > div:nth-child(1) {
-        width: calc(@w * 17);
-      }
-      .ant-form-item-label {
-        width: calc(@w * 17);
-      }
-    }
-  }
-}
-.form_styleNull{
-  > form {
-    > div:nth-child(1){
-      margin-left: 0;
-    }
-  }
-} 
-input:-internal-autofill-previewed,
-input:-internal-autofill-selected {
-  transition: background-color 5000s ease-in-out 0s !important;
-}

+ 0 - 403
src/components/Formitem/index.tsx

@@ -1,403 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react'
-import { Form, Input, DatePicker, Select, Button, Radio, Switch, Col, Upload, Modal,  InputNumber } from 'antd'
-import { Props, FormConfig, Children } from './type'
-import style from './index.less'
-import moment from 'moment'
-import locale from 'antd/es/date-picker/locale/zh_CN';
-import { Store } from 'antd/lib/form/interface'
-import { UploadOutlined } from '@ant-design/icons'
-import 'antd/es/modal/style';
-import 'antd/es/slider/style';
-import ImgCrop from 'antd-img-crop';
-import { useModel } from 'umi'
-import { RcFile } from 'antd/lib/upload/interface'
-import Demo from '../Cropper'
-
-const { Item } = Form
-const { Option } = Select;
-const { RangePicker } = DatePicker;
-/**
- * 
- * @param props
- * @param {Array} formConfig 必传
- * @param {string} flow 必传 'row' | 'column'
- * @param {string} formFlex 非必传 控制form flex排版方向
- * @param {string} title 非必传 header 标题
- * @param {Function} callback 非必传 传入回调函数执行提交表单后获取表单内的值
- * @param {object} getFormValues 非必传 传入回调函数执行提交表单后获取表单内的值
- * @param {object} labelCol  非必传 改变label的布局
- * @example
- * 按钮配置 htmlType:'submit' 组件上添加submit={callback} 点击按钮可获得所有form表单数据
- * 按钮配置 htmlType:'button' callback:Function 点击按钮可执行回调函数一般用于弹窗之类事件
- * 想要单个select之类组件onChange立即执行发送数据设置formConfig中配置callback
- * 弹窗用getFormSubmit回调拿数据
- * 普通用callback
- * //示例
- *  import Headers from './components/Formitem' //Formitem组件引入
-    import { FormConfig } from './components/Formitem/type' //formConfig声明文件
-    let formConfig: FormConfig[] = [
-        {
-            label: 'ID',
-            name: 'id',
-            tag: 'input',
-            placeholder: '请输入ID搜索',
-        }
-    ]
-    const getHeaderValue = (value: object) => {
-        console.log(value)
-    }
- *  <Headers formConfig={formConfig} formFlex="flex-start" title='Title' submit={getHeaderValue}/>
- */
-
-
-let Page = React.forwardRef((props: Props, ref) => {
-    let { formConfig, formFlex = 'flex-start', title, flow, defaultProps, getFormValues, getFormSubmit, setFormValues, labelCol, ew, isAll, isFirstLeftNull = false } = props
-    const [form] = Form.useForm();
-    const [lw, setLw] = useState(0)
-    const [allValues, setAllValues] = useState<any>()
-    const [file, setFile] = useState<any>({})
-    const [url, setUrl] = useState<string>('')
-    const { dispatch } = useModel('useOperating.useMaterialModal')
-    const { set } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')//存放到本地素材状态管理
-    const [fileList, setFileList] = useState<any>([])
-    const [previewVisible, setPreviewVisible] = useState<boolean>(false)
-    const [fileUrl, setFileUrl] = useState<string>('')
-    const [wh, setWh] = useState<number>(1 / 1)
-    const [cropSize, setCropSize] = useState<any>({ width: 900, height: 383 })
-
-    // useImperativeHandle(ref, () => ({
-    //     form
-    // }));
-    // base64转File
-    const dataURLtoFile = (dataurl: any, filename: any) => {
-        var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
-            bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
-        while (n--) {
-            u8arr[n] = bstr.charCodeAt(n);
-        }
-        return new File([u8arr], filename, { type: mime });
-    }
-    //初始化 defaultProps
-    const _initDefaultProps = useCallback((name: string, tag: string) => {
-        if (defaultProps) {
-            if (tag === 'DatePicker' || tag === 'RangePicker') {//处理日期
-                if (Array.isArray((defaultProps as any)[name])) {
-                    return [moment((defaultProps as any)[name][0]), moment((defaultProps as any)[name][1])]
-                }
-                return (defaultProps as any)[name] ? moment((defaultProps as any)[name]) : undefined
-            }
-            if (Array.isArray(defaultProps[name]) && tag === 'select') {//处理多选
-                return defaultProps[name].map((n: number) => n.toString())
-            }
-            return (defaultProps as any)[name]?.toString()
-        }
-    }, [defaultProps])
-    // 提交数据
-    const onFinish = useCallback((value: any) => {
-        let showTime: boolean = formConfig.some((a: any) => 'showTime' in a && a['showTime'] === true) //判断是否开启了时间表格的显示时分秒
-        let Value = JSON.parse(JSON.stringify(value));//深克隆一份value值
-        Object.keys(Value).forEach((name: string) => {//对时间进行格式化
-            if (Object.prototype.toString.call(value[name]) === '[object Object]') {
-                Value[name] = moment(value[name]).format(showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')
-            } else if (Array.isArray(value[name]) && typeof value[name][0] === 'object') {
-                Value[name][0] = `${moment(value[name][0]).format(showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')}`
-                Value[name][1] = `${moment(value[name][1]).format(showTime ? 'YYYY-MM-DD HH:mm:ss' : 'YYYY-MM-DD')}`
-
-            }
-            if (JSON.stringify(value[name]) === '[]') {
-                delete Value[name]
-            }
-        })
-        // submit && submit(Value)
-
-        return Value
-    }, [])
-    //映射提交
-    form.submit = useCallback(() => {
-        return () => form.validateFields().then((values: any) => {
-            let value = onFinish(values)
-            return value
-        }).catch((err: any) => console.log(err))
-    }, [])
-    //设置表单值
-    const setValue = useCallback((value: Store) => {
-        form.setFieldsValue(value)
-    }, [])
-    //回调函数获取表单值
-    const onValuesChange = useCallback((changedValues: any, allValues: any) => {
-        getFormValues && getFormValues({ changedValues, allValues })//如若父组件设置了getFormValues可实时获取表单输入的值
-        setAllValues(allValues)
-    }, [getFormValues])
-    //输入搜索的回调
-    const onSelect = useCallback((value: any, callback?: Function) => {
-        callback ? callback(value) : console.log('没有在headerConfig中配置对应的回调函数', value)
-
-    }, [])
-    const onRadio = (value: any) => {
-
-    }
-    //select按钮回调
-    const onChange = useCallback((value: string | string[], change?: boolean, callback?: (v: any) => void) => {
-        callback && callback(value)
-    }, [])
-    //文件上传获取
-    const fileChanage = useCallback((e: any) => {
-        try {
-            let file = e?.target?.files || e
-            console.log(file)
-            setValue({ 'file': 'true' })
-            dispatch({ type: 'file', params: { file: file[0] || file } })
-            set({ file: file[0] || file })
-            if (file) {
-                setFile(file[0] || file)
-            }
-        } catch (err) {
-            console.log(err)
-        }
-    }, [])
-    useEffect(() => {
-        getFormSubmit && getFormSubmit(form.submit)//如若父组件设置了getFormSubmit将submit方法传给父组件回调
-        setFormValues && setFormValues(setValue)//如若父组件设置了getFormSubmit将setValue方法传给父组件
-    }, [])
-    //默认的错误提示信息
-    const validateMessages = {
-        required: "'${name}' 是必选字段",
-        // ...
-    };
-    //预览
-    const preview = useCallback(() => {
-        let type = file.type.split('/')[0]
-        switch (type) {
-            case 'audio':
-                return <audio src={url} controls />
-            case 'video':
-                return <video src={url} controls />
-            case 'image':
-                return <img src={url} width='150' />
-            default:
-                return null
-        }
-    }, [file, url])
-    //上传字典
-    let fileType: any = {
-        '上传图片': 'image/gif,image/jpeg,image/png,image/jpg',
-        '上传视频': 'video/*',
-        '上传音频': 'audio/*',
-        '上传Excel': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/vnd.ms-excel'
-    }
-    return <div className={`${style.form_style} ${isFirstLeftNull && style.form_styleNull}`}>
-        <h1>{title}</h1>
-        <Form
-            form={form}
-            onFinish={onFinish}
-            style={flow === 'row' ? { justifyContent: formFlex, flexFlow: 'row wrap' } : { justifyContent: formFlex, flexFlow: 'column', alignItems: formFlex }}
-            onValuesChange={onValuesChange}
-            validateMessages={validateMessages}
-        // ref={fromEl}
-        >
-            {
-                formConfig.map((obj: FormConfig, index: number) => {
-                    let { Rule, name, tag, label, placeholder, disabled = false, btnType, htmlType, showTime, tagProps, mode, children, width, textSwitch, callback, icon, required, message = '请输入', defaultValue, rows, copy, change, isShowUp = true, formatter, parser } = obj
-                    if (label) {
-                        label.length > lw && setLw(label.length)
-                    }
-                    let objWidth: React.CSSProperties | undefined = width ? { minWidth: `${width}px`, float: 'left' } : undefined
-                    let Tag: JSX.Element = <></>
-                    switch (tag) {
-                        case 'input':
-                            Tag = <Input placeholder={placeholder} disabled={disabled} {...tagProps} allowClear style={objWidth} onBlur={callback} />
-                            break;
-                        case 'inputNumber':
-                            Tag = <InputNumber placeholder={placeholder} disabled={disabled} {...tagProps} formatter={formatter} parser={parser} style={objWidth ? objWidth : { width: "100%" }} onBlur={callback} />
-                            break;
-                        case 'inputFile':
-                            Tag = <>
-                                <div className={style.file}>
-                                    <Button type='primary'><UploadOutlined />{label === "上传Excel" ? "导入" : "上传文件"}</Button>
-                                    <input type='file' onChange={fileChanage} accept={fileType[(label as string)]} />
-                                </div>
-                                {
-                                    isShowUp && <>
-                                        <p>{file?.name}</p>
-                                        {
-                                            file?.name && preview()
-                                        }
-                                    </>
-                                }
-
-                            </>
-                            break;
-                        case 'imgCrop':
-                            Tag = <>
-                                <div style={{ display: 'flex' }}>
-                                    <ImgCrop
-                                        rotate
-                                        aspect={1 / 1}
-                                    >
-                                        <Upload
-                                            listType="picture-card"
-                                            accept='image/gif,image/jpeg,image/png,image/jpg'
-                                            beforeUpload={function (file: RcFile) {
-                                                fileChanage(file)
-                                                return false
-                                            }}
-                                            fileList={fileList}
-                                            onChange={(newFileList: any) => {
-                                                setFileList([...newFileList.fileList])
-                                            }}
-                                            onPreview={(file: any) => {
-                                                setPreviewVisible(true)
-                                                setFileUrl(file.thumbUrl)
-                                            }}
-                                        >
-                                            {fileList?.length < 1 && '1:1裁剪上传'}
-                                        </Upload>
-                                    </ImgCrop>
-                                    {
-                                        fileList?.length < 1 && <ImgCrop
-                                            rotate
-                                            aspect={2.35 / 1}
-                                        >
-                                            <Upload
-                                                listType="picture-card"
-                                                accept='image/gif,image/jpeg,image/png,image/jpg'
-                                                beforeUpload={function (file: RcFile) {
-                                                    fileChanage(file)
-                                                    return false
-                                                }}
-                                                fileList={fileList}
-                                                onChange={(newFileList: any) => {
-                                                    console.log(newFileList)
-                                                    setFileList([...newFileList.fileList])
-                                                }}
-                                                onPreview={(file: any) => {
-                                                    setPreviewVisible(true)
-                                                    setFileUrl(file.thumbUrl)
-                                                }}
-                                            >
-                                                {fileList?.length < 1 && '2.35:1裁剪上传'}
-                                            </Upload>
-                                        </ImgCrop>
-                                    }
-                                    {
-                                        fileList?.length < 1 && <Upload
-                                            listType="picture-card"
-                                            accept='image/gif,image/jpeg,image/png,image/jpg'
-                                            beforeUpload={function (file: RcFile) {
-                                                fileChanage(file)
-                                                return false
-                                            }}
-                                            fileList={fileList}
-                                            onChange={(newFileList: any) => {
-                                                setFileList([...newFileList.fileList])
-                                            }}
-                                            onPreview={(file: any) => {
-                                                setPreviewVisible(true)
-                                                setFileUrl(file.thumbUrl)
-                                            }}
-                                        >
-                                            {fileList?.length < 1 && '普通上传'}
-                                        </Upload>
-                                    }
-                                </div>
-                                {
-                                    fileList?.length < 1 && <div style={{ height: 80 }}>
-                                        <Demo width={1080} height={864} callback={(imgData: any) => {
-                                            let file = dataURLtoFile(imgData, Math.round(new Date() as any / 1000))
-                                            fileChanage(file)
-                                            setFileList([{
-                                                uid: Math.random() * 100,
-                                                thumbUrl: imgData
-                                            }])
-                                        }} btnName={<div style={{ display: 'flex', flexFlow: 'column', alignItems: 'center', justifyContent: 'center' }}>
-                                            <span>自定义裁剪可自行设置准确宽高</span>
-                                            <strong style={{ color: 'red' }}>默认:微信卡片图片1080*864</strong>
-                                        </div>} />
-                                    </div>
-                                }
-                                <Modal
-                                    visible={previewVisible}
-                                    footer={null}
-                                    onCancel={() => {
-                                        setPreviewVisible(false)
-                                    }}
-                                >
-                                    <img alt="example" style={{ width: '100%' }} src={fileUrl} />
-                                </Modal>
-                            </>
-                            break;
-                        case 'inputSearch':
-                            Tag = <Input.Search placeholder={placeholder} disabled={disabled} {...tagProps} allowClear style={objWidth} onSearch={value => onSelect(value, callback)} enterButton />
-                            break;
-                        case 'button':
-                            Tag = <Button type={btnType} htmlType={htmlType} {...tagProps} style={objWidth} onClick={htmlType === 'button' ? callback : undefined} icon={icon}>{label}</Button>
-                            break;
-                        case 'DatePicker':
-                            Tag = <DatePicker showTime={showTime} {...tagProps} autoComplete='off' locale={locale} style={objWidth} />
-                            break;
-                        case 'RangePicker':
-                            Tag = <RangePicker autoComplete='off' showTime={showTime} {...tagProps} locale={locale} style={objWidth} />
-                            break;
-                        case 'switch':
-                            Tag = <Switch checkedChildren={textSwitch ? textSwitch[0] : "开"} unCheckedChildren={textSwitch ? textSwitch[1] : "关"} defaultChecked {...tagProps} />
-                            break;
-                        case 'select':
-                            Tag = <Select
-                                {...tagProps}
-                                showSearch
-                                allowClear
-                                mode={mode}
-                                disabled={disabled} // Object.keys(defaultProps || {}).length !== 0 判断是否添加
-                                placeholder={placeholder}
-                                onChange={(value: string | string[]) => onChange(value, change, callback)}
-                                filterOption={(input: string, option: any) => {
-                                    return option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                                }}
-                                optionFilterProp="children"
-                                style={objWidth}
-                            >
-                                {
-                                    children && children.map((a: Children) => {
-                                        return <Option value={`${a.value}`} key={`${a.value}` as string}>{a.text}</Option>
-                                    })
-                                }
-                            </Select>
-                            break;
-                        case 'radio':
-                            Tag = <Radio.Group onChange={onRadio} {...tagProps}>
-                                {
-                                    children && children.map((a: Children) => {
-                                        return <Radio value={a.value} key={a.value as string}>{a.text}</Radio>
-                                    })
-                                }
-                            </Radio.Group>
-                            break;
-                        case 'TextArea':
-                            Tag = <Input.TextArea rows={rows} style={{ ...objWidth, marginBottom: '10px' }} placeholder={placeholder} />
-
-                            {/* <p onClick={() => { callback && callback(copy) }}>{copy}</p> */ }
-                            break;
-                    }
-                    return <Col key={index + 'i'} flex={flow !== 'row' ? 1 : undefined} className={ew ? style.form_row : undefined}>
-                        <Item
-                            name={tag !== 'button' ? name : undefined}//假如是按钮那就不需要name属性
-                            label={tag !== 'button' ? label : undefined}//假如是按钮就不需要label
-                            style={tag === 'button' ? undefined : { minWidth: '200px' }}
-                            // normalize={(value, prevValue, prevValues) => value }
-                            className={flow !== 'row' ? `${style[`form_item${lw}`]}` : undefined}
-                            initialValue={_initDefaultProps(name, tag) || (tag === 'DatePicker' ? defaultValue ? moment(defaultValue as string, 'YYYY/MM/DD') : undefined : defaultValue)}//默认值
-                            rules={required ? [{ required: required, message }, { ...Rule }] : []}
-                            colon={true}
-                            labelCol={labelCol ? labelCol : {}}
-                        >
-                            {Tag}
-                        </Item>
-                    </Col>
-                })
-            }
-        </Form>
-    </div >
-})
-
-
-export default Page

+ 0 - 60
src/components/Formitem/type.ts

@@ -1,60 +0,0 @@
-import { Rule } from "antd/es/form";
-import { ReactText } from "react";
-
-export interface Props {
-    formConfig: FormConfig[],
-    title?: string,
-    flow: 'row' | 'column',
-    submit?: (value: any, key: string) => void,
-    getFormValues?: (values: { changedValues: any, allValues: any }) => void,
-    getFormSubmit?: (fun: any) => void,
-    setFormValues?: (fun: any) => void,
-    defaultProps?: object,
-    formFlex?: 'flex-start' | 'flex-end' | 'space-around' | 'space-between' | 'space-evenly' | 'center',
-    labelCol?:{span?:number,offset?:number},
-    ew?: boolean,
-    isAll?:boolean,
-    isFirstLeftNull?: boolean
-}
-export interface Children {
-    value: string,
-    text: string
-}
-/**
- * @param {string} name 字段名
- * @param {string} tag 标签组件名
- * @param {string} label 标签的文本
- * @param {boolean} required 是否必填项
- * @param {object} tagProps 传入一个对象,为对应标签的参数具体有哪些参数查询antd对应组件的Api
- * @param {"button" | "submit" | "reset"} htmlType button 类型
- * @param {Function} callback 当button htmlType为button时 回调函数生效一般用于弹窗等事件
- * @param {boolean} change 立即执行回调函数
- */
-export interface FormConfig {
-    label?: string,
-    tag: 'input' | 'select' | 'DatePicker' | 'button' | 'RangePicker' | 'inputSearch' | 'radio' | 'switch' | 'inputSearch' | 'TextArea' | 'inputFile' | 'imgCrop' | 'inputNumber',
-    name: string,
-    placeholder?: string,
-    disabled?: boolean,
-    btnType?: "link" | "ghost" | "default" | "primary" | "dashed",
-    htmlType?: "button" | "submit" | "reset",
-    showTime?: boolean,
-    mode?: 'multiple' | 'tags',
-    tagProps?: object,
-    children?: Children[],
-    width?: number,
-    textSwitch?: string[],
-    callback?: (a?: any) => void,
-    icon?: React.ReactNode,
-    required?: boolean,
-    message?: string,
-    defaultValue?: string | string[],
-    rows?: number,
-    copy?: string,
-    change?: boolean
-    Rule?: any,
-    isShowUp?: boolean,
-    formatter?: ((value: string | number | undefined) => string) | undefined,
-    parser?: ((value: string) => ReactText) | undefined
-}
-

+ 0 - 23
src/components/HeaderSearch/index.less

@@ -1,23 +0,0 @@
-@import '~antd/es/style/themes/default.less';
-
-.headerSearch {
-  .input {
-    width: 0;
-    min-width: 0;
-    overflow: hidden;
-    background: transparent;
-    border-radius: 0;
-    transition: width 0.3s, margin-left 0.3s;
-    :global(.ant-select-selection) {
-      background: transparent;
-    }
-    input {
-      box-shadow: none !important;
-    }
-
-    &.show {
-      width: 210px;
-      margin-left: 8px;
-    }
-  }
-}

+ 0 - 102
src/components/HeaderSearch/index.tsx

@@ -1,102 +0,0 @@
-import { SearchOutlined } from '@ant-design/icons';
-import { AutoComplete, Input } from 'antd';
-import useMergeValue from 'use-merge-value';
-import { AutoCompleteProps } from 'antd/es/auto-complete';
-import React, { useRef } from 'react';
-
-import classNames from 'classnames';
-import styles from './index.less';
-
-export interface HeaderSearchProps {
-  onSearch?: (value?: string) => void;
-  onChange?: (value?: string) => void;
-  onVisibleChange?: (b: boolean) => void;
-  className?: string;
-  placeholder?: string;
-  options: AutoCompleteProps['options'];
-  defaultOpen?: boolean;
-  open?: boolean;
-  defaultValue?: string;
-  value?: string;
-}
-
-const HeaderSearch: React.FC<HeaderSearchProps> = (props) => {
-  const {
-    className,
-    defaultValue,
-    onVisibleChange,
-    placeholder,
-    open,
-    defaultOpen,
-    ...restProps
-  } = props;
-
-  const inputRef = useRef<Input | null>(null);
-
-  const [value, setValue] = useMergeValue<string | undefined>(defaultValue, {
-    value: props.value,
-    onChange: props.onChange,
-  });
-
-  const [searchMode, setSearchMode] = useMergeValue(defaultOpen || false, {
-    value: props.open,
-    onChange: onVisibleChange,
-  });
-
-  const inputClass = classNames(styles.input, {
-    [styles.show]: searchMode,
-  });
-
-  return (
-    <div
-      className={classNames(className, styles.headerSearch)}
-      onClick={() => {
-        setSearchMode(true);
-        if (searchMode && inputRef.current) {
-          inputRef.current.focus();
-        }
-      }}
-      onTransitionEnd={({ propertyName }) => {
-        if (propertyName === 'width' && !searchMode) {
-          if (onVisibleChange) {
-            onVisibleChange(searchMode);
-          }
-        }
-      }}
-    >
-      <SearchOutlined
-        key="Icon"
-        style={{
-          cursor: 'pointer',
-        }}
-      />
-      <AutoComplete
-        key="AutoComplete"
-        className={inputClass}
-        value={value}
-        options={restProps.options}
-        onChange={setValue}
-      >
-        <Input
-          size="small"
-          ref={inputRef}
-          defaultValue={defaultValue}
-          aria-label={placeholder}
-          placeholder={placeholder}
-          onKeyDown={(e) => {
-            if (e.key === 'Enter') {
-              if (restProps.onSearch) {
-                restProps.onSearch(value);
-              }
-            }
-          }}
-          onBlur={() => {
-            setSearchMode(false);
-          }}
-        />
-      </AutoComplete>
-    </div>
-  );
-};
-
-export default HeaderSearch;

+ 0 - 110
src/components/MaterialModal/db.less

@@ -1,110 +0,0 @@
-.footer {
-  display: flex;
-  justify-content: center;
-}
-.img_ScwxBox {
-  display: flex !important;
-  justify-content: space-between !important;
-  padding: 5px 0 !important;
-  img {
-    width: 56px;
-    height: 56px;
-    border-radius: 3px;
-    object-fit: cover;
-  }
-  span {
-    width: 200px;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    border-bottom: 1px solid #efefef;
-    -webkit-line-clamp: 2;
-    display: -webkit-box;
-    -webkit-box-orient: vertical;
-    margin-top: 10px;
-    height: 48px;
-  }
-}
-.box_card {
-  padding: 15px;
-  > div {
-    &:nth-child(2) {
-      padding: 0;
-    }
-  }
-  .img_ScwxBox:first-child {
-    flex-flow: column;
-    position: relative;
-    img {
-      width: 100%;
-      height: 131px;
-      order: 1;
-    }
-    span {
-      order: 2;
-      border: 0;
-      position: absolute;
-      left: 0;
-      bottom: 0;
-      background-image: linear-gradient(-180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
-      color: #fff;
-      width: 100%;
-      z-index: 33;
-      line-height: 24px;
-    }
-  }
-}
-
-.box {
-  display: flex;
-  flex-flow: row;
-  height: 500px;
-  overflow-y: scroll;
-  .ul {
-    width: 33%;
-    margin: 0;
-    padding: 0;
-    margin: 10px;
-    > li {
-      width: 100%;
-      margin: 0 0 15px 0;
-    }
-  }
-}
-.action {
-  position: relative;
-  // margin: 0 auto;
-  // text-align: center;
-  color: #4abe84;
-  background-color: #fff;
-  box-shadow: 0px 2px 7px 0px rgba(85, 110, 97, 0.35);
-  border-radius: 7px;
-  border: 1px solid rgba(74, 190, 132, 1);
-  overflow: hidden;
-  &::before {
-    content: '';
-    position: absolute;
-    right: 0;
-    bottom: 0;
-    border: 17px solid #4abe84;
-    border-top-color: transparent;
-    border-left-color: transparent;
-    z-index: 9;
-  }
-  &::after {
-    content: '';
-    width: 5px;
-    height: 12px;
-    position: absolute;
-    right: 6px;
-    bottom: 6px;
-    border: 2px solid #fff;
-    border-top-color: transparent;
-    border-left-color: transparent;
-    transform: rotate(45deg);
-    z-index: 9;
-  }
-}
-.btn {
-  display: flex;
-  justify-content: flex-end;
-}

+ 0 - 268
src/components/MaterialModal/graphic.less

@@ -1,268 +0,0 @@
-.header {
-  border-bottom: 1px solid #efefef;
-  padding-bottom: 15px;
-}
-.nickName {
-  color: orange;
-  border: 1px solid orange;
-  border-radius: 2px;
-  margin-right: 3px;
-  padding: 1px 5px;
-  font-size: 12px;
-  display: inline-block;
-}
-.centent {
-  height: 400px;
-  display: flex;
-  .left {
-    width: 200px;
-    height: 68px;
-    display: flex;
-    flex-flow: column;
-    justify-content: space-between;
-    p {
-      font-size: 12px;
-      margin-bottom: 0;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      display: -webkit-box;
-      -webkit-line-clamp: 2;
-      -webkit-box-orient: vertical;
-      color: #000;
-    }
-    span {
-      font-size: 12px;
-      color: rgb(153, 153, 153);
-    }
-  }
-  .list {
-    padding: 10px;
-    .box {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-      img {
-        width: 56px;
-        height: 56px;
-        object-fit: cover;
-      }
-    }
-  }
-  > div {
-    height: 100%;
-    overflow-y: scroll;
-    &:first-child {
-      width: 30%;
-      background-color: #fafafa;
-      .text {
-        display: flex;
-        justify-content: center;
-        padding: 9px;
-        flex-flow: column;
-        align-items: center;
-        color: #666;
-        font-size: 12px;
-        button {
-          margin-top: 10px;
-        }
-      }
-    }
-    &:last-child {
-      display: flex;
-      padding: 10px;
-      width: 75%;
-      label {
-        margin: 8px 0;
-        display: inline-block;
-      }
-      .editor {
-        border: 1px solid #efefef;
-        padding: 5px 5px;
-      }
-      > div {
-        &:last-child {
-          width: 30%;
-          padding: 10px;
-          display: flex;
-          flex-flow: column;
-          .imgupload:hover {
-            position: relative;
-            > div {
-              display: flex;
-            }
-          }
-          > span {
-            border: 1px dashed rgb(216, 216, 216);
-            width: 96px;
-            height: 96px;
-            text-align: center;
-            border: 1px dashed rgb(216, 216, 216);
-            background: rgb(255, 255, 255);
-            cursor: pointer;
-            align-self: center;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            overflow: hidden;
-            > div {
-              display: none;
-              position: absolute;
-              top: 0;
-              left: 0;
-              right: 0;
-              bottom: 0;
-              background-color: rgba(0, 0, 0, 0.6);
-              align-items: center;
-              justify-content: center;
-            }
-            img {
-              width: 100%;
-            }
-          }
-        }
-      }
-    }
-  }
-}
-.centent_2 {
-  height: 400px;
-  .list {
-    display: flex;
-    flex-flow: row wrap;
-    align-items: center;
-    justify-content: flex-start;
-    overflow-y: scroll;
-    height: 350px;
-    > div {
-      margin-right: 1.5%;
-      &:nth-child(3n) {
-        margin-right: 0;
-      }
-    }
-  }
-  > p {
-    padding-top: 15px;
-    span {
-      color: #999;
-    }
-  }
-  .box {
-    display: flex;
-    justify-content: space-between;
-    align-items: center;
-  }
-  .left {
-    width: 200px;
-    height: 68px;
-    display: flex;
-    flex-flow: column;
-    justify-content: space-between;
-    p {
-      font-size: 12px;
-      margin-bottom: 0;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      display: -webkit-box;
-      -webkit-line-clamp: 2;
-      -webkit-box-orient: vertical;
-      color: #000;
-    }
-    span {
-      font-size: 12px;
-      color: rgb(153, 153, 153);
-    }
-  }
-  img {
-    width: 56px;
-    height: 56px;
-    object-fit: cover;
-  }
-}
-.action {
-  > div {
-    position: relative;
-    margin: 0 auto;
-    // text-align: center;
-    color: #4abe84;
-    background-color: #fff;
-    box-shadow: 0px 2px 7px 0px rgba(85, 110, 97, 0.35);
-    border-radius: 7px;
-    border: 1px solid rgba(74, 190, 132, 1);
-    overflow: hidden;
-    &::before {
-      content: '';
-      position: absolute;
-      right: 0;
-      bottom: 0;
-      border: 17px solid #4abe84;
-      border-top-color: transparent;
-      border-left-color: transparent;
-      z-index: 9;
-    }
-    &::after {
-      content: '';
-      width: 5px;
-      height: 12px;
-      position: absolute;
-      right: 6px;
-      bottom: 6px;
-      border: 2px solid #fff;
-      border-top-color: transparent;
-      border-left-color: transparent;
-      transform: rotate(45deg);
-      z-index: 9;
-    }
-  }
-}
-i {
-  font-style: normal;
-}
-.graphic_list {
-  display: flex;
-  flex-flow: column;
-  > div {
-    &:last-child {
-      width: 100% !important;
-      flex-flow: row nowrap !important;
-      justify-content: space-between;
-      > div {
-        &:last-child {
-          .imgupload:hover {
-            position: relative;
-            > div {
-              display: flex;
-            }
-          }
-          > span {
-            border: 1px dashed rgb(216, 216, 216);
-            width: 96px;
-            height: 96px;
-            text-align: center;
-            border: 1px dashed rgb(216, 216, 216);
-            background: rgb(255, 255, 255);
-            cursor: pointer;
-            align-self: center;
-            display: flex;
-            align-items: center;
-            justify-content: center;
-            overflow: hidden;
-            > div {
-              display: none;
-              position: absolute;
-              top: 0;
-              left: 0;
-              right: 0;
-              bottom: 0;
-              background-color: rgba(0, 0, 0, 0.6);
-              align-items: center;
-              justify-content: center;
-            }
-            img {
-              width: 100%;
-            }
-          }
-        }
-      }
-    }
-  }
-}

+ 0 - 81
src/components/MaterialModal/index.less

@@ -1,81 +0,0 @@
-.img {
-  img {
-    object-fit: cover;
-    height: 150px;
-  }
-}
-.action {
-  > div {
-    > div {
-      div {
-        position: relative;
-        // margin: 0 auto;
-        // text-align: center;
-        color: #4abe84;
-        background-color: #fff;
-        box-shadow: 0px 2px 7px 0px rgba(85, 110, 97, 0.35);
-        border-radius: 7px;
-        // border: 1px solid rgba(74, 190, 132, 1);
-        overflow: hidden;
-        &::before {
-          content: '';
-          position: absolute;
-          right: 0;
-          bottom: 0;
-          border: 17px solid #4abe84;
-          border-top-color: transparent;
-          border-left-color: transparent;
-          z-index: 9;
-        }
-        &::after {
-          content: '';
-          width: 5px;
-          height: 12px;
-          position: absolute;
-          right: 6px;
-          bottom: 6px;
-          border: 2px solid #fff;
-          border-top-color: transparent;
-          border-left-color: transparent;
-          transform: rotate(45deg);
-          z-index: 9;
-        }
-      }
-    }
-  }
-}
-
-.qq_link {
-  display: flex;
-  flex-flow: row;
-  align-items: center;
-  margin-bottom: 20px;
-  label {
-    width: 100px;
-    text-align: right;
-    display: inline-block;
-    flex-shrink: 0;
-  }
-  input {
-    width: 400px;
-  }
-}
-.qq_iframe {
-  display: flex;
-  flex-flow: row;
-  align-items: flex-start;
-  label {
-    width: 100px;
-    text-align: right;
-    display: inline-block;
-  }
-  iframe {
-    border: 1px dashed #d8d8d8;
-  }
-}
-.box_img {
-  overflow: hidden;
-  white-space: nowrap;
-  text-overflow: ellipsis;
-  width: 150px;
-}

+ 0 - 182
src/components/MaterialModal/index.tsx

@@ -1,182 +0,0 @@
-import { Modal, Tabs, Image, Row, Col, Card, Tag, Pagination, Button, message } from 'antd'
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import { request, useModel } from 'umi';
-import style from './index.less'
-// import UploadModal from '@/pages/operatePage/material/cloud/components/Modal'
-const { TabPane } = Tabs;
-/**编辑器左侧选择图片弹窗 */
-type Props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOk: (param: { type: 'pushData', params: { menuId: string, thumbUrl: string } }) => void,
-    title: string,
-    data: any,
-    menuId: string,
-    isWx?: boolean
-}
-/**编辑器右侧选择图片弹窗*/
-let MaterialModal = React.memo((props: Props) => {
-    const [action, setAction] = useState<string>('')
-    const [key, setKey] = useState<string>('1')//菜单值
-    const [page, setPage] = useState<number>(1)//页码
-    let refM: { current: { onOpen: () => void, onCancel: () => void } } | any = useRef()//获取Modal实例方法
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const { getWeData, classGet, tagData, addData, getData, fileUrl } = useModel('useOperating.useMaterialContent', model => ({
-        getWeData: model.getWeData,
-        tagData: model.tagData,
-        classGet: model.classGet,
-        addData: model.addData,
-        getData: model.getData,
-        fileUrl: model.fileUrl
-    }))
-    let { state } = useModel('useOperating.useMaterialModal')
-
-    //选中图片
-    let handleClick = useCallback((url) => {
-        setAction(url)
-    }, [])
-    //个人共用切换
-    useEffect(() => {
-        setPage(1)
-        if (key === '1') {
-            props.data.run({
-                mediaType: 1,
-                pageNum: 1,
-                pageSize: 8,
-                type: 0
-            })
-        }
-        if (key === '3') {
-            props.data.run({
-                mediaType: 1,
-                pageNum: 1,
-                pageSize: 8,
-                isAdmin: true,
-                type: 1
-            })
-        }
-    }, [key])
-    //翻页
-    let pageSizeChange = useCallback((page: number, pageSize?: number) => {
-        setPage(page)
-        if (key === '1') {
-            props.data.run({
-                mediaType: 1,
-                pageNum: page,
-                pageSize: 10,
-                type: 0
-            })
-        } else {
-            props.data.run({
-                mediaType: 1,
-                pageNum: page,
-                pageSize: 10,
-                isAdmin: true,
-                type: 1
-            })
-        }
-    }, [props, key])
-    //确定插入
-    let handleOk = useCallback(() => {
-        props.onOk({ type: 'pushData', params: { menuId: props.menuId, thumbUrl: action } })
-        props.onCancel()
-    }, [action])
-    useEffect(() => {
-        if (actionWX?.appid) {
-            getWeData.run({
-                appId: actionWX?.appid,
-                count: 10,
-                offset: 0,
-                type: 1
-            })
-        }
-    }, [actionWX])
-    //新增编辑非图文素材弹窗确定发送
-    let modalOk = useCallback((fnc: () => Promise<any>, data: any) => {
-        fnc().then((res: any) => {
-            if (res) {
-                if (res?.file) {
-                    /**修改文件名以用户设置的文件title命名*/
-                    let newFile = new File([state?.file], res.title + '.' + state?.file?.name.split('.')[1], { type: state?.file?.type })
-                    let formData = new FormData();
-                    /**向阿里云请求上传地址*/
-                    fileUrl.run({ type: newFile.type }).then(res1 => {
-                        Object.keys(res1).forEach((key: string) => {
-                            if (key !== 'url') {
-                                formData.append(key, res1[key])
-                            }
-                        })
-                        formData.append('file', newFile)
-                        /**向阿里云返回的上传地址上传文件*/
-                        request(res1?.url, { method: 'post', body: formData }).then((res2: { code: number, data: { url: string } }) => {
-                            if (res2.code === 200) {
-                                message.success('上传成功')
-                                if (res) {
-                                    /**取到返回的文件地址向后端发送具体数据*/
-                                    if (res2?.data?.url) {
-                                        addData.run({ title: res.title, url: res2?.data?.url, mediaTagIds: res.mediaTagId, mediaType: 1, groupId: res.groupId }).then(() => {
-                                            refM?.current.onCancel()
-                                            getData.refresh()
-                                        })
-                                    }
-                                }
-                            } else {
-                                message.error('上传失败!')
-                            }
-                        })
-                    })
-                }
-            }
-        })
-    }, [getData.data, state])
-    return <>
-        <Modal
-            width={750}
-            title={props.title}
-            visible={props.visible}
-            okText='插入'
-            cancelText='取消'
-            onCancel={() => props.onCancel()}
-            onOk={handleOk}
-            destroyOnClose
-        >
-            <Tabs type="card" onChange={(key: string) => { setKey(key) }}
-                tabBarExtraContent={key === '1' ? <Button type='primary' onClick={() => {
-                    refM?.current?.onOpen('新建')
-                }}>新建图片</Button> : ''}
-            >
-                <TabPane tab="个人本地素材" key="1" style={{ padding: 10 }}>
-                    <Row justify='start' gutter={[15, 15]}>
-                        {
-                            props?.data?.data?.records?.map((item: any) => {
-                                return <Col key={item.id} className={`${style.img} ${action === item.url ? style.action : undefined}`}>
-                                    <Card bodyStyle={{ padding: 0, height: 150 }} bordered={false} hoverable>
-                                        <Image src={item.url} width={150} height={150} placeholder preview={false} onClick={() => handleClick(item.url)} />
-                                    </Card>
-                                </Col>
-                            })
-                        }
-                    </Row>
-                    <Pagination onChange={pageSizeChange} size={'small'} current={page} total={props.data?.data?.total} style={{ float: 'right' }} showTotal={(total: any) => <Tag color="cyan">总共{total}数据</Tag>} />
-                </TabPane>
-                <TabPane tab="共用本地素材" key="3" style={{ padding: 10 }}>
-                    <Row justify='start' gutter={[15, 15]}>
-                        {
-                            props?.data?.data?.records?.map((item: any) => {
-                                return <Col key={item.id} className={`${style.img} ${action === item.url ? style.action : undefined}`}>
-                                    <Card bodyStyle={{ padding: 0, height: 150 }} bordered={false} hoverable>
-                                        <Image src={item.url} width={150} height={150} placeholder preview={false} onClick={() => handleClick(item.url)} />
-                                    </Card>
-                                </Col>
-                            })
-                        }
-                    </Row>
-                    <Pagination onChange={pageSizeChange} size={'small'} current={page} total={props.data?.data?.total} style={{ float: 'right' }} showTotal={(total: any) => <Tag color="cyan">总共{total}数据</Tag>} />
-                </TabPane>
-            </Tabs>
-            {/* <UploadModal labelName='图片' ref={refM} submit={modalOk} title='图片' classs={classGet?.data} tags={tagData?.data} /> */}
-        </Modal>
-    </>
-})
-
-export default MaterialModal

+ 0 - 409
src/components/MaterialModal/modalBox.tsx

@@ -1,409 +0,0 @@
-import { Button, Card, Col, Empty, Image, Input, message, Modal, Pagination, Row, Select, Space, Tabs, Tag } from "antd"
-import React, { useMemo, useRef } from "react"
-import { useCallback, useEffect, useState } from "react"
-import { request, useModel } from "umi"
-import UploadModal from '@/pages/operatePage/material/cloud/components/Modal'
-const { TabPane } = Tabs;
-import style from './index.less'
-/**编辑器内容选择图片弹窗*/
-let config1 = {
-    1: '图片',
-    2: '音频',
-    3: '视频',
-    4: '文字',
-    5: '图文'
-}
-type Props = {
-    mediaType: number,
-    visible: boolean,
-    onOk: (url: string, type?: number) => void,
-    onCancel: () => void,
-    title: string,
-    actionKey?: string,
-    isShowWx?: boolean,
-    isAllData?: boolean
-}
-const ModalPage = (props: Props) => {
-    const [action, setAction] = useState<string>('')
-    const [actionData, setActionData] = useState<any>(null)
-    const { mediaType, visible, onOk, onCancel, title, actionKey, isShowWx = true, isAllData = false } = props
-    const [qqLink, setQqLink] = useState<string>('')
-    const [key, setKey] = useState<string>('1')//菜单值
-    const [page, setPage] = useState<number>(1)//页码
-    let refM: { current: { onOpen: () => void, onCancel: () => void } } | any = useRef()//获取Modal实例方法
-    const { access } = useModel('@@initialState', model => ({ access: model.initialState?.currentUser?.access }))
-    const { getData, getWeData, addData, tagData, classGet, fileUrl } = useModel('useOperating.useMaterialContent', model => ({
-        getData: model.getData,
-        getWeData: model.getWeData,
-        addData: model.addData,
-        tagData: model.tagData,
-        classGet: model.classGet,
-        fileUrl: model.fileUrl,
-    }))
-    let { state } = useModel('useOperating.useMaterialModal')
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const [className, setClassName] = useState<number>()
-    const [tagName, setTagName] = useState<number[]>([])
-    //搜索
-    let handleSelect = useCallback((name: number | number[], isTag: boolean) => {
-        if (isTag) {
-            setTagName(name as number[])
-            getData.run({ type: key === '3' ? 1 : 0, mediaType, groupId: className || '', tagIds: name, pageNum: 1, pageSize: 10 })
-            setPage(1)
-        } else {
-            setClassName(name as number)
-            getData.run({ type: key === '3' ? 1 : 0, mediaType, groupId: name || '', tagIds: tagName || '', pageNum: 1, pageSize: 10 })
-            setPage(1)
-        }
-    }, [tagName, className, key, mediaType,])
-    //
-    let tagArr = useMemo(() => {
-        if (tagData?.data) {
-            let arr = tagData?.data?.map((item: { id: string, tagName: string }) => ({ value: item.id, text: item.tagName }))
-            return arr
-        }
-        return []
-    }, [tagData?.data])
-    let classArr = useMemo(() => {
-        if (classGet?.data) {
-            let arrClass = classGet?.data?.map((item: { id: string, groupName: string }) => ({ value: item.id, text: item.groupName }))
-            return arrClass
-        }
-        return []
-    }, [classGet?.data])
-    //
-    useEffect(() => {
-        getData.run({
-            mediaType: mediaType,
-            pageNum: 1,
-            pageSize: 10,
-            type: 0
-        })
-    }, [mediaType, actionWX])
-    //qq视频
-    const qqLinkChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        let arr = v.split('/')
-        let vid = arr[arr.length - 1].replace('.html', '')
-        if (v.search(/http[s]?:\/\/v.qq.com[\S]*.html/ig) !== -1) {
-            setQqLink(`https://v.qq.com/iframe/player.html?vid=${vid}&auto=0`)
-        }
-    }, [])
-    //选中图片
-    let handleClick = useCallback((url, data?: any) => {
-        console.log(url)
-        setAction(url)
-        setActionData(data)
-    }, [])
-    //个人共用切换
-    useEffect(() => {
-        setPage(1)
-        if (key === '1') {
-            getData.run({
-                mediaType: mediaType,
-                pageNum: page,
-                pageSize: 10,
-                type: 0
-            })
-            tagData.run({ type: 0 })
-            classGet.run({ type: 0 })
-        }
-        if (key === '3') {
-            getData.run({
-                mediaType: mediaType,
-                pageNum: page,
-                pageSize: 10,
-                type: 1
-            })
-            tagData.run({ type: 1 })
-            classGet.run({ type: 1 })
-        }
-        if (key === '4') {
-            getWeData.run({
-                appId: actionWX?.appid,
-                size: 10,
-                page: 0,
-                type: mediaType
-            })
-        }
-    }, [key, mediaType, actionWX])
-    //翻页
-    let pageSizeChange = useCallback((page: number, pageSize?: number) => {
-        setPage(page)
-        if (key === '1') {
-            getData.run({
-                mediaType: mediaType,
-                pageNum: page,
-                pageSize: 10,
-                type: 0,
-                tagIds: tagName || '',
-                groupId: className || '',
-            })
-        } else {
-            getData.run({
-                mediaType: mediaType,
-                pageNum: page,
-                pageSize: 10,
-                type: 1,
-                tagIds: tagName || '',
-                groupId: className || '',
-            })
-        }
-    }, [mediaType, key, tagName, className])
-    let wxpageSizeChange = useCallback((page: number, pageSize?: number) => {
-        setPage(page)
-        if (actionWX?.appid) {
-            getWeData.run({
-                appId: actionWX?.appid,
-                size: pageSize,
-                page: page,
-                type: mediaType
-            })
-        }
-    }, [mediaType, actionWX])
-    //Ok
-    let ok = () => {
-        if (!actionKey) {
-            if (isAllData) {
-                if (actionData) {
-                    onOk(actionData, mediaType)
-                }
-
-            } else {
-                if (action) {
-                    onOk(action, mediaType)
-                }
-            }
-        }
-        if (actionKey === '1') {
-            if (qqLink) {
-                onOk(qqLink)
-            } else {
-                message.error('地址不正确')
-            }
-        }
-    }
-    //新增编辑非图文素材弹窗确定发送
-    let modalOk = useCallback((fnc: () => Promise<any>, data: any) => {
-        fnc().then((res: any) => {
-            if (res) {
-                if (res?.file) {
-                    /**修改文件名以用户设置的文件title命名*/
-                    let newFile = new File([state?.file], res.title + '.' + state?.file?.name.split('.')[1], { type: state?.file?.type })
-                    let formData = new FormData();
-                    /**向阿里云请求上传地址*/
-                    fileUrl.run({ type: newFile.type }).then(res1 => {
-                        Object.keys(res1).forEach((key: string) => {
-                            if (key !== 'url') {
-                                formData.append(key, res1[key])
-                            }
-                        })
-                        formData.append('file', newFile)
-                        /**向阿里云返回的上传地址上传文件*/
-                        request(res1?.url, { method: 'post', body: formData }).then((res2: { code: number, data: { url: string } }) => {
-                            if (res2.code === 200) {
-                                message.success('上传成功')
-                                if (res) {
-                                    /**取到返回的文件地址向后端发送具体数据*/
-                                    if (res2?.data?.url) {
-                                        addData.run({ title: res.title, url: res2?.data?.url, mediaTagIds: res.mediaTagId, mediaType, groupId: res.groupId, type: key === '3' ? 1 : 0 }).then(() => {
-                                            refM?.current.onCancel()
-                                            getData.refresh()
-                                        })
-                                    }
-                                }
-                            } else {
-                                message.error('上传失败!')
-                            }
-                        })
-                    })
-                }
-            }
-        })
-    }, [getData.data, state, key])
-    let Tags = (props: { url: string, data?: { title?: string, name?: string } }) => {
-        switch (mediaType) {
-            case 1:
-                return <Card bodyStyle={{ padding: 0, height: 150, display: 'flex', flexFlow: 'column' }} bordered={false} hoverable>
-                    <Image src={props.url} width={150} height={150} placeholder preview={false} onClick={() => handleClick(props.url, props?.data)} />
-                </Card >
-            case 3:
-                return <div>
-                    <Card bodyStyle={{ padding: 10, height: 165, display: 'flex', flexFlow: 'column', border: '1px solid #efefef' }} bordered={false} hoverable onClick={() => handleClick(props.url, props?.data)}>
-                        <video src={props.url} height='130px' controls />
-                        <span>名称: {props?.data?.title || props?.data?.name}</span>
-                    </Card>
-                </div>
-            default:
-                return <div>
-                    <Card bodyStyle={{ padding: 10, height: 80, display: 'flex', flexFlow: 'column', border: '1px solid #efefef' }} bordered={false} hoverable onClick={() => handleClick(props.url, props?.data)}>
-                        <audio src={props.url} controls />
-                        <span>名称: {props?.data?.title || props?.data?.name}</span>
-                    </Card>
-                </div>
-        }
-    }
-    return <Modal
-        title={title}
-        width={900}
-        visible={visible}
-        onOk={ok}
-        onCancel={onCancel}
-    >
-        <>
-            {
-                !actionKey && <>
-                    <Tabs
-                        type="card"
-                        onChange={(key: string) => { setKey(key) }}
-                        tabBarExtraContent={
-                            <Space>
-                                {
-                                    key !== '4' && <Select
-                                        style={{ width: 120 }}
-                                        allowClear
-                                        placeholder='标签搜索'
-                                        onChange={(value: any) => handleSelect(value, true)}
-                                        mode='multiple'
-                                        filterOption={(input, option) =>
-                                            option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                                        }
-                                    >
-                                        {
-                                            tagArr?.map((item: { value: string, text: string }) => {
-                                                return <Select.Option value={item.value} key={item.value}>{item.text}</Select.Option>
-                                            })
-                                        }
-                                    </Select>
-                                }
-                                {
-                                    key !== '4' && <Select
-                                        showSearch
-                                        style={{ width: 120 }}
-                                        allowClear
-                                        placeholder='类型搜索'
-                                        onChange={(value: any) => handleSelect(value, false)}
-                                        filterOption={(input, option) =>
-                                            option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                                        }
-                                    >
-                                        {
-                                            classArr?.map((item: { value: string, text: string }) => {
-                                                return <Select.Option value={item.value} key={item.value}>{item.text}</Select.Option>
-                                            })
-                                        }
-                                    </Select>
-                                }
-                                {
-                                    key === '1' ?
-                                        <Button type='primary' onClick={() => refM?.current?.onOpen('新建')}>新建{title}</Button> :
-                                        key === '3' && access === 'admin' ? <Button type='primary' onClick={() => refM?.current?.onOpen('新建')}>新建{title}</Button> :
-                                            key === '2' ? <Button type='primary' onClick={() => refM?.current?.onOpen('新建')}>新建{title}</Button> : ''
-                                }
-                            </Space>
-                        }
-                    >
-                        <TabPane tab="个人本地素材" key="1" style={{ padding: 10 }}>
-                            {
-                                getData?.data?.records?.length > 0 ? <Row justify='start' gutter={[15, 15]}>
-                                    {
-                                        getData?.data?.records?.map((item: any) => {
-                                            return <Col key={item.id} className={`${style.img} ${action === item.url ? style.action : undefined}`}>
-                                                <Tags url={item.url} data={item} />
-                                            </Col>
-                                        })
-                                    }
-                                </Row> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                            }
-                            <Pagination onChange={pageSizeChange} size={'small'} current={page} total={getData?.data?.total} style={{ float: 'right' }} showTotal={(total) => <Tag color="cyan">总共{total}数据</Tag>} />
-                        </TabPane>
-                        <TabPane tab="公共本地素材" key="3" style={{ padding: 10 }} >
-                            {
-                                getData?.data?.records?.length > 0 ? <Row justify='start' gutter={[15, 15]}>
-                                    {
-                                        getData?.data?.records?.map((item: any) => {
-                                            return <Col key={item.id} className={`${style.img} ${action === item.url ? style.action : undefined}`}>
-                                                <Tags url={item.url} data={item} />
-                                            </Col>
-                                        })
-                                    }
-                                </Row> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                            }
-                            <Pagination onChange={pageSizeChange} size={'small'} current={page} total={getData?.data?.total} style={{ float: 'right' }} showTotal={(total) => <Tag color="cyan">总共{total}数据</Tag>} />
-                        </TabPane>
-                        {
-                            isShowWx && false && <TabPane tab="微信素材" key="4" style={{ padding: 10 }}>
-                                {
-                                    getWeData?.data?.records?.length > 0 ? <Row justify='start' gutter={[15, 15]}>
-                                        {
-                                            getWeData?.data?.records?.map((item: any) => {
-                                                item = item?.content
-                                                return <Col key={item?.mediaId} className={`${style.img} ${action === item?.url ? style.action : undefined}`}>
-                                                    <Tags url={item?.url} data={item} />
-                                                </Col>
-                                            })
-                                        }
-                                    </Row> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                                }
-
-                                <Pagination onChange={wxpageSizeChange} size={'small'} current={page} total={getWeData?.data?.total} style={{ float: 'right' }} showTotal={(total) => <Tag color="cyan">总共{total}数据</Tag>} />
-                            </TabPane>
-                        }
-                    </Tabs>
-                    <UploadModal labelName={config1[mediaType]} ref={refM} submit={modalOk} title={title} classs={classGet?.data} tags={tagData?.data} />
-                </>
-            }
-            {
-                actionKey === '1' &&
-                <Tabs type="card">
-                    <TabPane tab="腾讯视频" key="2" style={{ padding: 10 }}>
-                        <Row>
-                            <Col className={style.qq_link}>
-                                <label>视频地址:</label>
-                                <Input placeholder='请输入腾讯视频地址' onChange={qqLinkChange} allowClear />
-                            </Col>
-                            <Col className={style.qq_iframe}>
-                                <label>预览:</label>
-                                <iframe
-                                    data-vidtype="2"
-                                    height="310"
-                                    width="500"
-                                    data-ratio="1.7666666666666666"
-                                    data-w="848"
-                                    src={qqLink}
-                                />
-                            </Col>
-                        </Row>
-                    </TabPane>
-                </Tabs>
-
-            }
-            {
-                actionKey === '2' && <Tabs type="card">
-                    <TabPane tab="音频" key="2" style={{ padding: 10 }}>
-                        <Row>
-                            <Col className={style.qq_link}>
-                                <label>视频地址:</label>
-                                <Input placeholder='请输入腾讯视频地址' />
-                            </Col>
-                            <Col className={style.qq_iframe}>
-                                <label>预览:</label>
-                                <iframe
-                                    data-vidtype="2"
-                                    height="310"
-                                    width="500"
-                                    data-ratio="1.7666666666666666"
-                                    data-w="848"
-                                    src="https://v.qq.com/iframe/player.html?vid=e3161ny316e&auto=0"
-                                />
-                            </Col>
-                        </Row>
-                    </TabPane>
-                </Tabs>
-            }
-
-        </>
-    </Modal>
-}
-
-export default ModalPage

+ 0 - 104
src/components/MaterialModal/mphnews.less

@@ -1,104 +0,0 @@
-.content{
-    margin-top: 10px;
-    height: 400px;
-    overflow: hidden;
-    overflow-y: scroll;
-}
-
-.box{
-    display: flex;
-    flex-flow: row;
-    .ul {
-        width: 33%;
-        margin: 0;
-        padding: 0;
-        margin: 10px;
-        > li {
-          width: 100%;
-          margin: 0 0 15px 0;
-        }
-      }
-}
-.action {
-    position: relative;
-    margin: 0 auto;
-    // text-align: center;
-    color: #4abe84;
-    background-color: #fff;
-    box-shadow: 0px 2px 7px 0px rgba(85, 110, 97, 0.35);
-    border-radius: 7px;
-    border: 1px solid rgba(74, 190, 132, 1);
-    overflow: hidden;
-    &::before {
-        content: '';
-        position: absolute;
-        right: 0;
-        bottom: 0;
-        border: 17px solid #4abe84;
-        border-top-color: transparent;
-        border-left-color: transparent;
-        z-index: 9;
-    }
-    &::after {
-        content: '';
-        width: 5px;
-        height: 12px;
-        position: absolute;
-        right: 6px;
-        bottom: 6px;
-        border: 2px solid #fff;
-        border-top-color: transparent;
-        border-left-color: transparent;
-        transform: rotate(45deg);
-        z-index: 9;
-    }
-}
-.box_card{
-    >.ant-card-body{
-        padding: 0;
-
-    }
-}
-.box_card {
-    padding: 5px;
-    > div {
-        &:nth-child(2){
-            padding: 0 ;
-        }
-    }
-    div.card_content{
-        box-sizing: border-box;
-        >h3{
-            line-height: 1.5;
-            font-size: 16px;
-            padding: 0 6px;
-            overflow: hidden;
-            text-overflow: ellipsis;
-            display: -webkit-box;
-            -webkit-line-clamp: 1;
-            -webkit-box-orient: vertical;
-            box-sizing: border-box;
-        }
-        >div{
-            display: flex;
-            justify-content: start;
-            >p{
-                flex: 1;
-                font-size: 12px;
-                margin: 0;
-                color: #999;
-                overflow: hidden;
-                text-overflow: ellipsis;
-                display: -webkit-box;
-                -webkit-line-clamp: 3;
-                -webkit-box-orient: vertical;
-                padding-right: 5px;
-            }
-            >img{
-                width: 50px;
-                height: 50px;
-                object-fit: cover;
-            }
-        }
-    }
-}

+ 0 - 110
src/components/MaterialModal/mpnews.less

@@ -1,110 +0,0 @@
-.footer {
-  display: flex;
-  justify-content: center;
-}
-.img_ScwxBox {
-  display: flex !important;
-  justify-content: space-between !important;
-  padding: 5px 0 !important;
-  img {
-    width: 56px;
-    height: 56px;
-    border-radius: 3px;
-    object-fit: cover;
-  }
-  span {
-    width: 200px;
-    overflow: hidden;
-    text-overflow: ellipsis;
-    border-bottom: 1px solid #efefef;
-    -webkit-line-clamp: 2;
-    display: -webkit-box;
-    -webkit-box-orient: vertical;
-    margin-top: 10px;
-    height: 48px;
-  }
-}
-.box_card {
-  padding: 15px;
-  > div {
-    &:nth-child(2) {
-      padding: 0;
-    }
-  }
-  .img_ScwxBox:first-child {
-    flex-flow: column;
-    position: relative;
-    img {
-      width: 100%;
-      height: 131px;
-      order: 1;
-    }
-    span {
-      order: 2;
-      border: 0;
-      position: absolute;
-      left: 0;
-      bottom: 0;
-      background-image: linear-gradient(-180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
-      color: #fff;
-      width: 100%;
-      z-index: 33;
-      line-height: 24px;
-    }
-  }
-}
-
-.box {
-  display: flex;
-  flex-flow: row;
-  height: 500px;
-  overflow-y: scroll;
-  .ul {
-    width: 33%;
-    margin: 0;
-    padding: 0;
-    margin: 10px;
-    > li {
-      width: 100%;
-      margin: 0 0 15px 0;
-    }
-  }
-}
-.action {
-  position: relative;
-  // margin: 0 auto;
-  // text-align: center;
-  color: #4abe84;
-  background-color: #fff;
-  box-shadow: 0px 2px 7px 0px rgba(85, 110, 97, 0.35);
-  border-radius: 7px;
-  border: 1px solid rgba(74, 190, 132, 1);
-  overflow: hidden;
-  &::before {
-    content: '';
-    position: absolute;
-    right: 0;
-    bottom: 0;
-    border: 17px solid #4abe84;
-    border-top-color: transparent;
-    border-left-color: transparent;
-    z-index: 9;
-  }
-  &::after {
-    content: '';
-    width: 5px;
-    height: 12px;
-    position: absolute;
-    right: 6px;
-    bottom: 6px;
-    border: 2px solid #fff;
-    border-top-color: transparent;
-    border-left-color: transparent;
-    transform: rotate(45deg);
-    z-index: 9;
-  }
-}
-.btn {
-  display: flex;
-  justify-content: flex-end;
-}

+ 0 - 471
src/components/MaterialModal/msgWxGraphicListModal.tsx

@@ -1,471 +0,0 @@
-import { PlusOutlined, ExclamationCircleOutlined } from '@ant-design/icons'
-import { Button, Col, Input, InputNumber, message, Modal, Radio, Row, Space, Tag, Tooltip } from 'antd'
-import { RadioChangeEvent } from 'antd/lib/radio'
-import React, { useCallback, useEffect, useState } from 'react'
-import MsgWxLeft from './msgWxLeft'
-import style from './graphic.less'
-import { useModel } from 'umi'
-import WxMpnews from '@/components/MaterialModal/wxMpnews'
-import WxHistoryBD from '@/components/MaterialModal/wxHistorBD'
-import { isArray } from 'lodash'
-import { exportMediaByUrl1 } from '@/services/operating/material'
-import useIndexDB from '@/Hook/useIndexDB'
-import SmMaterialModal from '@/components/MaterialModal/smModalBox'
-import filePng from '../../../public/file.png'
-import WxSelect from '../WxSelect'
-/**客服,延迟,立即回复,公众号菜单使用中 */
-
-/**
- * @param isProhibitMs 是否禁止多图文按钮 默认 false 不禁用
- * @param tooltipTxt 多图文单图文按钮提示文字配置
- * @param ImportBtShow  导入按钮控制 {1: 历史图文, 2: 素材图文,3: 全部展示} 默认值 3
- * @param historyType //历史图文type  默认 0: 智能互动消息历史  1:客服消息历史
- */
-
-type Props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOK: (props: any, type?: number) => void,
-    defaultData: any,
-    msgType?: number,
-    isProhibitMs?: boolean,  // 是否禁止多图文按钮
-    tooltipTxt?: string, // 提示信息
-    ImportBtShow?: number,  // {1: 历史图文, 2: 素材图文,3: 全部展示} 默认值 3
-    historyType?: number,
-    title?: string,//弹窗标题
-    isKnews?: boolean, // 是否k图文新建
-}
-const MsgWxGraphicListModal: React.FC<Props> = (props) => {
-    const { drawerState: { dataArr, actionId, AllData }, dispatchMate } = useModel('useOperating.useMsgMaterialDrawer', model => ({ drawerState: model.state, dispatchMate: model.dispatch }))
-    const { visible, onCancel, onOK, defaultData, msgType, isProhibitMs = false, tooltipTxt = "", ImportBtShow = 3, historyType = 0, title, isKnews = false } = props
-    const [isShow, setIsShow] = useState<boolean>(false)//图片弹窗
-    const [ref, setRef] = useState<any>(null)//存放实例
-    const [range, setRange] = useState<Range>()//存放光标丢失位置
-    const { state: { actionWX, selectWx }, initSelectWx } = useModel('useOperating.useWxGroupList')
-    const [it, setIt] = useState<number>(0)//单图文多图文切换
-    const [indexId, setIndexId] = useState<number>(0)  //前面列表id
-    const [mpVisible, setMpVisible] = useState<boolean>(false)  // 素材弹窗
-    const [showNews, setShowNews] = useState<boolean>(false)//导入文章
-    const [newsUrl, setNewsUrl] = useState<string>('')//文章地址
-    const [showBD, setShowBD] = useState<boolean>(false)//BD导入弹窗
-    const [titleNum, setTitleNum] = useState<number>(0)
-    const [v, setV] = useState<number>(1)//图篇或k图文 filebox使用
-    const [sort, setSort] = useState<number>(0)
-    const [noFile, setNoFile] = useState<boolean>(false)
-
-    //DB
-    const { add } = useIndexDB()
-    //导入文章
-    const handleImportNews = useCallback(() => {
-        let str = newsUrl
-        if (str.indexOf(',') === -1) {
-            str = str.replace(/\s/ig, ',')
-        }
-        let arr = str.split(/[,,]/)
-        let newArr: string[] = []
-        arr.forEach((url: string) => {
-            url = url.replace(/\s*/g, '')
-            if (url !== "" && url) {
-                newArr.push(url)
-            }
-        })
-        let isOk = newArr.every((url: string, index: number) => {
-            if (url.search(/http[s]?:\/\/mp.weixin.qq.com/ig) === 0) {
-                return true
-            } else {
-                message.error(`第${index + 1}的地址错误,请输入正确的文章地址!`)
-                return false
-            }
-        })
-        if (newArr.length > (9 - actionId)) {
-            message.error('你输入的链接条数超过了当前剩余可新增的条数')
-            return
-        }
-        if (isOk) {
-            let promiseAll: any[] = []
-            newArr.forEach((url: string, index: number) => {
-                // promiseAll.push(exportMediaByUrl1(url).then((res) => { return res.json() }))
-                promiseAll.push(exportMediaByUrl1(encodeURIComponent(url)).then((res) => { return res.json() }))
-            })
-            Promise.all(promiseAll).then((res: any) => {
-                let arr: any[] = []
-                if (res) {
-                    res.forEach((r: { data: any, code: 200 }, index: number) => {
-                        if (r.code === 200) {
-                            let { content, contentSourceUrl, digest, thumbUrl, title, thumbMediaUrl } = r.data
-                            contentSourceUrl = contentSourceUrl.replace(/['"]*/g, '')
-                            content = content.replace('data-src', 'src').replace(/\<mpvoice[\s\S]*\<\/mpvoice\>/ig, '')
-                            arr.push({ menuId: actionId + index, content, contentSourceUrl, digest, thumbUrl: thumbUrl || thumbMediaUrl, title })
-                        }
-                    })
-                    arr = arr.sort((a: { menuId: number }, b: { menuId: number }) => { return a.menuId - b.menuId })
-                    dispatchMate({ type: 'importNews', params: { data: { dataArrs: arr, actionId } } })
-                }
-            }).catch(err => { console.log(err) })
-            setShowNews(false)
-        }
-    }, [newsUrl, actionId])
-    useEffect(() => {
-        if (it === 1) {
-            dispatchMate({ type: 'action', params: { menuId: dataArr[0].menuId } })
-        }
-    }, [it])  // 单图文默认1
-
-    useEffect(() => { // 禁止设置选中单图文链接按钮
-        if (isProhibitMs) {
-            setIt(1)
-        }
-    }, [isProhibitMs])
-
-    useEffect(() => {
-        if (msgType === 1) {
-            setIt(1)
-        }
-    }, [msgType])
-    //确定
-    const callback = useCallback((isBD?: boolean) => {
-        let oldarr: any = dataArr
-        if (it === 1) {
-            let ac = oldarr[actionId - 1]
-            oldarr = [ac]
-        }
-        let arr = oldarr.filter((item: any) => JSON.stringify(item) !== '{}')//筛除空对象|| 
-        arr = arr.filter((item: any) => {
-            return item.title
-        })
-        arr = arr.map((item: any) => {
-            console.log(item)
-            let obj = {
-                knewsThumbUrl: item.thumbUrl, // 图片
-                title: item.title.replace(/<[/]?span[^>]*>/ig, '#'), // 图文标题
-                description: item.digest, // 描述内容
-                knewsLink: item.contentSourceUrl, // 链接设置
-                knewsThumbInfo: item?.knewsThumbInfo
-            }
-            if (item?.knewsThumbId) {
-                obj['knewsThumbId'] = item?.knewsThumbId
-            }
-            return obj
-        })
-        console.log(arr)
-        let isOk: boolean = arr.length > 0 && arr.every((item: any) => (item.knewsThumbUrl || item?.knewsThumbId || item?.knewsThumbInfo) && item.description && item.knewsLink && item.title)//检测全部必填项
-        if (isBD) {
-            add({ data: arr })//保存进DB
-            return
-        }
-        if (isOk) {
-            let params: any = { newsList: arr, indexId: indexId, mpIds: selectWx }
-            if (isKnews) {
-                params.sort = sort
-            }
-            onOK(params, 5)
-            initSelectWx()
-            dispatchMate({ type: 'initData' })
-        } else {
-            message.error('请检测标题,图片,描述,链接是否填写完整!不需要的篇章请全部留空')
-        }
-
-    }, [dataArr, it, AllData, actionId, add, selectWx, sort])
-    const handelRadioIt = useCallback((e: RadioChangeEvent) => {
-        let v = e.target.value
-        setIt(v)
-    }, [])
-    //开关图片弹窗
-    const closeModal = useCallback((v?: any) => {
-        console.log(v)
-        if (v) {
-            setV(v)
-        }
-        setIsShow(!isShow)
-    }, [isShow])
-    /**选中图片,单独选择图片在传id 选择k图文直接映射*/
-    const handleOk = (data: any) => {
-        let obj: any = { menuId: actionId, thumbUrl: data.url }
-        if (data?.id && !data?.mediaId) {//存在ID不存在媒体ID证明是本地素材才添加
-            obj['knewsThumbId'] = data?.id
-        }
-        obj['knewsThumbInfo'] = {
-            folder: data?.folder,
-            title: data?.title,
-            number: data?.number
-        }
-        if (v === 6) {
-            obj['title'] = data?.title
-            obj['contentSourceUrl'] = data?.knewsLink
-            obj['digest'] = data?.description
-            obj['thumbUrl'] = data?.knewsThumbUrl
-            obj['knewsThumbId'] = data?.knewsThumbId
-            obj['knewsThumbInfo'] = { folder: data?.folder }
-        }
-        dispatchMate({ type: 'pushData', params: obj })
-        closeModal()
-    }
-    //插入粉丝昵称
-    const pushName = useCallback(() => {
-        let span = document.createElement('span')
-        span.className = style.nickName
-        span.setAttribute('contentEditable', 'false')
-        span.innerText = `粉丝昵称`
-        range?.insertNode(span)
-        dispatchMate({ type: 'pushData', params: { menuId: actionId, title: ref.innerHTML } })
-    }, [range, actionId])
-    //光标丢失记录位置
-    const onBlur = useCallback(() => {
-        let selection = window.getSelection()
-        let range = selection?.getRangeAt(0)
-        setRange(range)
-        if (ref.innerHTML) {
-            dispatchMate({ type: 'pushData', params: { menuId: actionId, title: ref.innerHTML.replace(/&quot;/ig, '"').replace(/&amp;/ig, '&').replace(/&lt;/ig, '<').replace(/&gt;/ig, '>').replace(/<\s+/g, '<') } })
-        }
-    }, [ref, actionId])
-    useEffect(() => {
-        ref?.focus()
-    }, [ref])
-    //连接输入
-    const handelLink = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        dispatchMate({ type: 'pushData', params: { menuId: actionId, contentSourceUrl: v } })
-    }, [actionId])
-    //摘要输入
-    const handelText = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        let v = e.target.value
-        dispatchMate({ type: 'pushData', params: { menuId: actionId, digest: v } })
-    }, [actionId])
-    //复制只取纯文本
-    function textPaste(event: any) {
-        event.preventDefault();
-        let text;
-        let clp = (event.originalEvent || event).clipboardData;
-        // 兼容chorme或hotfire
-        text = clp.getData('text')
-        if (text !== "") {
-            document.execCommand('insertHtml', false, text);
-        }
-    }
-    /**编辑回填 */
-    useEffect(() => {
-        if (defaultData?.newsList) {
-            let arr = defaultData?.newsList.map((item: any) => {
-                let obj = {
-                    title: item.title.replace('#粉丝昵称#', `<span class=${style.nickName} contenteditable="false">粉丝昵称</span>`),
-                    thumbUrl: item.knewsThumbUrl,
-                    contentSourceUrl: item.knewsLink,
-                    digest: item.description,
-                    knewsThumbInfo: item?.knewsThumbInfo,
-                    knewsThumbId: item?.knewsThumbId
-                }//转义
-                setSort(item?.sort || 0)
-                return obj
-            })
-            // arr = [...arr, ...Object.values(Array(8 - arr.length).fill({})).map(n => n)]  //不足8个填充
-            arr = arr.map((item: any, i: number) => {
-                return { menuId: i + 1, ...item }
-            })
-            setIndexId(defaultData?.indexId)
-            dispatchMate({ type: 'initData', params: { data: { dataArr: arr } } })
-            if (arr.length === 1) {
-                setIt(1)
-                dispatchMate({ type: 'action', params: { menuId: dataArr[0].menuId } })
-            }
-        }
-        return () => {
-            dispatchMate({ type: 'initData' })
-        }
-    }, [defaultData])
-    return <Modal
-        title={title || '编辑图文内容'}
-        width={1100}
-        visible={visible}
-        onCancel={() => {
-            onCancel()
-            dispatchMate({ type: 'initData' })
-        }}
-        footer={<div>
-            <Button onClick={() => {
-                onCancel()
-                dispatchMate({ type: 'initData' })
-            }}>取消</Button>
-            <Button onClick={() => callback()} type='primary'>确定</Button>
-            <Button onClick={() => callback(true)}>保存到浏览器本地</Button>
-        </div>}
-        destroyOnClose
-    >
-        <div>
-            <div style={{ marginBottom: '10px' }}>
-                <Space>
-                    <Radio.Group value={it} onChange={handelRadioIt}>
-                        <Radio.Button value={0} disabled={msgType === 1}>多图文链接</Radio.Button>
-                        <Radio.Button value={1}>单图文链接</Radio.Button>
-                    </Radio.Group>
-                    <Tooltip title={tooltipTxt !== "" ? tooltipTxt : "多图文链接只有立即回复(关注与扫码)可设置且只能放在第一条,延迟消息只支持单图文链接"}>
-                        <ExclamationCircleOutlined />
-                    </Tooltip>
-                </Space>
-            </div>
-            <div className={style.header}>
-                <label>导入方式:</label>
-                <Space>
-                    {
-                        ImportBtShow === 1 ?
-                            null
-                            : ImportBtShow === 2 ?
-                                <Button type="primary" size='small' onClick={() => setMpVisible(true)}>素材库导入</Button>
-                                : <Button type="primary" size='small' onClick={() => setMpVisible(true)}>素材库导入</Button>
-                    }
-                    <Button type='primary' size="small" onClick={() => setShowNews(true)}>链接导入</Button>
-                    <Button type='primary' size="small" onClick={() => setShowBD(true)}>浏览器本地导入</Button>
-                    <Button type='primary' size="small" onClick={() => closeModal(6)}>K-图文</Button>
-                </Space>
-            </div>
-            {
-                // 自定义设置
-                <div className={style.centent}>
-                    <div >
-                        <MsgWxLeft it={it} dataArr={dataArr}></MsgWxLeft>
-                    </div>
-                    <div className={style.graphic_list}>
-                        {
-                            dataArr?.map((list: any, index: number) => {
-                                return actionId === list?.menuId && <div key={index}>
-                                    <Row style={{ width: '80%' }}>
-                                        <Col span={24}>
-                                            <label >图文标题 :<Space><span>(必填)</span><span>(<span style={{ color: titleNum > 64 ? 'red' : '#000' }}>{titleNum}</span>/64)</span></Space></label>
-                                            <div
-                                                contentEditable="true"
-                                                className={style.editor}
-                                                ref={(ref) => setRef(ref)}
-                                                onBlur={onBlur}
-                                                dangerouslySetInnerHTML={{ __html: list?.title }}
-                                                onPaste={textPaste}
-                                                onKeyUp={() => {
-                                                    setTitleNum(ref?.innerHTML?.length || 0)
-                                                }}
-                                            />
-                                            {/* <label >点击插入:<Tag color='orange' onClick={pushName}>粉丝昵称</Tag></label> */}
-                                        </Col>
-                                        <Col span={24}>
-                                            <label >描述内容 :</label>
-                                            <Input.TextArea rows={5} placeholder='填写图文描述' onChange={handelText} value={list?.digest} />
-                                        </Col>
-                                        <Col span={24}>
-                                            <label >链接设置 :<span>(必填)</span></label>
-                                            <Input placeholder='请输入跳转链接,且必须以http://或https://开头' onChange={handelLink} value={list?.contentSourceUrl} />
-                                        </Col>
-                                        {isKnews && <Col span={24}>
-                                            <label >排序 :<span>(必填)</span><Tag color='warning'>数值越大越靠前</Tag></label>
-                                            <InputNumber
-                                                style={{ width: '100%' }}
-                                                value={sort}
-                                                placeholder='请输入序号, 数值越大越靠前'
-                                                onChange={(e: number) => {
-                                                    setSort(e)
-                                                }}
-                                            />
-                                        </Col>}
-                                        <WxSelect />
-                                    </Row>
-                                    <div>
-                                        <label >图文封面:</label>
-                                        <span className={list?.thumbUrl ? style.imgupload : ''} onClick={() => { closeModal(1); setNoFile(true) }}>
-                                            {
-                                                // (list?.thumbUrl || list?.knewsThumbInfo) ? <img src={list?.knewsThumbInfo?.folder ? filePng : list?.knewsThumbInfo?.id ? list?.knewsThumbInfo?.url : list?.thumbUrl} /> : <PlusOutlined style={{ fontSize: 30 }} />
-                                                (list?.thumbUrl || list?.knewsThumbId) ? <img src={list?.thumbUrl || (list.knewsThumbId ? filePng : 'https://s.weituibao.com/static/1552098829922/bigfm.png')} /> : <PlusOutlined style={{ fontSize: 30 }} />
-                                                // list?.knewsThumbInfo?.folder ? <img src={filePng} /> : (list?.thumbUrl) ? <img src={list?.thumbUrl} /> : <PlusOutlined style={{ fontSize: 30 }} />
-                                            }
-                                            <div><PlusOutlined style={{ fontSize: 30, color: '#fff' }} /> </div>
-                                        </span>
-                                        <div style={{ display: 'flex', flexFlow: 'column', width: 100 }}>
-                                            <span>名称:{list?.knewsThumbInfo?.title || '网图'} </span>
-                                            <span>编号:{list?.knewsThumbInfo?.number || '网图'}</span>
-                                        </div>
-                                    </div>
-                                </div>
-                            })
-                        }
-                    </div>
-                    {isShow && <SmMaterialModal
-                        visible={visible}
-                        onCancel={() => { closeModal(); setNoFile(false) }}
-                        title={`选择图片`}
-                        onOk={(props: any) => {
-                            handleOk(props)
-                            setNoFile(false)
-                        }}
-                        mediaType={v}
-                        isShowWx={v === 1 ? true : false}
-                        isAllData
-                        noFile={noFile}
-                    />}
-                </div>
-            }
-            {mpVisible && <WxMpnews
-                visible={mpVisible}
-                onCancel={() => setMpVisible(false)}
-                onOK={(data: any) => {
-                    if (data) {
-                        let articles: any[] = data?.news
-                        if (isArray(articles) && articles.length > 0) {
-                            dispatchMate({ type: 'initData', params: { data: { dataArr: articles.map((ar: any, index: number) => { return { menuId: index + 1, digest: ar.digest, contentSourceUrl: ar.contentSourceUrl, title: ar.title, thumbUrl: ar.thumbUrl || ar.thumbMediaUrl } }) } } })
-                            setMpVisible(false)
-                        }
-                    }
-                }}
-                defaultData=''
-                wx={actionWX}
-            />}
-            <WxHistoryBD
-                visible={showBD}
-                onCancel={() => setShowBD(false)}
-                onOK={(data: any) => {
-                    if (data) {
-                        dispatchMate({
-                            type: 'initData', params: {
-                                data: {
-                                    dataArr: data.map((arr: any, index: number) => {
-                                        return { menuId: index + 1, digest: arr.description || arr.newsDescription, contentSourceUrl: arr.knewsLink || arr.newsUrl, title: arr.title || arr.newsTitle, thumbUrl: arr.knewsThumbUrl || arr.newsPicUrl, knewsThumbInfo: arr?.knewsThumbInfo, knewsThumbId: arr?.knewsThumbId }
-                                    })
-                                }
-                            }
-                        })
-                        setShowBD(false)
-                    }
-                }}
-            />
-            {/* 链接导入弹窗 */}
-            <Modal
-                visible={showNews}
-                title='导入文章'
-                onCancel={() => { setShowNews(false) }}
-                onOk={handleImportNews}
-                destroyOnClose
-            >
-                <Input.TextArea
-                    placeholder={
-                        ` 请填写文章url地址,支持批量,批量传入需要在每个链接后面加上逗号或者换行,从你当前选中的篇数开始导入替换,一次只能导入8篇,输入的链接地址不能超过可新建的篇数,假如你从第5篇开始导入那只能导入4篇
-                        
-方式1:支持末尾加,号分割导入                     https://mp.weixin.qq.com/s/C4qcDnPwfAlf4Y2P9qeThA,https://mp.weixin.qq.com/s/tVGyg6rxR6BoppjqIbKoGg
-方式2:支持换行分割导入
-https://mp.weixin.qq.com/s/C4qcDnPwfAlf4Y2P9qeThA
-https://mp.weixin.qq.com/s/tVGyg6rxR6BoppjqIbKoGg
-`
-                    }
-                    rows={10}
-                    onChange={(e: React.ChangeEvent<HTMLTextAreaElement>) => {
-                        let url = e.target.value
-                        if (url) {
-                            setNewsUrl(url)
-                        }
-                    }}
-
-                />
-            </Modal>
-        </div>
-    </Modal>
-}
-export default React.memo(MsgWxGraphicListModal, (a, b) => {
-    if (JSON.stringify(a) === JSON.stringify(b)) {
-        return true
-    } else {
-        return false
-    }
-})

+ 0 - 102
src/components/MaterialModal/msgWxLeft.tsx

@@ -1,102 +0,0 @@
-import React from 'react'
-import style from './text.less'
-import { ArrowDownOutlined, ArrowUpOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'
-import { useModel } from 'umi'
-import filePng from '../../../public/file.png'
-import { Tooltip } from 'antd'
-const MsgWxLeft = (props: { it: number, dataArr: any[] }) => {
-    const { it } = props
-    const { drawerState, dispatch } = useModel('useOperating.useMsgMaterialDrawer', model => ({ drawerState: model.state, dispatch: model.dispatch }))
-    const { dataArr, actionId } = drawerState
-    const handleFensDisplay = (arrv: string) => {
-        return arrv ? arrv.replace(/<[/]?span[^>]*>/ig, '#').replace(new RegExp('&nbsp;', "g"), ' ') : ''
-    }
-    return <div className={style.left}>
-        {
-            it === 0 ? <div className={style.left_ul}>
-                <ul>
-                    {
-                        props.dataArr?.map((item: any, index: number) => {
-                            return index === 0
-                                ?
-                                <li
-                                    className={`${style.first} ${actionId === item.menuId && style.action}`}
-                                    key={item.menuId}
-                                    onClick={() => dispatch({ type: 'action', params: { menuId: item.menuId } })}
-                                >
-                                    <p>
-                                        {/* <img src='https://mmbiz-qpic-cn.weituibao.com/mmbiz_png/o0slOoU0qk1qibibvCYeHB7tCwW6HGia7wntuqFtE7IYfqkp8lsCegVicBdRNQTFgZdQRLctqVIebWqu5EOib5ejHMQ/0?wx_fmt=png&wxb_id=4so7eVwgLV_RCXsMR1e4Y4hgYPtVj_qfNimo_frijeI' /> */}
-                                        {/* <img src={item.thumbUrl || 'https://s.weituibao.com/static/1552098829922/bigfm.png'} alt="" /> */}
-                                        <Tooltip placement="right" title={<div style={{ display: 'flex', flexFlow: 'column' }}>
-                                            <span>名称:{item?.knewsThumbInfo?.imgTitle || '网图'}</span>
-                                            <span>编号:{item?.knewsThumbInfo?.number || '网图'}</span>
-                                        </div>}>
-                                            {/* <img src={(item?.knewsThumbInfo?.folder ? filePng : item?.knewsThumbInfo?.id ? item?.knewsThumbInfo?.url : item?.thumbUrl) || ('https://s.weituibao.com/static/1552098829922/bigfm.png')} /> */}
-                                            <img src={item?.thumbUrl || (item?.knewsThumbId ? filePng : 'https://s.weituibao.com/static/1552098829922/bigfm.png')} />
-                                        </Tooltip>
-                                    </p>
-                                    <span className={style.title}>{handleFensDisplay(item.title) || '标题'}</span>
-                                    <div>
-                                        <span>
-                                            <ArrowUpOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index, up: true } })} />
-                                            <ArrowDownOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index } })} />
-                                        </span>
-                                        <DeleteOutlined onClick={() => dispatch({ type: 'delDataArr', params: { menuId: item.menuId } })} />
-                                    </div>
-                                </li>
-                                :
-                                <li
-                                    className={`${index === dataArr.length - 1 && style.last} ${actionId === item.menuId && style.action}`}
-                                    key={item.menuId}
-                                    onClick={() => dispatch({ type: 'action', params: { menuId: item.menuId } })}
-                                >
-                                    <p>
-                                        <span className={style.title1}>{handleFensDisplay(item.title) || '标题'}</span>
-                                        <Tooltip placement="right" title={<div style={{ display: 'flex', flexFlow: 'column' }}>
-                                            <span>名称:{item?.knewsThumbInfo?.imgTitle || '网图'}</span>
-                                            <span>编号:{item?.knewsThumbInfo?.number || '网图'}</span>
-                                        </div>}>
-                                            {/* <img src={(item?.knewsThumbInfo?.folder ? filePng : item?.knewsThumbInfo?.id ? item?.knewsThumbInfo?.url : item?.thumbUrl) || ('https://s.weituibao.com/static/1552098829922/bigfm.png')} /> */}
-                                            <img src={item?.thumbUrl || (item?.knewsThumbId ? filePng : 'https://s.weituibao.com/static/1552098829922/bigfm.png')} />
-                                        </Tooltip>
-                                    </p>
-                                    <span />
-                                    <div>
-                                        <span>
-                                            <ArrowUpOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index, up: true } })} />
-                                            <ArrowDownOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index } })} />
-                                        </span>
-                                        <DeleteOutlined onClick={() => dispatch({ type: 'delDataArr', params: { menuId: item.menuId } })} />
-                                    </div>
-                                </li>
-                        })
-                    }
-                </ul>
-                {
-                    props.dataArr?.length < 8 && <span onClick={() => dispatch({ type: 'addDataArr' })} ><PlusOutlined />新建</span>
-                }
-            </div> :
-                <div className={style.msgLeftD}>
-                    {
-                        dataArr?.map((item: any, index: number) => {
-                            return <div className={`${actionId === item.menuId && style.select}`} onClick={() => dispatch({ type: 'action', params: { menuId: item.menuId } })} key={index}>
-                                <h3>{handleFensDisplay(item?.title) || '标题'}</h3>
-                                <div>
-                                    <p>{item?.digest || '描述'}</p>
-                                    <Tooltip placement="right" title={<div style={{ display: 'flex', flexFlow: 'column' }}>
-                                        <span>名称:{item?.knewsThumbInfo?.imgTitle || '网图'}</span>
-                                        <span>编号:{item?.knewsThumbInfo?.number || '网图'}</span>
-                                    </div>}>
-                                        {/* <img src={(item?.knewsThumbInfo?.folder ? filePng : item?.knewsThumbInfo?.id ? item?.knewsThumbInfo?.url : item?.thumbUrl) || ('https://s.weituibao.com/static/1552098829922/bigfm.png')} /> */}
-                                        <img src={item?.thumbUrl || (item?.knewsThumbId ? filePng : 'https://s.weituibao.com/static/1552098829922/bigfm.png')} />
-                                    </Tooltip>
-                                </div>
-                            </div>
-                        })
-                    }
-                </div>
-        }
-
-    </div>
-}
-export default MsgWxLeft

+ 0 - 97
src/components/MaterialModal/previewLocalModal.tsx

@@ -1,97 +0,0 @@
-import { message, Modal, Select, Tag } from "antd"
-import React, { useEffect, useState } from "react"
-import { useModel } from "umi"
-
-interface Props {
-    previewId: number | undefined, // 预览素材ID
-    visible?: boolean,
-    onClose?: () => void
-}
-
-/**
- * 本地素材预览
- * @returns 
- */
-const PreviewLocalModal: React.FC<Props> = (props) => {
-
-    /**==================*/
-    const { previewId, visible, onClose } = props
-    const { localPreview } = useModel('useOperating.useNews')
-    const { searchFans } = useModel('useOperating.useFans')
-    const { state: { filterWxs } } = useModel('useOperating.useWxGroupList')
-    const [fansId, setFansId] = useState<number | undefined>() // 粉丝ID
-    const [selectWx, setSelectWx] = useState<number>()
-    const [fansData, setFansData] = useState<any[]>([])
-    /**==================*/
-
-    /**存放昵称 */
-    const PreviewChange = (value: number, option: any) => {
-        setFansId(value)
-    }
-    const onSearch = (val: string) => {
-        searchFans.run({ mpId: selectWx, nickname: val })
-    }
-
-    useEffect(() => {
-        let data = searchFans.data
-        if (data?.length > 0) {
-            setFansData(data?.map((item: any) => { return { id: item?.id, nickname: item?.nickname, headimgurl: item?.headimgurl } }))
-        }
-    }, [searchFans.data])
-
-    const handleOk = () => {
-        console.log(fansId, previewId, selectWx)
-        if (!selectWx) {
-            message.error('请选择公众号')
-            return
-        }
-        if (!fansId) {
-            message.error('请选择粉丝')
-            return
-        }
-        localPreview.run({ sysMediaId: previewId, mpId: selectWx, fansId }).then(res => {
-            if (res) {
-                onClose && onClose()
-            }
-        })
-    }
-
-    return <Modal title="本地素材预览" okText='发送预览' confirmLoading={localPreview?.loading} visible={visible} onOk={handleOk} onCancel={() => onClose && onClose()}>
-        <Select
-            showSearch
-            style={{ width: '100%', marginTop: 15 }}
-            placeholder="选择公众号"
-            optionFilterProp="children"
-            onChange={(value) => { setSelectWx(value); setFansId(undefined); setFansData([]) }}
-            allowClear
-            filterOption={(input, option) =>
-                option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-            }
-            value={selectWx}
-        >
-            {filterWxs?.map((item: any) => <Select.Option value={item?.id} key={item?.id}>{item?.nickName}</Select.Option>)}
-        </Select>
-        <Select
-            showSearch
-            style={{ margin: '10px 0', width: '100%' }}
-            placeholder="请输入微信号名称自动模糊搜索匹配"
-            optionFilterProp="children"
-            onChange={PreviewChange}
-            onSearch={onSearch}
-            allowClear={true}
-            disabled={!selectWx}
-            value={fansId}
-        >
-            {
-                fansData?.map((item: { id: number, nickname: string, headimgurl: string }) => {
-                    return <Select.Option key={item.id} value={item.id}>
-                        <img src={item?.headimgurl} alt="" style={{ width: 20 }} />&nbsp;{item?.nickname}
-                    </Select.Option>
-                })
-            }
-        </Select>
-        <Tag color='warning'>预览功能仅用于公众号查看文章效果,不适用于公众传播,预览链接会在短期内失效</Tag>
-    </Modal>
-}
-
-export default React.memo(PreviewLocalModal)

+ 0 - 359
src/components/MaterialModal/previewModal.tsx

@@ -1,359 +0,0 @@
-import { EyeOutlined } from '@ant-design/icons'
-import { Button, message, Modal, Select, Space, Tag, Tooltip } from 'antd'
-import { SizeType } from 'antd/lib/config-provider/SizeContext';
-import React, { useCallback, useState } from 'react'
-import { useEffect } from 'react';
-import { useModel } from 'umi'
-const { Option } = Select;
-
-/**预览数据弹窗 */
-function PreviewModal(props: { data?: { msgType?: string, theEdit?: any, mpIds?: any[], msgContents?: any }, type?: 'text' | 'icon', isKf?: boolean, isYc?: boolean, isTem?: boolean, size?: SizeType, buttonType?: "text" | "primary" | "link" | "ghost" | "default" | "dashed" | undefined }) {
-    const { data, type = 'text', isKf = false, isYc = false, isTem = false, size="middle", buttonType="primary" } = props
-    const [ylVisible, setYlVisible] = useState<boolean>(false)//预览弹窗
-    const [value, setValue] = useState<string>('')//微信号名称
-    const { postPreview, kfPreview } = useModel('useOperating.useNews', model => ({ postPreview: model.postPreview, kfPreview: model.kfPreview }))
-    const { postReplyStrategyPreview } = useModel('useOperating.useInteract', model => ({ postReplyStrategyPreview: model.postReplyStrategyPreview }))
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const { searchFans } = useModel('useOperating.useFans', model => ({ searchFans: model.searchFans }))
-    const { temPreview } = useModel('useOperating.useAtemplate', model => ({ temPreview: model.temPreviewAjax }))
-    const [names, setNames] = useState<{ id: number, nickname: string, headimgurl: string }[]>([])
-    /**存放昵称 */
-    const PreviewChange = useCallback((value: string, option: any) => {
-        setValue(value)
-    }, [actionWX])
-    const onSearch = useCallback((val: string) => {
-        let mpId = ''
-        if (isKf) {
-            mpId = (data?.mpIds as any[])[0]?.id || '0'
-        } else {
-            mpId = actionWX?.id
-        }
-        searchFans.run({ mpId, nickname: val })
-    }, [actionWX, data?.mpIds])
-    useEffect(() => {
-        let data = searchFans.data
-        if (data?.length > 0) {
-            setNames(data?.map((item: any) => { return { id: item?.id, nickname: item?.nickname, headimgurl: item?.headimgurl } }))
-        }
-    }, [searchFans.data])
-    /**预览数据 */
-    const handlePreview = useCallback(() => {
-        if (isKf) {//客服消息预览逻辑
-            let { mpIds, msgContents } = data as { mpIds: any[], msgContents: any }
-            let newMsgContents = msgContents ? JSON.parse(JSON.stringify(msgContents)) : []
-            let params: any = {}
-            if (mpIds?.length > 0) {//mpid处理
-                params['mpIds'] = []
-                mpIds.forEach((wx: { id: number }) => {
-                    params['mpIds'].push(wx.id)
-                })
-            }
-            params['msgContents'] = newMsgContents?.map((item: { textContent: any, msgType: string, newsList: any[], platformMediaId?: any, mediaId?: any }) => {
-                if (item?.msgType === 'text' && Array.isArray(item.textContent)) {
-                    let textContent = ''
-                    item?.textContent.forEach((key: string, index: number) => {
-                        textContent += `${key.replace(/_href/ig, 'href')}${index !== item?.textContent.length - 1 ? '<br/>' : ''}`
-                    })
-                    item['textContent'] = textContent
-                } else if (item?.msgType === 'news') {
-                    let reg = new RegExp('&nbsp;', "g")
-                    let newsList = item?.newsList?.map((nl: { title: string }) => {
-                        return { ...nl, title: nl?.title.replace(reg, ' ') }
-                    })
-                    item['newsList'] = newsList
-                }
-                // platformMediaId
-                if (!item?.platformMediaId) {
-                    item['platformMediaId'] = item.mediaId
-                }
-                return item
-            })
-            names?.forEach((item: { id: number, nickname: string }) => {
-                if (value === item?.nickname + '_' + item?.id) {
-                    params['fansIds'] = item?.id
-                    localStorage.setItem('fans', JSON.stringify(item))
-                }
-            })
-            if (!params?.mpIds) {
-                message.error('请添加公众号!')
-                return
-            }
-            if (params?.msgContents?.length === 0) {
-                message.error('请添加素材!')
-                return
-            }
-            if (!params.fansIds) {
-                message.error('请输入昵称')
-                return
-            }
-            kfPreview.run(params)
-        } else if (isYc) {//延迟消息预览
-            let { mpIds, msgContents } = data as { mpIds: any[], msgContents: any }
-            let params: any = {}
-            if (mpIds?.length > 0) {//mpid处理
-                params['mpIds'] = []
-                mpIds.forEach((wx: { id: number }) => {
-                    params['mpIds'].push(wx.id)
-                })
-            }
-            let newMsgContents: any[] = []
-            msgContents.forEach((item: any) => {
-                let { webType, indexId, newsList } = item
-                switch (webType) {
-                    case 5:
-                        let reg = new RegExp('&nbsp;', "g")
-                        let data = newsList?.map((item: { title: string }) => {
-                            return { ...item, title: item?.title.replace(reg, ' ') }
-                        })
-                        newMsgContents.push({ newsList: data, type: 3, msgType: "news", webType: 5, indexId })
-                        break;
-                    case 4:
-                        let textContent: string = ''
-                        item?.textContent?.forEach((key: string, index: number) => {
-                            textContent += index !== item.textContent.length - 1 ? key.replace(/_href/ig, 'href') + `<br/>` : key.replace(/_href/ig, 'href')
-                        })
-                        newMsgContents.push({ msgType: "text", textContent, indexId, webType: 4, type: 2 })
-                        break;
-                    case 6:
-                        if (!item?.platformMediaId) {
-                            item['platformMediaId'] = item.mediaId
-                        }
-                        newMsgContents.push(item)
-                        break;
-                    default:
-                        if (!item?.platformMediaId) {
-                            item['platformMediaId'] = item.mediaId
-                        }
-                        newMsgContents.push(item)
-                        break;
-                }
-            })
-            params['msgContents'] = newMsgContents
-            names?.forEach((item: { id: number, nickname: string }) => {
-                if (value === item?.nickname + '_' + item?.id) {
-                    params['fansIds'] = item?.id
-                    localStorage.setItem('fans', JSON.stringify(item))
-                }
-            })
-            if (params?.msgContents?.length === 0) {
-                message.error('请添加素材!')
-                return
-            }
-            if (!params.fansIds) {
-                message.error('请输入昵称')
-                return
-            }
-            postReplyStrategyPreview.run(params)
-        } else if (isTem) {
-            // 模板消息预览
-            let { msgContents } = data as { msgContents: any }
-            let { fields, queryForm, tagObj } = msgContents
-            let dataQuery: any = {}
-            let { taskName, fansAll, templateId, enabled, fansFilterSex, isUrl, url, miniprogramAppid, miniprogramPagepath, triggerType, sendTime } = queryForm
-            dataQuery.mpId = actionWX?.id
-            dataQuery.taskName = taskName
-            dataQuery.fansAll = fansAll
-            dataQuery.enabled = enabled === 1 ? true : false
-            if (!fansAll) {
-                if (fansFilterSex !== 'all') {
-                    dataQuery.fansFilterSex = fansFilterSex  // 性别
-                }
-                if (tagObj.fansFilterTagids.length !== 0) {
-                    dataQuery.fansFilterTagType = tagObj.fansFilterTagType
-                    dataQuery.fansFilterTagids = tagObj.fansFilterTagids
-                }
-            }
-            if (!templateId) { message.error('请选择模板'); return }
-            // if(fields.findIndex((item: any) => item.value === '') !== -1) { message.error('模板内容空'); return }
-            dataQuery.templateId = templateId
-            dataQuery.contentFields = fields
-            if (isUrl) {
-                if (url) {
-                    dataQuery.isUrl = isUrl
-                    dataQuery.url = url
-                }
-            } else {
-                if (!miniprogramAppid || !miniprogramPagepath) {
-                } else {
-                    dataQuery.isUrl = isUrl
-                    dataQuery.miniprogramAppid = miniprogramAppid
-                    dataQuery.miniprogramPagepath = miniprogramPagepath
-                }
-            }
-            dataQuery.triggerType = triggerType
-            if (triggerType === 1) {
-                if (sendTime) {
-                    dataQuery.sendTime = sendTime
-                }
-            }
-            names?.forEach((item: { id: number, nickname: string }) => {
-                if (value === item?.nickname + '_' + item?.id) {
-                    dataQuery['fansIds'] = item?.id
-                    localStorage.setItem('fans', JSON.stringify(item))
-                }
-            })
-            temPreview.run(dataQuery)
-        } else {//高级群发预览逻辑
-            let { msgType, theEdit } = data as any
-            let textContent = ''
-            let obj: any = {}
-            theEdit?.textContent?.forEach((key: string, index: number) => {
-                textContent += `${key.replace(/_href/ig, 'href')}${index !== theEdit?.textContent.length - 1 ? '<br/>' : ''}`
-            })
-            if (theEdit?.content?.news) {//图文
-                obj = { ...obj, news: theEdit?.content?.news }
-            }
-            if (theEdit?.content?.news && theEdit?.isWx) {
-                obj = { ...obj, wxMediaId: theEdit?.mediaId }
-            }
-            if (theEdit?.fileType === 'video' || theEdit?.msgType === 'video' || theEdit?.msgType === 'mpvideo') {//视频
-                obj = {
-                    ...obj,
-                    videoDescription: theEdit?.videoDescription,//视频描述
-                    videoTitle: theEdit?.videoTitle,//视频标题
-                    url: theEdit?.url,//链接  
-                }
-            }
-            if (theEdit?.msgType === 'text' || theEdit?.fileType === 'text') {//文本
-                obj = {
-                    ...obj,
-                    textContent
-                }
-            }
-            if (theEdit?.fileType === 'image' || theEdit?.fileType === 'voice' || theEdit?.msgType === 'image' || theEdit?.msgType === 'voice') {//图片或音频
-                obj = {
-                    ...obj,
-                    title: theEdit?.title,//标题
-                    url: theEdit?.url,//链接
-                }
-            }
-            obj = {
-                ...obj,
-                mediaType: theEdit?.fileType || theEdit?.msgType,//类型
-            }
-            if (theEdit?.mediaId && theEdit?.msgType !== "mpnews") {
-                obj['wxMediaId'] = theEdit?.mediaId
-            }
-            if (!theEdit) {
-                message.error('请选择素材')
-                return
-            }
-            if (!actionWX) {
-                message.error('没有选择公众号')
-                return
-            }
-            if (!value) {
-                message.error('请输入昵称')
-                return
-            }
-            if (actionWX) {
-                // let textContent = ''
-                // theEdit?.textContent?.forEach((key: string, index: number) => {
-                //     textContent += `${key.replace(/_href/ig, 'href')}${index !== (theEdit?.textContent as string[]).length - 1 ? '<br/>' : ''}`
-                // })
-                obj = {
-                    ...obj,
-                    mpId: actionWX?.id,
-                    msgType,
-                    // mediaId: theEdit?.mediaId,
-                    // content: textContent,
-                    // wxName: value?.split('_')[0],
-                    fansId: value?.split('_')[1],
-                }
-                localStorage.setItem('fans', JSON.stringify({ nickname: value?.split('_')[0] }))
-                postPreview.run(obj)
-            }
-        }
-    }, [data, actionWX, value, postPreview, names, kfPreview])
-    /**清空昵称 */
-    useEffect(() => {
-        if (Array.isArray(data?.mpIds) && ylVisible) {
-            let fans = localStorage.getItem('fans') ? JSON.parse(localStorage.getItem('fans') as string) : ''
-            let wx = data?.mpIds[0]
-            if (fans && wx) {
-                searchFans.run({ mpId: wx?.id, nickname: fans?.nickname })
-            }
-        }
-    }, [data, ylVisible])
-    useEffect(() => {
-        if (!ylVisible) {
-            setNames([])
-            setValue('')
-            searchFans.mutate([])
-        } else {
-            if (Array.isArray(data?.mpIds)) {
-                let fans = localStorage.getItem('fans') ? JSON.parse(localStorage.getItem('fans') as string) : ''
-                let wx = data?.mpIds[0]
-                if (fans && wx) {
-                    searchFans.run({ mpId: wx?.id, nickname: fans?.nickname })
-                }
-            }
-        }
-    }, [ylVisible])
-    return <>
-        {
-            type === 'text' ?
-                <Button onClick={() => { setYlVisible(true) }} type={buttonType} size={size}>预览</Button>
-                :
-                <Tooltip placement="top" title='预览'><EyeOutlined onClick={() => { setYlVisible(true) }} /></Tooltip >
-        }
-        <Modal
-            width={500}
-            visible={ylVisible}
-            title="发送手机预览"
-            onCancel={() => setYlVisible(false)}
-            // onOk={handlePreview}
-            okText='发送预览'
-            confirmLoading={postPreview?.loading}
-            destroyOnClose
-            footer={<Space>
-                <Button onClick={() => setYlVisible(false)}>取消</Button>
-                <Button type='primary' onClick={handlePreview} loading={postReplyStrategyPreview?.loading || postPreview?.loading || kfPreview?.loading || temPreview?.loading}>发送预览</Button>
-            </Space>}
-        >
-            <div>
-                <p>默认预览选择的第一个公众号,关注公众号后,才能接收图文消息预览!</p>
-                {
-                    data?.mpIds?.map((item: { headImg: string, nickName: string }, index: number) => {
-                        if (index === 0) {
-                            return <span style={{ border: '1px dashed #d8d8d8', padding: 5, borderRadius: '3px', display: 'flex', justifyContent: 'space-between', width: 100 }} key={index}>
-                                <img src={item?.headImg || localStorage?.bookImg} alt="头像" style={{ width: 20, height: 20 }} />
-                                <span>{item?.nickName}</span>
-                            </span>
-                        }
-                        return null
-                    })
-                }
-            </div>
-            {/* <Input placeholder='请输入微信号名称' style={{ marginBottom: 10 }} onChange={PreviewChange} /> */}
-            <Select
-                showSearch
-                style={{ margin: '10px 0', width: '100%' }}
-                placeholder="请输入微信号名称自动模糊搜索匹配"
-                optionFilterProp="children"
-                onChange={PreviewChange}
-                onSearch={onSearch}
-                allowClear={true}
-            // filterOption={(input: any, option: any) =>
-            //     option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-            // }
-            >
-                {
-                    names?.map((item: { id: number, nickname: string, headimgurl: string }) => {
-                        return <Option key={item.id} value={item.nickname + '_' + item.id}>
-                            <img src={item?.headimgurl} alt="" style={{ width: 20 }} />&nbsp;{item?.nickname}
-                        </Option>
-                    })
-                }
-            </Select>
-            <Tag color='warning'>预览功能仅用于公众号查看文章效果,不适用于公众传播,预览链接会在短期内失效</Tag>
-        </Modal>
-    </>
-}
-
-export default React.memo(PreviewModal, (a, b) => {
-    if (JSON.stringify(a) === JSON.stringify(b)) {
-        return true
-    }
-    return false
-})

+ 0 - 250
src/components/MaterialModal/smModalBox.tsx

@@ -1,250 +0,0 @@
-import React, { useCallback, useEffect, useState } from "react"
-import { Card, Col, Empty, Modal, Pagination, Row, Tabs, Tag, Image, Input, message, Button, Space } from "antd"
-import { useModel } from 'umi'
-import FlieBox from '@/components/FileBox'
-const { TabPane } = Tabs
-import style from './index.less'
-type Props = {
-    mediaType: number,
-    visible: boolean,
-    onOk: (url: string, type?: number) => void,
-    onCancel: () => void,
-    title: string,
-    actionKey?: string,
-    isShowWx?: boolean,
-    isAllData?: boolean,
-    noFile?: boolean//是否禁止选择文件夹
-}
-let config2 = {
-    1: 'image',
-    2: 'voice',
-    3: 'video',
-    5: 'news',
-    6: 'knews'
-}
-const SmModalBox = (props: Props) => {
-    const { mediaType, visible, onOk, onCancel, title, actionKey, isShowWx = true, isAllData = false, noFile = false } = props
-    const { getWeData, update } = useModel('useOperating.useMaterialContent', model => ({
-        getWeData: model.getWeData,
-        update: model.update,
-    }))
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const { state, set, getList, init, typeEnum } = useModel('useOperating.useBdMediaPup')
-    const { fileType, belongUser, parentId, selectItem } = state
-    const [actionData, setActionData] = useState<any>(null)
-    const [action, setAction] = useState<string>('')
-    const [page, setPage] = useState<number>(1)//页码
-    const [qqLink, setQqLink] = useState<string>('')
-    //
-    let ok = useCallback(() => {
-        if (!actionKey) {
-            if (isAllData) {
-                if (belongUser == 0 || belongUser == 1) {
-
-                    if (selectItem && Object.keys(selectItem).length > 0) {
-                        onOk(selectItem, mediaType)
-                    } else {
-                        message.error('选择本地图片')
-                    }
-                } else if (belongUser == 3) {
-                    if (actionData) {
-                        onOk(actionData, mediaType)
-                    } else {
-                        message.error('选择微信图片')
-                    }
-                }
-            } else {
-                if (action) {
-                    onOk(action, mediaType)
-                }
-            }
-        } else if (actionKey === '1') {
-            if (qqLink) {
-                onOk(qqLink)
-            } else {
-                message.error('地址不正确')
-            }
-        }
-    }, [actionKey, actionData, selectItem, belongUser])
-    useEffect(() => {
-        if (belongUser == 0 || belongUser == 1) {
-            getList()
-        } else if (belongUser == 3) {
-            setPage(1)
-            getWeData.run({
-                mpId: actionWX?.id,
-                pageSize: 20,
-                pageNum: 1,
-                mediaType: config2[mediaType]
-            })
-        }
-    }, [fileType, belongUser, parentId, actionWX?.id])
-    useEffect(() => {
-        init({ fileType: config2[mediaType] })
-    }, [mediaType])
-    // 分页
-    let wxpageSizeChange = useCallback((page: number, pageSize?: number) => {
-        setPage(page)
-        if (actionWX?.id) {
-            getWeData.run({
-                mpId: actionWX?.id,
-                pageSize: pageSize,
-                pageNum: page,
-                mediaType: config2[mediaType]
-            })
-        }
-    }, [mediaType, actionWX])
-    //选中图片
-    let handleClick = useCallback((url, data?: any) => {
-        setAction(url)
-        setActionData(data)
-    }, [])
-    //qq视频
-    const qqLinkChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        let arr = v.split('/')
-        let vid = arr[arr.length - 1].replace('.html', '')
-        if (v.search(/http[s]?:\/\/v.qq.com[\S]*.html/ig) !== -1) {
-            setQqLink(`https://v.qq.com/iframe/player.html?vid=${vid}&auto=0`)
-        }
-    }, [])
-    // 更新公众号下素材
-    let sync = useCallback(() => {
-        update.run({ mpId: actionWX?.id, mediaType: config2[mediaType] }).then((res) => {
-            if (res) {
-                setPage(0)
-                if (actionWX?.id) {
-                    getWeData.run({
-                        mpId: actionWX?.id,
-                        pageSize: 20,
-                        pageNum: 1,
-                        mediaType: config2[mediaType]
-                    })
-                }
-            }
-        })
-    }, [update, actionWX?.id, mediaType])
-
-    let Tags = (props: { url: string, data?: { title?: string, name?: string } }) => {
-        switch (mediaType) {
-            case 1:
-                return <Card bodyStyle={{ padding: 0, height: 150, display: 'flex', flexFlow: 'column' }} bordered={false} hoverable>
-                    <Image src={props.url} width={150} height={150} placeholder preview={false} onClick={() => handleClick(props.url, props?.data)} />
-                </Card >
-            case 3:
-                return <div>
-                    <Card bodyStyle={{ padding: 10, height: 165, display: 'flex', flexFlow: 'column', border: '1px solid #efefef' }} bordered={false} hoverable onClick={() => handleClick(props.url, props?.data)}>
-                        <video src={props.url} height='130px' controls />
-                        <span>名称: {props?.data?.title || props?.data?.name}</span>
-                    </Card>
-                </div>
-            default:
-                return <div>
-                    <Card bodyStyle={{ padding: 10, height: 80, display: 'flex', flexFlow: 'column', border: '1px solid #efefef' }} bordered={false} hoverable onClick={() => handleClick(props.url, props?.data)}>
-                        <audio src={props.url} controls />
-                        <span>名称: {props?.data?.title || props?.data?.name}</span>
-                    </Card>
-                </div>
-        }
-    }
-
-    return <Modal
-        title={title}
-        width={1200}
-        visible={visible}
-        onOk={ok}
-        onCancel={onCancel}
-        maskClosable={false}
-    >
-        {
-            !actionKey && <>
-                <Tabs
-                    type="card"
-                    onChange={(activeKey: any) => { set({ belongUser: activeKey }) }}
-                    activeKey={belongUser}
-                    tabBarExtraContent={
-                        <Space>
-                            {
-                                belongUser === '3' ? <Button type='primary' onClick={sync} loading={update?.loading}>更新公众号下素材</Button> : ''
-                            }
-                        </Space>
-                    }
-                >
-                    <TabPane tab={'个人本地'} key={1} />
-                    <TabPane tab={'公共本地'} key={0} />
-                    {
-                        isShowWx && <TabPane tab={"微信素材"} key={3}>
-                            {
-                                getWeData?.data?.records?.length > 0 ? <Row justify='start' gutter={[15, 15]}>
-                                    {
-                                        getWeData?.data?.records?.map((item: any) => {
-                                            return <Col key={item?.mediaId} className={`${style.img} ${actionData?.id === item?.id ? style.action : undefined}`}>
-                                                <Tags url={item?.url} data={item} />
-                                            </Col>
-                                        })
-                                    }
-                                </Row> : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                            }
-
-                            <Pagination onChange={wxpageSizeChange} size={'small'} defaultPageSize={20} current={page} total={getWeData?.data?.total} style={{ float: 'right' }} showTotal={(total) => <Tag color="cyan">总共{total}数据</Tag>} />
-                        </TabPane>
-                    }
-                </Tabs>
-            </>
-        }
-
-        {
-            (belongUser == 1 || belongUser == 0) && !actionKey && <FlieBox isAll={false}  noFile={noFile} />
-        }
-
-        {
-            actionKey === '1' &&
-            <Tabs type="card">
-                <TabPane tab="腾讯视频" key="2" style={{ padding: 10 }}>
-                    <Row>
-                        <Col className={style.qq_link}>
-                            <label>视频地址:</label>
-                            <Input placeholder='请输入腾讯视频地址' onChange={qqLinkChange} allowClear />
-                        </Col>
-                        <Col className={style.qq_iframe}>
-                            <label>预览:</label>
-                            <iframe
-                                data-vidtype="2"
-                                height="310"
-                                width="1000"
-                                data-ratio="1.7666666666666666"
-                                data-w="848"
-                                src={qqLink}
-                            />
-                        </Col>
-                    </Row>
-                </TabPane>
-            </Tabs>
-
-        }
-        {
-            actionKey === '2' && <Tabs type="card">
-                <TabPane tab="音频" key="2" style={{ padding: 10 }}>
-                    <Row>
-                        <Col className={style.qq_link}>
-                            <label>视频地址:</label>
-                            <Input placeholder='请输入腾讯视频地址' />
-                        </Col>
-                        <Col className={style.qq_iframe}>
-                            <label>预览:</label>
-                            <iframe
-                                data-vidtype="2"
-                                height="310"
-                                width="1000"
-                                data-ratio="1.7666666666666666"
-                                data-w="848"
-                                src="https://v.qq.com/iframe/player.html?vid=e3161ny316e&auto=0"
-                            />
-                        </Col>
-                    </Row>
-                </TabPane>
-            </Tabs>
-        }
-    </Modal>
-}
-export default React.memo(SmModalBox)

+ 0 - 136
src/components/MaterialModal/synthetic.less

@@ -1,136 +0,0 @@
-.synthetic_body {
-  position: fixed;
-  z-index: 100;
-  right: 10px;
-  top: 50px;
-  .synthetic_body_hot {
-    width: 50px;
-    display: flex;
-    height: 50px;
-    border-radius: 50%;
-    align-items: center;
-    justify-content: center;
-    color: #fff;
-    background-color: #00bcd4;
-    cursor: pointer;
-  }
-}
-.synthetic_body .hover {
-  transition: all 1s;
-}
-ul.synthetic_body_ul {
-  display: flex;
-  flex-flow: column;
-  padding: 10px;
-  overflow-y: auto;
-  width: 280px;
-  max-height: 450px;
-  overflow-y: scroll;
-  li {
-    position: relative;
-    border: 1px solid #efefef;
-    border-bottom: 0;
-    > p {
-      display: flex;
-      padding: 15px;
-      flex-flow: row;
-      justify-content: space-between;
-      margin-bottom: 0;
-      img {
-        width: 60px;
-        height: 60px;
-        border-radius: 3px;
-        object-fit: cover;
-      }
-      > span {
-        overflow: hidden;
-        text-overflow: ellipsis;
-        -webkit-line-clamp: 2;
-        display: -webkit-box;
-        -webkit-box-orient: vertical;
-        margin-top: 10px;
-        height: 48px;
-      }
-    }
-    > div {
-      opacity: 0;
-      display: flex;
-      justify-content: space-between;
-      padding: 0 10px;
-      align-items: center;
-      color: #fff;
-      position: absolute;
-      bottom: 0;
-      left: 0;
-      width: 100%;
-      z-index: 99;
-      height: 30px;
-      background: rgba(0, 0, 0, 0.6);
-      > span {
-        cursor: pointer;
-        > span {
-          margin-right: 10px;
-        }
-      }
-    }
-  }
-  li.last {
-    border-bottom: 1px solid #efefef;
-    > div {
-      > span {
-        > span {
-          &:nth-child(2) {
-            display: none;
-          }
-        }
-      }
-    }
-  }
-  li.first {
-    border: 0;
-    > span {
-      position: absolute;
-      bottom: 0;
-      left: 0;
-      right: 0;
-      height: 30px;
-      background: rgba(0, 0, 0, 0.6);
-      color: #fff;
-      line-height: 30px;
-      padding-left: 10px;
-    }
-    > div {
-      > span {
-        > span {
-          &:nth-child(1) {
-            display: none;
-          }
-        }
-      }
-    }
-    > p {
-      position: relative;
-      width: 100%;
-      height: 0px;
-      padding-top: 40%;
-      border-radius: 2px;
-      margin-bottom: 0;
-      img {
-        position: absolute;
-        left: 0px;
-        top: 0px;
-        width: 100%;
-        height: 100%;
-        object-fit: cover;
-      }
-    }
-  }
-  li:hover {
-    > div {
-      opacity: 1;
-    }
-  }
-  li.action {
-    border: 1px solid rgb(59, 116, 255);
-  }
-}

+ 0 - 148
src/components/MaterialModal/synthetic.tsx

@@ -1,148 +0,0 @@
-import { ArrowDownOutlined, ArrowUpOutlined, DeleteOutlined } from '@ant-design/icons'
-import { Badge, Empty, message, Popconfirm } from 'antd'
-import React, { useCallback, useRef } from 'react'
-import { useModel } from 'umi'
-import style from './synthetic.less'
-
-/**合成器 */
-let offset = { topRight: [-42, 50], topLeft: [-8, 50], bottomRight: [-42, 0], bottomLeft: [-8, 0] }
-function Synthetic(props: { show: any }) {
-    const divRef: { current: HTMLDivElement | null } = useRef(null)
-    const { dispatchDrawer } = useModel('useOperating.useMaterialDrawer', model => ({ dispatchDrawer: model.dispatch }))
-    const { state, dispatch } = useModel('useOperating.useSynthetic')
-    const { isHover, fx, dataArr, actionId } = state
-    /**合成事件 */
-    let handleOk = useCallback(() => {
-        if (dataArr.length > 0) {
-            props.show()
-            // dispatchDrawer({ type: 'initData', params: { data: { dataArr, actionId: 1 } } })
-            dispatchDrawer({ type: 'actionData', params: { data: { dataArr: dataArr, actionId: 1} } })//设置编辑器的内容
-        } else {
-            message.error('请添加素材');
-        }
-    }, [dataArr, props.show])
-    /**按下移动事件 */
-    let handleMouseDown = useCallback((event: React.MouseEvent<HTMLDivElement, MouseEvent>) => {
-        event.preventDefault()
-        event.persist();
-        if (event.button === 0) {
-            let div = divRef.current
-            if (div) {
-                let disX = event.pageX - parseInt(div.offsetLeft + '');
-                let disY = event.pageY - parseInt(div.offsetTop + '');
-                document.onmousemove = function (e) {
-                    if (div) {
-                        let documentW = document.body.clientWidth
-                        let documentH = document.body.clientHeight
-                        let letf = e.pageX - disX
-                        let top = e.pageY - disY
-                        if (letf > documentW / 2 && top < documentH / 2 && fx !== 'topRight') {
-                            dispatch({ type: 'fx', params: { fx: 'topRight' } })
-                        }
-                        if (letf > documentW / 2 && top > documentH / 2 && fx !== 'bottomRight') {
-                            dispatch({ type: 'fx', params: { fx: 'bottomRight' } })
-                        }
-                        if (letf < documentW / 2 && top < documentH / 2 && fx !== 'topLeft') {
-                            dispatch({ type: 'fx', params: { fx: 'topLeft' } })
-                        }
-                        if (letf < documentW / 2 && top > documentH / 2 && fx !== 'bottomLeft') {
-                            dispatch({ type: 'fx', params: { fx: 'bottomLeft' } })
-                        }
-                        if (letf < 0) {
-                            div.style.left = "0px";
-                            return
-                        }
-                        if (letf > documentW - 25) {
-                            div.style.left = documentW - 50 + "px";
-                            return
-                        }
-                        if (top < 0) {
-                            div.style.top = "0px";
-                            return
-                        }
-                        if (top > documentH - 50) {
-                            div.style.top = documentH - 50 + "px";
-                            return
-                        }
-                        div.style.left = letf + "px";
-                        div.style.top = top + "px";
-                    }
-                };
-                document.onmouseup = function () {
-                    document.onmousemove = null;
-                }
-            }
-        }
-    }, [divRef, fx])
-    return <div
-        className={`${style.synthetic_body} ${isHover ? style.hover : ''} `}
-        onClick={() => { }}
-        onMouseDown={handleMouseDown}
-        ref={divRef}
-    >
-        <Popconfirm
-            placement={fx === 'topRight' ? 'bottomRight' : fx === 'topLeft' ? 'bottomLeft' : fx === 'bottomRight' ? 'topRight' : 'topLeft'}
-            title={
-                <ul className={style.synthetic_body_ul}>
-                    {
-                        dataArr.length > 0 ? dataArr?.map((item: any, index: number) => {
-                            return index === 0
-                                ?
-                                <li
-                                    className={`${style.first} ${actionId === item.menuId && style.action}`}
-                                    key={item.menuId}
-                                    onClick={() => dispatch({ type: 'action', params: { menuId: item.menuId } })}
-                                >
-                                    <p>
-                                        {/* <img src='https://mmbiz-qpic-cn.weituibao.com/mmbiz_png/o0slOoU0qk1qibibvCYeHB7tCwW6HGia7wntuqFtE7IYfqkp8lsCegVicBdRNQTFgZdQRLctqVIebWqu5EOib5ejHMQ/0?wx_fmt=png&wxb_id=4so7eVwgLV_RCXsMR1e4Y4hgYPtVj_qfNimo_frijeI' /> */}
-                                        <img src={item?.thumbUrl || item?.thumbMediaUrl || 'https://s.weituibao.com/static/1552098829922/bigfm.png'} alt="" />
-                                    </p>
-                                    <span className={style.title}>{item.title || '标题'}</span>
-                                    <div>
-                                        <span>
-                                            <ArrowUpOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index, up: true } })} />
-                                            <ArrowDownOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index } })} />
-                                        </span>
-                                        <DeleteOutlined onClick={() => dispatch({ type: 'delDataArr', params: { menuId: item.menuId } })} />
-                                    </div>
-                                </li>
-                                :
-                                <li
-                                    className={`${index === dataArr.length - 1 && style.last} ${actionId === item.menuId && style.action}`}
-                                    key={item.menuId}
-                                    onClick={() => dispatch({ type: 'action', params: { menuId: item.menuId } })}
-                                >
-                                    <p>
-                                        <span className={style.title1}>{item.title || '标题'}</span> <img src={item?.thumbUrl || item?.thumbMediaUrl || 'https://s.weituibao.com/static/1552098829922/bigfm.png'} alt="" />
-                                    </p>
-                                    <span />
-                                    <div>
-                                        <span>
-                                            <ArrowUpOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index, up: true } })} />
-                                            <ArrowDownOutlined onClick={() => dispatch({ type: 'mobile', params: { eq: index } })} />
-                                        </span>
-                                        <DeleteOutlined onClick={() => dispatch({ type: 'delDataArr', params: { menuId: item.menuId } })} />
-                                    </div>
-                                </li>
-                        }) : <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
-                    }
-                </ul>
-            }
-            onConfirm={handleOk}
-            onCancel={() => { dispatch({ type: 'init' }) }}
-            okText="合成"
-            cancelText="清空"
-            icon={null}
-        >
-            <Badge count={state.dataArr.length} offset={offset[fx]} size='small'>
-                <span
-                    className={style.synthetic_body_hot}
-                >
-                    合成器
-            </span>
-            </Badge>
-        </Popconfirm>
-    </div>
-}
-
-export default Synthetic

+ 0 - 334
src/components/MaterialModal/text.less

@@ -1,334 +0,0 @@
-.header {
-  padding: 10px;
-  background-color: #f8f8f8;
-  border-bottom: 1px solid #eee;
-}
-.box {
-  border: 1px solid #eee;
-}
-.editor {
-  height: 150px;
-  overflow-y: scroll;
-  padding: 10px;
-  div {
-    height: 20px;
-  }
-}
-.nickName {
-  color: #f50;
-  border: 1px solid #f50;
-  border-radius: 2px;
-  margin-right: 3px;
-  padding: 1px 5px;
-  font-size: 12px;
-  display: inline-block;
-}
-.popover {
-  width: 500px;
-  > div {
-    display: flex;
-    align-items: center;
-    margin-bottom: 15px;
-    > label {
-      width: 70px;
-      flex-shrink: 0;
-    }
-    .group {
-      margin-bottom: 5px;
-    }
-    input {
-      margin-bottom: 5px;
-    }
-  }
-}
-[contenteditable]:focus {
-  outline: none;
-}
-i {
-  font-style: normal;
-}
-
-.left {
-  width: 100%;
-  box-sizing: border-box;
-  > p {
-    display: flex;
-    justify-content: left;
-    align-items: center;
-    padding: 10px;
-    border-bottom: 1px solid #efefef;
-    font-weight: 500;
-  }
-  .left_ul {
-    // height: calc(100vh - 150px);
-    height: 100%;
-    overflow-y: hidden;
-    > ul {
-      display: flex;
-      flex-flow: column;
-      padding: 10px;
-      overflow-y: hidden;
-      li {
-        position: relative;
-        border: 1px solid #efefef;
-        border-bottom: 0;
-        > p {
-          display: flex;
-          padding: 15px;
-          flex-flow: row;
-          justify-content: space-between;
-          margin-bottom: 0;
-          img {
-            width: 60px;
-            height: 60px;
-            border-radius: 3px;
-            object-fit: cover;
-          }
-        }
-        > div {
-          opacity: 0;
-          display: flex;
-          justify-content: space-between;
-          padding: 0 10px;
-          align-items: center;
-          color: #fff;
-          position: absolute;
-          bottom: 0;
-          left: 0;
-          width: 100%;
-          z-index: 99;
-          height: 30px;
-          background: rgba(0, 0, 0, 0.6);
-          > span {
-            cursor: pointer;
-            > span {
-              margin-right: 10px;
-            }
-          }
-        }
-      }
-      li.last {
-        border-bottom: 1px solid #efefef;
-        > div {
-          > span {
-            > span {
-              &:nth-child(2) {
-                display: none;
-              }
-            }
-          }
-        }
-      }
-      li.first {
-        border: 0;
-        > span {
-          position: absolute;
-          bottom: 0;
-          left: 0;
-          right: 0;
-          height: 30px;
-          background: rgba(0, 0, 0, 0.6);
-          color: #fff;
-          line-height: 30px;
-          padding-left: 10px;
-        }
-        > div {
-          > span {
-            > span {
-              &:nth-child(1) {
-                display: none;
-              }
-            }
-          }
-        }
-        > p {
-          position: relative;
-          width: 100%;
-          height: 0px;
-          padding-top: 40%;
-          border-radius: 2px;
-          margin-bottom: 0;
-          img {
-            position: absolute;
-            left: 0px;
-            top: 0px;
-            width: 100%;
-            height: 100%;
-            object-fit: cover;
-          }
-        }
-      }
-      li:hover {
-        > div {
-          opacity: 1;
-        }
-      }
-      li.action {
-        border: 1px solid rgb(59, 116, 255);
-      }
-    }
-    > span {
-      height: 50px;
-      border: 1px dashed #bbbbbb;
-      display: flex;
-      justify-content: center;
-      align-items: center;
-      margin: 0 10px;
-    }
-    > span:hover {
-      border-color: rgb(59, 116, 255);
-      color: rgb(59, 116, 255);
-    }
-  }
-  .msgLeftD {
-    padding: 0 5px;
-    margin-top: 5px;
-    box-sizing: border-box;
-    > div {
-      border: 1px solid #d3d3d3;
-      padding: 5px;
-      box-sizing: border-box;
-      margin-bottom: 8px;
-      > h3 {
-        line-height: 1.5;
-        font-size: 16px;
-        padding: 0 6px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        display: -webkit-box;
-        -webkit-line-clamp: 1;
-        -webkit-box-orient: vertical;
-        box-sizing: border-box;
-      }
-      > div {
-        display: flex;
-        justify-content: start;
-        > p {
-          flex: 1;
-          font-size: 12px;
-          color: #999;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          display: -webkit-box;
-          -webkit-line-clamp: 3;
-          -webkit-box-orient: vertical;
-          padding-right: 5px;
-        }
-        > img {
-          width: 50px;
-          height: 50px;
-          object-fit: cover;
-        }
-      }
-    }
-    > .select {
-      position: relative;
-      border: 1px solid #4abe84;
-      border-radius: 5px;
-      &::after {
-        content: '';
-        width: 5px;
-        height: 12px;
-        position: absolute;
-        right: 6px;
-        bottom: 6px;
-        border: 2px solid #fff;
-        border-top-color: transparent;
-        border-left-color: transparent;
-        transform: rotate(45deg);
-        z-index: 9;
-      }
-      &::before {
-        content: '';
-        position: absolute;
-        right: 0;
-        bottom: 0;
-        border: 17px solid #4abe84;
-        border-top-color: transparent;
-        border-left-color: transparent;
-        z-index: 9;
-      }
-    }
-  }
-}
-.fixed_pop {
-  position: fixed;
-  display: none;
-  min-width: 250px;
-  min-height: 50px;
-  background-color: rgba(0, 0, 0, 0.9);
-  color: #fff;
-  border-radius: 5px;
-  justify-content: space-evenly;
-  align-items: center;
-  transform: translateX(-50%);
-  .fixed_pop_link {
-    display: flex;
-    justify-content: space-between;
-    width: 400px;
-  }
-  .fixed_pop_wx {
-    display: flex;
-    justify-content: space-between;
-    width: 500px;
-    > span {
-      &:first-child {
-        margin: 10px 0;
-      }
-      &:last-child {
-        display: flex;
-        justify-content: space-between;
-      }
-    }
-  }
-  input {
-    background-color: transparent;
-    outline: none !important;
-    border: none !important;
-    caret-color: #fff;
-    color: #fff;
-  }
-  a {
-    display: inline-block;
-    font-size: 24px;
-    font-weight: bolder;
-    margin: 0 10px;
-    text-decoration: none;
-    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
-  }
-  input:focus {
-    border: none !important;
-    box-shadow: none;
-  }
-  > span {
-    cursor: pointer;
-  }
-  &::after {
-    content: '';
-    width: 10px;
-    height: 10px;
-    background-color: rgba(0, 0, 0, 0.9);
-    position: absolute;
-    left: 50%;
-    transform: translateX(-50%);
-    top: -5px;
-    transform: rotate(45deg);
-  }
-}
-.editable {
-  font-family: sans-serif;
-  width: 100%;
-  min-height: 100px;
-  padding: 5px;
-  resize: none;
-}
-
-textarea.editable {
-  font-family: monospace, monospace;
-}
-.fixed_pop_wx_radio {
-  padding-left: 10px;
-  span {
-    color: #fff;
-  }
-}

+ 0 - 443
src/components/MaterialModal/textModal.tsx

@@ -1,443 +0,0 @@
-import { Button, Input, message, Modal, Popover, Radio, Space, Tooltip } from 'antd'
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import Expression from '@/components/Expression'
-import style from './text.less'
-import sanitizeHtml from 'sanitize-html';
-import { RadioChangeEvent } from 'antd/lib/radio';
-type Props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOK: (props: any, type?: number) => void
-    defaultData?: any,
-    hdLink?: boolean,
-    fansName?: boolean
-}
-const sanitizeConf: sanitizeHtml.IOptions = {
-    allowedTags: ['br', 'a'],
-    allowedAttributes: { a: ["href", "_href", "data-miniprogram-appid", "data-miniprogram-path"] },
-    allowedSchemes: ['http', 'https', 'weixin']
-};
-/**文本弹窗 */
-const WxTextModal = React.memo((props: Props) => {
-    const { visible, onCancel, onOK, fansName = true, hdLink = true } = props
-    const [value, setValue] = useState<string>('')//存放连接文字
-    const [content, setContent] = useState<string>('')//存放发送文字
-    const [isShow, setIsShow] = useState<boolean>(false)//互动弹窗
-    const [range, setRange] = useState<Range>()//丢失焦点存放焦点位置
-    const [ref, setRef] = useState<any>(null)//存放编辑框的实例
-    const [aLink, setAlink] = useState<string>('')//存放页面链接
-    const [appID, setAppID] = useState<string>('')//存放小程序APPID
-    const [path, setPath] = useState<string>('')//存放小程序路径
-    const [userId, setUserId] = useState<any>(2)//小程序路径插入userID
-    const [textData, setTextData] = useState<any>({ range: null, left: -100, top: -100, text: '' })
-    const [isLink, setIsLink] = useState<boolean>(false)
-    const [isWxLink, setIsWxLink] = useState<boolean>(false)
-    const [isHtml, setIsHtml] = useState<boolean>(false)
-    const text = useRef('');
-    const [phoneType, setPhoneType] = useState<1 | 2 | 3|4>(3)
-    /**
-     * 发送处理
-     */
-    const callback = useCallback(() => {
-        if (ref.innerHTML) {
-            console.log(ref.innerHTML)
-            let textContent: any = sanitizeHtml(ref.innerHTML, sanitizeConf);
-            console.log(textContent)
-            textContent = textContent.replace(/&quot;/ig, '"')
-                .replace(/&amp;/ig, '&')
-                .replace(/&lt;/ig, '<')
-                .replace(/&gt;/ig, '>')
-                .replace(/<\s+/g, '<')
-                .replace(/[\f\n\r\t\v]/g, '<br/>')//将回车变成br
-                .replace(/\&nbsp;(<br>)?/g, '')
-                .replace(/<[/]?myspan[^>]*>/ig, '#')
-                .replace(/#<br>/g, '#')
-                .replace(/<([a-z]+?)(?:\s+?[^>]*?)?>[\s(<br>)]*?<\/\1>/ig, '<br/>')//替换所有空标签或空标签带<br>的标签为<br>
-                .replace(/(\b<div>(<br>)?)|((<br>)?<div>)/ig, '<br/>')//<div>or<br><div>or<div><br>转br
-                .replace(/<\/div>/ig, '')//</div>转‘’
-                .replace(/_href="\s+/ig, '_href="')//清除href头部空格
-                .replace(/href=weixin/ig,'href="weixin')
-                .replace(/msgmenuid="/ig,'msgmenuid= "')
-                .replace(/"=""/ig,'')
-                // .replace(/\s+"/ig, '"')//清除href尾部空格
-                .split('<br/>')
-            onOK({
-                textContent: textContent, indexId: props.defaultData?.indexId //textContent.filter((str)=> str!=='') 注释保留空格和换行
-            }, 4)
-        } else {
-            alert('元素获取失败请复制内容刷新页面')
-            message.error('请输入文字')
-        }
-        handleClose()
-    }, [ref])
-    /**
-     * 互动连接文字
-     */
-    const textChange = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        let v = e.target.value
-        setValue(v)
-    }, [])
-    /**
-     * 互动发送文本
-     */
-    const contentChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        setContent(v)
-    }, [])
-    /**
-    * 网页小程序连接地址
-    */
-    const aLinkChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        setAlink(v)
-    }, [])
-    /**
-    * 小程序路径
-    */
-    const pathChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        setPath(v)
-    }, [])
-    /**
-    * 小程序ID
-    */
-    const appIDChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        setAppID(v)
-    }, [])
-    /**
-     * 插入表情
-     */
-    const getStr = useCallback((str: string, range: Range) => {
-        if (range) {
-            let selection = window.getSelection()
-            selection?.empty()//清空选择range
-            selection?.addRange(range)//插入新的range
-            document.execCommand('insertHtml', false, str + '&nbsp;');
-        }
-    }, [])
-    /**
-     * 光标丢失记录位置
-     */
-    const onBlur = useCallback(() => {
-        try {
-            let selection = window.getSelection()
-            let range = selection?.getRangeAt(0)
-            setRange(range)
-        } catch (err) {
-        }
-    }, [text])
-    /**
-     * 插入粉丝昵称
-     */
-    const pushName = useCallback(() => {
-        let selection = window.getSelection()
-        selection?.empty()//清空选择range
-        selection?.addRange(range as Range)//插入新的range
-        document.execCommand('insertHtml', false, `#粉丝昵称#`);
-        selection?.collapseToEnd()//光标插入到末尾
-    }, [range])
-    /**
-     * 插入互动链
-     */
-    const pushLink = useCallback(() => {
-        if (!value || !content) {
-            setIsShow(false)
-            return
-        }
-        let selection = window.getSelection()
-        selection?.empty()//清空选择range
-        selection?.addRange(range as Range)//插入新的range
-        if(phoneType === 4){
-            document.execCommand('insertHtml', false, `<a href="a href=weixin://bizmsgmenu?msgmenucontent=${content}&msgmenuid=+++">${value}</a>`);
-        }else{
-            document.execCommand('insertHtml', false, `<a href='weixin://${phoneType === 1 ? 'kefumenu' : 'bizmsgmenu'}?${phoneType === 1 ? `kefumenucontent=${content}` : `msgmenucontent=${content}`}&${phoneType === 1 ? 'kefumenuid=0' : phoneType === 2 ? `msgmenuid= ` : 'msgmenuid=0'}' >${value}</a>`);
-        }
-        selection?.collapseToEnd()//光标插入到末尾
-        setValue('')
-        setContent('')
-        setIsShow(false)
-    }, [range, value, content, phoneType])
-    /**
-     * 初始光标选中
-     */
-    useEffect(() => {
-        console.log('ref')
-        if (ref) {
-            ref?.focus()
-        }
-    }, [ref])
-    //复制只取纯文本
-    function textPaste(event: any) {
-        event.preventDefault();
-        let text;
-        let clp = (event.originalEvent || event).clipboardData;
-        // 兼容chorme或hotfire
-        text = (clp.getData('text/plain') || clp.getData('text'))
-            .replace(/&quot;/ig, '"')
-            .replace(/&amp;/ig, '&')
-            .replace(/&lt;/ig, '<')
-            .replace(/&gt;/ig, '>')
-            .replace(/<\s+/g, '<')
-            .replace(/href="weixin/ig,'href=weixin')
-        text = sanitizeHtml(text, sanitizeConf) || "";
-        if (text !== "") {
-            document.execCommand('insertHtml', false, text);
-        }
-    }
-    /**
-     * 编辑默认内容写入
-     */
-    useEffect(() => {
-        console.log('编辑默认内容写入', props?.defaultData?.textContent)
-        if (props?.defaultData?.textContent && ref) {
-            let text = '';
-            if (Array.isArray(props?.defaultData?.textContent)) {
-                props?.defaultData?.textContent?.map((key: any, index: number) => {
-                    key = key.replace(/href="weixin/ig,'href=weixin')
-                    if (key.indexOf('&lt;') !== -1) {//假如存在就是原文
-                        setIsHtml(true)
-                    }
-                    text += index !== props?.defaultData?.textContent?.length - 1 ? `${key}<br/>` : key
-                })
-            } else {
-                text = `${props?.defaultData?.textContent}`
-            }
-            document.execCommand('insertHtml', true, text);
-        }
-    }, [ref])
-    /**切换文本原文 */
-    const onHtml = useCallback(() => {
-        let str: string = ref.innerHTML
-        str = str.replace(/&quot;/ig, '"').replace(/&amp;/ig, '&').replace(/&lt;/ig, '<').replace(/&gt;/ig, '>').replace(/<\s+/g, '<').replace(/""/ig,'"').replace(/"="/ig,'')
-        if (isHtml) {
-            console.log('str1',str)
-            setIsHtml(false)
-            ref.innerHTML = ''
-            ref.innerHTML = str
-
-        } else {
-            console.log('str2',str)
-            setIsHtml(true)
-            ref.innerHTML = ''
-            ref.innerText = str.replace(/<br[\/]?>/ig, '\n').replace(/&nbsp;/ig, ' ')
-        }
-    }, [ref, text, isHtml])
-    //文本选中
-    let handleSelectText = useCallback((event: React.SyntheticEvent<HTMLPreElement, Event>) => {
-        let selection = window.getSelection ? window.getSelection() : (document.getSelection ? document.getSelection() : (document?.selection ? document?.selection.createRange().text : ""))
-        let text = selection.toString() || selection.text
-        if (text) {//存在文本弹窗
-            let range = selection?.getRangeAt(0)
-            let { top, left } = range?.getBoundingClientRect()
-            setTextData({ range, top, left, text })
-        } else {
-            handleClose()//关闭弹窗
-        }
-    }, [])
-    //点击设置连接转换输入,清空连接处理
-    let handleLink = useCallback((type: number) => {
-        console.log('点击设置连接转换输入,清空连接处理')
-        switch (type) {
-            case 1:
-                setIsLink(true)
-                break;
-            case 2:
-                setIsWxLink(true)
-                break;
-            default:
-                let selection = window.getSelection()
-                selection?.empty()//清空选择range
-                selection?.addRange(textData?.range)//插入新的range
-                document.execCommand('unlink')//清除连接
-                selection?.collapseToEnd()//光标插入到末尾
-                handleClose()//关闭弹窗
-                break
-        }
-    }, [textData])
-    //清空数据并关闭弹窗
-    let handleClose = useCallback(() => {
-        console.log('清空数据并关闭弹窗')
-        setTextData({ range: null, left: -100, top: -100, text: '' })
-        setIsWxLink(false)
-        setIsLink(false)
-        setAppID('')
-        setAlink('')
-        setPath('')
-    }, [])
-    //ok插入连接数据
-    let handleOk = useCallback(() => {
-        let selection = window.getSelection()
-        selection?.empty()//清空选择range
-        selection?.addRange(textData?.range)//插入新的range
-        if (isWxLink) {
-            if (aLink && appID && path) {
-                let Apath = path
-                if (userId) {
-                    if (userId === 1 && path && !path.includes('#USER_ID#')) {
-                        Apath = Apath + '#USER_ID#'
-                    } else if (userId === 2 && path && !path.includes('#QC_USER_ID#')) {
-                        Apath = Apath + '#QC_USER_ID#'
-                    }
-                }
-                document.execCommand('insertHTML', true, `<a href='${aLink}' data-miniprogram-appid='${appID}' data-miniprogram-path='${Apath}' >${textData?.text}</a>`);//插入连接
-                selection?.collapseToEnd()
-                handleClose()
-            } else {
-                message.error('请填写完整')
-            }
-        } else {
-            if (aLink && aLink.search(/http[s]?:\/\//ig) !== -1) {//
-                document.execCommand('createLink', false, aLink);//插入连接
-                selection?.collapseToEnd()
-                handleClose()
-            } else {
-                message.error('请填入正确的连接')
-            }
-        }
-    }, [textData, aLink, appID, path, isWxLink, range, userId])
-    //处理选中的文本
-    return <Modal
-        title='编辑文字内容'
-        visible={visible}
-        width={1100}
-        onCancel={() => {
-            handleClose()
-            text.current = ''
-            onCancel()
-        }}
-        onOk={callback}
-        destroyOnClose
-    >
-        <div className={style.box}>
-            <div className={style.header}>
-                <Space>
-                    <Expression getStr={getStr} range={range as Range} />
-                    {
-                        // fansName && <Button size='small' onClick={pushName}>粉丝昵称</Button>
-                    }
-                    {
-                        hdLink && <Popover
-                            placement="right"
-                            title={'新建互动链'}
-                            visible={isShow}
-                            onVisibleChange={(visible) => { setIsShow(visible) }}
-                            content={<div className={style.popover}>
-                                <div>
-                                    <label>连接文字:</label>
-                                    <Input.TextArea rows={2} placeholder='互动链显示的文字' onChange={textChange} value={value} />
-                                </div>
-                                <div>
-                                    <label>点击发送:</label>
-                                    <Input placeholder='粉丝点击互动链后,自动向公众号发送的消息' onChange={contentChange} value={content} />
-                                </div>
-                                <div>
-                                    <label>系&nbsp;&nbsp;统:</label>
-                                    <Radio.Group
-                                        onChange={(e: RadioChangeEvent) => {
-                                            setPhoneType(e.target.value)
-                                        }}
-                                        value={phoneType}
-                                    >
-                                        <Radio value={3}>通用</Radio>
-                                        <Radio value={1}>安卓1</Radio>
-                                        <Radio value={4}>安卓2</Radio>
-                                        <Radio value={2}>苹果</Radio>
-
-                                    </Radio.Group>
-                                </div>
-                                <div>
-                                    <label>提&nbsp;&nbsp;示:</label>
-                                    {
-                                        phoneType === 1 ?
-                                            <strong style={{ color: 'red' }}>
-                                                8.0.9——8.0.11(最新版本),共3个版本均可激活48小时互动!<br />
-                                            8.0.7及以下版本,点击新蓝链会跳转空页面,无法激活!<br />
-                                            iOS用户点击新蓝链,系统无法模拟用户回复消息!!!
-                                             </strong>
-                                            :
-                                            phoneType === 3 ?
-                                                <strong>
-                                                    原来的篮字方式无法激活48小时互动但所有机型通用
-                                                 </strong> 
-                                                :phoneType === 4 ?<strong>
-                                                    安卓用户可以看到,ios看不到
-                                                </strong>:<strong>
-                                                    只对IOS有效
-                                                </strong>
-                                    }
-                                </div>
-                                <Button onClick={pushLink} type='primary'>确定</Button>
-                            </div>}
-                            trigger="click"
-                        >
-                            <Button size='small' >互动链</Button>
-                        </Popover>
-                    }
-                    <Button size='small' onClick={onHtml}>文本转译</Button>
-                </Space>
-            </div>
-            <pre
-                className={style.editable} //样式
-                onBlur={onBlur}//焦点丢失
-                contentEditable="true"
-                dangerouslySetInnerHTML={{ __html: text.current }}
-                onSelect={handleSelectText}//选中事件
-                ref={(ref: any) => { setRef(ref) }}
-                onKeyDown={(e: React.KeyboardEvent<HTMLPreElement>) => {
-                    if (e.key === 'Enter') {
-                        document.execCommand('insertHTML', false, '\n')
-                        e.preventDefault()
-                    }
-                }}
-                onKeyUp={(e: React.KeyboardEvent<HTMLPreElement>) => {
-                    if (e.key === 'Enter') {
-                        e.preventDefault()
-                    }
-                }}
-                onPaste={textPaste}
-            />
-        </div>
-        <div
-            className={style.fixed_pop}
-            style={{ left: textData?.left, top: textData?.top + 30, display: textData.left > 0 ? 'flex' : '' }}
-        >
-            <>
-                {isLink && <div className={style.fixed_pop_link}>
-                    <Input placeholder='输入链接,以http://或https://开头' onChange={aLinkChange} />
-                    <a onClick={handleOk}>✓</a>
-                    <a onClick={handleClose}>×</a>
-                </div>}
-                {
-                    isWxLink && <div className={style.fixed_pop_wx}>
-                        <span>
-                            <Input placeholder='填写小程序AppID,跳转小程序需与当前公众号绑定关联关系' onChange={appIDChange} />
-                            <Input placeholder='填写小程序路径,例如:pages/index' onChange={pathChange} />
-                            <Input placeholder='备用网页,以http://或https://开头' onChange={aLinkChange} />
-                            <div className={style.fixed_pop_wx_radio}>
-                                <span>路径插入用户:</span>
-                                <Radio.Group onChange={(e: any) => { setUserId(Number(e.target.value)) }} value={userId} >
-                                    <Radio value={1}>普通用户</Radio>
-                                    <Radio value={2}>趣程用户</Radio>
-                                    <Radio value={0}>否</Radio>
-                                </Radio.Group>
-                            </div>
-                        </span>
-                        <span>
-                            <a onClick={handleOk}>✓</a>
-                            <a onClick={handleClose}>×</a>
-                        </span>
-                    </div>
-
-                }
-                {!isLink && !isWxLink && <>
-                    <span onClick={() => { handleLink(1) }}>设置连接</span>
-                    <span onClick={() => { handleLink(2) }}>设置小程序</span>
-                    <span onClick={() => { handleLink(3) }}>清空连接</span>
-                </>
-                }
-            </>
-        </div>
-    </Modal >
-})
-export default WxTextModal

+ 0 - 6
src/components/MaterialModal/updata.less

@@ -1,6 +0,0 @@
-.uploadlistinline {
-    .ant-upload-list-item {
-        float: left;
-        margin-right: 10px !important;
-    }
-}

+ 0 - 227
src/components/MaterialModal/updata.tsx

@@ -1,227 +0,0 @@
-import { PlusOutlined } from '@ant-design/icons';
-import { Button, Divider, InputNumber, message, Tag, Upload } from 'antd'
-import Modal from 'antd/lib/modal/Modal'
-import React, { useCallback, useReducer, useState } from 'react'
-import { request, useModel } from 'umi';
-import { api } from '@/services/api'
-import './updata.less'
-import getMD5 from '../MD5';
-type State = {
-    visible?: boolean,//批量弹窗
-    fileList?: any[],//已上传的文件列表
-    previewVisible?: boolean,//查看图片弹窗
-    previewImage?: string,//查看图片地址
-    previewTitle?: string//查看图片标题
-}
-type Action = {
-    type: 'visible' | 'fileList' | 'delList' | 'previewVisible' | 'init',
-    params?: any
-}
-const initData: State = {
-    visible: false,
-    fileList: [],
-    previewVisible: false,
-    previewImage: '',
-    previewTitle: ''
-}
-function reducer(state: State, action: Action) {
-    let { type, params } = action
-    switch (type) {
-        case 'visible':
-            return { ...state, visible: params.visible }
-        case 'previewVisible':
-            return { ...state, ...params }
-        case 'delList':
-            let delArr = state?.fileList?.filter((file: { uid: string }) => file.uid !== params?.uid)
-            return { ...state, fileList: delArr }
-        case 'fileList':
-            let arr = state?.fileList ? [...state?.fileList, ...params.fileList as any[]] : params.fileList
-            return { ...state, fileList: arr }
-        case 'init':
-            return { ...initData }
-        default:
-            return { ...state }
-    }
-}
-/**文件限制字典 */
-const fileTypes: any = {
-    '1': 'image/gif,image/jpeg,image/png,image/jpg',
-    '3': 'video/*',
-    '2': 'audio/*',
-}
-// type: 0 | 1,
-function Updata(props: { mediaType: '3' | '2' | '1', callBcak: (str: boolean) => void, type: 0 | 1, isAll: boolean }) {
-    const [state, dispatch] = useReducer(reducer, initData)
-    const { mediaType, callBcak, type, isAll } = props
-    const { deloss } = useModel('useOperating.useMaterialContent')
-    const { visible, fileList, previewVisible, previewImage, previewTitle } = state
-    const { state: bdState, add, list } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    const { parentId, belongUser, fileType } = bdState
-    const [sort, setSort] = useState<number>(0)
-    //创建
-    const submit = useCallback(() => {
-        let arr: any[] = []
-        fileList.forEach((file: { type: number, mediaType: number, url: string, name: string, sort: number, fileMd5: string, fileSize: number }) => {
-            let { url, name, sort, fileMd5, fileSize } = file
-            let obj = { title: name, fileType, folder: false, parentId, belongUser, url, sort, fileMd5, fileSize }
-            arr.push(obj)
-        })
-        if (arr.length > 0) {
-            arr.forEach((item) => {
-                add.run(item).then((res) => {
-                    list.refresh()
-                })
-            })
-        }
-        dispatch({ type: 'init' })
-        callBcak(false)
-    }, [fileList, list])
-    //取消
-    const cancel = useCallback(() => {
-        if (fileList.length > 0) {
-            message.warning('你有已上传的文件没有删除或保存,如果放弃请先删除图片,释放服务器空间')
-            return
-        }
-        dispatch({ type: 'init' })
-        callBcak(false)
-    }, [fileList])
-    //批量删除
-    const allDel = useCallback(() => {
-        fileList.forEach((file: { key: string, uid: string }) => {
-            let { key, uid } = file
-            dispatch({ type: 'delList', params: { uid } })
-            deloss.run(key).then((res: any) => {//删除OSS文件
-                console.log(res)
-            })
-        })
-    }, [fileList])
-    return <>
-        {/* <span onClick={() => { dispatch({ type: 'visible', params: { visible: true } }) }}>批量创建素材</span> */}
-        {/* <Button onClick={() => { dispatch({ type: 'visible', params: { visible: true } }) }} type='primary'>批量创建素材</Button> */}
-        <Modal
-            visible={true}
-            title={<span>批量新增素材<small style={{ color: '#999' }}>(请先手动将文件名重命名为要创建的素材标题)</small></span>}
-            onOk={submit}
-            onCancel={cancel}
-            width={800}
-        >
-            <Button type='primary' size='small' style={{ float: 'right', marginBottom: 5 }} onClick={allDel}>全部删除</Button>
-            <Divider />
-            <Tag color='warning'>数值越大越靠前</Tag>
-            <div>
-                <InputNumber
-                    style={{ width: 300, marginTop: 10, marginBottom: 10 }}
-                    value={sort}
-                    placeholder='请输入序号, 数值越大越靠前'
-                    onChange={(e: number) => {
-                        setSort(e)
-                    }}
-                />
-            </div>
-            <Upload
-                accept={fileTypes[mediaType]}
-                action="" //上传的地址1
-                listType="picture-card" //上传列表的内建样式,支持三种基本样式 text, picture 和 picture-card
-                fileList={fileList} //已经上传的文件列表
-                onPreview={(file) => {
-                    dispatch({
-                        type: 'previewVisible',
-                        params: {
-                            previewVisible: true,
-                            previewImage: file.url,
-                            previewTitle: file.name
-                        }
-                    })
-                }} //点击文件链接或预览图标时的回调
-                onChange={() => { }} //上传文件改变时的状态
-                multiple={true} //是否支持多选文件,ie10+ 支持。开启后按住 ctrl 可选择多个文件
-                customRequest={(options: any) => {
-                    let formData = new FormData();
-                    if (mediaType === '2') {
-                        if (options.file.size > 2097152) {
-                            message.error('请上传小于2M的音频')
-                            return
-                        }
-                    }
-                    if (mediaType === '1' || mediaType === '3') {
-                        if (options.file.size > 10485760) {
-                            message.error('请上传小于10M的素材')
-                            return
-                        }
-                    }
-                    request(`${api}/system/oss/ossUpload?type=${options.file.type}`).then((res) => { //请求后端获取ossKey
-                        if (res.data) {
-                            Object.keys(res.data).forEach((key: string) => {
-                                if (key !== 'url') {
-                                    formData.append(key, res.data[key])
-                                }
-                            })
-                            formData.append('file', options.file)
-                            //请求OSS上传
-                            request(res?.data?.ossUrl, { method: 'post', body: formData }).then(async (res2: { code: number, data: { url: string } }) => {
-                                console.log(res2)
-                                if (res2.code === 200) {
-                                    let fileMd5 = await getMD5(options.file)
-                                    dispatch({
-                                        type: 'fileList', params: {
-                                            fileList: [
-                                                {
-                                                    url: res2.data.url,
-                                                    name: options.file.name,
-                                                    uid: options.file.uid,
-                                                    // type,
-                                                    mediaType,
-                                                    key: res.data.key,
-                                                    sort,
-                                                    fileMd5,
-                                                    fileSize: options.file.size
-                                                }
-                                            ]
-                                        }
-                                    })
-                                } else {
-                                    message.error(`${options.file.name}上传失败!`)
-                                }
-                            })
-                        }
-                    })
-                }}
-                // transformFile={} //在上传之前转换文件。支持返回一个 Promise 对象  
-                onRemove={(file: any) => {
-                    let uid = file.uid
-                    dispatch({ type: 'delList', params: { uid } })
-                    deloss.run(file.key).then((res: any) => {//删除OSS文件
-                        console.log(res)
-                    })
-                }} //点击移除文件时的回调,返回值为 false 时不移除。支持返回一个 Promise 对象,Promise 对象 resolve(false) 或 reject 时不移除   
-            >
-                <div>
-                    <PlusOutlined />
-                    <div style={{ marginTop: 8 }}>Upload</div>
-                </div>
-            </Upload>
-            <Modal
-                visible={previewVisible}
-                title={previewTitle}
-                footer={null}
-                onCancel={() => {
-                    dispatch({
-                        type: 'previewVisible', params: {
-                            previewVisible: false,
-                            previewImage: '',
-                            previewTitle: ''
-                        }
-                    })
-                }}
-            >
-                {
-                    mediaType === '1' ? <img alt="example" style={{ width: '100%' }} src={previewImage} /> :
-                        mediaType === '3' ? <video src={previewImage} controls width='100%' /> : <audio src={previewImage} controls />
-                }
-
-            </Modal>
-        </Modal>
-    </>
-}
-
-export default Updata

+ 0 - 291
src/components/MaterialModal/wxGraphicListModal.tsx

@@ -1,291 +0,0 @@
-import { PlusOutlined } from '@ant-design/icons'
-import { Button, Card, Col, Input, message, Modal, Radio, Row, Tag } from 'antd'
-import { RadioChangeEvent } from 'antd/lib/radio'
-import React, { useCallback, useEffect, useReducer, useState } from 'react'
-import WxModalBox from './wxModalBox'
-import style from './graphic.less'
-import { useModel } from 'umi'
-type Props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOK: (props: any, type?: number) => void,
-    defaultData: any,
-}
-type State = {
-    actionData?: any//数据
-}
-export type Action = {
-    type: 'pushData' | 'initData' | 'range',
-    params?: any
-}
-function reducer(state: State, action: Action) {
-    let { type, params } = action
-    let newData = JSON.parse(JSON.stringify(state.actionData))
-    switch (type) {
-        case 'pushData':
-            let { eq, ...param } = params
-            Object.keys(param).forEach((key: string) => {
-                newData.articles.forEach((obj: any, index: number) => {
-                    if (index === eq) {
-                        obj[key] = params[key]
-                    }
-                })
-            })
-            return { ...state, actionData: newData }
-        case 'initData':
-            return { ...state, actionData: params.actionData }
-        default:
-            return state;
-    }
-}
-const WxGraphicListModal = (props: Props) => {
-    const [state, dispatch] = useReducer(reducer, { actionData: { articles: [{}, {}, {}, {}, {}, {}, {}, {}] } })
-    const { actionData: action } = state
-    const { visible, onCancel, onOK, defaultData } = props
-    const [isShow, setIsShow] = useState<boolean>(false)//图片弹窗
-    const [eq, setEq] = useState<number>(1)//切换
-    const [ref, setRef] = useState<any>(null)//存放实例
-    const [range, setRange] = useState<Range>()//存放光标丢失位置
-    const [isImport, setIsImport] = useState<boolean>(false)//点击导入
-    const [radio, setRadio] = useState<number>(0)
-    const getWeItData = useModel('useOperating.useMaterialContent', model => model.getWeItData)
-    const actionWX = useModel('useOperating.useWxGroupList', model => model.state.actionWX)
-
-    //确定
-    const callback = useCallback(() => {
-        let arr: any = action.articles.filter((item: any) => JSON.stringify(item) !== '{}')//筛除空对象|| 
-        arr = arr.filter((item: any) => {
-            return item.title
-        })
-        arr = arr.map((item: any) => {
-            return { newsPicUrl: item.thumbUrl, newsUrl: item.contentSourceUrl, newsDescription: item.digest, newsTitle: item.title.replace(/<[/]?span[^>]*>/ig, '#') }
-        })
-        let isOk: boolean = arr.every((item: any) => item.newsPicUrl && item.newsDescription && item.newsUrl && item.newsTitle)//检测全部必填项
-        if (isOk) {
-            onOK({ newsList: arr, indexId: action.indexId }, 5)
-        } else {
-            message.error('请检测标题,图片,描述,链接是否填写完整!不需要的篇章请全部留空')
-        }
-    }, [action])
-    //切换
-    const handelRadio = useCallback((e: RadioChangeEvent) => {
-        let v = e.target.value
-        setEq(v)
-    }, [])
-    //选中素材时的操作
-    const handelAction = useCallback((data: any) => {
-        let obj = { mediaId: data.mediaId, articles: [...data.content.articles, ...Object.values(Array(8 - data.content.articles.length).fill({})).map(n => n)] }
-        dispatch({ type: 'initData', params: { actionData: obj } })//存放选中数据
-    }, [ref, eq])
-    //开关图片弹窗
-    const closeModal = useCallback(() => {
-        setIsShow(!isShow)
-    }, [isShow])
-    //选中图片
-    const handleOk = (data: any) => {
-        dispatch({ type: 'pushData', params: { thumbUrl: data.url, eq: radio } })
-        closeModal()
-    }
-    //插入粉丝昵称
-    const pushName = useCallback(() => {
-        let span = document.createElement('span')
-        span.className = style.nickName
-        span.setAttribute('contentEditable', 'false')
-        span.innerText = `粉丝昵称`
-        range?.insertNode(span)
-        dispatch({ type: 'pushData', params: { title: ref.innerHTML, eq: radio } })
-    }, [range, radio])
-    //复制只取纯文本
-    function textPaste(event: any) {
-        event.preventDefault();
-        let text;
-        let clp = (event.originalEvent || event).clipboardData;
-        // 兼容chorme或hotfire
-        text = clp.getData('text') 
-        console.log(text)
-        if (text !== "") {
-            document.execCommand('insertHtml', false, text);
-        }
-    }
-    //光标丢失记录位置
-    const onBlur = useCallback(() => {
-        let selection = window.getSelection()
-        let range = selection?.getRangeAt(0)
-        setRange(range)
-        dispatch({ type: 'pushData', params: { title: ref.innerHTML, eq: radio } })
-    }, [ref, radio])
-    // useEffect(() => {
-    //     if (ref) {
-    //         let { title } = action?.articles[radio]
-    //         ref.innerText = title || ''
-    //     }
-
-    // }, [radio, ref, action])
-    //初始光标选中
-    useEffect(() => {
-        ref?.focus()
-    }, [ref])
-    //获取微信图文列表
-    useEffect(() => {
-        if(actionWX){
-            getWeItData.run({ appId: actionWX.appid, count: 1000, offset: 0 })
-        }
-    }, [actionWX])
-    //获取同步更新素材
-    const sync = () => {
-        getWeItData.run({ appId: actionWX.appid, count: 1000, offset: 0, isNew: true })
-    }
-    //连接输入
-    const handelLink = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        dispatch({ type: 'pushData', params: { contentSourceUrl: v, eq: radio } })
-    }, [radio])
-    //摘要输入
-    const handelText = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        let v = e.target.value
-        dispatch({ type: 'pushData', params: { digest: v, eq: radio } })
-    }, [radio])
-    /**篇数选择 */
-    const radioChange = useCallback((e: RadioChangeEvent) => {
-        let v = e.target.value
-        setRadio(v)
-    }, [])
-    //list渲染
-    const List = useCallback((props: { width: string, action: any }) => {
-        let { action } = props
-        return <div className={style.list}>
-            {
-                getWeItData?.data?.items?.map((item: any, index: any) => {
-                    let isAction = action?.mediaId === item.mediaId
-                    return <Card
-                        hoverable
-                        style={{ width: props.width, borderRadius: 5, marginBottom: 10 }}
-                        bodyStyle={{ padding: '5px' }}
-                        className={isAction ? style.action : ''}
-                        bordered={isAction ? false : true}
-                        key={index}
-                        onClick={() => handelAction(item)}
-                    >
-                        <div className={style.box}>
-                            <div className={style.left}>
-                                <p>{item.content.articles[0].title}</p>
-                                <span>最近编辑:{item.content?.updateTime?.replace(/T|\.000\+0800/ig, ' ')}</span>
-                            </div>
-                            <img src={item.content.articles[0].thumbUrl} />
-                        </div>
-                    </Card>
-                })
-            }
-        </div>
-    }, [getWeItData])
-    /**编辑回填 */
-    useEffect(() => {
-        if (defaultData?.newsList) {
-            let arr = defaultData?.newsList.map((item: any) => {
-                return { title: item.newsTitle.replace('#粉丝昵称#', `<span class=${style.nickName} contenteditable="false">粉丝昵称</span>`), thumbUrl: item.newsPicUrl, contentSourceUrl: item.newsUrl, digest: item.newsDescription }//转义
-            })
-            arr = [...arr, ...Object.values(Array(8 - arr.length).fill({})).map(n => n)]  //不足8个填充
-            dispatch({ type: 'initData', params: { actionData: { articles: arr, indexId: defaultData?.indexId } } })
-        }
-    }, [defaultData])
-    return <Modal
-        title='编辑图文内容'
-        width={1100}
-        visible={visible}
-        onCancel={onCancel}
-        onOk={callback}
-    >
-        <div>
-            <div className={style.header}>
-                <label>添加方式:</label>
-                <Radio.Group onChange={handelRadio} value={eq}>
-                    <Radio value={1}>自定义设置</Radio>
-                    {/* <Radio value={2}>素材库导入</Radio> */}
-                </Radio.Group>
-                <Button type='primary' onClick={sync} loading={getWeItData?.loading}>同步最新素材</Button>
-            </div>
-            {
-                eq === 1
-                    ?
-                    // 自定义设置
-                    <div className={style.centent}>
-                        <div >
-                            {
-                                !isImport
-                                    ?
-                                    <div className={style.text}>
-                                        <span>
-                                            您可以点击下方”导入图文内容”按钮,直接从微信素材导入,也可以在右边表单手动添加内容。
-                                         </span>
-                                        <Button type='primary' size='small' onClick={() => { setIsImport(true) }} disabled={getWeItData?.loading} loading={getWeItData?.loading}>导入图文内容</Button>
-                                    </div>
-                                    :
-                                    <div className={style.text}>
-                                        <span>选择图文导入:</span>
-                                        <List width='100%' action={action} />
-                                    </div>
-                            }
-                        </div>
-                        <div className={style.graphic_list}>
-                            <Radio.Group
-                                onChange={radioChange}
-                                value={radio}>
-                                {
-                                    action?.articles?.map((list: any, index: number) => {
-                                        return <Radio key={index} value={index}>第{index + 1}篇</Radio>
-                                    })
-                                }
-                            </Radio.Group>
-                            {
-                                action?.articles?.map((list: any, index: number) => {
-
-                                    return radio === index && <div key={index}>
-                                        <Row style={{ width: '80%' }}>
-                                            <Col span={24}>
-                                                <label >图文标题 :<span>(必填)</span></label>
-                                                <div
-                                                    contentEditable="true"
-                                                    className={style.editor}
-                                                    ref={(ref) => setRef(ref)}
-                                                    onBlur={onBlur}
-                                                    dangerouslySetInnerHTML={{ __html: list?.title }}
-                                                    onPaste={textPaste}
-                                                />
-                                                {/* <label >点击插入:<Tag color='orange' onClick={pushName}>粉丝昵称</Tag></label> */}
-                                            </Col>
-                                            <Col span={24}>
-                                                <label >描述内容 :</label>
-                                                <Input.TextArea rows={5} placeholder='填写图文描述' onChange={handelText} value={list?.digest} />
-                                            </Col>
-                                            <Col span={24}>
-                                                <label >链接设置 :<span>(必填)</span></label>
-                                                <Input placeholder='请输入跳转链接,且必须以http://或https://开头' onChange={handelLink} value={list?.contentSourceUrl} />
-                                            </Col>
-                                        </Row>
-                                        <div>
-                                            <label >图文封面 :</label>
-                                            <span className={list?.thumbUrl ? style.imgupload : ''} onClick={closeModal}>
-                                                {
-                                                    list?.thumbUrl ? <img src={list?.thumbUrl} /> : <PlusOutlined style={{ fontSize: 30 }} />
-                                                }
-                                                <div><PlusOutlined style={{ fontSize: 30, color: '#fff' }} /> </div>
-                                            </span>
-                                        </div>
-                                    </div>
-                                })
-                            }
-                        </div>
-                        {isShow && <WxModalBox mediaType={1} onCancel={closeModal} title={`公众号图片素材`} visible={isShow} onOk={handleOk} />}
-                    </div>
-                    :
-                    //素材库导入
-                    <div className={style.centent_2}>
-                        <p>选择图文 <span>(因官方接口限制,智能推送仅支持导入单图文素材)</span></p>
-                        <List width='32%' action={action} />
-                    </div>
-            }
-
-        </div>
-    </Modal>
-}
-export default WxGraphicListModal

+ 0 - 239
src/components/MaterialModal/wxGraphicModal.tsx

@@ -1,239 +0,0 @@
-import { PlusOutlined } from '@ant-design/icons'
-import { Button, Card, Col, Input, message, Modal, Radio, Row, Tag } from 'antd'
-import { RadioChangeEvent } from 'antd/lib/radio'
-import React, { useCallback, useEffect, useState } from 'react'
-import WxModalBox from './wxModalBox'
-import style from './graphic.less'
-import { useModel } from 'umi'
-type Props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOK: (props: any, type?: number) => void,
-    defaultData: any,
-}
-const WxGraphicModal = (props: Props) => {
-    const { visible, onCancel, onOK } = props
-    const [isShow, setIsShow] = useState<boolean>(false)//图片弹窗
-    const [eq, setEq] = useState<number>(1)//切换
-    const [action, setAction] = useState<any>(null)//选中
-    const [img, setImg] = useState<any>(null)//存放图片数据
-    const [ref, setRef] = useState<any>(null)
-    const [range, setRange] = useState<Range>()
-    const [isImport, setIsImport] = useState<boolean>(false)//点击导入
-    const [link, setLink] = useState<string>('')//link
-    const [text, setText] = useState<string>('')//摘要
-    const getWeItData = useModel('useOperating.useMaterialContent', model => model.getWeItData)
-    const actionWX = useModel('useOperating.useWxGroupList', model => model.state.actionWX)
-    //确定
-    const callback = useCallback(() => {
-        if (eq === 2) {
-            onOK(action, 5)
-        } else {
-            if (link && text && img && ref.innerHTML.replace(/<[/]?span[^>]*>/ig, '#')) {
-                onOK({
-                    newsUrl: link,
-                    newsDescription: text,
-                    newsPicUrl: img,
-                    newsTitle: ref.innerHTML.replace(/<[/]?span[^>]*>/ig, '#'),
-                    indexId: props.defaultData?.indexId
-                }, 5)
-
-            } else {
-                message.error('有遗漏未填项!')
-            }
-        }
-
-    }, [action, eq, link, text, img, ref])
-    //切换
-    const handelRadio = useCallback((e: RadioChangeEvent) => {
-        let v = e.target.value
-        setEq(v)
-        setAction(null)
-    }, [])
-    //选中素材时的操作
-    const handelAction = useCallback((data: any) => {
-        let { title, contentSourceUrl, digest, thumbUrl } = data.content.articles[0]
-        setAction({ mediaId: data.mediaId, articles: { title, contentSourceUrl, digest, thumbUrl } })//存放选中数据
-        if (eq !== 2) {
-            setLink(contentSourceUrl)//存放选中的连接
-            setText(digest)//存放选中的摘要
-            setImg(thumbUrl)//存放图片
-            ref.innerText = title//标题
-        }
-    }, [ref, eq])
-    //开关图片弹窗
-    const closeModal = useCallback(() => {
-        setIsShow(!isShow)
-    }, [isShow])
-    //选中图片
-    const handleOk = (data: any) => {
-        setImg(data.url)
-        closeModal()
-    }
-    //插入粉丝昵称
-    const pushName = useCallback(() => {
-        let span = document.createElement('span')
-        span.className = style.nickName
-        span.setAttribute('contentEditable', 'false')
-        span.innerText = `粉丝昵称`
-        range?.insertNode(span)
-    }, [range])
-    //光标丢失记录位置
-    const onBlur = useCallback(() => {
-        let selection = window.getSelection()
-        let range = selection?.getRangeAt(0)
-        setRange(range)
-    }, [])
-    //初始光标选中
-    useEffect(() => {
-        ref?.focus()
-    }, [ref])
-    //获取微信图文列表
-    useEffect(() => {
-        getWeItData.run({ appId: actionWX.appid, count: 1000, offset: 0 })
-    }, [actionWX])
-    //连接输入
-    const handelLink = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let v = e.target.value
-        setLink(v)
-    }, [])
-    //摘要输入
-    const handelText = useCallback((e: React.ChangeEvent<HTMLTextAreaElement>) => {
-        let v = e.target.value
-        setText(v)
-    }, [])
-    //复制只取纯文本
-    function textPaste(event: any) {
-        event.preventDefault();
-        let text;
-        let clp = (event.originalEvent || event).clipboardData;
-        // 兼容chorme或hotfire
-        text = clp.getData('text')
-        console.log(text)
-        if (text !== "") {
-            document.execCommand('insertHtml', false, text);
-        }
-    }
-    //编辑回填内容
-    useEffect(() => {
-        if (props.defaultData && ref) {
-            let { newsList } = props.defaultData
-            let { newsUrl, newsDescription, newsPicUrl, newsTitle } = newsList[0]
-            newsTitle = newsTitle.replace('#粉丝昵称#', `<span class=${style.nickName} contenteditable="false">粉丝昵称</span>`)
-            setImg(newsPicUrl)
-            setText(newsDescription)
-            setLink(newsUrl)
-            ref.innerHTML = newsTitle
-        }
-    }, [ref])
-    //list渲染
-    const List = useCallback((props: { width: string, action: any }) => {
-        let { action } = props
-        return <div className={style.list}>
-            {
-                getWeItData?.data?.items?.map((item: any, index: any) => {
-                    let isAction = action?.mediaId === item.mediaId
-                    return <Card
-                        hoverable
-                        style={{ width: props.width, borderRadius: 5, marginBottom: 10 }}
-                        bodyStyle={{ padding: '5px' }}
-                        className={isAction ? style.action : ''}
-                        bordered={isAction ? false : true}
-                        key={index}
-                        onClick={() => handelAction(item)}
-                    >
-                        <div className={style.box}>
-                            <div className={style.left}>
-                                <p>{item.content.articles[0].title}</p>
-                                <span>最近编辑:{item.content?.updateTime?.replace(/T|\.000\+0800/ig, ' ')}</span>
-                            </div>
-                            <img src={item.content.articles[0].thumbUrl} />
-                        </div>
-                    </Card>
-                })
-            }
-        </div>
-    }, [getWeItData])
-    return <Modal
-        title='编辑图文内容'
-        width={1100}
-        visible={visible}
-        onCancel={onCancel}
-        onOk={callback}
-    >
-        <div>
-            <div className={style.header}>
-                <label>添加方式:</label>
-                <Radio.Group onChange={handelRadio} value={eq}>
-                    <Radio value={1}>自定义设置</Radio>
-                    {/* <Radio value={2}>素材库导入</Radio> */}
-                </Radio.Group>
-            </div>
-            {
-                eq === 1
-                    ?
-                    // 自定义设置
-                    <div className={style.centent}>
-                        <div >
-                            {
-                                !isImport
-                                    ?
-                                    <div className={style.text}>
-                                        <span>
-                                            您可以点击下方”导入图文内容”按钮,直接从微信素材导入,也可以在右边表单手动添加内容。
-                                         </span>
-                                        <Button type='primary' size='small' onClick={() => { setIsImport(true) }} disabled={getWeItData?.loading} loading={getWeItData?.loading}>导入图文内容</Button>
-                                    </div>
-                                    :
-                                    <div className={style.text}>
-                                        <span>选择图文导入:</span>
-                                        <List width='100%' action={action} />
-                                    </div>
-                            }
-                        </div>
-                        <div>
-                            <Row style={{ width: '80%' }}>
-                                <Col span={24}>
-                                    <label >图文标题 :<span>(必填)</span></label>
-                                    <div
-                                        contentEditable="true"
-                                        className={style.editor}
-                                        ref={(ref) => setRef(ref)}
-                                        onBlur={onBlur}
-                                        onPaste={textPaste}
-                                    />
-                                    {/* <label >点击插入:<Tag color='orange' onClick={pushName}>粉丝昵称</Tag></label> */}
-                                </Col>
-                                <Col span={24}>
-                                    <label >描述内容 :</label>
-                                    <Input.TextArea rows={5} placeholder='填写图文描述' onChange={handelText} value={text} />
-                                </Col>
-                                <Col span={24}>
-                                    <label >链接设置 :<span>(必填)</span></label>
-                                    <Input placeholder='请输入跳转链接,且必须以http://或https://开头' onChange={handelLink} value={link} />
-                                </Col>
-                            </Row>
-                            <div>
-                                <label >图文封面 :</label>
-                                <span className={img ? style.imgupload : ''} onClick={closeModal}>
-                                    {
-                                        img ? <img src={img} /> : <PlusOutlined style={{ fontSize: 30 }} />
-                                    }
-                                    <div><PlusOutlined style={{ fontSize: 30, color: '#fff' }} /> </div>
-                                </span>
-                            </div>
-                        </div>
-                        {isShow && <WxModalBox mediaType={1} onCancel={closeModal} title={`公众号图片素材`} visible={isShow} onOk={handleOk} />}
-                    </div>
-                    :
-                    //素材库导入
-                    <div className={style.centent_2}>
-                        <p>选择图文 <span>(因官方接口限制,智能推送仅支持导入单图文素材)</span></p>
-                        <List width='32%' action={action} />
-                    </div>
-            }
-
-        </div>
-    </Modal>
-}
-export default WxGraphicModal

+ 0 - 101
src/components/MaterialModal/wxHistorBD.tsx

@@ -1,101 +0,0 @@
-import useIndexDB from '@/Hook/useIndexDB';
-import { Modal, Row, Pagination, Card, Input, Button, Space } from 'antd'
-import React, { useCallback, useEffect, useState } from 'react'
-import { useModel } from 'umi';
-import style from './db.less'
-import filePng from '../../../public/file.png'
-
-/**
- * @param historyType //历史图文type  0: 智能互动消息历史  1:客服消息历史
- */
-
-type props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOK: (props: any, type?: number) => void,
-    wx?: any,
-}
-
-const WxHistoryMpnews: React.FC<props> = (props) => {
-    const { visible, onCancel, onOK, } = props
-    const [action, setAction] = useState<number>(0)
-    const [actionData, setActionData] = useState()
-    let { state: { data, total } } = useModel('useOperating.useDB')
-    const { query, del } = useIndexDB()
-    //ok
-    const pageSize = 10  // 每页请求多少数据
-
-    let ok = useCallback(() => {
-        onOK(actionData)
-    }, [actionData])
-
-    let pageSizeChange = useCallback((pageNum, pageSize) => {
-        console.log(pageNum, pageSize)
-        query({ start: pageNum, end: pageSize })
-    }, [query])
-    //选中图片
-    let handleClick = useCallback((data) => {
-        setAction(data?.id)
-        setActionData(data?.data)
-    }, [])
-    useEffect(() => {
-        query()
-    }, [query])
-    return <Modal
-        visible={visible}
-        title={<span>浏览器本地素材库<span style={{ color: 'red' }}>不需要的数据请手动删除避免太多数据会很卡,存放上限跟个人浏览器浏览器性能相关!</span></span>}
-        onCancel={onCancel}
-        onOk={ok}
-        width={1000}
-    >
-        {/* <Row justify='space-between'>
-            <Col>
-                <Search placeholder="请输入" enterButton="搜索" loading={false} />
-            </Col>
-            <Col><Button>一键清空</Button></Col>
-        </Row> */}
-        <div className={style.content}>
-            <div style={{ borderBottom: '1px solid #efefef', paddingBottom: 10 }}>
-                <Space>
-                    <Input.Search placeholder="模糊查询(支持链接,内容,标题)" onSearch={(value: string) => { query({ str: value }) }} style={{ width: 300 }} />
-                    <Button onClick={() => del(action)} type='primary' disabled={!action}>删除</Button>
-                </Space>
-            </div>
-            <div className={style.box}>
-                {
-                    [0, 1, 2].map((n) => {
-                        return <ul className={style.ul} key={n}>
-                            {
-                                data.length > 0 && data?.map((item: any, index: number) => {
-                                    if (index % 3 === n) {
-                                        return <li key={item?.id} className={action === item?.id ? style.action : ""} onClick={() => handleClick(item)}>
-                                            <Card
-                                                hoverable
-                                                className={style.box_card}
-                                                cover={
-                                                    item?.data?.map((a: any, eq: number) => {
-                                                        return <div className={style.img_ScwxBox} key={eq}>
-                                                            <span>{a?.title || a?.newsTitle}</span>
-                                                            {/* <img src={(a?.knewsThumbInfo?.folder ? filePng : a?.knewsThumbInfo?.id ? a?.knewsThumbInfo?.url : a?.knewsThumbUrl) || ('https://s.weituibao.com/static/1552098829922/bigfm.png')} /> */}
-                                                            {Object.keys(a)?.includes('newsPicUrl') ? <img src={a?.newsPicUrl} /> : <img src={a?.knewsThumbUrl || (a?.knewsThumbId ? filePng : 'https://s.weituibao.com/static/1552098829922/bigfm.png')} />}
-                                                        </div>
-                                                    })
-                                                }
-                                            />
-                                        </li>
-                                    }
-                                    return null
-                                })
-                            }
-                        </ul>
-                    })
-                }
-            </div>
-        </div>
-        <Row justify='center' style={{ paddingTop: 10, borderTop: '1px solid #efefef' }}>
-            <Pagination size="small" total={total} showQuickJumper pageSize={pageSize} onChange={pageSizeChange} />
-        </Row>
-    </Modal>
-}
-
-export default WxHistoryMpnews

+ 0 - 188
src/components/MaterialModal/wxModalBox.tsx

@@ -1,188 +0,0 @@
-import { Button, Card, Col, Image, message, Modal, Pagination, Row, Tabs, Tag } from "antd"
-import React, { useMemo, useRef } from "react"
-import { useCallback, useEffect, useState } from "react"
-import { useModel } from "umi"
-import Tables from "../Tables";
-const { TabPane } = Tabs;
-import style from './index.less'
-/**微信图片弹窗 */
-/**
- * 微信图片素材弹窗组件 
- * 
- * 立即回复 图片 视频 音频
- * 
- * 立即回复 延迟回复 新建推送里 图片 视频 音频
- * 
- * 高级群发 新建 图片消息 语言消息 视频消息
- */
-const type = {
-    'mpnews': 5,
-    'mpvideo': 3,
-    'voice': 2,
-    'image': 1,
-    'text': 4
-}
-type Props = {
-    mediaType: number,
-    visible: boolean,
-    onOk: (url: string, type?: number) => void,
-    onCancel: () => void,
-    title: string,
-    action?: any,
-}
-const ModalPage = (props: Props) => {
-    const [action, setAction] = useState<any>(null)
-    const { mediaType, visible, onOk, onCancel, title } = props
-    const [selectedRowKeys, setSelectedRowKeys] = useState<string[] | number[]>([0])
-    let refNews: { current: any } = useRef()
-    const { getData, update } = useModel('useOperating.useMaterialContent', model => ({
-        getData: model.getWeData,
-        update: model.update
-    }))
-    const [pageNum, setPageNum] = useState(1)
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX, }))
-    let config: any = {
-        '5': 'news',
-        '3': 'video',
-        '2': 'voice',
-        '1': 'image'
-    }
-    let types = useMemo(() => {
-        return config[mediaType]
-    }, [mediaType])
-
-    useEffect(() => {
-        getData.run({ mediaType: types, mpId: actionWX.id, pageNum: 1, pageSize: 10 })
-    }, [actionWX.id, types])
-    //同步更新
-    const sync = () => {
-        update.run({ mpId: actionWX?.id, mediaType: types }).then((res: any) => {
-            if(res) {
-                getData.run({ mediaType: types, mpId: actionWX.id, pageNum: pageNum, pageSize: 10 })
-            }
-        })
-    }
-    //选中图片
-    let handleClick = useCallback((data) => {
-        setAction(data)
-    }, [])
-    /**
-     * 获取当前类型
-     */
-    
-    //翻页
-    let pageSizeChange = useCallback((pageNum, pageSize) => {
-        setPageNum(pageNum)
-        getData.run({
-            mediaType: types,
-            pageNum: pageNum,
-            pageSize: pageSize,
-            mpId: actionWX.id
-        })
-    }, [actionWX.id, types])
-    //Ok
-    let ok = () => {
-        if (!action) {
-            message.error('请选择素材')
-            return
-        }
-        onOk({ ...action }, mediaType)
-    }
-    //编辑时选中默认
-    useEffect(() => {
-        setSelectedRowKeys([0])
-        setAction(null)
-        if (props.action && type[props?.action?.mediaType] === props.mediaType) {
-            if (props?.action?.msgType === 'image') {
-                setAction(props.action)
-            } else {
-                getData?.data?.records?.forEach((item: { mediaId: any }, index: number) => {
-                    if (item?.mediaId === props?.action?.mediaId) {
-                        setSelectedRowKeys([index + 1])
-                        setAction(item)
-                    }
-                })
-            }
-
-        }
-    }, [props.action, getData?.data])
-    //table单选事件
-    const rowSelection = {
-        onChange: (selectedRowKeys: any, selectedRows: any) => {
-            setSelectedRowKeys(selectedRowKeys)
-            setAction(selectedRows[0])
-        }
-    };
-    return <Modal
-        title={title}
-        width={750}
-        visible={visible}
-        onOk={ok}
-        onCancel={onCancel}
-        destroyOnClose
-    >
-        <Tabs type="card" tabBarExtraContent={<Button type='primary' onClick={sync} loading={update?.loading}>同步最新素材</Button>}>
-            <TabPane tab="公众号素材" key="1" style={{ padding: 10 }}>
-                {
-                    mediaType === 1 && <>
-                        <Row justify='start' gutter={[15, 15]} style={{ height: 400, overflowY: 'scroll' }}>
-                            {
-                                getData?.data?.records?.map((item: any, index: number) => {
-                                    return <Col key={item?.mediaId + index || item?.wxMediaId + index} className={`${style.img} ${action?.mediaId === item?.mediaId ? style.action : undefined}`}>
-                                        <Card bodyStyle={{ padding: 0, display: 'flex', flexFlow: 'column' }} bordered={false} hoverable >
-                                            <Image src={item?.url} width={150} placeholder preview={false} onClick={() => handleClick(item)} />
-                                        </Card >
-                                    </Col>
-                                })
-                            }
-                        </Row>
-                        <Pagination
-                            onChange={pageSizeChange}
-                            size={'small'}
-                            defaultCurrent={1}
-                            total={getData?.data?.total}
-                            style={{ float: 'right' }}
-                            showTotal={(total) => <Tag color="cyan">总共{total}数据</Tag>}
-                            pageSizeOptions={['10', '20']}
-                        />
-                    </>
-                }
-                {
-                    mediaType !== 1 && <Tables
-                        dataSource={getData?.data?.records?.map((item: any, index: number) => ({ ...item, id: index + 1 })) || []}
-                        columns={columns}
-                        rowSelection={{
-                            type: 'radio',
-                            selectedRowKeys,
-                            ...rowSelection
-                        }}
-                    />
-                }
-
-            </TabPane>
-        </Tabs>
-    </Modal >
-}
-
-export default ModalPage
-
-const columns = [
-    {
-        title: 'ID',
-        dataIndex: 'id',
-        key: 'id',
-        align: 'center',
-    },
-    {
-        title: '素材名称',
-        dataIndex: 'name',
-        key: 'name',
-        align: 'center',
-    },
-    {
-        title: '创建日期',
-        dataIndex: 'updateTime',
-        key: 'updateTime',
-        align: 'center',
-    },
-]

+ 0 - 153
src/components/MaterialModal/wxMpnews.tsx

@@ -1,153 +0,0 @@
-import { Button, Card, Modal, Pagination, Tabs, Tag } from 'antd'
-import React, { useCallback, useEffect, useRef, useState } from 'react'
-import DrawerPage from "@/components/FileBox/components/newsModal"
-import { useModel } from 'umi'
-import style from './mpnews.less'
-import FileBox from '../FileBox'
-
-/**
- * 
- * 图文素材 
- * 
- * 编辑图文内容 素材库导入
- */
-
-type Props = {
-    visible: boolean,
-    onCancel: () => void,
-    onOK: (props: any, type?: number) => void,
-    defaultData: any,
-    wx?: any,
-    isNews?: boolean
-}
-/**微信图文弹窗 */
-const WxMpnews = React.memo((props: Props) => {
-    const { visible, onCancel, onOK, wx } = props
-    const [action, setAction] = useState<any>('')
-    const { getData, update } = useModel('useOperating.useMaterialContent', model => ({ getData: model.getWeData, update: model.update }))
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    let refD: { current: { showDrawer: (props?: any) => void } } | any = useRef()//DrawerPage获取实例方法
-    const { state, set, getList } = useModel('useOperating.useBdMedia')
-    const [isWx, setIsWx] = useState<boolean>(false)
-    const { fileType, belongUser, parentId, selectItem } = state
-    /**加载组件或数据更新执行请求列表 */
-    useEffect(() => {
-        set({ fileType: 'news' })//设置获取图文列表
-        if (belongUser === '1' || belongUser === '0') {
-            getList()//获取列表
-        }
-    }, [fileType, belongUser, parentId])
-    let pageSizeChange = useCallback((pageNum, pageSize) => {
-        getData.run({
-            pageNum: pageNum,
-            pageSize: pageSize,
-            mpId: actionWX?.id,
-            mediaType: 'news'
-        })
-    }, [actionWX?.id])
-    //同步更新
-    let sync = useCallback(() => {
-        update.run({ mpId: actionWX?.id, mediaType: 'news' })
-    }, [actionWX?.id])
-    //选中图片
-    let handleClick = useCallback((data) => {
-        setAction(data)
-    }, [])
-    //ok
-    let ok = useCallback(() => {
-        if (isWx) {
-            onOK(action)
-        } else {
-            onOK(selectItem)
-        }
-    }, [action, isWx, selectItem])
-    useEffect(() => {
-        if (actionWX?.id) {
-            getData.run({ mpId: actionWX?.id, mediaType: 'news', pageSize: 9, pageNum: 1 })
-        }
-    }, [actionWX?.id])
-    useEffect(() => {
-        if (props.defaultData) {
-            setAction(props.defaultData)
-        }
-    }, [props.defaultData])
-    //tabs切换
-    const change = useCallback((s: string) => {
-        setIsWx(s === '1' ? false : true)
-    }, [])
-    return <div >
-        <Modal
-            visible={visible}
-            title='图文素材'
-            onCancel={onCancel}
-            onOk={ok}
-            width={1200}
-            destroyOnClose
-            maskClosable={false}
-        >
-            <Tabs defaultActiveKey="1" onChange={change} type='card'>
-                <Tabs.TabPane tab="本地素材" key="1">
-                    <Tabs onChange={(activeKey: any) => { set({ belongUser: activeKey }) }} activeKey={belongUser}>
-                        <Tabs.TabPane tab={'个人本地'} key={1} />
-                        <Tabs.TabPane tab={'公共本地'} key={0} />
-                    </Tabs>
-                    <FileBox isAll={false} noFile={true} height={450} showDrawer={refD?.current?.showDrawer} isBd={true} />
-                </Tabs.TabPane>
-                <Tabs.TabPane tab="微信素材" key="2">
-                    <div className={style.btn}>
-                        <Button type='primary' onClick={() => { refD?.current.showDrawer() }} loading={getData?.loading} style={{ marginRight: 10 }}>新建微信素材</Button>
-                        <Button type='primary' onClick={sync} loading={update?.loading}>更新公众号下素材</Button>
-                    </div>
-                    <div className={style.box}>
-                        {
-                            [0, 1, 2].map((n) => {
-                                return <ul className={style.ul} key={n}>
-                                    {
-                                        getData?.data?.records?.map((item: any, index: number) => {
-                                            if (index % 3 === n) {
-                                                return <li key={item.mediaId} className={action?.mediaId === item.mediaId ? style.action : ""} onClick={() => handleClick(item)}>
-                                                    <Card
-                                                        hoverable
-                                                        className={style.box_card}
-                                                        cover={
-                                                            item?.news?.map((list: any, index: number) => {
-                                                                return <div className={style.img_ScwxBox} key={index}>
-                                                                    <span>{list.title}</span>
-                                                                    <img src={list.thumbMediaUrl} />
-                                                                </div>
-                                                            })
-                                                        }
-                                                    />
-                                                </li>
-                                            }
-                                            return null
-                                        })
-                                    }
-                                </ul>
-                            })
-                        }
-                    </div>
-                    <div className={style.footer}>
-                        <Pagination
-                            onChange={pageSizeChange}
-                            size={'small'}
-                            defaultCurrent={1}
-                            defaultPageSize={9}
-                            total={getData?.data?.total}
-                            style={{ float: 'right' }}
-                            showTotal={(total) => <Tag color="cyan">总共{total}数据</Tag>}
-                        />
-                    </div>
-                </Tabs.TabPane>
-            </Tabs>
-            <DrawerPage ref={refD} syncNews={false} isWx={isWx} isAll={false} />
-        </Modal>
-    </div >
-}, (a, b) => {
-    if (JSON.stringify(a) === JSON.stringify(b)) {
-        return true
-    }
-    return false
-})
-
-export default WxMpnews

+ 0 - 125
src/components/NoticeIcon/NoticeIcon.tsx

@@ -1,125 +0,0 @@
-import { BellOutlined } from '@ant-design/icons';
-import { Badge, Spin, Tabs } from 'antd';
-import useMergeValue from 'use-merge-value';
-import React from 'react';
-import classNames from 'classnames';
-import NoticeList, { NoticeIconTabProps } from './NoticeList';
-import HeaderDropdown from '../HeaderDropdown';
-import styles from './index.less';
-
-const { TabPane } = Tabs;
-
-export interface NoticeIconProps {
-  count?: number;
-  bell?: React.ReactNode;
-  className?: string;
-  loading?: boolean;
-  onClear?: (tabName: string, tabKey: string) => void;
-  onItemClick?: (item: API.NoticeIconData, tabProps: NoticeIconTabProps) => void;
-  onViewMore?: (tabProps: NoticeIconTabProps, e: MouseEvent) => void;
-  onTabChange?: (tabTile: string) => void;
-  style?: React.CSSProperties;
-  onPopupVisibleChange?: (visible: boolean) => void;
-  popupVisible?: boolean;
-  clearText?: string;
-  viewMoreText?: string;
-  clearClose?: boolean;
-  emptyImage?: string;
-  children?: React.ReactElement<NoticeIconTabProps>[];
-}
-
-const NoticeIcon: React.FC<NoticeIconProps> & {
-  Tab: typeof NoticeList;
-} = (props) => {
-  const getNotificationBox = (): React.ReactNode => {
-    const {
-      children,
-      loading,
-      onClear,
-      onTabChange,
-      onItemClick,
-      onViewMore,
-      clearText,
-      viewMoreText,
-    } = props;
-    if (!children) {
-      return null;
-    }
-    const panes: React.ReactNode[] = [];
-    React.Children.forEach(children, (child: React.ReactElement<NoticeIconTabProps>): void => {
-      if (!child) {
-        return;
-      }
-      const { list, title, count, tabKey, showClear, showViewMore } = child.props;
-      const len = list && list.length ? list.length : 0;
-      const msgCount = count || count === 0 ? count : len;
-      const tabTitle: string = msgCount > 0 ? `${title} (${msgCount})` : title;
-      panes.push(
-        <TabPane tab={tabTitle} key={tabKey}>
-          <NoticeList
-            clearText={clearText}
-            viewMoreText={viewMoreText}
-            list={list}
-            tabKey={tabKey}
-            onClear={(): void => onClear && onClear(title, tabKey)}
-            onClick={(item): void => onItemClick && onItemClick(item, child.props)}
-            onViewMore={(event): void => onViewMore && onViewMore(child.props, event)}
-            showClear={showClear}
-            showViewMore={showViewMore}
-            title={title}
-          />
-        </TabPane>,
-      );
-    });
-    return (
-      <>
-        <Spin spinning={loading} delay={300}>
-          <Tabs className={styles.tabs} onChange={onTabChange}>
-            {panes}
-          </Tabs>
-        </Spin>
-      </>
-    );
-  };
-
-  const { className, count, bell } = props;
-
-  const [visible, setVisible] = useMergeValue<boolean>(false, {
-    value: props.popupVisible,
-    onChange: props.onPopupVisibleChange,
-  });
-  const noticeButtonClass = classNames(className, styles.noticeButton);
-  const notificationBox = getNotificationBox();
-  const NoticeBellIcon = bell || <BellOutlined className={styles.icon} />;
-  const trigger = (
-    <span className={classNames(noticeButtonClass, { opened: visible })}>
-      <Badge count={count} style={{ boxShadow: 'none' }} className={styles.badge}>
-        {NoticeBellIcon}
-      </Badge>
-    </span>
-  );
-  if (!notificationBox) {
-    return trigger;
-  }
-
-  return (
-    <HeaderDropdown
-      placement="bottomRight"
-      overlay={notificationBox}
-      overlayClassName={styles.popover}
-      trigger={['click']}
-      visible={visible}
-      onVisibleChange={setVisible}
-    >
-      {trigger}
-    </HeaderDropdown>
-  );
-};
-
-NoticeIcon.defaultProps = {
-  emptyImage: 'https://gw.alipayobjects.com/zos/rmsportal/wAhyIChODzsoKIOBHcBk.svg',
-};
-
-NoticeIcon.Tab = NoticeList;
-
-export default NoticeIcon;

+ 0 - 103
src/components/NoticeIcon/NoticeList.less

@@ -1,103 +0,0 @@
-@import '~antd/es/style/themes/default.less';
-
-.list {
-  max-height: 400px;
-  overflow: auto;
-  &::-webkit-scrollbar {
-    display: none;
-  }
-  .item {
-    padding-right: 24px;
-    padding-left: 24px;
-    overflow: hidden;
-    cursor: pointer;
-    transition: all 0.3s;
-
-    .meta {
-      width: 100%;
-    }
-
-    .avatar {
-      margin-top: 4px;
-      background: @component-background;
-    }
-    .iconElement {
-      font-size: 32px;
-    }
-
-    &.read {
-      opacity: 0.4;
-    }
-    &:last-child {
-      border-bottom: 0;
-    }
-    &:hover {
-      background: @primary-1;
-    }
-    .title {
-      margin-bottom: 8px;
-      font-weight: normal;
-    }
-    .description {
-      font-size: 12px;
-      line-height: @line-height-base;
-    }
-    .datetime {
-      margin-top: 4px;
-      font-size: 12px;
-      line-height: @line-height-base;
-    }
-    .extra {
-      float: right;
-      margin-top: -1.5px;
-      margin-right: 0;
-      color: @text-color-secondary;
-      font-weight: normal;
-    }
-  }
-  .loadMore {
-    padding: 8px 0;
-    color: @primary-6;
-    text-align: center;
-    cursor: pointer;
-    &.loadedAll {
-      color: rgba(0, 0, 0, 0.25);
-      cursor: unset;
-    }
-  }
-}
-
-.notFound {
-  padding: 73px 0 88px;
-  color: @text-color-secondary;
-  text-align: center;
-  img {
-    display: inline-block;
-    height: 76px;
-    margin-bottom: 16px;
-  }
-}
-
-.bottomBar {
-  height: 46px;
-  color: @text-color;
-  line-height: 46px;
-  text-align: center;
-  border-top: 1px solid @border-color-split;
-  border-radius: 0 0 @border-radius-base @border-radius-base;
-  transition: all 0.3s;
-  div {
-    display: inline-block;
-    width: 50%;
-    cursor: pointer;
-    transition: all 0.3s;
-    user-select: none;
-
-    &:only-child {
-      width: 100%;
-    }
-    &:not(:only-child):last-child {
-      border-left: 1px solid @border-color-split;
-    }
-  }
-}

+ 0 - 112
src/components/NoticeIcon/NoticeList.tsx

@@ -1,112 +0,0 @@
-import { Avatar, List } from 'antd';
-
-import React from 'react';
-import classNames from 'classnames';
-import styles from './NoticeList.less';
-
-export interface NoticeIconTabProps {
-  count?: number;
-  name?: string;
-  showClear?: boolean;
-  showViewMore?: boolean;
-  style?: React.CSSProperties;
-  title: string;
-  tabKey: string;
-  onClick?: (item: API.NoticeIconData) => void;
-  onClear?: () => void;
-  emptyText?: string;
-  clearText?: string;
-  viewMoreText?: string;
-  list: API.NoticeIconData[];
-  onViewMore?: (e: any) => void;
-}
-const NoticeList: React.FC<NoticeIconTabProps> = ({
-  list = [],
-  onClick,
-  onClear,
-  title,
-  onViewMore,
-  emptyText,
-  showClear = true,
-  clearText,
-  viewMoreText,
-  showViewMore = false,
-}) => {
-  if (!list || list.length === 0) {
-    return (
-      <div className={styles.notFound}>
-        <img
-          src="https://gw.alipayobjects.com/zos/rmsportal/sAuJeJzSKbUmHfBQRzmZ.svg"
-          alt="not found"
-        />
-        <div>{emptyText}</div>
-      </div>
-    );
-  }
-  return (
-    <div>
-      <List<API.NoticeIconData>
-        className={styles.list}
-        dataSource={list}
-        renderItem={(item, i) => {
-          const itemCls = classNames(styles.item, {
-            [styles.read]: item.read,
-          });
-          // eslint-disable-next-line no-nested-ternary
-          const leftIcon = item.avatar ? (
-            typeof item.avatar === 'string' ? (
-              <Avatar className={styles.avatar} src={item.avatar} />
-            ) : (
-              <span className={styles.iconElement}>{item.avatar}</span>
-            )
-          ) : null;
-
-          return (
-            <List.Item
-              className={itemCls}
-              key={item.id || i}
-              onClick={() => onClick && onClick(item)}
-            >
-              <List.Item.Meta
-                className={styles.meta}
-                avatar={leftIcon}
-                title={
-                  <div className={styles.title}>
-                    {item.title}
-                    <div className={styles.extra}>{item.extra}</div>
-                  </div>
-                }
-                description={
-                  <div>
-                    <div className={styles.description}>{item.description}</div>
-                    <div className={styles.datetime}>{item.datetime}</div>
-                  </div>
-                }
-              />
-            </List.Item>
-          );
-        }}
-      />
-      <div className={styles.bottomBar}>
-        {showClear ? (
-          <div onClick={onClear}>
-            {clearText} {title}
-          </div>
-        ) : null}
-        {showViewMore ? (
-          <div
-            onClick={(e) => {
-              if (onViewMore) {
-                onViewMore(e);
-              }
-            }}
-          >
-            {viewMoreText}
-          </div>
-        ) : null}
-      </div>
-    </div>
-  );
-};
-
-export default NoticeList;

+ 0 - 35
src/components/NoticeIcon/index.less

@@ -1,35 +0,0 @@
-@import '~antd/es/style/themes/default.less';
-
-.popover {
-  position: relative;
-  width: 336px;
-}
-
-.noticeButton {
-  display: inline-block;
-  cursor: pointer;
-  transition: all 0.3s;
-}
-.icon {
-  padding: 4px;
-  vertical-align: middle;
-}
-
-.badge {
-  font-size: 16px;
-}
-
-.tabs {
-  :global {
-    .ant-tabs-nav-list {
-      margin: auto;
-    }
-
-    .ant-tabs-nav-scroll {
-      text-align: center;
-    }
-    .ant-tabs-bar {
-      margin-bottom: 0;
-    }
-  }
-}

+ 0 - 158
src/components/NoticeIcon/index.tsx

@@ -1,158 +0,0 @@
-import React, { useEffect, useState, useCallback } from 'react';
-import { Tag, message } from 'antd';
-import { groupBy } from 'lodash';
-import moment from 'moment';
-import { useModel } from 'umi';
-import { queryNotices } from '@/services/user';
-
-import NoticeIcon from './NoticeIcon';
-import styles from './index.less';
-
-const getNoticeData = (
-  notices: API.NoticeIconData[],
-): {
-  [key: string]: API.NoticeIconData[];
-} => {
-  if (!notices || notices.length === 0 || !Array.isArray(notices)) {
-    return {};
-  }
-
-  const newNotices = notices.map((notice) => {
-    const newNotice = { ...notice };
-
-    if (newNotice.datetime) {
-      newNotice.datetime = moment(notice.datetime as string).fromNow();
-    }
-
-    if (newNotice.id) {
-      newNotice.key = newNotice.id;
-    }
-
-    if (newNotice.extra && newNotice.status) {
-      const color = {
-        todo: '',
-        processing: 'blue',
-        urgent: 'red',
-        doing: 'gold',
-      }[newNotice.status];
-      newNotice.extra = (
-        <Tag
-          color={color}
-          style={{
-            marginRight: 0,
-          }}
-        >
-          {newNotice.extra}
-        </Tag>
-      );
-    }
-
-    return newNotice;
-  });
-  return groupBy(newNotices, 'type');
-};
-
-const getUnreadData = (noticeData: { [key: string]: API.NoticeIconData[] }) => {
-  const unreadMsg: {
-    [key: string]: number;
-  } = {};
-  Object.keys(noticeData).forEach((key) => {
-    const value = noticeData[key];
-
-    if (!unreadMsg[key]) {
-      unreadMsg[key] = 0;
-    }
-
-    if (Array.isArray(value)) {
-      unreadMsg[key] = value.filter((item) => !item.read).length;
-    }
-  });
-  return unreadMsg;
-};
-
-export interface GlobalHeaderRightProps {
-  fetchingNotices?: boolean;
-  onNoticeVisibleChange?: (visible: boolean) => void;
-  onNoticeClear?: (tabName?: string) => void;
-}
-
-const NoticeIconView = () => {
-  const { initialState } = useModel('@@initialState');
-  const { currentUser } = initialState || {};
-  const [notices, setNotices] = useState<API.NoticeIconData[]>([]);
-
-  useEffect(() => {
-    queryNotices().then(({ data }) => setNotices(data));
-  }, []);
-
-  const noticeData = getNoticeData(notices);
-  const unreadMsg = getUnreadData(noticeData || {});
-
-  const changeReadState = useCallback((id: string) => {
-    setNotices(
-      notices.map((item) => {
-        const notice = { ...item };
-        if (notice.id === id) {
-          notice.read = true;
-        }
-        return notice;
-      }),
-    );
-  }, []);
-
-  const clearReadState = (title: string, key: string) => {
-    setNotices(
-      notices.map((item) => {
-        const notice = { ...item };
-        if (notice.type === key) {
-          notice.read = true;
-        }
-        return notice;
-      }),
-    );
-    message.success(`${'清空了'} ${title}`);
-  };
-
-  return (
-    <NoticeIcon
-      className={styles.action}
-      count={currentUser && currentUser.unreadCount}
-      onItemClick={(item) => {
-        changeReadState(item.id);
-      }}
-      onClear={(title: string, key: string) => clearReadState(title, key)}
-      loading={false}
-      clearText="清空"
-      viewMoreText="查看更多"
-      onViewMore={() => message.info('Click on view more')}
-      clearClose
-    >
-      <NoticeIcon.Tab
-        tabKey="notification"
-        count={unreadMsg.notification}
-        list={noticeData.notification}
-        title="通知"
-        emptyText="你已查看所有通知"
-        showViewMore
-      />
-      <NoticeIcon.Tab
-        tabKey="message"
-        count={unreadMsg.message}
-        list={noticeData.message}
-        title="消息"
-        emptyText="您已读完所有消息"
-        showViewMore
-      />
-      <NoticeIcon.Tab
-        tabKey="event"
-        title="待办"
-        emptyText="你已完成所有待办"
-        count={unreadMsg.event}
-        list={noticeData.event}
-        showViewMore
-      />
-    </NoticeIcon>
-  );
-};
-
-export default NoticeIconView;

+ 0 - 18
src/components/TagSelect/index.less

@@ -1,18 +0,0 @@
-.tag {
-  display: flex;
-  flex-flow: column;
-  .select {
-    margin-bottom: 5px;
-    > label {
-      display: inline-block;
-      text-align: right;
-    }
-  }
-  .tags {
-    width: calc(100%);
-    margin-top: 10px;
-    > span {
-      margin-bottom: 5px;
-    }
-  }
-}

+ 0 - 99
src/components/TagSelect/index.tsx

@@ -1,99 +0,0 @@
-import { Select, Space, Tag, Tooltip } from 'antd'
-import React, { useState, useCallback, useEffect } from 'react'
-import { useModel } from 'umi'
-import { bgColor } from '@/utils/color'
-import style from './index.less'
-import { QuestionCircleFilled } from '@ant-design/icons'
-type Props = {
-    labelWith?: number,
-    change: (v: any) => void,
-    value: {
-        sex: 'all' | 0 | 1 | 2,// 'all'全部,0未知,1男,2女
-        tagIds: any[],
-        tagType: 0 | 1 | 2, // 0:并集,1:交集,2:取反
-    }
-}
-/**
- * 粉丝标签选定
- * @param labelWith label的宽度
- * @param change 回调
- * 
- */
-const TagSelect = React.memo((props: Props) => {
-    const { labelWith, change, value } = props
-    const [selectedTags, setSelectedTags] = useState<any[]>([])
-    const [tagType, setTagType] = useState<number>(0)
-    const { fansTagList } = useModel('useOperating.useFans', model => ({ fansTagList: model.get }))
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const wx = useModel('useOperating.useNews', model => model.state.actionWX)
-
-    /**
-     * 标签选择
-     */
-    const handleChange = useCallback((tag: number, checked: any) => {
-        const nextSelectedTags = checked ? [...selectedTags, tag] : selectedTags.filter(t => t !== tag);
-        setSelectedTags(nextSelectedTags);
-        change({ tagType, tagIds: nextSelectedTags })
-    }, [selectedTags, tagType])
-    /**
-     * 标签类型
-     */
-    const handleTagType = useCallback((tagType: number) => {
-        setTagType(tagType)
-        change({ tagType, tagIds: selectedTags })
-    }, [selectedTags])
-    /**
-     * 获取粉丝列表
-    */
-    useEffect(() => {
-        if (actionWX || wx) {
-            fansTagList.run({ mpId: actionWX?.id || wx?.id })
-        }
-    }, [actionWX, wx])
-    /**
-     * 回填
-     */
-    useEffect(() => {
-        setTagType(value.tagType)
-        setSelectedTags(value.tagIds && Array.isArray(value.tagIds) ? value.tagIds : [value.tagIds])
-    }, [value])
-   
-    return <div className={style.tag}>
-        <div className={style.select}>
-            <label style={{ width: labelWith }}>标签:</label>
-            <Space>
-                <Select style={{ width: 100 }} value={tagType} onChange={handleTagType}>
-                    <Select.Option value={0}>并集</Select.Option>
-                    <Select.Option value={1}>交集</Select.Option>
-                    <Select.Option value={2}>反向</Select.Option>
-                </Select>
-                <Tooltip
-                    placement="right"
-                    title={
-                        <>
-                            <div>【并集】:包含A标签或者包含B标签的粉丝;</div>
-                            <div>【交集】:同时包含A标签和B标签的粉丝;</div>
-                            <div>【反向】:剔除包含所选标签的粉丝。</div>
-                        </>
-                    }>
-                    <QuestionCircleFilled />
-                </Tooltip>
-            </Space>
-        </div>
-        <div className={style.tags} style={{ paddingLeft: labelWith }}>
-            {
-                fansTagList?.data?.map((tag: { id: number, moId: number, name: string }, index: number) => {
-                    return <Tag.CheckableTag
-                        checked={selectedTags.indexOf(tag?.id) > -1}
-                        onChange={checked => handleChange(tag?.id, checked)}
-                        key={tag?.id}
-                        style={selectedTags.indexOf(tag?.id) > -1 ? { background: bgColor[index] } : { background: '#f9f9f9' }}
-                    >
-                        {tag.name}
-                    </Tag.CheckableTag>
-                })
-            }
-        </div>
-    </div>
-})
-export default TagSelect

+ 0 - 22
src/components/UpImg/index.less

@@ -1,22 +0,0 @@
-.upimgBox {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  left: 0;
-  top: 0;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  .xj {
-    width: 45px;
-    height: 45px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-    opacity: 0;
-    background-color: rgba(0, 0, 0, .6);
-    &:hover {
-      opacity: 1;
-    }
-  }
-}

+ 0 - 62
src/components/UpImg/index.tsx

@@ -1,62 +0,0 @@
-import React, { useCallback, useState ,useEffect} from 'react'
-import { Upload } from 'antd';
-import ImgCrop from 'antd-img-crop';
-import { RcFile } from 'antd/lib/upload';
-import { CameraOutlined } from '@ant-design/icons';
-import style from './index.less'
-/**上传图片单独组件*/
-type Props={
-    callbakc:(fileData:{file:File,fileUrl:any})=>void
-}
-function UpImg(props:Props) {
-    const [fileList, setFileList] = useState<any[]>([])
-    const [previewVisible, setPreviewVisible] = useState<boolean>(false)
-    const [fileUrl, setFileUrl] = useState<any>('')
-    const [file, setFile] = useState<any>({})
-     //文件上传获取
-     const fileChanage = useCallback((e: any) => {
-        try {
-            let file = e?.target?.files || e
-            if (file) {
-                setFile(file[0] || file)
-                let reader = new FileReader()
-                reader.readAsDataURL(file)
-                reader.onload=function(e){
-                    setFileUrl(this.result)
-                }
-            }
-        } catch (err) {
-            console.log(err)
-        }
-    }, [])
-    //回调
-    useEffect(()=>{
-        if(fileUrl){
-            props.callbakc({file,fileUrl})
-        }
-    },[file,fileUrl])
-    return <div className={style.upimgBox}>
-        <ImgCrop rotate>
-            <Upload
-                // listType="picture-card"
-                accept='image/gif,image/jpeg,image/png,image/jpg'
-                beforeUpload={function (file: RcFile) {
-                    fileChanage(file)
-                    return false
-                }}
-                // fileList={fileList}
-                showUploadList={false}
-                onChange={(newFileList: any) => {
-                    setFileList([...newFileList.fileList])
-                }}
-                onPreview={(file: any) => {
-                    setPreviewVisible(true)
-                    setFileUrl(file.thumbUrl)
-                }}
-            >
-                <div className={style.xj}><CameraOutlined style={{color:'#1890ff',fontSize:20}}/></div>
-            </Upload>
-        </ImgCrop>
-    </div>
-}
-export default UpImg

+ 0 - 31
src/components/WeChatImgCard/index.less

@@ -1,31 +0,0 @@
-.add {
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  flex-flow: column;
-  height: 100%;
-}
-.pos {
-  position: absolute;
-  top: 0;
-  left: 0;
-  height: 100%;
-  width: 100%;
-  opacity: 0;
-  color: #fff;
-}
-.pos:hover {
-  opacity: 1;
-  background: rgba(0, 0, 0, 0.6);
-}
-.row_style{
-    width: 100%;
-    >div:nth-child(1){
-        width: 120px;
-        text-align: right;
-    }
-    >div:nth-child(2){
-        width: 100%;
-    }
-    
-}

+ 0 - 183
src/components/WeChatImgCard/index.tsx

@@ -1,183 +0,0 @@
-import { Col, Input, Modal, Radio, Row, Space } from 'antd'
-import React, { useCallback, useEffect, useState } from 'react'
-import SmMaterialModal from '@/components/MaterialModal/smModalBox';
-import style from './index.less'
-import { PlusOutlined } from '@ant-design/icons';
-interface Props {
-    visible: boolean,
-    onCancel: () => void,
-    onOk: (v: any) => void,
-    title: string,
-    weCathType: 'img' | 'card',
-    defaultData?: { appid: string, appPath: string, cardTitle: string, img: string, imgInfo: any },
-    isOnUserId?: boolean
-}
-function WeChatImgCard(props: Props) {
-    const { visible = false, title, onCancel, weCathType, onOk, isOnUserId = true } = props
-    const [imgVisible, setImgVisible] = useState<boolean>(false)
-    const [appid, setAppid] = useState<string>('')
-    const [href, setHref] = useState<string>('')
-    const [appPath, setAppPath] = useState<string>('')
-    const [img, setImg] = useState<string>('')
-    const [cardTitle, setCardTitle] = useState<string>('')
-    const [imgInfo, setImgInfo] = useState<any>(null)
-    const [userId, setUserId] = useState<any>(0)//小程序路径插入userID
-    /**确定 */
-    const handleOk = useCallback(() => {
-        let newAp = appPath
-        if (!!userId) {
-            if (userId === 1) {
-                newAp = !newAp.includes('#USER_ID#') ? newAp.replace('#QC_USER_ID#', '') + '#USER_ID#' : newAp
-            }
-            if (userId === 2) {
-                newAp = !newAp.includes('#QC_USER_ID#') ? newAp.replace('#USER_ID#', '') + '#QC_USER_ID#' : newAp
-            }
-        } else {
-            newAp = newAp.includes('#USER_ID#') || newAp.includes('#QC_USER_ID#') ? newAp?.replace(/(#USER_ID#)|(#QC_USER_ID#)/g, '') : newAp
-        }
-        let obj: any = isOnUserId ? {
-            appid,
-            appPath: newAp,
-            img,
-            imgInfo
-        } : {
-                appid,
-                appPath,
-                img,
-                imgInfo
-            }
-        if (weCathType === 'img') {
-            obj = { ...obj, href }
-        } else {
-            obj = { ...obj, cardTitle }
-        }
-        if (!obj?.imgInfo) {
-            obj.imgInfo = props?.defaultData?.imgInfo
-        }
-        onOk(obj)
-    }, [appid, href, appPath, img, weCathType, cardTitle, imgInfo, userId, isOnUserId])
-    /**回填 */
-    useEffect(() => {
-        if (props?.defaultData) {
-            setAppPath(props?.defaultData?.appPath)
-            setAppid(props?.defaultData?.appid)
-            setCardTitle(props?.defaultData?.cardTitle)
-            setImg(props?.defaultData?.img)
-            let path = props?.defaultData?.appPath
-            setUserId(path.includes('#QC_USER_ID#') ? 2 : path.includes('#USER_ID#') ? 1 : 0)
-        }
-    }, [props?.defaultData])
-    return <div>
-        <Modal
-            visible={visible}
-            title={title}
-            onCancel={onCancel}
-            onOk={handleOk}
-            maskClosable={false}
-        >
-            <Row gutter={[10, 20]}>
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>AppId:</span>
-                        <Input
-                            placeholder={'填写小程序AppID,跳转小程序需与当前公众号绑定关联关系'}
-                            size='small'
-                            style={{ width: '100%' }}
-                            value={appid}
-                            onChange={(event: React.ChangeEvent<HTMLInputElement>) => { setAppid(event.target.value) }}
-                        />
-                    </Space>
-                </Col>
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>小程序路径:</span>
-                        <Input
-                            placeholder={'填写小程序路径,例如:pages/index'}
-                            size='small'
-                            style={{ width: '100%' }}
-                            value={appPath}
-                            onChange={(event: React.ChangeEvent<HTMLInputElement>) => { setAppPath(event.target.value) }}
-                        />
-                    </Space>
-                </Col>
-                {isOnUserId && <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>插入用户:</span>
-                        <Radio.Group onChange={(e: any) => { setUserId(Number(e.target.value)) }} value={userId} >
-                            <Radio value={1}>普通用户</Radio>
-                            <Radio value={2}>趣程用户</Radio>
-                            <Radio value={0}>否</Radio>
-                        </Radio.Group>
-                    </Space>
-                </Col>}
-                <Col span={24}>
-                    {
-                        weCathType === 'img' ?
-                            <Space className={style.row_style}>
-                                <span>备用网页:</span>
-                                <Input
-                                    placeholder={'备用网页,以http://或https://开头'}
-                                    size='small'
-                                    style={{ width: '100%' }}
-                                    value={href}
-                                    onChange={(event: React.ChangeEvent<HTMLInputElement>) => { setHref(event.target.value) }}
-                                />
-                            </Space> :
-                            <Space className={style.row_style}>
-                                <span>卡片标题:</span>
-                                <Input
-                                    placeholder={'请填写卡片标题'}
-                                    size='small'
-                                    style={{ width: '100%' }}
-                                    value={cardTitle}
-                                    onChange={(event: React.ChangeEvent<HTMLInputElement>) => { setCardTitle(event.target.value) }}
-                                />
-                            </Space>
-                    }
-
-                </Col>
-                <Col span={24}>
-                    <Space className={style.row_style}>
-                        <span>选择图片:</span>
-                        <div onClick={() => setImgVisible(true)} style={{ width: '100%', height: 200, border: '1px dashed #d8d8d8', position: 'relative', cursor: 'pointer' }}>
-                            {
-                                img ?
-                                    <img src={img} style={{ width: '100%', height: '100%', objectFit: 'cover' }} />
-                                    :
-                                    <span className={`${style.add} ${img ? style.pos : ''} `}>
-                                        <PlusOutlined style={{ fontSize: 32 }} />
-                                    </span>
-                            }
-                          {weCathType !== 'img' &&  <strong style={{color:'red'}}>注:图片尺寸1080 * 864,不然无法创建成功!</strong>}
-                        </div>
-                    </Space>
-                    {
-                        imgVisible && <SmMaterialModal
-                            visible={imgVisible}
-                            onCancel={() => setImgVisible(false)}
-                            title='选择图片'
-                            onOk={(props: any) => {
-                                console.log('props===>', props)
-                                let obj: any = {}
-                                if (props?.mediaId) {//微信素材
-                                    obj.wxMediaId = props?.id
-                                    obj.thumbUrl = props?.url
-                                } else {
-                                    obj.thumbUrl = props?.url
-                                }
-                                setImg(obj?.thumbUrl)
-                                setImgInfo(props)
-                                setImgVisible(false)
-                            }}
-                            mediaType={1}
-                            isShowWx={false}
-                            isAllData
-                            noFile={false}
-                        />
-                    }
-                </Col>
-            </Row>
-        </Modal>
-    </div>
-}
-export default WeChatImgCard

+ 0 - 262
src/components/WxDetailsBox/index.less

@@ -1,262 +0,0 @@
-.box {
-  height: 100%;
-  border: 1px solid rgb(224, 224, 224);
-  .top {
-    background: url('https://zx-oss-dev.oss-cn-hangzhou.aliyuncs.com/file/23B6D0D2A21E43AD9C46EB159992C5F5.png') no-repeat;
-    background-size: 100%;
-    height: 52px;
-    border-bottom: 1px solid rgb(224, 224, 224);
-  }
-  .content {
-    height: calc(100% - 92px);
-    background-color: #f0f0f0;
-    padding: 15px;
-    overflow-y: scroll;
-    .img_ScwxBox {
-      display: flex;
-      justify-content: space-between;
-      margin-bottom: 5px;
-      padding: 10px;
-      position: relative;
-      img {
-        width: 56px;
-        height: 56px;
-        border-radius: 3px;
-        object-fit: cover;
-      }
-      > span {
-        width: 220px;
-        border-bottom: 1px solid #efefef;
-        padding: 0 10px;
-        > span {
-          text-overflow: -o-ellipsis-lastline;
-          overflow: hidden;
-          text-overflow: ellipsis;
-          display: -webkit-box;
-          -webkit-line-clamp: 2;
-          line-clamp: 2;
-          -webkit-box-orient: vertical;
-          max-height: 45px;
-        }
-      }
-      &:last-child {
-        span {
-          border-bottom: 0;
-        }
-      }
-    }
-    .box_card {
-      background-color: #fff;
-      > div {
-        &:nth-child(1) {
-          padding: 0;
-        }
-      }
-
-      .img_ScwxBox:first-child {
-        flex-flow: column;
-        position: relative;
-        img {
-          width: 100%;
-          height: 95px;
-          order: 1;
-        }
-        > span {
-          order: 2;
-          border: 0;
-          left: 0;
-          bottom: 0;
-          background-image: linear-gradient(-180deg, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.8) 100%);
-          color: #fff;
-          width: 100%;
-          z-index: 33;
-          line-height: 24px;
-          position: absolute;
-        }
-      }
-      .one {
-        order: 2;
-        padding: 10px;
-        > p {
-          margin-bottom: 0;
-          &:last-child {
-            font-size: 14px;
-            line-height: 22px;
-            color: #999999;
-          }
-          &:first-child {
-            font-size: 16px;
-            line-height: 16px;
-            color: #1a1a1a;
-            margin-bottom: 10px;
-          }
-        }
-      }
-    }
-    .image {
-      > img {
-        &:first-child {
-          width: 36px;
-          height: 36px;
-          float: left;
-          margin-right: 10px;
-        }
-        &:last-child {
-          border-radius: 4px;
-          width: 150px;
-          float: left;
-        }
-      }
-    }
-    .mpvideo {
-      background-color: #fff;
-      img {
-        width: 100%;
-        height: 127px;
-        object-fit: cover;
-      }
-      p {
-        padding: 16px;
-        margin-bottom: 0;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        display: -webkit-box;
-        -webkit-line-clamp: 2;
-        -webkit-box-orient: vertical;
-      }
-    }
-    .text {
-      display: flex;
-      justify-content: flex-start;
-      > img {
-        width: 36px;
-        height: 36px;
-        margin-right: 10px;
-      }
-      > p {
-        padding: 16px;
-        background-color: #aed581;
-        border-radius: 4px;
-        width: 87%;
-      }
-    }
-    .temCon {
-      background: #fff;
-      padding: 10px;
-      border-radius: 3px;
-      font-size: 12px;
-      .title {
-        font-size: 12px;
-        color: #000;
-      }
-      .rq {
-        font-size: 12px;
-        color: #c7c7cb;
-        margin-bottom: 8px;
-      }
-    }
-    .voice {
-      background: #ffffff;
-      border: 1px solid #e9e9e9;
-      border-radius: 4px;
-      width: 100%;
-      padding: 37px 16px;
-      display: flex;
-      flex-flow: row;
-      justify-content: space-between;
-      p {
-        width: 80%;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        display: -webkit-box;
-        -webkit-line-clamp: 3;
-        -webkit-box-orient: vertical;
-      }
-      img {
-        width: 32px;
-        height: 32px;
-        float: right;
-        margin-top: 4px;
-      }
-    }
-  }
-}
-.details_header {
-  display: flex;
-  justify-content: space-between;
-}
-.btn {
-  margin-bottom: 20px;
-}
-.action {
-  position: relative;
-  margin: 0 auto;
-  // text-align: center;
-  color: #4abe84;
-  background-color: #fff;
-  box-shadow: 0px 2px 7px 0px rgba(85, 110, 97, 0.35);
-  border-radius: 5px;
-  border: 1px solid rgba(74, 190, 132, 1);
-  overflow: hidden;
-  &::before {
-    content: '';
-    position: absolute;
-    right: 0;
-    bottom: 0;
-    border: 12px solid #4abe84;
-    border-top-color: transparent;
-    border-left-color: transparent;
-    z-index: 34;
-  }
-  &::after {
-    content: '';
-    width: 5px;
-    height: 10px;
-    position: absolute;
-    right: 5px;
-    bottom: 3px;
-    border: 2px solid #fff;
-    border-top-color: transparent;
-    border-left-color: transparent;
-    transform: rotate(45deg);
-    z-index: 34;
-  }
-}
-.deleted {
-  width: 100%;
-  height: 100%;
-  position: absolute;
-  left: 0;
-  top: 0;
-  background: rgba(0, 0, 0, 0.5);
-  z-index: 999;
-  display: flex;
-  justify-content: center;
-  align-items: center;
-  color: red;
-}
-.miniprogrampage {
-  display: flex;
-  flex-flow: column;
-  width: 300px;
-  background-color: #ece7e7;
-  border-radius: 8px;
-  padding: 20px 10px 15px;
-  > span:nth-child(1) {
-    margin-bottom: 10px;
-  }
-  > span:nth-child(3) {
-    margin-top: 10px;
-    &::before {
-      content: '';
-      display: inline-block;
-      vertical-align: middle;
-      width: 18px;
-      height: 18px;
-      margin-top: -0.2em;
-      margin-right: 4px;
-      background-size: cover;
-      background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 18 18'%3E %3Cpath fill='%236467F0' fill-rule='evenodd' d='M12.753 9.743l-.177.003c-.535 0-.846-.393-.645-.845a1.16 1.16 0 0 1 .816-.651c.981-.237 1.648-1.004 1.648-1.897 0-1.081-1.032-1.963-2.322-1.963s-2.322.882-2.322 1.963v5.392c0 1.899-1.698 3.428-3.788 3.428s-3.788-1.53-3.788-3.428c0-1.665 1.314-3.087 3.105-3.357h.144c.405 0 .697.243.697.589a.64.64 0 0 1-.008.122.464.464 0 0 1-.044.134c-.13.301-.46.562-.816.651-.974.236-1.648.998-1.648 1.86 0 1.082 1.032 1.964 2.322 1.964s2.322-.882 2.322-1.963V6.353c0-1.899 1.698-3.428 3.788-3.428s3.788 1.53 3.788 3.428c0 1.674-1.283 3.079-3.072 3.39z'/%3E%3C/svg%3E");
-    }
-  }
-}

+ 0 - 378
src/components/WxDetailsBox/index.tsx

@@ -1,378 +0,0 @@
-import { Button, Checkbox, Input, Popconfirm, Space } from 'antd'
-import React, { useCallback, useEffect, useMemo, useReducer, useState } from 'react'
-import { useModel } from 'umi'
-import moment from 'moment'
-import style from './index.less'
-import filePng from '../../../public/file.png'
-
-/**
- * 模板消息 模板预览
- * 高级群发 新增预览 编辑预览 详情预览
- */
-
-type Props = {
-    data: any,
-    del?: boolean,
-    newsDispatch?: (type: any) => void,
-    isShowEdit?: boolean,
-    showDrawer?: (props?: any) => void,//图文素材弹窗事件
-    isShowEditBtn?: boolean,//是否开启编辑内容按钮
-    actionId?: number,
-    linsFn?: (params: any) => void
-}
-interface State {
-    mediaIds: number[],
-    checked: boolean,
-    indeterminate: boolean,
-    links?: string[],//当前图文中的原文链接数组
-    linksSR?: any
-}
-interface Action {
-    type: 'pushData' | 'checked' | 'delData' | 'returnData' | 'setLinks' | 'setLinksSR',
-    params?: any
-}
-function reducer(state: State, action: Action) {
-    let { type, params } = action
-    switch (type) {
-        case 'pushData':
-            return { ...state, mediaIds: [...state?.mediaIds, ...params?.mediaIds] }
-        case 'delData':
-            let mediaIds = [...state?.mediaIds]
-            mediaIds = mediaIds.filter((mediaId: number) => {
-                if (params?.mediaIds?.every((id: number) => id !== mediaId)) {
-                    return mediaId
-                }
-                return
-            })
-            return { ...state, mediaIds }
-        case 'returnData':
-            return { ...state, mediaIds: params?.mediaIds }
-        case 'checked':
-            return { ...state, checked: params?.checked, indeterminate: params?.indeterminate }
-        case 'setLinks':
-            console.log('setLinks')
-            return { ...state, links: params?.links }
-        case 'setLinksSR':
-            let newlinksSR = { ...state.linksSR }
-            Object.keys(params?.links).forEach(key => {
-                newlinksSR[key] = params?.links[key]
-            })
-            return { ...state, linksSR: newlinksSR }
-        default:
-            return { ...state }
-    }
-}
-const initState = {
-    mediaIds: [],
-    checked: false,
-    indeterminate: false,
-    links: [],
-    linksSR: {}
-}
-const WxDetailsBox = React.memo((props: Props) => {
-    const { data, del = false, newsDispatch, isShowEdit = false, showDrawer, isShowEditBtn = true, actionId, linsFn } = props
-    const [state, dispatch] = useReducer(reducer, initState)
-    const { mediaIds, checked, indeterminate, links, linksSR } = state
-    const [isEdit, setIsEdit] = useState<boolean>(false)
-    const num = useMemo(() => { return data?.content?.news?.length }, [data])
-    const { dispatch: dDispatch } = useModel('useOperating.useMaterialDrawer')//素材内容管理器
-    // const { getWXInfo } = useModel('useOperating.useMaterialContent')//获取微信素材详情
-    // const { get } = useModel('useOperating.useBdMediaPup')//获取本地素材详情
-    const { delMsgGroup, getDetail } = useModel('useOperating.useNews', model => ({ delMsgGroup: model.delMsgGroup, getDetail: model.getDetail }))
-    /**手动点击添加 */
-    const handleAdd = useCallback((mediaId: number) => {
-        dispatch({ type: 'pushData', params: { mediaIds: [mediaId] } })
-    }, [num])
-    /**手动点击删除 */
-    const handleDel = useCallback((mediaId: number) => {
-        dispatch({ type: 'delData', params: { mediaIds: [mediaId] } })
-    }, [num])
-    /**反选 */
-    const handelReturn = useCallback(() => {
-        let articles = data?.content?.news
-        let newMediaIds = articles?.filter((item: { id: number, deleted: boolean }) => {
-            if (mediaIds.every((mediaId: number) => mediaId !== item.id) && !item.deleted) {
-                return item.id
-            }
-            return
-        })
-        let newArr: number[] = []
-        newMediaIds.forEach((item: { id: number }) => {
-            newArr.push(item.id)
-        })
-        dispatch({ type: 'returnData', params: { mediaIds: newArr } })
-    }, [data, mediaIds])
-    /**全选 */
-    const handleAll = useCallback(() => {
-        if (mediaIds?.length === num) {
-            dispatch({ type: 'returnData', params: { mediaIds: [] } })
-        } else {
-            let newArr: number[] = []
-            data?.content?.news?.forEach((item: { id: number, deleted: boolean }) => {
-                if (!item.deleted) {
-                    newArr.push(item.id)
-                }
-            })
-            dispatch({ type: 'returnData', params: { mediaIds: newArr } })
-        }
-
-    }, [data, mediaIds, num])
-    /**删除 */
-    const deleteNews = useCallback(() => {
-        if (mediaIds?.length > 0) {
-            delMsgGroup.run({ id: data.id, list: mediaIds }).then((res) => {
-                if (res) {
-                    getDetail.refresh().then((res: any) => {
-                        let { mediaInfo, msgType, mediaId } = res
-                        let { name, url, title, } = mediaInfo
-                        let theEdit = {
-                            url: url,
-                            title: name || title,
-                            msgType,
-                            mediaId,
-                            content: mediaInfo,//NEWS使用
-                        }
-                        if (res) {
-                            console.log(res)
-                            newsDispatch && newsDispatch({ type: 'setDefaultData', params: { defaultData: { ...res, theEdit } } })
-                            dispatch({ type: 'pushData', params: { mediaIds: [] } })
-                            dispatch({ type: 'checked', params: { checked: false, indeterminate: false } })
-                        }
-                    })
-                }
-            })
-        }
-    }, [mediaIds, data])
-    useEffect(() => {
-        let len = mediaIds?.length
-        if (len < num && len !== 0) {
-            dispatch({ type: 'checked', params: { checked: true, indeterminate: true } })
-        }
-        if (len === num) {
-            dispatch({ type: 'checked', params: { checked: true, indeterminate: false } })
-        }
-        if (len === 0) {
-            dispatch({ type: 'checked', params: { checked: false, indeterminate: false } })
-        }
-    }, [mediaIds, num])
-    //编辑链接
-    const editLinks = useCallback(() => {
-        if (data && data?.msgType === 'mpnews') {
-            let links: string[] = []
-            data?.content?.news?.forEach((item: { contentSourceUrl: string }) => {
-                links.push(item?.contentSourceUrl || '')
-            })
-            dispatch({ type: 'setLinks', params: { links } })
-        }
-    }, [data])
-    //编辑内容
-    const editContent = useCallback(() => {
-        dDispatch({ type: 'actionData', params: { data: { dataArr: data?.content?.news, actionId: 1 } } })//设置编辑器的内容
-        showDrawer && showDrawer({ isEdit: true, editId: data?.id })//开启新建素材弹窗
-    }, [showDrawer, data])
-    //保存链接
-    const saveLink = useCallback(() => {
-        if (!actionId) {
-            //替换文章中的链接
-            let news = data?.content?.news?.map((item: { contentSourceUrl: string }, index: number) => {
-                if (item.contentSourceUrl !== links[index]) {
-                    item.contentSourceUrl = links[index]
-                }
-                return item
-            })
-            setIsEdit(false)
-        }else{
-            setIsEdit(false)
-        }
-    }, [links, data, actionId, linksSR])
-    //默认全选
-    useEffect(() => {
-        handleAll()
-    }, [])
-    const Box = useCallback(() => {
-        switch (data?.msgType) {
-            case 'mpnews':
-                return <>
-                    {
-                        del && <div className={style.details_header}>
-                            <Space className={style.btn}>
-                                <Checkbox indeterminate={indeterminate} onChange={handleAll} checked={checked}>全选</Checkbox>
-                                <Button onClick={handelReturn} type='dashed' size='small'>反选</Button>
-                            </Space>
-                            <Popconfirm
-                                title='确定要删除吗?'
-                                onConfirm={deleteNews}
-                                placement='left'
-                            >
-                                <Button type='primary' size='small'>删除</Button>
-                            </Popconfirm>
-
-                        </div>
-                    }
-                    <div className={style.box_card}>
-                        {
-                            data?.content?.news?.map((list: any, index: number) => {
-                                let isAction = mediaIds?.length > 0 ? mediaIds.some((mediaId: number) => mediaId === list.id) : false
-                                let isOne = data?.content?.news?.length === 1
-                                // if (list.deleted) {
-                                return (
-                                    <div
-                                        className={`${style.img_ScwxBox} ${del && isAction ? style.action : ''} `}
-                                        key={(list.thumbMediaId || list.sysMediaId || list.id) + index + (list.menuId || '')}
-                                        onClick={() => {
-                                            if (!list.deleted) {
-                                                if (isAction) {
-                                                    handleDel(list.id)
-                                                } else {
-                                                    handleAdd(list.id)
-                                                }
-                                            }
-                                        }
-                                        }>
-                                        {!isOne && <span><span>{list.title}</span></span>}
-                                        <img src={list?.thumbMediaUrl || list?.thumbUrl} />
-                                        {isOne && <div className={style.one}>
-                                            <p>{list.title}</p>
-                                            <p>{list.digest}</p>
-                                        </div>}
-                                        {
-                                            list.deleted && <div className={style.deleted}>已删除</div>
-                                        }
-                                    </div>
-                                )
-                                // }
-                                return
-                            })
-                        }
-                    </div>
-                </>
-            case 'news':
-                return <div className={style.box_card}>
-                    {
-                        data?.newsList?.map((list: any, index: number) => {
-                            let isOne = data?.newsList?.length === 1
-                            return <div className={`${style.img_ScwxBox} `} key={index}>
-                                {!isOne && <span>{list?.title}</span>}
-                                <img src={list?.knewsThumbUrl || (list?.knewsThumbId ? filePng : 'https://s.weituibao.com/static/1552098829922/bigfm.png')} />
-                                {isOne && <div className={style.one}>
-                                    <p>{list?.title}</p>
-                                    <p>{list?.description}</p>
-                                </div>}
-                            </div>
-                        })
-                    }
-                </div>
-            case 'mpvideo':
-                return <div className={style.mpvideo}>
-                    <img src={require('../../../public/image/video.png')} />
-                    <p>{data?.name || data?.title}</p>
-                </div>
-            case 'video':
-                return <div className={style.mpvideo}>
-                    <img src={require('../../../public/image/video.png')} />
-                    <p>{data?.name || data?.title}</p>
-                </div>
-            case 'voice':
-                return <div className={style.voice}>
-                    <p>{data?.name || data?.title}</p>
-                    <img src={require('../../../public/image/voice.png')} />
-                </div>
-            case 'image':
-                return <div className={style.image}>
-                    <img src='https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png' />
-                    <img src={data?.url || data?.thumbUrl || data?.imageUrl} />
-                </div>
-            case 'text':
-                let str = ''
-                if (Array.isArray(data?.textContent)) {
-                    data?.textContent?.forEach((key: string, index: number) => {
-                        // if (key) {
-                        str += `${key}${index !== data?.textContent.length - 1 ? '<br/>' : ''}`
-                        // }
-                    })
-                } else {
-                    str = data?.textContent
-                }
-                return <div className={style.text}>
-                    <img src='https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png' />
-                    <p dangerouslySetInnerHTML={{ __html: str }}></p>
-                </div>
-            case 'tem':
-                let { title, dataTem } = data?.data
-                let temStr = dataTem?.replace(/\n/g, '<br>')
-                return <>
-                    {
-                        dataTem ? <div className={style.temCon}>
-                            <div className={style.title}>{title}</div>
-                            <div className={style.rq}>{moment(new Date()).format('MM月DD日')}</div>
-                            <p dangerouslySetInnerHTML={{ __html: temStr }}></p>
-                        </div> :
-                            <div></div>
-                    }
-                </>
-            case 'miniprogrampage':
-                return <div className={style.miniprogrampage}>
-                    <span className={style.miniprogrampage_title}>{data?.title}</span>
-                    <img className={style.miniprogrampage_img} src={data?.imageUrl} />
-                    <span className={style.miniprogrampage_bottom}>小程序</span>
-                </div>
-        }
-        return <></>
-    }, [data, del, mediaIds, indeterminate, checked])
-    return <div className={style.box}>
-        <div className={style.top} />
-        <div className={style.content} >
-            {
-                isEdit ? actionId ? <div>
-                    {//存在actionID表示私人定制多选批量
-                        (linksSR[actionId] || links)?.map((url: string, index: number) => {//存在编辑过的链接使用编辑过的,没有就用默认
-                            return <div key={index} style={{ marginBottom: 15 }}>
-                                <span>第{index + 1}篇:</span>
-                                <Input.TextArea value={url} onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
-                                    let newLinks = JSON.parse(JSON.stringify(linksSR[actionId] || links))
-                                    newLinks[index] = event.target.value
-                                    let newlinksSR = { ...state.linksSR }
-                                    newlinksSR[actionId] = newLinks
-                                    console.log()
-                                    linsFn && linsFn(newlinksSR)
-                                    dispatch({ type: 'setLinksSR', params: { links: { [actionId]: newLinks } } })
-                                }} disabled={!isShowEdit}/>
-                            </div>
-                        })
-                    }
-                </div> : <div>
-                    {//常规操作没有批量
-                        links?.map((url: string, index: number) => {
-                            return <div key={index} style={{ marginBottom: 15 }}>
-                                <span>第{index + 1}篇:</span>
-                                <Input.TextArea value={url} onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
-                                    let newLinks = JSON.parse(JSON.stringify(links))
-                                    newLinks[index] = event.target.value
-                                    console.log(3333, event.target.value)
-                                    dispatch({ type: 'setLinks', params: { links: newLinks } })
-                                }} disabled={!isShowEdit}/>
-                            </div>
-                        })
-                    }
-                </div> : <Box />
-            }
-            {
-                data?.msgType === 'mpnews'  && <Space style={{ width: '100%', display: 'flex', justifyContent: 'center' }}>
-                    {
-                        isEdit ?
-                            <>
-                                {isShowEdit && <Button onClick={saveLink}>保存</Button>}
-                                <Button onClick={() => { setIsEdit(false) }}>取消</Button>
-                            </>
-                            :
-                            <>
-                                <Button onClick={() => { setIsEdit(true); editLinks() }}>{isShowEdit ? '编辑链接':'查看连接'}</Button>
-                                {isShowEditBtn && <Button onClick={editContent}>编辑内容</Button>}
-                            </>
-                    }
-                </Space>
-            }
-        </div>
-    </div>
-})
-export default WxDetailsBox

+ 0 - 35
src/components/WxSelect/index.tsx

@@ -1,35 +0,0 @@
-import { Select } from 'antd'
-import React from 'react'
-import { useModel } from 'umi'
-//当前账号所有公众号筛选Select
-function WxSelect(props: { mode?: 1 | 2, isAll?: boolean }) {
-    const { mode = 2,isAll = true } = props
-    const { state: { filterWxs, selectWx }, dispatch } = useModel('useOperating.useWxGroupList')
-    const { getList } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    return <Select
-        showSearch
-        style={{ width: '100%', marginTop: 15 }}
-        placeholder="关联公众号"
-        optionFilterProp="children"
-        onChange={(value) => {
-            dispatch({ type: 'selectWx', params: { selectWx: value } });
-            if (mode === 1) {
-                getList({mpId:value})
-            }
-        }}
-        mode={mode === 1 ? undefined : 'multiple'}
-        allowClear
-        filterOption={(input, option) =>
-            option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-        }
-        value={selectWx}
-    >
-        {
-            filterWxs?.map((item: any) => {
-                // console.log(item)
-                return <Select.Option value={item?.id} key={item?.id}>{item?.nickName}</Select.Option>
-            })
-        }
-    </Select>
-}
-export default WxSelect

+ 0 - 96
src/models/useOperating/useAccountyyb.ts

@@ -1,96 +0,0 @@
-import { useAjax } from '@/Hook/useAjax'
-import {
-    getGdtAccountApi, gdtAccountProps, addGdtAccountApi, addGdtAccointProps, editGdtAccountApi, editGdtAccountProps,
-    delGdtAccountApi, queryApi, checkGdtAccountGdtApi, checkGdtAccountProps, getQuickAppAccountApi, QuickAppAccout, addQuickAppAccountApi,
-    AddQuickAppAccount, editQuickAppAccountApi, EditQuickAppAccount, delQuickAppAccountApi, checkQuickAppAccountApi, CheckQuickAppAccount,
-    getKyyListApi, KyyListProps, getResourceOfUserApi, getGdtChangeRecordApi, getAccountChangeRecordApi, editAccountChangeRecordApi, editGdtChangeRecordApi
-} from '@/services/operating/accountyyb'
-
-import {
-    businessGroup, getBookAll, getPeriodAll, allBook, listByPlatform, lins, resourceChangeRecord, insertCutRecordApi, insetCutProps,
-    editCutRecordApi, editCutProps, delCutRecordApi
-} from "@/services/operating/book"
-import { getAllUser } from "@/services/operating/account"
-import { useEffect, useState } from 'react'
-
-export default function useAccountyyb() {
-    const getGdtAccount = useAjax((params: gdtAccountProps) => getGdtAccountApi(params), { debounceInterval: 200 })
-    const addGdtAccount = useAjax((params: addGdtAccointProps) => addGdtAccountApi(params), { msgNmae: '添加' })
-    const editGdtAccount = useAjax((params: editGdtAccountProps) => editGdtAccountApi(params), { msgNmae: '编辑' })
-    const delGdtAccount = useAjax((params: { gdtAccountIds: string }) => delGdtAccountApi(params), { msgNmae: '删除' })
-    const checkGdtAccountGdt = useAjax((params: checkGdtAccountProps) => checkGdtAccountGdtApi(params), { msgNmae: '切号' })
-    const getGdtChangeRecord = useAjax((params: { gdtAccountId: number, pageNum: number, pageSize: number }) => getGdtChangeRecordApi(params), { debounceInterval: 200 })
-    const editGdtChangeRecord = useAjax((params: { recordId: number, putResourceId: number, beginTime: string, endTime: string }) => editGdtChangeRecordApi(params), { msgNmae: '编辑' })
-
-    const getQuickAppAccount = useAjax((params: QuickAppAccout) => getQuickAppAccountApi(params), { debounceInterval: 200 })
-    const addQuickAppAccount = useAjax((params: AddQuickAppAccount) => addQuickAppAccountApi(params), { msgNmae: '添加' })
-    const editQuickAppAccount = useAjax((params: EditQuickAppAccount) => editQuickAppAccountApi(params), { msgNmae: '编辑' })
-    const delQuickAppAccount = useAjax((params: { quickAppAccountIds: string }) => delQuickAppAccountApi(params), { msgNmae: '删除' })
-    const checkQuickAppAccount = useAjax((params: CheckQuickAppAccount) => checkQuickAppAccountApi(params), { msgNmae: '切号' })
-    const getAccountChangeRecord = useAjax((params: { quickAppAccountId: number, pageNum: number, pageSize: number }) => getAccountChangeRecordApi(params), { debounceInterval: 200 })
-    const editAccountChangeRecord = useAjax((params: { recordId: number, putResourceId: number, beginTime: string, endTime: string }) => editAccountChangeRecordApi(params), { msgNmae: '编辑' })
-
-    const getResource = useAjax((params: { resourceType: string; resourceName: string }) => queryApi(params), { debounceInterval: 800 })
-    const getResourceOfUser = useAjax((params: { userId: number, resourceType: 10 | 0 }) => getResourceOfUserApi(params))
-
-    const getKyyList = useAjax((params: KyyListProps) => getKyyListApi(params))
-    const businessGroupALL = useAjax(() => businessGroup())//项目组
-    const getBookALL = useAjax(() => getBookAll())//书
-    const getPeriodALL = useAjax(() => getPeriodAll())//期数
-    const allBookCity = useAjax(() => allBook())//书城
-    const platformAll = useAjax((platformId: number) => listByPlatform(platformId))//获取账号
-    const cutBookPlatform = useAjax((params: any) => lins(params), { msgNmae: '切书切平台' }) //
-    const gitCutRecordList = useAjax((params: any) => resourceChangeRecord(params)) //获取记录列表
-    const getAllUserList = useAjax(() => getAllUser()) //获取所有用户列表
-
-    const insertCutRecord = useAjax((params: insetCutProps) => insertCutRecordApi(params), { msgNmae: '插入' })
-    const editCutRecord = useAjax((params: editCutProps) => editCutRecordApi(params), { msgNmae: '编辑' })
-    const delCutRecord = useAjax((id: number) => delCutRecordApi(id), { msgNmae: '删除' })
-
-    const [groupData, setGroupData] = useState<any>({})
-    useEffect(() => {
-        if (sessionStorage.getItem('Admin-Token')) {
-            businessGroupALL.run().then(res => {
-                console.log(1111111111, res);
-                if (res && Array.isArray(res)) {
-                    let data: any = {}
-                    res.forEach((item: { id: number, businessGroupName: string }) => {
-                        data[item?.id?.toString()] = item?.businessGroupName
-                    })
-                    setGroupData({ ...data })
-                }
-            })
-        }
-    }, [sessionStorage.getItem('Admin-Token')])
-    return {
-        getGdtAccount,
-        addGdtAccount,
-        editGdtAccount,
-        delGdtAccount,
-        getResource,
-        checkGdtAccountGdt,
-        getQuickAppAccount,
-        addQuickAppAccount,
-        editQuickAppAccount,
-        delQuickAppAccount,
-        checkQuickAppAccount,
-        getKyyList,
-        businessGroupALL,
-        groupData,
-        getBookALL,
-        getPeriodALL,
-        allBookCity,
-        platformAll,
-        cutBookPlatform,
-        gitCutRecordList,
-        getAllUserList,
-        insertCutRecord,
-        editCutRecord,
-        delCutRecord,
-        getResourceOfUser,
-        getGdtChangeRecord,
-        getAccountChangeRecord,
-        editAccountChangeRecord,
-        editGdtChangeRecord
-    }
-}

+ 0 - 12
src/models/useOperating/useAdCensus.ts

@@ -1,12 +0,0 @@
-import { useAjax } from '@/Hook/useAjax'
-import { getAdProfitAjax, AdProfit, getxcxAllAjax } from '@/services/operating/adCensus'
-
-export default function useAdCensus() {
-    const getAdProfit = useAjax((params: AdProfit) => getAdProfitAjax(params), { formatResult: true })
-    const getxcxAll = useAjax(() => getxcxAllAjax(), { formatResult: true })
-
-    return {
-        getAdProfit,
-        getxcxAll
-    }
-}

+ 0 - 263
src/models/useOperating/useAservice.ts

@@ -1,263 +0,0 @@
-import { useAjax } from '@/Hook/useAjax';
-import { kefuMsgStrategyAdd, kefuMsgStrategyDel, kefuMsgStrategyDetail, kefuMsgStrategyEdit, kefuMsgStrategyGet, kefuMsgStrategyOn, kefuMsgStrategyRestart, kefuMsgStrategyDays, kefuMsgStrategyHistoryNews, kefuMsgStrategyDels } from '@/services/operating/news';
-import moment from 'moment';
-import { useCallback, useEffect, useReducer } from 'react'
-type State = {
-    visible: boolean,//弹窗开启与否
-    wxVisible: boolean,//微信公众号选择弹窗
-    moreVisible: boolean,//批量弹窗
-    msgVisible: boolean,//图片,视频,音频类型弹窗
-    textVisible: boolean,//文字类型弹窗
-    graphicVisible: boolean,//图文类型弹窗
-    msgContents: any[],//当前出入的数据
-    delId: number[],//上次删除的ID集合
-    fans: 0 | 1,//群发粉丝
-    taskName: string,//任务名称
-    msgType: 'mpnews' | 'text' | 'voice' | 'mpvideo' | 'image',//消息类型
-    mobile?: string,
-    actionWX: any,//当前微信
-    mpIds: any[],//批量选中的微信
-    triggerType: number,//发送方式
-    weekDay: number,//星期几
-    time: string,//时分
-    sendTime: string,//指定时间
-    enabled: 0 | 1,//0暂停1启用
-    msgStrategy: 0 | 1, // 0全部推送 1 随机回复一条
-    mpFansListDto: {
-        sex: 'all' | 0 | 1 | 2,// 'all'全部,0未知,1男,2女
-        tagIds: any[],
-        tagType: 0 | 1 | 2, // 0:并集,1:交集,2:取反
-
-    },
-
-}
-export type Action = {
-    type: 'show' | 'wxShow' | 'moreShow' |
-    'msgType' | 'msgVisible' |
-    'textVisible' | 'graphicVisible' |
-    'setDate' | 'setTime'  | 'setWeekDay' | 'setFans' | 'setSex' |
-    'setMpFansListDto' | 'initData' | 'setActionWX' | 'setActionWXs' | 'setName' | 'triggerType' | 'setEnabled' | 'setMsgStrategy' |
-    'addList' | 'delList' | 'edit' | 'up' | 'down'
-    ,
-    params?: any
-}
-function reducer(state: State, action: Action) {
-    let { type, params } = action
-    let { msgContents } = state
-    let newArr: any[] = []
-    switch (type) {
-        case 'addList':
-            newArr = [...msgContents]
-            let indexId: number
-            let newIds: any[] = []
-            if (state?.delId?.length > 0) {//假如delId存在代表删除过数据,取删除的数据的Id做为新素材的ID避免重复ID
-                indexId = state.delId[0]
-                newIds = state.delId.filter((id) => id !== state.delId[0])
-            } else {//假如不存在那就是第一次新建只要设ID为数组的长度+1就行
-                indexId = msgContents.length + 1
-            }
-            if (params.list.index && !params.list.indexId) {//index存在indexId不存在表示是插入
-                newArr.forEach((item: any, index: number) => {
-                    if (item.indexId === params.list.index) {
-                        newArr.splice(index + 1, 0, { ...params.list, indexId })
-                    }
-                })
-            } else {//最后插入
-                newArr.push({ ...params.list, indexId })
-            }
-            return { ...state, msgContents: newArr, delId: newIds }
-        case 'edit':
-            newArr = [...msgContents]
-            newArr.forEach((item: any, index: number) => {
-                if (item.indexId === params.list.index) {
-                    newArr.splice(index, 1, { ...item, ...params.list })
-                }
-            })
-            return { ...state, msgContents: newArr }
-        case 'delList':
-            let delId = [...state.delId, params.indexId]//存放本次删除的ID以备新增时使用
-            return { ...state, msgContents: msgContents.filter((item: any) => item.indexId !== params.indexId), delId }
-        case 'up':
-            newArr = [...msgContents]
-            msgContents.forEach((item: any, index: number) => {
-                if (item.indexId === params.indexId) {
-                    newArr[index - 1] = item
-                    newArr[index] = msgContents[index - 1]
-                }
-            })
-            return { ...state, msgContents: newArr }
-        case 'down':
-            newArr = [...msgContents]
-            msgContents.forEach((item: any, index: number) => {
-                if (item.indexId === params.indexId) {
-                    newArr[index + 1] = item
-                    newArr[index] = msgContents[index + 1]
-                }
-            })
-            return { ...state, msgContents: newArr }
-        case 'setActionWX':
-            return { ...state, actionWX: params.actionWX }
-        case 'setActionWXs':
-            return { ...state, mpIds: params.mpIds }
-        case 'show':
-            return { ...state, visible: !state.visible }
-        case 'wxShow':
-            return { ...state, wxVisible: !state.wxVisible }
-        case 'moreShow':
-            return { ...state, moreVisible: !state.moreVisible }
-        case 'msgType':
-            return { ...state, msgType: params.msgType }
-        case 'msgVisible':
-            return { ...state, msgVisible: !state.msgVisible }
-        case 'textVisible':
-            return { ...state, textVisible: !state.textVisible }
-        case 'graphicVisible':
-            return { ...state, graphicVisible: !state.graphicVisible }
-        case 'setDate':
-            return { ...state, sendTime: params.sendTime }
-        case 'setWeekDay':
-            return { ...state, weekDay: params.weekDay }
-        case 'triggerType':
-            return { ...state, triggerType: params.triggerType }
-        case 'setTime':
-            return { ...state, time: params.time }
-        case 'setEnabled':
-            return { ...state, enabled: params.enabled }
-        case 'setMsgStrategy':
-            return { ...state, msgStrategy: params.msgStrategy }
-        case 'setFans':
-            return { ...state, fans: params.fans }
-        case 'setSex':
-            return { ...state, sex: params.sex }
-        case 'setName':
-            return { ...state, taskName: params.taskName }
-        case 'setMpFansListDto':
-            return { ...state, mpFansListDto: { ...state.mpFansListDto, ...params } }
-        case 'initData':
-            if (!params) {
-                return {
-                    visible: false,
-                    wxVisible: false,
-                    moreVisible: false,
-                    msgType: 'mpnews',
-                    msgVisible: false,
-                    graphicVisible: false,
-                    textVisible: false,
-                    time: moment(new Date()).format('HH:mm'),
-                    fans: 1,
-                    taskName: '',
-                    sex: 'all',
-                    actionWX: null,
-                    msgContents: [],
-                    delId: [],
-                    mpIds: [],
-                    triggerType: 0,
-                    enabled: 1,
-                    msgStrategy: 0,
-                    weekDay: 2,
-                    sendTime: null,
-                    resDelayHours: 0,//时
-                    resDelayMinutes: 0,//分
-                    resDelaySecond: 0,//秒
-                    mpFansListDto: {
-                        sex: 'all',
-                        tagIds: [],
-                        tagType: 0
-                    }
-                }
-            }
-            return { ...state, ...params }
-        default:
-            return state;
-    }
-}
-export default function useAservice() {
-    const [state, dispatch] = useReducer(reducer, {
-        visible: false,
-        wxVisible: false,
-        moreVisible: false,
-        msgType: 'mpnews',
-        msgVisible: false,
-        msgContents: [],
-        delId: [],
-        graphicVisible: false,
-        textVisible: false,
-        time: moment(new Date()).format('HH:mm'),
-        fans: 1,
-        taskName: '',
-        sex: 'all',
-        actionWX: null,
-        mpIds: [],
-        triggerType: 1,
-        enabled: 1,
-        msgStrategy: 0,
-        weekDay: 1,
-        sendTime: null,
-        resDelayHours: 0,//时
-        resDelayMinutes: 0,//分
-        resDelaySecond: 0,//秒
-        mpFansListDto: {
-            sex: 'all',
-            tagIds: [],
-            tagType: 0
-        }
-    })
-    const addKefuMsgStrategy = useAjax((params?: any) => kefuMsgStrategyAdd(params))
-    const editKefuMsgStrategy = useAjax((params: any) => kefuMsgStrategyEdit(params), { msgNmae: '编辑' })
-    const delKefuMsgStrategy = useAjax((params: any) => kefuMsgStrategyDel(params), { msgNmae: '删除' })
-    const delskefu = useAjax((params) => kefuMsgStrategyDels(params), { msgNmae: '批量删除' })
-    const restartKefuMsgStrategy = useAjax((params: { strategyId: number, belongUserId: number }) => kefuMsgStrategyRestart(params), { msgNmae: '启动' })
-    const onKefuMsgStrategy = useAjax((params: any) => kefuMsgStrategyOn(params), { msgNmae: '操作' })
-    const getKefuMsgStrategy = useAjax((params: any) => kefuMsgStrategyGet(params))
-    const detailKefuMsgStrategy = useAjax((params: any) => kefuMsgStrategyDetail(params))
-    const daysKefuMsgStrategy = useAjax((params: { strategyId: number, pageNum: number, pageSize: number, belongUserId: number, mpId?: string }) => kefuMsgStrategyDays(params))
-    const historyKefuMsgStrategy = useAjax((params: { pageNum: number, pageSize: number }) => kefuMsgStrategyHistoryNews(params))
-
-    /** 初始化数据*/
-    const initData = useCallback((data: any) => {
-        dispatch({ type: 'initData', params: { data } })
-    }, [])
-    /** 添加list*/
-    const addList = useCallback((list: any) => {
-        dispatch({ type: 'addList', params: { list } })
-    }, [])
-    const editList = useCallback((list: any) => {
-        dispatch({ type: 'edit', params: { list } })
-    }, [])
-    /**删除list */
-    const delList = useCallback((indexId: any) => {
-        dispatch({ type: 'delList', params: { indexId } })
-    }, [])
-    /** 向上移动*/
-    const up = useCallback((indexId: any) => {
-        dispatch({ type: 'up', params: { indexId } })
-    }, [])
-    /** 向下移动*/
-    const down = useCallback((indexId: any) => {
-        dispatch({ type: 'down', params: { indexId } })
-    }, [])
-    useEffect(() => {
-        localStorage.setItem('collapsed', state.visible ? '1' : '0')
-    }, [state.visible])
-    console.log('useAservice=>sate.msgContents====>', state?.msgContents)
-    return {
-        state,
-        addKefuMsgStrategy,
-        editKefuMsgStrategy,
-        delKefuMsgStrategy,
-        getKefuMsgStrategy,
-        onKefuMsgStrategy,
-        detailKefuMsgStrategy,
-        restartKefuMsgStrategy,
-        daysKefuMsgStrategy,
-        historyKefuMsgStrategy,
-        delskefu,
-        initData,
-        dispatch,
-        addList,
-        delList,
-        editList,
-        up,
-        down,
-    }
-}

+ 0 - 65
src/models/useOperating/useAtemplate.ts

@@ -1,65 +0,0 @@
-import { useAjax } from '@/Hook/useAjax';
-import { listOfPageApi, templateMsgApi, syncTemplateApi, strategyApi, temDelApi, modifyStrategyApi, temPreviewApi } from '@/services/operating/news';
-
-export default function useAtemplate() {
-    const getKefuMsgStrategy = useAjax((params: {mpId: string}) => templateMsgApi(params)) 
-    const listOfPageAjax = useAjax((params: {mpId?: string, taskName?: string, executionStatus?: number, pageNum: number, pageSize: number}) => listOfPageApi(params))
-    const syncTemplateAjax = useAjax((params: {mpId: string}) => syncTemplateApi(params)) 
-    const strategyAjax = useAjax((params: {mpId: string, 
-        templateId: number, 
-        taskName: string, 
-        fansAll: boolean, 
-        fansFilterTagType?: number,
-        fansFilterTagids?: any[]
-        contentFields: any[],
-        url?: string,
-        miniprogramAppid?: string,
-        miniprogramPagepath?: string,
-        triggerType: number,
-        sendTime?: string,
-        enabled: boolean,
-        isUrl: boolean,
-        fansFilterSex?: number}) => strategyApi(params)) 
-    const modifyStrategyAjax = useAjax((params: {mpId: string, 
-            id: number,
-            templateId: number, 
-            taskName: string, 
-            fansAll: boolean, 
-            fansFilterTagType?: number,
-            fansFilterTagids?: any[]
-            contentFields: any[],
-            url?: string,
-            miniprogramAppid?: string,
-            miniprogramPagepath?: string,
-            triggerType: number,
-            sendTime?: string,
-            enabled: boolean,
-            isUrl: boolean,
-            fansFilterSex?: number}) => modifyStrategyApi(params), { msgNmae: '修改' }) 
-    const temDelAjax = useAjax((params: {id: number}) => temDelApi(params)) 
-    const temPreviewAjax = useAjax((params: {mpId: number, 
-        fansIds: number,
-        templateId: number, 
-        taskName: string, 
-        fansAll: boolean, 
-        fansFilterTagType?: number,
-        fansFilterTagids?: any[]
-        contentFields: any[],
-        url?: string,
-        miniprogramAppid?: string,
-        miniprogramPagepath?: string,
-        triggerType: number,
-        sendTime?: string,
-        enabled: boolean,
-        isUrl: boolean,
-        fansFilterSex?: number}) => temPreviewApi(params), { msgNmae: '预览' }) 
-    return {
-        getKefuMsgStrategy,
-        listOfPageAjax,
-        syncTemplateAjax,
-        strategyAjax,
-        temDelAjax,
-        modifyStrategyAjax,
-        temPreviewAjax
-    }
-}

+ 0 - 30
src/models/useOperating/useDB.tsx

@@ -1,30 +0,0 @@
-import { useReducer } from 'react'
-type State = {
-    data?: any[],
-    total?: number
-}
-export type Action = {
-    type: 'set',
-    params: any
-}
-export function reducer(state: State, action: Action) {
-    let { type, params } = action
-    let newState = JSON.parse(JSON.stringify(state))
-    switch (type) {
-        case 'set':
-            Object.keys(params as State).forEach((key: string) => {
-                newState[key] = (params as State)[key]
-            })
-            return newState
-        default:
-            return state;
-    }
-}
-const defultData = { data: [], total: 0 }
-export default function useDB() {
-    const [state, dispatch] = useReducer(reducer, defultData)
-    return {
-        state,
-        dispatch
-    }
-}

+ 0 - 64
src/models/useOperating/useExamine.ts

@@ -1,64 +0,0 @@
-import { useEffect, useReducer } from 'react'
-import { useAjax } from '@/Hook/useAjax'
-import { getAdvancedList, getAserviceList, getAtemplateList, getInteractList, reviewAdvanced, reviewAservice, reviewAtemplate, reviewInteract, seeAdvanced, seeAservice, seeAtemplate, seeInteract } from '@/services/operating/examine'
-type State = {
-    userList?: any[]//公众号列表
-    mpId?: number | string//选中的公众号
-}
-const initData: State = {
-    userList: [],
-    mpId: ''
-}
-export type Action = {
-    type: 'set',
-    params: State
-}
-export function reducer(state: State, action: Action) {
-    let { type, params } = action
-    let newState = JSON.parse(JSON.stringify(state))
-    switch (type) {
-        case 'set':
-            Object.keys(params).forEach((key) => {
-                newState[key] = params[key]
-            })
-            return newState
-        default:
-            return state;
-    }
-}
-
-export default function useWxGroupList() {
-    const [state, dispatch]: [State, React.Dispatch<Action>] = useReducer(reducer, initData)
-    /**==========================群发============================*/
-    const advancedList = useAjax((params) => getAdvancedList(params))
-    const putReviewAdvanced = useAjax((params) => reviewAdvanced(params))
-    const lookAdvanced = useAjax((params) => seeAdvanced(params))
-    /**==========================客服============================*/
-    const aserviceList = useAjax((params) => getAserviceList(params))
-    const putReviewAservice = useAjax((params) => reviewAservice(params))
-    const lookAservice = useAjax((params) => seeAservice(params))
-    /**==========================模板============================*/
-    const atemplateList = useAjax((params) => getAtemplateList(params))
-    const putReviewAtemplate = useAjax((params) => reviewAtemplate(params))
-    const lookAtemplate = useAjax((params) => seeAtemplate(params))
-    /**==========================立即/延迟============================*/
-    const interactList = useAjax((params) => getInteractList(params))
-    const putReviewInteract = useAjax((params) => reviewInteract(params))
-    const lookInteract = useAjax((params) => seeInteract(params))
-    return {
-        state,
-        dispatch,
-        advancedList,
-        putReviewAdvanced,
-        putReviewAservice,
-        putReviewAtemplate,
-        putReviewInteract,
-        lookAdvanced,
-        aserviceList,
-        lookAservice,
-        atemplateList,
-        lookAtemplate,
-        interactList,
-        lookInteract
-    }
-}

+ 0 - 124
src/models/useOperating/useFans.ts

@@ -1,124 +0,0 @@
-import { useCallback, useReducer } from 'react';
-import {
-  addFansTag,
-  editFansTag,
-  getFansTagList,
-  selectFansTagList,
-  delFansTag,
-  FansTag,
-  getFansList,
-  getFansDetail,
-  putFansTag,
-  setFansRemark,
-  putFansSync,
-  putFansSyncAll,
-  Fans,
-  fansSearch,
-  syncAllTag,
-  catFansNum,
-  getFansStatOnlineApi,
-  getFansOrderListApi,
-  syncAllBooksApi,
-  isBoundAdAccount,
-  createAdUserPackage,
-} from '@/services/operating/fans';
-import { useAjax } from '@/Hook/useAjax';
-type State = {
-  visible: boolean; //弹窗开启与否
-};
-export type Action = {
-  type: 'show';
-  params?: any;
-};
-export function reducer(state: State, action: Action) {
-  let { type } = action;
-  switch (type) {
-    case 'show':
-      return { ...state, visible: !state.visible };
-    default:
-      return state;
-  }
-}
-
-export default function useWxGroupList() {
-  const [state, dispatch] = useReducer(reducer, { visible: false });
-  /**添加粉丝标签 */
-  const add = useAjax((params: FansTag) => addFansTag(params), { msgNmae: '新建标签' });
-  /**同步粉丝标签 */
-  const tagSyncAll = useAjax((mpId: number) => syncAllTag(mpId), { msgNmae: '同步标签' });
-  /**编辑粉丝标签 */
-  const edit = useAjax((params: FansTag) => editFansTag(params), { msgNmae: '编辑标签' });
-  /**获取粉丝标签全部列表 */
-  const get = useAjax((params: { mpId: string }) => getFansTagList(params));
-  /**查询粉丝标签 */
-  const select = useAjax((params: FansTag) => selectFansTagList(params));
-  /**删除粉丝标签 */
-  const del = useAjax((params: { tagId: string }) => delFansTag(params), { msgNmae: '删除标签' });
-  /**粉丝列表*/
-  const fansList = useAjax((params: Fans) => getFansList(params));
-  /**粉丝统计信息*/
-  const getFansStatOnline = useAjax((mpId: number) => getFansStatOnlineApi(mpId));
-  /**粉丝订单数据*/
-  const getFansOrderList = useAjax(
-    (props: {
-      queryDate: string;
-      platformId: number;
-      mpId: string;
-      openId: string;
-      pageNum: number;
-      pageSize: number;
-      orderStatus?: 0 | 1 | 2 | -1;
-    }) => getFansOrderListApi(props),
-  );
-  /**粉丝详情*/
-  const fansDetail = useAjax((params: { fansId: string }) => getFansDetail(params));
-  /**粉丝name搜索*/
-  const searchFans = useAjax((params: { nickname: string; mpId: number }) => fansSearch(params), {
-    debounceInterval: 100,
-  });
-  /**给粉丝打标签*/
-  const fansTag = useAjax((params: Fans) => putFansTag(params));
-  /**给粉丝设置备注*/
-  const fansRemark = useAjax((params: any) => setFansRemark(params));
-  /**重新同步指定粉丝的信息*/
-  const fansSync = useAjax((params: { fansId: string }) => putFansSync(params));
-  /**重新同步公众号所有粉丝信息*/
-  const fansSyncAll = useAjax((params: { mpId: string }) => putFansSyncAll(params));
-  /** 同步书城信息 */
-  const syncAllBooks = useAjax((params: { mpId: number; platformId: number }) =>
-    syncAllBooksApi(params),
-  );
-  /**显示关闭弹窗 */
-  const visible = useCallback(() => {
-    dispatch({ type: 'show' });
-  }, []);
-  /**条件查找粉丝活跃人数 */
-  const catFans = useAjax((params) => catFansNum(params));
-  /**是否绑定广告账户*/
-  const is_boundAdAccount = useAjax((mpId)=>isBoundAdAccount(mpId))
-  /**创建人群包*/
-  const create_adUserPackage = useAjax((params)=>createAdUserPackage(params),{msgNmae:'创建'})
-  return {
-    state,
-    get,
-    add,
-    del,
-    edit,
-    select,
-    visible,
-    fansList,
-    fansDetail,
-    fansTag,
-    fansRemark,
-    fansSync,
-    fansSyncAll,
-    searchFans,
-    tagSyncAll,
-    catFans,
-    getFansStatOnline,
-    getFansOrderList,
-    syncAllBooks,
-    is_boundAdAccount,
-    create_adUserPackage
-  };
-}

+ 0 - 309
src/models/useOperating/useInteract.ts

@@ -1,309 +0,0 @@
-import { useCallback, useReducer } from 'react';
-import {
-  addMsgResStrategy,
-  editMsgResStrategy,
-  getMsgResStrategy,
-  searchMsgResStrategy,
-  getMpClickMenuList,
-  searchImMsgResStrategy,
-  delMsgResStrategy,
-  searchDetails,
-  Params,
-  editEnabled,
-  editMsgResStrategyIm,
-  replyStrategyPreview,
-  importPushExcle,
-} from '@/services/operating/interact';
-import { useAjax } from '@/Hook/useAjax';
-type State = {
-  msgContents: any[]; //当前出入的数据
-  textKey: string; //关键字
-  resDelayHours: number; //时
-  resDelayMinutes: number; //分
-  resDelaySecond: number; //秒
-  strategyDesc: string; //策略描述
-  textKeyStrategy: number; //全匹配 半匹配
-  msgStrategy: number; //推送方式
-  eventType: number; //触发条件
-  delId: number[]; //上次删除的ID集合
-  menuKeys: string[];
-  fansSelectValue?: any;
-  fansType:0|1
-};
-export type Action = {
-  type:
-    | 'addList'
-    | 'delList'
-    | 'edit'
-    | 'up'
-    | 'down'
-    | 'setTextKey'
-    | 'setMenuKeys'
-    | 'setTime'
-    | 'setStrategyDesc'
-    | 'setMsgStrategy'
-    | 'setTextKeyStrategy'
-    | 'setEventType'
-    | 'initData'
-    | 'setFansSelectValue'
-    | 'setFansType'
-  params: any;
-};
-export function reducer(state: State, action: Action) {
-  let { msgContents } = state;
-  let { type, params } = action;
-  let newArr: any[] = [];
-  let newState = JSON.parse(JSON.stringify(state));
-  switch (type) {
-    case 'addList':
-      newArr = [...msgContents];
-      console.log('ADDLIST', msgContents);
-      let indexId: number;
-      let newIds: any[] = [];
-      if (state?.delId?.length > 0) {
-        //假如delId存在代表删除过数据,取删除的数据的Id做为新素材的ID避免重复ID
-        console.log('从删除的数组里取序号');
-        indexId = state.delId[0];
-        newIds = state.delId.filter((id) => id !== state.delId[0]);
-      } else {
-        //假如不存在那就是第一次新建只要设ID为数组的长度+1就行
-        indexId = msgContents.length + 1;
-        console.log('新增序号');
-      }
-      // console.log(params.list,'params.list')
-      if (params.list.index && !params.list.indexId && newArr?.length > 0) {
-        //index存在indexId不存在表示是插入
-        console.log('按位置插入');
-        newArr.forEach((item: any, index: number) => {
-          if (item.indexId === params.list.index) {
-            newArr.splice(index + 1, 0, { ...params.list, indexId });
-          }
-        });
-      } else {
-        //最后插入
-        console.log('最后插入', params.list, indexId);
-        newArr.push({ ...params.list, indexId });
-      }
-      return { ...state, msgContents: newArr, delId: newIds };
-    case 'edit':
-      console.log(params, 'params');
-      newArr = [...msgContents];
-      newArr.forEach((item: any, index: number) => {
-        if (item.indexId === params.list.index) {
-          newArr.splice(index, 1, { ...item, ...params.list });
-        }
-      });
-      return { ...state, msgContents: newArr };
-    case 'delList':
-      let delId = [...state.delId, params.indexId]; //存放本次删除的ID以备新增时使用
-      return {
-        ...state,
-        msgContents: msgContents.filter((item: any) => item.indexId !== params.indexId),
-        delId,
-      };
-    case 'up':
-      newArr = [...msgContents];
-      msgContents.forEach((item: any, index: number) => {
-        if (item.indexId === params.indexId) {
-          newArr[index - 1] = item;
-          newArr[index] = msgContents[index - 1];
-        }
-      });
-      return { ...state, msgContents: newArr };
-    case 'down':
-      newArr = [...msgContents];
-      msgContents.forEach((item: any, index: number) => {
-        if (item.indexId === params.indexId) {
-          newArr[index + 1] = item;
-          newArr[index] = msgContents[index + 1];
-        }
-      });
-      return { ...state, msgContents: newArr };
-    case 'setTextKey':
-      return { ...state, textKey: params.textKey };
-    case 'setMenuKeys':
-      return { ...state, menuKeys: params.menuKeys };
-    case 'setTime':
-      Object.keys(params).forEach((key) => {
-        newState[key] = params[key];
-      });
-      return { ...newState };
-    case 'setStrategyDesc':
-      return { ...state, strategyDesc: params.strategyDesc };
-    case 'setMsgStrategy':
-      return { ...state, msgStrategy: params.msgStrategy };
-    case 'setTextKeyStrategy':
-      return { ...state, textKeyStrategy: params.textKeyStrategy };
-    case 'setEventType':
-      return { ...state, eventType: params.eventType };
-    case 'setFansSelectValue':
-      return { ...state, fansSelectValue: params.fansSelectValue };
-    case 'setFansType':
-      return { ...state, fansType: params.fansType };
-    case 'initData':
-      return { ...params.data.data };
-    default:
-      return state;
-  }
-}
-const defultData = {
-  msgContents: [],
-  textKey: '',
-  resDelayHours: 0,
-  resDelayMinutes: 0, //分
-  resDelaySecond: 0, //秒
-  strategyDesc: '',
-  msgStrategy: 0,
-  textKeyStrategy: 0,
-  eventType: 0,
-  enabled: true,
-  delId: [],
-  fansType:1,
-  fansSelectValue:{
-    fansFilterOsType: [],//操作系统
-    fansFilterMember: '',//是否是会员
-    fansFilterSex: [],//粉丝性别
-    fansFilterSubscribeTimeType: '',//关注时间
-    fansFilterSubscribeTimeBegin: '',//关注起始时间
-    fansFilterSubscribeTimeEnd: '',//关注截至时间
-    fansFilterRechargeCountMin: '',//充值次数(最少)
-    fansFilterRechargeCountMax: '',//充值次数(最多)
-    fansFilterRechargeTimeMin: '',//上次充值时间(最少 n天内)
-    fansFilterRechargeTimeMax: '',//上次充值时间(最大 n天内)
-    fansFilterRechargeMin: '',//最低充值金额
-    fansFilterRechargeMax: '',//最大充值金额
-    fansFilterCoinCountMin: '',//最低书币余额
-    fansFilterCoinCountMax: '',//最高书币余额
-    fansFilterActiveTimeMin: '',//上次活跃距今时间(最低)
-    fansFilterActiveTimeMax: '',//上次活跃距今时间(最高)
-    rechargeType: '',//充值情况选项
-    dayType: '',//天数选项
-    countType: '',//书币选项
-    timeType: ''//时间选项
-}
-};
-export default function useInteract() {
-  const [state, dispatch] = useReducer(reducer, defultData);
-  const addMsg = useAjax((params: Params) => addMsgResStrategy(params), { msgNmae: '添加' });
-  const editMsg = useAjax((params: Params) => editMsgResStrategy(params), { msgNmae: '编辑' });
-  const editMsgIm = useAjax((params: Params) => editMsgResStrategyIm(params), { msgNmae: '保存' });
-  const delMsg = useAjax((params: { strategyId: string }) => delMsgResStrategy(params), {
-    msgNmae: '删除',
-  });
-  const getMsg = useAjax((params: { strategyId: string }) => getMsgResStrategy(params));
-  const searchMsg = useAjax((params: { mpId: string; eventType?: number; strategyDesc?: string }) =>
-    searchMsgResStrategy(params),
-  );
-  const searchImMsg = useAjax((params: { mpId: string; eventType?: number; textKey?: string }) =>
-    searchImMsgResStrategy(params),
-  );
-  const searchDetail = useAjax((params: { strategyId: string }) => searchDetails(params));
-  const getMenuList = useAjax((params: { mpId: string }) => getMpClickMenuList(params));
-  const postReplyStrategyPreview = useAjax(
-    (params: { fansIds?: string; mpIds: any[] }) => replyStrategyPreview(params),
-    { msgNmae: '预览' },
-  );
-  const upLoad = useAjax((params: any) => importPushExcle(params), { msgNmae: '导入' });
-
-  const setEnabled = useAjax(
-    (params: { strategyId: number; enabled: boolean }) => editEnabled(params),
-    { msgNmae: '设置' },
-  );
-  /** 初始化数据*/
-  const initData = useCallback((data: any) => {
-    console.log('initData====>')
-    dispatch({ type: 'initData', params: { data } });
-  }, []);
-  /** 添加list*/
-  const addList = useCallback((list: any) => {
-    console.log('插入list', list);
-    dispatch({ type: 'addList', params: { list } });
-  }, []);
-  const editList = useCallback((list: any) => {
-    console.log(list);
-    dispatch({ type: 'edit', params: { list } });
-  }, []);
-  /**删除list */
-  const delList = useCallback((indexId: any) => {
-    dispatch({ type: 'delList', params: { indexId } });
-  }, []);
-  /** 向上移动*/
-  const up = useCallback((indexId: any) => {
-    dispatch({ type: 'up', params: { indexId } });
-  }, []);
-  /** 向下移动*/
-  const down = useCallback((indexId: any) => {
-    dispatch({ type: 'down', params: { indexId } });
-  }, []);
-  /** 设置关键字*/
-  const setTextKey = useCallback((textKey: string) => {
-    dispatch({ type: 'setTextKey', params: { textKey } });
-  }, []);
-  /** 设置菜单点击*/
-  const setMenuKeys = useCallback((menuKeys: string[]) => {
-    dispatch({ type: 'setMenuKeys', params: { menuKeys } });
-  }, []);
-  /** 设置时间*/
-  const setTime = useCallback((time: { [name: string]: any }) => {
-    dispatch({ type: 'setTime', params: time });
-  }, []);
-  /** 设置策略描述*/
-  const setStrategyDesc = useCallback((strategyDesc: string) => {
-    dispatch({ type: 'setStrategyDesc', params: { strategyDesc } });
-  }, []);
-  /** 设置推送方式*/
-  const setMsgStrategy = useCallback((msgStrategy: number) => {
-    dispatch({ type: 'setMsgStrategy', params: { msgStrategy } });
-  }, []);
-  /** 设置半匹配 全匹配*/
-  const setTextKeyStrategy = useCallback((textKeyStrategy: number) => {
-    dispatch({ type: 'setTextKeyStrategy', params: { textKeyStrategy } });
-  }, []);
-  /** 设置触发条件*/
-  const setEventType = useCallback((eventType: number) => {
-    dispatch({ type: 'setEventType', params: { eventType } });
-  }, []);
-  const setDeflault = useCallback(() => {
-    dispatch({ type: 'initData', params: { data: { data: { ...defultData } } } }); // id: state?.id
-  }, [state]);
-  const setFans = useCallback((fansSelectValue:any) => {
-    console.log('setFans====>')
-    dispatch({type:'setFansSelectValue',params:{fansSelectValue}})
-  }, []);
-  const setFansType = useCallback((fansType:any) => {
-      console.log('fansType===>',fansType)
-    dispatch({type:'setFansType',params:{fansType}})
-  }, []);
-//   console.log('useInteract=>sate.msgContents====>', state)
-  return {
-    state,
-    addList,
-    delList,
-    editList,
-    up,
-    down,
-    setTextKey,
-    setMenuKeys,
-    setTime,
-    setStrategyDesc,
-    setMsgStrategy,
-    setTextKeyStrategy,
-    setEventType,
-    setFans,
-    setFansType,
-    addMsg,
-    editMsg,
-    delMsg,
-    getMsg,
-    searchMsg,
-    searchImMsg,
-    initData,
-    setEnabled,
-    editMsgIm,
-    setDeflault,
-    searchDetail,
-    getMenuList,
-    postReplyStrategyPreview,
-    upLoad,
-  };
-}

+ 0 - 209
src/models/useOperating/useMaterialContent.ts

@@ -1,209 +0,0 @@
-import { useCallback, useEffect, useReducer } from 'react'
-import { useAjax } from '@/Hook/useAjax'
-import {
-    addMediaList, delMediaList, editMediaList, getMediaList, MediaList, GetMediaList, getTagList,
-    getClass, delClass, editClass, addClass, createGraphic, CreateGraphic, getGraphicList, editGraphic, EditGraphic, GetGraphicList,
-    getWeChatITData, GetWeChatITData, GetWeChatData, getWeChatData, getWxMediaInfo, syncMedias, syncPermanentGraphicMedias, delMediawx,
-    createGraphicMaterial, editGraphicWxMaterial, getFileUrl, getGraphicDetail, exportMediaByUrl, updateMediaCache, syncResult, bantchAdd, delOss
-} from '@/services/operating/material'
-import {  notification } from 'antd'
-import { useModel } from 'umi'
-type State = {
-    mediaType: string,//弹窗开关
-    isPublic: 0 | 1,//个人本地和公共本地
-    allData: any[],
-    syncIds: any[],//同步的素材ID,用于判断是否是当前素材在同步展示login
-}
-type Action = {
-    type: 'setType' | 'isPublic' | 'addData' | 'initData' | 'syncIds',
-    params?: any
-}
-export function reducer(state: State, action: Action) {
-    let { allData } = state
-    let { type, params } = action
-    switch (type) {
-        case 'setType':
-            return { ...state, mediaType: params.mediaType }
-        case 'isPublic':
-            return { ...state, isPublic: params.isPublic }
-        case 'addData':
-            return { ...state, allData: [...allData, ...params.data] }
-        case 'syncIds':
-            let arr: any[] = []
-            if (params.del) {
-                arr = state.syncIds.filter((id: any) => id !== params.del)
-            } else {
-                arr = [...state.syncIds, params.add]
-            }
-            return { ...state, syncIds: arr }
-        case 'initData':
-            return { ...state, allData: params?.data ? params.data : [], }
-        default:
-            return state;
-    }
-}
-
-export default function useMaterialContent() {
-    const { dispatchNews } = useModel('useOperating.useNews', (model: { dispatch: any }) => ({ dispatchNews: model.dispatch }))
-    const getData = useAjax((params: GetMediaList) => getMediaList(params), { cacheKey: 'getModaldata' })
-    const delData = useAjax((params: { id: string }) => delMediaList(params), { msgNmae: '删除' })
-    const delWxData = useAjax((id: number) => delMediawx(id), { msgNmae: '删除' })
-    const addData = useAjax((params: MediaList) => addMediaList(params), { msgNmae: '添加' })
-    const editData = useAjax((params: MediaList) => editMediaList(params), { msgNmae: '编辑' })
-    const tagData = useAjax((params: { type: string }) => getTagList(params), { cacheKey: 'tagData' })
-    const classGet = useAjax((params: any) => getClass(params))
-    const classDel = useAjax((params: { id: string }) => delClass(params), { msgNmae: '删除' })
-    const classAdd = useAjax((params: { groupName: string }) => addClass(params), { msgNmae: '添加' })
-    const classEdit = useAjax((params: { groupName: string, id: string }) => editClass(params), { msgNmae: '编辑' })
-    const addGraphic = useAjax((params: CreateGraphic) => createGraphic(params), { msgNmae: '添加' })
-    const addGraphicMaterial = useAjax((params: CreateGraphic) => createGraphicMaterial(params), { msgNmae: '添加' })
-    const getGraphic = useAjax((params: GetGraphicList) => getGraphicList(params), { cacheKey: 'getGraphicList' })
-    const graphicEdit = useAjax((params: EditGraphic) => editGraphic(params), { msgNmae: '编辑' })
-    const graphicMaterialEdit = useAjax((params: EditGraphic) => editGraphicWxMaterial(params), { msgNmae: '编辑' })
-    const getWeData = useAjax((params: GetWeChatData) => getWeChatData(params), { cacheKey: 'getWeChatData' })
-    const getWeItData = useAjax((params: GetWeChatITData) => getWeChatITData(params), { cacheKey: 'getWeChatITData' })
-    const getWXInfo = useAjax((params: {id: number, isCon?: boolean}) => getWxMediaInfo(params))
-    const getBdGraphicDetail = useAjax((params: { id: string }) => getGraphicDetail(params), { cacheKey: 'getGraphicDetail' })
-    const sync = useAjax((params: { appId: string[], mediaId: string }) => syncMedias(params), { msgNmae: '同步' })
-    const syncWx = useAjax((params: { appId: string[], mediaId: string }) => syncPermanentGraphicMedias(params), { msgNmae: '操作' })
-    const update = useAjax((params: { mpId: number, mediaType: string }) => updateMediaCache(params), { msgNmae: '更新' })
-    const importNews = useAjax((params: { url: string }) => exportMediaByUrl(params))
-    const syncQuery = useAjax((params: any) => syncResult(params))
-    const bantchAdds = useAjax((params: any) => bantchAdd(params))
-    const deloss = useAjax((params: any) => delOss(params))
-
-    //请求上传地址
-    const fileUrl = useAjax((params: { type: string }) => getFileUrl(params), {
-        manual: true,
-    })
-    const [state, dispatch] = useReducer(reducer, { mediaType: 5, isPublic: 0, allData: [], syncIds: [] })
-    let config: any = {
-        '图文素材': '5',
-        '视频': '3',
-        '音频': '2',
-        '图片': '1'
-    }
-    const actionKey = useCallback((key: string) => {
-        dispatch({ type: 'setType', params: { mediaType: config[key] } })
-    }, [])
-
-    //首次获取类型列表
-    useEffect(() => {
-        if (sessionStorage.getItem('Admin-Token')) {
-            // classGet.run()
-        }
-    }, [])
-    //群发轮询查询媒体id
-    let pollNews = useCallback((data, props) => {
-        let time: any = null
-        let tokens: string[] = []
-        data?.forEach((wx: string) => {
-            Object.values(wx).forEach((token: string) => {
-                tokens.push(token)
-            })
-        })
-        time = setInterval(() => syncQuery.run(tokens).then((res: any) => {
-            if (res) {
-                let isOk = res.every((wx: { appId: string, name: string, state: 0 | 1 | 2, mediaId: string }) => {//是否全部同步完成
-                    if (wx.state !== 0) { //是否状态不等同步中
-                        if (wx.state === 1) {//同步完成
-                            notification.success({
-                                message: wx.name + '同步素材成功,可以正常群发!',
-                            });
-                            dispatchNews({ type: 'mediaId', params: { mediaId: wx.mediaId } })
-                        }
-                        if (wx.state === 2) {//同步失败
-                            notification.error({
-                                message: wx.name + '同步素材失败,无法正常群发,请重操作!',
-                            });
-                        }
-                    }
-                    return wx.state !== 0
-                })
-                if (isOk) {
-                    clearInterval(time)
-                    time = null
-                }
-            }
-        }), 3000)
-    }, [])
-    //轮询查询结果
-    let poll = useCallback((data, mediaId) => {
-        let time: any = null
-        let tokens: string[] = []
-        let newArr = [...data]
-        newArr.forEach((wx: string) => {
-            Object.values(wx).forEach((token: string) => {
-                tokens.push(token)
-            })
-        })
-        time = setInterval(() => syncQuery.run(tokens).then((res: any[]) => {
-            if (res) {
-                let isOk = res.every((wx: { appId: string, name: string, state: 0 | 1 | 2, mediaId: string }) => {//是否全部同步完成
-                    if (wx.state !== 0) { //是否状态不等同步中
-                        if (wx.state === 1) {//同步完成
-                            notification.success({
-                                message: wx.name + '同步素材成功!',
-                            });
-                        }
-                        if (wx.state === 2) {//同步失败
-                            notification.error({
-                                message: wx.name + '同步素材失败!',
-                            });
-                        }
-                        newArr.forEach((arr: any) => {//同步成功或失败剔除下次查询
-                            Object.keys(arr).forEach((id: string) => {
-                                if (id === wx.appId) {
-                                    tokens = tokens.filter((token: string) => token !== arr[id])
-                                }
-                            })
-                        })
-                    }
-                    return wx.state !== 0
-                })
-                if (isOk) {
-                    notification.success({
-                        message: '全部公众号同步完成!',
-                    });
-                    dispatch({ type: 'syncIds', params: { del: mediaId || '' } })
-                    clearInterval(time)
-                    time = null
-                }
-            }
-        }), 3000)
-    }, [])
-    return {
-        state,
-        actionKey,
-        dispatch,
-        getData,
-        delData,
-        addData,
-        editData,
-        tagData,
-        classGet,
-        classDel,
-        classAdd,
-        classEdit,
-        addGraphic,
-        getGraphic,
-        graphicEdit,
-        getWeData,
-        getWeItData,
-        getWXInfo,
-        sync,
-        syncWx,
-        delWxData,
-        addGraphicMaterial,
-        graphicMaterialEdit,
-        fileUrl,
-        getBdGraphicDetail,
-        importNews,
-        update,
-        poll,
-        pollNews,
-        syncQuery,
-        bantchAdds,
-        deloss,
-    }
-}

+ 0 - 218
src/models/useOperating/useNews.ts

@@ -1,218 +0,0 @@
-import { useAjax } from '@/Hook/useAjax';
-import { getMpMsgGroupSendStrategy, addMpMsgGroupSendStrategy, executionNowApi, editMpMsgGroupSendStrategy, delMpMsgGroupSendStrategy, Props, preview, localPreviewApi, sendPreview, refreshSendResult, catLogs, mpMsgGroupSendStrategy, getDetails, delByLog, getRestart } from '@/services/operating/news';
-import moment from 'moment';
-import { useEffect, useReducer } from 'react'
-type State = {
-    visible: boolean,//弹窗开启与否
-    wxVisible: boolean,//微信公众号选择弹窗
-    msgVisible: boolean,//图片,视频,音频类型弹窗
-    textVisible: boolean,//文字类型弹窗
-    graphicVisible: boolean,//图文类型弹窗
-    theEdit: any,//选中的数据
-    rules: 0 | 1,//微信后台权限 
-    fans: 0 | 1,//群发粉丝
-    name: string,//任务名称
-    msgType: 'mpnews' | 'text' | 'voice' | 'mpvideo' | 'image',//消息类型
-    mobile?: string,
-    sendIgnoreReprint: boolean,
-    actionWX: any,
-    triggerType: number,//发送方式
-    weekDay: number,//星期几
-    time: string,//时分
-    sendTime: string,//指定时间
-    enabled: boolean,//启停开关
-    resDelayHours: number,//时
-    resDelayMinutes: number,//分
-    resDelaySecond: number,//秒
-    mpFansListDto: {
-        sex: 'all' | 0 | 1 | 2,// 'all'全部,0未知,1男,2女
-        tagIds: any[],
-        tagType: 0 | 1 | 2, // 0:并集,1:交集,2:取反
-
-    },
-
-}
-export type Action = {
-    type: 'show' | 'wxShow' |
-    'msgType' | 'msgVisible' |
-    'textVisible' | 'graphicVisible' |
-    'theEdit' | 'setDate' | 'setTime' | 'setTime3' |
-    'setRules' | 'setFans' | 'setSex' |
-    'setPhone' | 'setSendIgnoreReprint' |
-    'setMpFansListDto' | 'initData' | 'setActionWX' | 'setName' | 'mediaId' | 'triggerType' | 'setWeekDay' | 'setEnabled'
-    ,
-    params?: any
-}
-function reducer(state: State, action: Action) {
-    let { type, params } = action
-    switch (type) {
-        case 'setActionWX':
-            return { ...state, actionWX: params.actionWX }
-        case 'show':
-            return { ...state, visible: !state.visible }
-        case 'wxShow':
-            return { ...state, wxVisible: params.show ? params.show : !state.wxVisible }
-        case 'msgType':
-            return { ...state, msgType: params.msgType }
-        case 'msgVisible':
-            return { ...state, msgVisible: !state.msgVisible }
-        case 'textVisible':
-            return { ...state, textVisible: !state.textVisible }
-        case 'graphicVisible':
-            return { ...state, graphicVisible: !state.graphicVisible }
-        case 'theEdit':
-            console.log('params.theEdit ', params.theEdit)
-            return { ...state, theEdit: params.theEdit }
-        case 'mediaId':
-            return { ...state, theEdit: { ...state.theEdit, mediaId: params.mediaId } }
-        case 'setDate':
-            console.log('setDate', params.sendTime)
-            return { ...state, sendTime: params.sendTime }
-        case 'setWeekDay':
-            console.log('setWeekDay', params.weekDay)
-            return { ...state, weekDay: params.weekDay }
-        case 'triggerType':
-            console.log('triggerType', params.triggerType)
-            return { ...state, triggerType: params.triggerType }
-        case 'setTime':
-            return { ...state, time: params.time }
-        case 'setRules':
-            return { ...state, rules: params.rules }
-        case 'setFans':
-            return { ...state, fans: params.fans, rules: params.fans === 0 ? 1 : state.rules }
-        case 'setSex':
-            return { ...state, sex: params.sex }
-        case 'setPhone':
-            return { ...state, mobile: params.mobile }
-        case 'setName':
-            return { ...state, name: params.name }
-        case 'setEnabled':
-            return { ...state, enabled: params.enabled }
-        case 'setSendIgnoreReprint':
-            return { ...state, sendIgnoreReprint: params.sendIgnoreReprint }
-        case 'setMpFansListDto':
-            return { ...state, mpFansListDto: { ...state.mpFansListDto, ...params } }
-        case 'setTime3':
-            Object.keys(params).forEach((key) => {
-                state[key] = params[key]
-            })
-            return { ...state }
-        case 'initData':
-            if (!params) {
-                return {
-                    visible: false,
-                    wxVisible: false,
-                    msgType: 'mpnews',
-                    msgVisible: false,
-                    theEdit: null,
-                    graphicVisible: false,
-                    textVisible: false,
-                    time: moment(new Date()).format('HH:mm'),
-                    rules: 1,
-                    fans: 1,
-                    sex: 'all',
-                    name: '',
-                    triggerType: 1,
-                    weekDay: 1,
-                    sendTime: null,
-                    sendIgnoreReprint: false,
-                    actionWX: null,
-                    enabled: true,
-                    resDelayHours: 0,//时
-                    resDelayMinutes: 0,//分
-                    resDelaySecond: 0,//秒
-                    mpFansListDto: {
-                        sex: 'all',
-                        tagIds: [],
-                        tagType: 0
-                    }
-                }
-            }
-            let { appId, mpId, appName, msgType, content, fansAll, tagIds, sex, tagType, title, items, downUrl, sendTime, ...param } = params
-            let data = {
-                ...param,
-                actionWX: { appId, id: mpId, nickName: appName },
-                // theEdit: msgType === 'text' ? { textContent: content.split('<br/>'), msgType } : {
-                //     thumbUrl: downUrl,
-                //     name: title ,
-                //     msgType
-                // },
-                fans: fansAll ? 1 : 0,
-                msgType,
-                sendTime,
-                mpFansListDto: {
-                    tagIds: tagIds ? tagIds && Array.isArray(tagIds) ? tagIds : [tagIds] : [],
-                    sex: sex !== null ? sex : 'all',
-                    tagType
-                }
-            }
-            return { ...state, ...data }
-        default:
-            return state;
-    }
-}
-export default function useNews() {
-    const [state, dispatch] = useReducer(reducer, {
-        visible: false,
-        wxVisible: false,
-        msgType: 'mpnews',
-        msgVisible: false,
-        theEdit: null,
-        graphicVisible: false,
-        textVisible: false,
-        time: moment(new Date()).format('HH:mm'),
-        rules: 1,
-        fans: 1,
-        name: '',
-        sex: 'all',
-        triggerType: 1,
-        weekDay: 1,
-        sendTime: null,
-        sendIgnoreReprint: false,
-        actionWX: null,
-        enabled: true,
-        resDelayHours: 0,//时
-        resDelayMinutes: 0,//分
-        resDelaySecond: 0,//秒
-        mpFansListDto: {
-            sex: 'all',
-            tagIds: [],
-            tagType: 0
-        }
-    })
-    const getMsgGroup = useAjax((params?: { date?: string, state?: number, appId?: string, pageNum: number, pageSize: number }) => getMpMsgGroupSendStrategy(params))
-    const delMsgGroup = useAjax((params: { id: number }) => delMpMsgGroupSendStrategy(params), { msgNmae: '删除' })
-    const addMsgGroup = useAjax((params: Props) => addMpMsgGroupSendStrategy(params), { msgNmae: '新增' })
-    const editMsgGroup = useAjax((params: Props) => editMpMsgGroupSendStrategy(params), { msgNmae: '编辑' })
-    const postPreview = useAjax((params: { appId: string, content: any, mediaId: string, msgType: string, openId: string, wxName: string }) => preview(params), { msgNmae: '预览' })
-    const localPreview = useAjax((params: { sysMediaId: number, mpId: number, fansId: number }) => localPreviewApi(params), { msgNmae: '预览' })
-    const kfPreview = useAjax((params: { fansIds: string, mpIds: any[] }) => sendPreview(params), { msgNmae: '预览' })
-    const refresh = useAjax((params: { id: string }) => refreshSendResult(params), { msgNmae: '刷新状态' })
-    const catlog = useAjax((id) => catLogs(id))
-    const enabled = useAjax((params) => mpMsgGroupSendStrategy(params))
-    const getDetail = useAjax((id) => getDetails(id))
-    const delLog = useAjax((id) => delByLog(id), { msgNmae: '删除成功' })
-    const restart = useAjax((id) => getRestart(id), { msgNmae: '执行成功' })
-    const executionNow = useAjax((id) => executionNowApi(id), { msgNmae: '重发' })
-    useEffect(() => {
-        localStorage.setItem('collapsed', state.visible ? '1' : '0')
-    }, [state.visible])
-    return {
-        state,
-        getMsgGroup,
-        delMsgGroup,
-        addMsgGroup,
-        editMsgGroup,
-        postPreview,
-        localPreview,
-        dispatch,
-        kfPreview,
-        refresh,
-        catlog,
-        enabled,
-        getDetail,
-        delLog,
-        restart,
-        executionNow
-    }
-}

+ 0 - 64
src/models/useOperating/useOperate.ts

@@ -1,64 +0,0 @@
-import { useReducer } from 'react'
-import {
-    getStatistics, getArticleSummary, getFanGrowth, getFansAttribute, getFansActive, getFansInteractive, getFansKeep, Fans, getStatisticsMpId
-} from '@/services/operating/operate'
-import { useAjax } from '@/Hook/useAjax'
-type State = {
-    fansData?: any,//对应公众号头部粉丝数据
-}
-export type Action = {
-    type: 'setFansData',
-    params?: any
-}
-export function reducer(state: State, action: Action) {
-    let { type, params } = action
-    switch (type) {
-        case 'setFansData':
-            return { ...state, fansData: params.fansData }
-        default:
-            return state;
-    }
-}
-
-export default function useWxGroupList() {
-    const [state, dispatch] = useReducer(reducer,{})
-    /**总览统计 */
-    const statistics = useAjax((params: {userId: number}) => getStatistics(params))
-    /**指定公众号的统计数据 */
-    const statisticsMpId = useAjax((mpId) => getStatisticsMpId(mpId))
-    /**图文分析 */
-    const articleSummary = useAjax((params: Fans) => getArticleSummary(params))
-    /**粉丝增长 */
-    const fanGrowth = useAjax((params: Fans) => getFanGrowth(params))
-    /**粉丝属性 */
-    const fansAttribute = useAjax((params: Fans) => getFansAttribute(params))
-    /**统计指定公众号粉丝的活跃数据 */
-    const fansActive = useAjax((params: {
-        mpId: string;
-        timeDto: any;
-    }) => getFansActive(params))
-    /**统计指定公众号粉丝的互动数据 */
-    const fansInteractive = useAjax((params: {
-        mpId: string;
-        timeDto: any;
-    }) => getFansInteractive(params))
-    /**统计指定公众号粉丝的忠诚度 */
-    const fansKeep = useAjax((params: {
-        mpId: string;
-        statisticsKeepDto: any;
-    }) => getFansKeep(params))
-
-
-    return {
-        state,
-        dispatch,
-        statistics,
-        statisticsMpId,
-        articleSummary,
-        fanGrowth,
-        fansAttribute,
-        fansActive,
-        fansInteractive,
-        fansKeep
-    }
-}

+ 9 - 2
src/pages/gameDataStatistics/allSurvey/index.tsx

@@ -4,6 +4,8 @@ import { Button, Card, Form, Select, Space, Statistic } from "antd"
 import React, { useEffect, useRef, useState } from "react"
 import style from './index.less'
 import LineC from "./lineC";
+import { AllSurveyTotalDataProps, getAllSurveyTotalDataApi } from "@/services/gameData/allSurvey";
+import { useAjax } from "@/Hook/useAjax";
 const AllSurvey: React.FC = () => {
 
     /* ==================== */
@@ -21,12 +23,13 @@ const AllSurvey: React.FC = () => {
     const [leftShow, setLeftShow] = useState<boolean>(false)
     const [rightShow, setRightShow] = useState<boolean>(false)
     const [isPass, setIsPass] = useState<boolean>(false)  // 容器是否大于内容宽度
+    const [queryForm, setQueryForm] = useState<AllSurveyTotalDataProps>({})
 
     const [form] = Form.useForm();
     /* ==================== */
 
+    const getAllSurveyTotalData = useAjax((params) => getAllSurveyTotalDataApi(params))
     // console.log('size3---->', size3);
-    
 
     // 处理左右按钮隐藏 显示
     useEffect(() => {
@@ -68,6 +71,10 @@ const AllSurvey: React.FC = () => {
         }
     }
 
+    useEffect(() => {
+        getAllSurveyTotalData.run(queryForm)
+    }, [queryForm])
+
     return <div className={style.allSurver}>
         <Space direction="vertical" style={{ width: '100%' }}>
             <div ref={ref3}>
@@ -216,7 +223,7 @@ const AllSurvey: React.FC = () => {
                 </div>
             </div>
         </Space>
-        <LineC height={size3.height || 0}/>
+        <LineC height={size3.height || 0} />
     </div>
 }
 

+ 0 - 610
src/pages/gameDataStatistics/components/TableData/indexTab.tsx

@@ -1,610 +0,0 @@
-import DatePickePage from '@/components/DatePicker'
-import GroupWxTabs from '@/components/GroupWxTabs'
-import Tables from '@/components/Tables'
-import { quanpin } from '@/utils/fullScreen'
-import { CloudDownloadOutlined, FullscreenExitOutlined, FullscreenOutlined, QuestionCircleOutlined, SearchOutlined, SettingOutlined } from '@ant-design/icons'
-import { Button, Card, Col, Drawer, Input, InputNumber, Radio, Row, Select, Space, Statistic, Table, Tabs, Tooltip, Transfer } from 'antd'
-import { SelectValue } from 'antd/es/select'
-import { RadioChangeEvent } from 'antd/lib/radio'
-import { ColumnsType } from 'antd/lib/table'
-import { TransferDirection } from 'antd/lib/transfer'
-import { Moment } from 'moment'
-import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
-// import { useModel, history } from 'umi'
-import style from './index.less'
-import Sortable from 'sortablejs'
-import { useDebounce } from 'ahooks'
-
-interface Prosp {
-    isTableName?: boolean,//是否开启公众号名称搜索
-    sortArr?: { label: string, value: string }[],//排序参数名列表
-    isTableId?: boolean,//是否开公众号ID搜索
-    isTableDate?: boolean,//是否开启单日期搜索
-    isTableDay?: boolean,//是否开启N天搜索
-    isBook?: boolean,//是否开启小说搜索
-    isGroup?: boolean,//是否开启切换
-    isZj?: boolean,//是否查总计
-    isQs?: boolean,//是否开启期数
-    isInputName?: boolean, // 是否开启输入框 输入公众号
-    isPitcher?: boolean,//默认关闭,关闭下使用左侧组员组件选中的名称,开启后使用input输入筛选
-    isAdmin?: boolean, // 是否admin展示 普通员工不展示 与isGroupTab 配合 isGroupTab关闭 isAdmin可打开 
-    isCPitcher?: boolean, //是否传Pitcher
-    isUserId?: boolean, // 是否传入usid
-    isDownload?: boolean,//是否开启下载
-    isPlatform?: boolean,//是否开启书城
-    isTableDateArr?: boolean,//是否开启双日期搜索
-    tableTotal?: { [key: string]: string },//是个开启总计
-    isLocation?: boolean,//是否开启投放位置
-    isType?: boolean,//是否开启投放位置
-    scroll?: { x?: number, y?: number },//开启行滑动并设置容器最大宽度
-    columns: () => ColumnsType<any>,//table列表配置
-    title?: string,//tabel的标题
-    tooltip?: JSX.Element,//是否在标题后加问号展示说明
-    dataSource: any[],//table的数据
-    expandedRowRender?: (data: any) => JSX.Element,
-    ajax: any,//请求
-    isTdColor?: boolean,//是否需要开启背景色
-    isGroupTab?: boolean,//是否开启组员tab
-    className?: string,//自定义class
-    isSelctAcc?: boolean, // 是否用data公众号
-    isdownload?: boolean, // 是否下载
-    isDataSelectPitcher?: boolean,  // 选择数据服务传回来的投手
-    isLoginId?: boolean, // 传登陆ID
-}
-/**
- * 
- * @param  isTableName boolean是否开启公众号名称搜索
- * @param isTableId boolean,//是否开公众号ID搜索
- * @param isTableDate boolean,//是否开启单日期搜索
- * @param isTableDay  boolean,//是否开启N天搜索
- * @param isBook   boolean,//是否开启小说搜索
- * @param isTableDateArr  boolean,//是否开启双日期搜索
- * @param tableTotal  { [key: string]: string },//是个开启总计
- * @param x  number,//开启行滑动并设置容器最大宽度
- * @param dataSource any[],//table的数据
- * @param columns  () => ColumnsType<any>,//table列表配置
- * @param title  string,//tabel的标题
- * @param tooltip  JSX.Element//是否在标题后加问号展示说明
- * @param ajax  (params: Params) => Promise<any>//请求
- */
-function Page(props: Prosp) {
-    // const { isInputName, isTableName, isGroup, isTableId, isTableDate, isSelctAcc = false, isLoginId = false, isTableDay, isCPitcher = true, isDataSelectPitcher = false, isLocation, isBook, isTableDateArr, isType, isPitcher = false, isdownload = false, isAdmin = false, isUserId = false, isPlatform, isDownload, isGroupTab = true, tableTotal, isQs, isZj, scroll, columns, title, tooltip, ajax, dataSource, expandedRowRender, sortArr, isTdColor, className } = props
-    // const { state, dispatch, getAccAjax, getUserAjax } = useModel('useData.useTableData')
-    // const { state: userState } = useModel('useOperating.useUser')
-    // const { currentUser }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser }))
-    // const { state: { groupActionWx } } = useModel('useOperating.useWxGroupList')
-    // const [size, setSize] = useState<'small' | 'middle' | 'large'>('small')
-    // const [page, setPage] = useState<number>(1)
-    // const [pageSize, setPageSize] = useState<number>(100)
-    // const [total, setTotal] = useState<number>(0)
-    // const { selectdName, isFell } = userState
-    // const [visible, setVisible] = useState<boolean>(false)
-    // const [selectedKeys, setSelectedKeys] = useState<any[]>([])
-    // const [statistical, setStatistical] = useState<any>({})
-    // const [fixedNum, setFixedNum] = useState<number | string>(localStorage.getItem(`${title}fixedNum`) || 1)
-    // const [targetKeys, setTargetKeys] = useState<any[]>(localStorage?.getItem(`${title}`) ? JSON.parse(localStorage?.getItem(`${title}`) as string) : [])
-    // const { channel, tableDate, date_range, start, end, tableId, book, order_by, order, location, stage, type, platform, pitcher, tableValue = '1' } = state
-    // const [showZj, setShowZj] = useState<boolean>(false)
-    // const [value, setValue] = useState<string>('');
-    // const [searchValue, setSearchValue] = useState<any>([])
-    // const ref = useRef(null)
-
-    // useEffect(() => {
-    //     return () => {
-    //         console.log('卸载。。。');
-    //         dispatch({ type: 'dataSource', params: { dataSource: [] } })
-    //     }
-    // }, [])
-    // /**点击书名搜索书名 */
-    // useEffect(() => {
-    //     let bookName = history?.location?.query?.bookName
-    //     if (bookName) {
-    //         dispatch({ type: 'book', params: { book: bookName } })
-    //         tableSubmut({ bookName })
-    //     }
-    // }, [history.location])
-    // const handleSearch = useCallback((value: string) => {
-    //     setValue(value)
-    // }, [])
-    // const debouncedValue = useDebounce(value, { wait: 300 });
-    // useEffect(() => {
-    //     if (debouncedValue) {
-    //         getAccAjax.run({ user_id: userState?.selectdUserId, name: debouncedValue })
-    //     }
-    // }, [debouncedValue, isSelctAcc, userState?.selectdUserId])
-    // useEffect(() => {
-    //     if (isDataSelectPitcher) {
-    //         getUserAjax.run({ user_id: userState?.selectdUserId }).then((res: any) => {
-    //             setSearchValue(res?.data || [])
-    //         })
-    //     }
-    // }, [isDataSelectPitcher, userState?.selectdUserId])
-    // /**table搜索事件 */
-    // const tableSubmut = useCallback(
-    //     (props: {
-    //         pagination?: { current?: number, pageSize?: number, gzh?: string },
-    //         filters?: any,
-    //         sortData?: {
-    //             column: { dataIndex: string },
-    //             order?: "ascend" | "descend"
-    //         },
-    //         bookName?: any,
-    //         download?: boolean,
-    //     }) => {
-    //         let { pagination, filters, sortData, bookName, download, } = props
-    //         let data = {}
-    //         if (isCPitcher) {
-    //             data = { pitcher: isPitcher ? pitcher : selectdName }//'潘晨虹'||
-    //         }
-    //         if (isDataSelectPitcher) {
-    //             data = { pitcher: pitcher }//'潘晨虹'||
-    //         }
-    //         if (isUserId) {
-    //             if (currentUser.userId === 1) {
-    //                 data['user_id'] = userState.selectdUserId || 1
-    //             } else {
-    //                 data['user_id'] = currentUser.userId || 1
-    //             }
-    //         }
-    //         if (isLoginId) {
-    //             data['user_id'] = currentUser.userId || 1
-    //         }
-    //         !download && (data['page'] = pagination?.current || 1)
-    //         !download && (data['page_size'] = pagination?.pageSize || 100)
-    //         // console.log(sortData)
-    //         setPageSize(pagination?.pageSize || 100)
-    //         setPage(pagination?.current || 1)
-    //         let gzh = pagination?.gzh || channel //'寒龙书海'||
-    //         isBook && (book || bookName) && (data['book'] = bookName || book)
-    //         isQs && stage && (data['stage'] = stage)
-    //         isTableName && gzh && (data['channel'] = gzh)
-    //         isInputName && (data['channel'] = channel)
-    //         isSelctAcc && (data['channel'] = channel)
-    //         // data['channel'] = '龙鳞文学'
-    //         isTableId && tableId && (data['state'] = tableId === '2' ? '在投' : '停投')
-    //         isTableDate && tableDate && (data['date'] = tableDate)
-    //         isTableDay && date_range && (data['date_range'] = date_range)
-    //         isTableDateArr && start && (data['start'] = start)
-    //         isTableDateArr && end && (data['end'] = end)
-    //         sortData?.order && (data['order'] = sortData?.order === 'ascend' ? 'asc' : 'desc');
-    //         sortData?.column?.dataIndex && (data['order_by'] = sortData?.column?.dataIndex)
-    //         isLocation && location && (data['location'] = location)
-    //         isType && type && (data['type'] = type)
-    //         isPlatform && platform && (data['platform'] = platform)
-    //         isDownload && download && (data['download'] = 1)
-    //         if (ajax) {
-    //             ajax.run(data).then((res: any) => {
-    //                 if (res?.data) {
-    //                     let dateArr: string[] = []
-    //                     let arr = []
-    //                     if (isTdColor) {
-    //                         arr = res?.data?.map((item: any, index: number) => {
-    //                             item['id'] = (pagination?.current || 1) + index + + Math.random()*100
-    //                             if (dateArr.indexOf(item.date) !== -1) {//假如日期在dateArr中存在
-    //                                 item['color'] = `color${dateArr.indexOf(item.date)}`//那么颜色等于dateArr的位置
-    //                             } else {//假如不存在dateArr中
-    //                                 dateArr.push(item.date)//向dateArr添加日期以备相同日期对比
-    //                                 item['color'] = `color${dateArr.length - 1}`//颜色的值等于dateArr的长度-1
-    //                             }
-    //                             return item
-    //                         })
-    //                     } else {
-    //                         arr = res?.data?.map((item: any, index: number) => {
-    //                             item['id'] = (pagination?.current || 1) + index + Math.random()*100
-    //                             return item
-    //                         })
-    //                     }
-    //                     setStatistical(res?.total_data)
-    //                     dispatch({ type: 'dataSource', params: { dataSource: arr } })
-    //                     setTotal(res?.total)
-    //                 } else {
-    //                     setStatistical({})
-    //                     dispatch({ type: 'dataSource', params: { dataSource: [] } })
-    //                 }
-    //             })
-    //         }
-    //     }, [tableDate, channel, start, end, tableId, book, date_range, selectdName, ajax, order, order_by, isTdColor, location, stage, platform, type])
-    // /**tableName事件 */
-    // const tableNameChange = useCallback((value: SelectValue) => {
-    //     // let value = e.target.value
-    //     // setChannel(value)
-    //     dispatch({ type: 'channel', params: { channel: value as string } })
-    // }, [])
-    // /**tableBook事件 */
-    // const tableBookChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    //     let value = e.target.value
-    //     // setBook(value)
-    //     dispatch({ type: 'book', params: { book: value } })
-    // }, [])
-    // /**书城*/
-    // const platformChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    //     let value = e.target.value
-    //     // setPlatform(value)
-    //     dispatch({ type: 'setState', params: { platform: value } })
-    // }, [])
-    // const platformChangeInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    //     let value = e.target.value
-    //     console.log(value);
-
-    //     dispatch({ type: 'setState', params: { platform: value } })
-    // }, [])
-    // /**投手名称*/
-    // const pitcherChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    //     let value = e.target.value
-    //     // setPitcher(value)
-    //     dispatch({ type: 'setState', params: { pitcher: value } })
-    // }, [])
-    // /**tableQs事件 */
-    // const tableQsChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    //     let value = e.target.value
-    //     // setStage(value)
-    //     dispatch({ type: 'setState', params: { stage: value } })
-    // }, [])
-    // /**table单日期事件 */
-    // const tableDateChange = useCallback((arr: Moment[], formatString: string | string[]) => {
-    //     // setTableDate(formatString)
-    //     dispatch({ type: 'tableDate', params: { tableDate: formatString as string } })
-    // }, [])
-    // /**table双日期事件 */
-    // const tableDateArrChange = useCallback((arr: Moment[], formatString: string | string[]) => {
-    //     // setStart((formatString as string[])[0])
-    //     // setEnd((formatString as string[])[1])
-    //     dispatch({ type: 'tableDateArr', params: { start: (formatString as string[])[0], end: (formatString as string[])[1] } })
-    // }, [])
-    // /**tableDay事件 */
-    // const tableDayChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-    //     let value = e.target.value
-    //     // setDate_range(value)
-    //     dispatch({ type: 'date_range', params: { date_range: value } })
-    // }, [])
-    // /**tableId事件 */
-    // const tableIdChange = useCallback((value: string) => {
-    //     // setTableId(value)
-    //     dispatch({ type: 'tableId', params: { tableId: value } })
-    // }, [])
-    // /**排序选择 */
-    // const sortChange = useCallback((value: SelectValue) => {
-    //     // setOrder_by(value)
-    //     dispatch({ type: 'setState', params: { order_by: value as string } })
-    // }, [])
-    // /**投放位置1 */
-    // const locationChange = useCallback((value: SelectValue) => {
-    //     // setLocation(value)
-    //     dispatch({ type: 'setState', params: { location: value as 'MP' | 'GDT' } })
-    // }, [])
-    // /**投放位置2 */
-    // const typeChange = useCallback((value: SelectValue) => {
-    //     // setType(value)
-    //     dispatch({ type: 'setState', params: { type: value as 'MP' | 'GDT' } })
-    // }, [])
-    // const orderChange = useCallback((value: SelectValue) => {
-    //     // setOrder(value)
-    //     dispatch({ type: 'setState', params: { order: value as 'asc' | 'desc' } })
-    // }, [])
-    // /**table字段设置 */
-    // const handleChange = useCallback((nextTargetKeys: string[], direction: TransferDirection, moveKeys: string[]) => {
-    //     setTargetKeys(nextTargetKeys)
-    // }, [])
-    // const handleSelectChange = useCallback((sourceSelectedKeys: string[], targetSelectedKeys: string[]) => {
-    //     setSelectedKeys([...sourceSelectedKeys, ...targetSelectedKeys])
-    // }, [])
-    // const handleScroll = (direction: TransferDirection, e: React.SyntheticEvent<HTMLUListElement, Event>) => {
-    //     // console.log('direction:', direction);
-    //     // console.log('target:', e.target);
-    // };
-    // /**table切换事件 */
-    // const tableChange = useCallback((e: RadioChangeEvent) => {
-    //     dispatch({ type: 'dataSource', params: { dataSource: [] } })
-    //     let value = e.target.value
-    //     dispatch({ type: 'setState', params: { tableValue: value } })
-    // }, [])
-    // /**卸载组件清空数据 */
-    // useEffect(() => {
-    //     return () => {
-    //         dispatch({ type: 'dataSource', params: { dataSource: [] } })
-    //         // setPitcher('')
-    //         setTargetKeys([])
-    //         // setOrder_by(undefined)
-    //         dispatch({ type: 'setState', params: { order_by: undefined, targetKeys: [], pitcher: '' } })
-    //         // setTargetKeys([])
-    //     }
-    // }, [])
-    // /**首次加载请求or投手名称变化 */
-    // useEffect(() => {
-    //     let { channel } = history?.location?.query as any//假如路径中带公众号号名称
-    //     tableSubmut({ pagination: { current: 1, pageSize: 100, gzh: channel, }, download: isdownload })
-    // }, [selectdName])
-    // /**重组选中的字段 */
-    // const newColumns = useMemo(() => {
-    //     console.log(123)
-    //     let arr: any[] = []
-    //     if (targetKeys && targetKeys.length > 0) {
-    //         let column: any[] = columns()
-    //         targetKeys?.forEach((v: string, index: number) => {
-    //             column?.forEach((item: { dataIndex: string, fixed: any }) => {
-    //                 if (item.dataIndex === v) {
-    //                     if (index < fixedNum) {
-    //                         item.fixed = true
-    //                     } else {
-    //                         item.fixed = false
-    //                     }
-    //                     arr.push(item)
-    //                 }
-    //             })
-    //         })
-    //         localStorage.setItem(`${title}`, JSON.stringify(targetKeys))//保存至本地浏览器
-    //         return arr
-    //     }
-    //     return arr
-    // }, [targetKeys, fixedNum])
-    // useEffect(() => {
-    //     if (visible) {
-    //         let ul: any = document.getElementsByClassName('ant-transfer-list-content-show-remove')[0]
-    //         if (ul) {
-    //             new Sortable(ul, {
-    //                 animation: 150,
-    //                 dragClass: style.blue,
-    //                 onEnd: (evt: any) => {
-    //                     let newTargetKeys: any[] = []
-    //                     for (let item of ul?.children) {
-    //                         sortArr?.forEach((arr: any) => {
-    //                             if (item?.title === arr?.title) {
-    //                                 newTargetKeys.push(arr?.key)
-    //                             }
-    //                         })
-    //                     }
-    //                     setTargetKeys(newTargetKeys)
-    //                 }
-    //             });
-    //         }
-    //     }
-    // }, [visible, targetKeys])
-    // const header = <Col span={24}>
-    //     <Row gutter={[0, 10]}>
-    //         {
-    //             isGroup && <Col span={24}>
-    //                 <Radio.Group onChange={tableChange} value={tableValue}>
-    //                     <Radio.Button value={'1'}>日期汇总</Radio.Button>
-    //                     <Radio.Button value={'2'}>公众号汇总</Radio.Button>
-    //                 </Radio.Group>
-    //             </Col>
-    //         }
-    //         <Col span={24}>
-    //             <Space>
-    //                 {
-    //                     isPitcher && <Input placeholder='请输投手名称' onChange={pitcherChange} allowClear style={{ width: 140 }} value={pitcher} />
-    //                 }
-    //                 {
-    //                     isDataSelectPitcher && <Select
-    //                         style={{ width: 150 }}
-    //                         placeholder='请输投手名称'
-    //                         onChange={(value: any) => { dispatch({ type: 'setState', params: { pitcher: value } }) }}
-    //                         showArrow
-    //                         showSearch
-    //                         allowClear
-    //                         value={pitcher || null}
-    //                     >
-    //                         {
-    //                             searchValue?.map((list: any, eq: number) => {
-    //                                 return <Select.Option key={list?.user_id} value={list?.nick_name}>
-    //                                     {list?.nick_name}
-    //                                 </Select.Option>
-    //                             })
-    //                         })
-    //                 </Select>
-    //                 }
-    //                 {
-    //                     isBook && <Input placeholder='请输入小说名称' onChange={tableBookChange} allowClear style={{ width: 140 }} value={book} />
-    //                 }
-    //                 {
-    //                     isQs && <Input placeholder='请输入期数名称' onChange={tableQsChange} allowClear style={{ width: 140 }} value={stage} />
-    //                 }
-    //                 {
-    //                     isPlatform && <Input placeholder='请输入书城' onChange={platformChange} allowClear style={{ width: 140 }} value={platform} />
-    //                 }
-    //                 {
-    //                     isTableName && <Select
-    //                         style={{ width: 150 }}
-    //                         placeholder="输入搜索公众号"
-    //                         onChange={(value: any) => { tableNameChange(value) }}
-    //                         showSearch
-    //                         allowClear
-    //                         value={channel}
-    //                     >
-    //                         {
-    //                             groupActionWx?.map((list: any, eq: number) => {
-    //                                 return <Select.Option key={list?.id} value={list?.nickName}>
-    //                                     <img src={list?.headImg || localStorage?.bookImg} className={style.item_img} /> {list?.nickName}
-    //                                 </Select.Option>
-    //                             })
-    //                         })
-    //                 </Select>
-    //                 }
-    //                 {
-    //                     isSelctAcc && <Select
-    //                         style={{ width: 150 }}
-    //                         placeholder="输入搜索公众号"
-    //                         onChange={(value: any) => { tableNameChange(value) }}
-    //                         showSearch
-    //                         allowClear
-    //                         defaultActiveFirstOption={false}
-    //                         showArrow={false}
-    //                         filterOption={false}
-    //                         onSearch={handleSearch}
-    //                         value={channel}
-    //                         notFoundContent={null}
-    //                     >
-    //                         {
-    //                             getAccAjax?.data?.data?.map((list: any, eq: number) => {
-    //                                 return <Select.Option key={list?.id} value={list?.nick_name}>
-    //                                     {list?.nick_name}
-    //                                 </Select.Option>
-    //                             })
-    //                         })
-    //                 </Select>
-    //                 }
-    //                 {
-    //                     isInputName && <Input onChange={(event: React.ChangeEvent<HTMLInputElement>) => { tableNameChange(event.target.value) }} placeholder='请输入公众号' allowClear />
-    //                 }
-    //                 {
-    //                     isTableId && <Select value={tableId} placeholder='状态' onChange={tableIdChange} allowClear style={{ minWidth: 100 }}>
-    //                         <Select.Option value='1'>停投</Select.Option>
-    //                         <Select.Option value='2'>在投</Select.Option>
-    //                     </Select>
-    //                 }
-    //                 {
-    //                     isLocation && <Select value={location} placeholder='投放位置' onChange={locationChange} allowClear style={{ minWidth: 100 }}>
-    //                         <Select.Option value='MP'>MP</Select.Option>
-    //                         <Select.Option value='GDT'>GDT</Select.Option>
-    //                     </Select>
-    //                 }
-    //                 {
-    //                     isType && <Select value={type} placeholder='投放位置' onChange={typeChange} allowClear style={{ minWidth: 100 }}>
-    //                         <Select.Option value='MP'>MP</Select.Option>
-    //                         <Select.Option value='GDT'>GDT</Select.Option>
-    //                     </Select>
-    //                 }
-    //                 {
-    //                     isTableDate && <DatePickePage model='DatePicker' DatePickerChange={tableDateChange} allowClear date={tableDate} />
-    //                 }
-    //                 {
-    //                     isTableDateArr && <DatePickePage model='RangePicker' DatePickerChange={tableDateArrChange} allowClear date={start ? [start, end] : undefined} />
-    //                 }
-    //                 {
-    //                     isTableDay && <Input
-    //                         style={{ width: 120 }}
-    //                         value={date_range}
-    //                         onChange={tableDayChange}
-    //                         allowClear
-    //                         placeholder='过去N天'
-    //                     >
-    //                     </Input>
-    //                 }
-    //                 <Button type='primary' onClick={() => tableSubmut({})}><SearchOutlined />搜索</Button>
-    //                 {isDownload && <Button type='primary' onClick={() => tableSubmut({ download: true })}><CloudDownloadOutlined />下载EXCEL</Button>}
-    //             </Space>
-    //             {/*紧凑*/}
-    //             <Space style={{ float: 'right' }}>
-    //                 <Button
-    //                     size='small'
-    //                     type='text'
-    //                     onClick={() => {
-    //                         setVisible(true)
-    //                     }}>
-    //                     <SettingOutlined />
-    //                 </Button>
-    //                 <Button
-    //                     type='text'
-    //                     size='small'
-    //                     onClick={() => {
-    //                         if (ref?.current) {
-    //                             quanpin(ref?.current)
-    //                         }
-    //                     }}>
-    //                     {
-    //                         <Tooltip title={!isFell ? '全屏' : '退出全屏'}>{!isFell ? <FullscreenOutlined /> : <FullscreenExitOutlined />}</Tooltip>
-    //                     }
-    //                 </Button>
-    //                 <Drawer
-    //                     title="table字段设置"
-    //                     width={420}
-    //                     visible={visible}
-    //                     getContainer={ref?.current || false}
-    //                     onClose={() => {
-    //                         setVisible(false)
-    //                     }}
-    //                 >
-    //                     <div>
-    //                         <span>请输入固定列数值:</span>
-    //                         <InputNumber
-    //                             size="small"
-    //                             min={1}
-    //                             max={100000}
-    //                             onChange={(v) => {
-    //                                 setFixedNum(v as number)
-    //                                 localStorage.setItem(`${title}fixedNum`, `${v}`)
-    //                             }}
-    //                             value={fixedNum}
-    //                             style={{ marginBottom: 10 }}
-    //                             placeholder='请输入固定列数值'
-    //                         />
-    //                     </div>
-    //                     <Transfer
-    //                         dataSource={sortArr || []}
-    //                         titles={['不展示', '展示']}
-    //                         showSearch
-    //                         targetKeys={targetKeys || []}
-    //                         selectedKeys={selectedKeys || []}
-    //                         onChange={handleChange}
-    //                         onSelectChange={handleSelectChange}
-    //                         onScroll={handleScroll}
-    //                         render={(item: any) => item?.title}
-    //                         oneWay
-    //                         style={{ marginBottom: 16 }}
-    //                         listStyle={{
-    //                             height: 'calc(100vh - 140px)',
-    //                         }}
-    //                     />
-    //                 </Drawer>
-    //             </Space>
-    //         </Col>
-    //     </Row>
-    // </Col>
-    // const content = <Row gutter={[0, 20]} ref={ref} style={isFell ? { background: '#fff' } : {}}>
-    //     {/**table */}
-    //     <Col span={24}>
-    //         <Row gutter={[0, 20]}>
-    //             {header}
-    //             <Tab {...{ size, className, isZj, newColumns, columns, statistical, scroll, isFell, showZj, page, pageSize, dataSource, tableSubmut, expandedRowRender, total, ajax }} />
-    //         </Row>
-    //     </Col>
-    // </Row >
-    return <>
-        {
-            // content
-        }
-    </>
-}
-/**表格 */
-const Tab = React.memo((props: any) => {
-    const { size, className, isZj, newColumns, columns, statistical, scroll, isFell, showZj, page, pageSize, dataSource, tableSubmut, expandedRowRender, total, ajax } = props
-    return < Col span={24} >
-        <div className={`${style[size]} ${className ? style[className] : ''} `}>
-            {
-                isZj && <Tables
-                    bordered
-                    columns={newColumns?.length > 0 ? newColumns : columns()}
-                    dataSource={[{ ...statistical, id: 1 }]}
-                    scroll={scroll ? isFell ? { ...scroll, y: document.body.clientHeight - 300 } : scroll : {}}
-                    size={size}
-                    pagination={false}
-                    hideOnSinglePage
-                    className='total_table'
-                />
-            }
-            <Tables
-                className={`all_table ${className ? className : ''}`}
-                bordered
-                current={showZj ? 1 : page}
-                pageSize={pageSize}
-                columns={newColumns?.length > 0 ? newColumns : columns()}
-                dataSource={showZj ? [{ ...statistical, id: 1 }] : dataSource}
-                scroll={scroll ? isFell ? { ...scroll, y: document.body.clientHeight - 300 } : scroll : {}}
-                onChange={(pagination: any, filters: any, sorter: any) => tableSubmut({ pagination, filters, sortData: sorter })}
-                rowClassName={(record: { color: string }) => style[record['color']]}
-                expandedRowRender={expandedRowRender ? expandedRowRender : undefined}
-                size={size}
-                total={showZj ? 1 : total}
-                loading={ajax?.loading}
-                defaultPageSize={100}
-            />
-        </div>
-    </Col >
-}, (a, b) => {
-    if (JSON.stringify(a) === JSON.stringify(b)) {
-        return true
-    } else {
-        return false
-    }
-})
-export default Page

+ 1 - 1
src/pages/gameDataStatistics/rankingList/game/index.tsx

@@ -58,7 +58,7 @@ const Game: React.FC = () => {
                 </Radio.Group>
             </Space>}
             scroll={{ x: 1000, y: 600 }}
-            ajax={null}
+            ajax={getRechargeGameList}
             fixed={{ left: 1, right: 0 }}
             dataSource={[]}
             title='游戏充值排行榜'

+ 34 - 0
src/services/gameData/allSurvey.ts

@@ -0,0 +1,34 @@
+import { request } from 'umi';
+import { api } from '../api';
+let wapi = api + '/gameData'
+
+export interface AllSurveyTotalDataProps {
+    accountId?: number,  // 推广账号
+    agentId?: number,    // 推广渠道
+    beginDate?: string,  // 开始时间
+    endDate?: string,    // 结束时间
+    gameId?: number,     // 游戏ID
+    pitcherId?: number   // 投手
+}
+/**
+ * 获取整体概况数据
+ * @param data 
+ * @returns 
+ */
+export async function getAllSurveyTotalDataApi(data: AllSurveyTotalDataProps) {
+    return request(wapi + `/allSurvey/totalData`, {
+        method: 'POST',
+        data
+    });
+}
+/**
+ * 获取折线图数据
+ * @param data 
+ * @returns 
+ */
+export async function getAllSurveyLineDataApi(data: AllSurveyTotalDataProps) {
+    return request(wapi + `/allSurvey/lineData`, {
+        method: 'POST',
+        data
+    });
+}

+ 6 - 4
src/services/gameData/rankingList.ts

@@ -20,14 +20,16 @@ export interface Paging {
  * @param sysUserId 投手ID
  */
 export interface GameRechargeListType extends Paging {
-    beginDay?: string,  // 开始日期
-    endDay?: string,    // 结束日期
+    beginDay?: string,  // 充值开始日期
+    endDay?: string,    // 充值结束日期
     companyId?: number, // 公司ID
     sysUserId?: number  // 投手ID
+    sortFiled?: string, // 排序字段
+    sortType?: string,  // 排序方式:升序asc;降序desc
 }
 export async function getRechargeGameListApi(data: GameRechargeListType) {
-    return request(wapi + `/game/ranking/recharge/game`, {
-        method: 'PUT',
+    return request(wapi + `/ranking/game`, {
+        method: 'POST',
         data
     });
 }

+ 0 - 155
src/services/operating/fans.ts

@@ -1,155 +0,0 @@
-import { request } from 'umi';
-import { api } from '../api'
-export interface FansTag {
-    mpId?: string | number,
-    beginDate?: string,
-    endDate?: string,
-    name?: string,
-    params?: any,
-    pageNum?: number,
-    pageSize?: number,
-    tagId?: number | string
-    /**0:并集,1:交集,2:取反, */
-    tagType?: 0 | 1 | 2,
-}
-export interface Fans {
-    mpId?: string | number,
-    tagId?: number | string,
-    tagIds?: number | string,
-    fansId?: number | string,
-    fansIds?: number | string,
-    nickname?: string,
-    openId?: string,
-    pageNum?: number,
-    pageSize?: number,
-    sex?: number
-    subscribe?: boolean
-}
-
-/**新增粉丝标签 */
-export async function addFansTag(params: FansTag) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/fans/tag/add/${mpId}`, {
-        method: 'POST',
-        data: param
-    });
-}
-/**粉丝标签列表 */
-export async function getFansTagList(params: { mpId: string }) {
-    return request(`${api}/system/mp/fans/tag/all/${params.mpId}`);
-}
-/**删除标签*/
-export async function delFansTag(params: { tagId: string }) {
-    return request(`${api}/system/mp/fans/tag/del/${params.tagId}`, {
-        method: 'DELETE',
-    });
-}
-/**分页查询粉丝标签 */
-export async function selectFansTagList(params: FansTag) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/fans/tag/list/${mpId}`, {
-        method: 'POST',
-        data: param,
-    });
-}
-/**同步标签*/
-export async function syncAllTag(mpId: number) {
-    return request(`${api}/system/mp/fans/tag/syncAll/${mpId}`, {
-        method: 'PUT'
-    });
-}
-/**同步书城信息*/
-export async function syncAllBooksApi({ mpId, platformId }: { mpId: number, platformId: number }) {
-    return request(`${api}/system/mp/fans/syncPlatformFansInfo/${mpId}/${platformId}`, {
-        method: 'PUT'
-    });
-}
-/**修改标签*/
-export async function editFansTag(params: FansTag) {
-    let { tagId, ...param } = params
-    return request(`${api}/system/mp/fans/tag/modify/${tagId}`, {
-        method: 'PUT',
-        data: param,
-    });
-}
-
-
-
-/**粉丝列表*/
-export async function getFansList(params: any) {
-    let { mpId, ...param } = params
-    if (param?.tagIds && !Array.isArray(param?.tagIds)) {
-        param['tagIds'] = [param?.tagIds]
-    }
-    return request(`${api}/system/mp/fans/list/${mpId}`, {
-        method: 'PUT',
-        data: param,
-    });
-}
-/** 粉丝统计信息 */
-export async function getFansStatOnlineApi(mpId: number) {
-    return request(`${api}/system/mp/fans/fansStatOnline/${mpId}`);
-}
-/** 获取粉丝订单数据 */
-export async function getFansOrderListApi(props: { queryDate: string, platformId: number, mpId: string, openId: string, pageNum: number, pageSize: number, orderStatus?: 0 | 1 | 2 | -1 }) {
-    return request(`${api}/platform/platformOrder/queryOrder`, { method: 'POST', data: props });
-}
-/**粉丝详情*/
-export async function getFansDetail(params: { fansId: string }) {
-    return request(`${api}/system/mp/fans/detail/${params.fansId}`);
-}
-/**给粉丝打标签*/
-export async function putFansTag(params: Fans) {
-    return request(`${api}/system/mp/fans/fansTag`, {
-        method: 'PUT',
-        data: params
-    });
-}
-/**粉丝name搜索*/
-export async function fansSearch(params: { nickname: string, mpId: number }) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/fans/search/${mpId}`, {
-        method: 'GET',
-        params: param
-    });
-}
-
-/**给粉丝设置备注*/
-export async function setFansRemark(params: any) {
-    let { fansId, mpId, ...param } = params
-    return request(`${api}/system/mp/fans/remark/${mpId}/${fansId}`, {
-        method: 'POST',
-        data: param,
-    });
-}
-/**重新同步指定粉丝的信息*/
-export async function putFansSync(params: { fansId: string }) {
-    return request(`${api}/system/mp/fans/sync/${params.fansId}`, {
-        method: 'PUT',
-    });
-}
-/**重新同步公众号所有粉丝信息*/
-export async function putFansSyncAll(params: { mpId: string }) {
-    return request(`${api}/system/mp/fans/syncAll/${params.mpId}`, {
-        method: 'PUT',
-    });
-}
-/**条件查找粉丝活跃人数 */
-export async function catFansNum(params: any) {
-    return request(`${api}/system/mp/fans/sendCount`, {
-        method: 'POST',
-        data: params
-    })
-}
-/**是否绑定广告账户*/
-export async function isBoundAdAccount(mpId: any) {
-    return request(`${api}/system/mp/isBoundAdAccount/${mpId}`)
-}
-/**创建人群包*/
-export async function createAdUserPackage(params:any) {
-    let {mpId,...param} = params
-    return request(`${api}/system/mp/fans/createAdUserPackage/${mpId}`, {
-        method: 'POST',
-        data: param
-    })
-}

+ 0 - 107
src/services/operating/interact.ts

@@ -1,107 +0,0 @@
-import { queryStr } from "@/utils/query";
-import { request } from "umi";
-import { api } from '../api'
-export interface Params {
-    eventType?: number,
-    medias?: {
-        mediaId?: number,
-        msgType?: string,
-        textContent?: string,
-        type?: number,
-        wxMediaId?: string
-    }[],
-    mpId?: number,
-    msgStrategy?: number,
-    resDelayTime?: number,
-    strategyDesc?: string,
-    textKey?: string,
-    strategyId?: string
-}
-/**新建策略 */
-export async function addMsgResStrategy(params: Params) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/replyStrategy/delay/${mpId}`, {
-        method: 'POST',
-        data: param
-    });
-}
-/**策略详情 */
-export async function getMsgResStrategy(params: { strategyId: string }) {
-    return request(`${api}/system/mp/msgResStrategy/detail/${params.strategyId}`);
-}
-/**删除策略*/
-export async function delMsgResStrategy(params: { strategyId: string }) {
-    return request(`${api}/system/mp/replyStrategy/del/${params.strategyId}`, {
-        method: 'DELETE',
-    });
-}
-
-/**编辑策略*/
-export async function editMsgResStrategy(params: Params) {
-    let { mpId, strategyId, ...param } = params
-    console.log('mpId===>',mpId,params)
-    return request(`${api}/system/mp/replyStrategy/delay/${mpId}/${strategyId}`, {
-        method: 'PUT',
-        data: param,
-    });
-}
-
-/**新建或者编辑立即回复策略*/
-export async function editMsgResStrategyIm(params: Params) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/replyStrategy/immediately/${mpId}`, {
-        method: 'PUT',
-        data: param,
-    });
-}
-/**查询指定公众号的消息回复策略 */
-export async function searchMsgResStrategy(params: { mpId: string, eventType?: number, strategyDesc?: string }) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/replyStrategy/delay/search/${mpId}`, {
-        method: 'POST',
-        data: param
-    });
-}
-/** 开关策略*/
-export async function editEnabled(params: { strategyId: number, enabled: boolean }) {
-    let { strategyId, enabled } = params
-    return request(`${api}/system/mp/replyStrategy/enabled/${strategyId}/${enabled}`, {
-        method: 'PUT',
-    });
-}
-
-/**查询指定公众号立即回复的消息回复策略 */
-export async function searchImMsgResStrategy(params: { mpId: string, eventType?: number, textKey?: string }) {
-    let { mpId, ...param } = params
-    return request(`${api}/system/mp/replyStrategy/immediately/${mpId}${queryStr(param)}`);
-}
-
-/**回复策略获取详情 */
-export async function searchDetails(params: { strategyId: string }) {
-    let { strategyId } = params
-    return request(`${api}/system/mp/replyStrategy/${strategyId}`);
-}
-
-/**回复策略获取详情 */
-export async function getMpClickMenuList(params: { mpId: string }) {
-    let { mpId } = params
-    return request(`${api}/system/mp/replyStrategy/mpClickMenuList/${mpId}`);
-}
-/**延迟消息预览 */
-export async function replyStrategyPreview(params: { fansIds?: string, mpIds: any[] }) {
-    let { fansIds, ...param } = params
-    return request(`${api}/system/mp/replyStrategy/preview/${param?.mpIds[0]}/${fansIds}`, {
-        method: 'POST',
-        data: param
-    });
-}
-
-
-/**延迟消息导入Excel*/
-export async function importPushExcle(props: { data: FormDataEntryValue }) {
-    return request(`${api}/system/mp/replyStrategy/import`, {
-        method: 'POST',
-        body: props.data
-    })
-}
-

+ 0 - 280
src/services/operating/news.ts

@@ -1,280 +0,0 @@
-import { queryStr } from '@/utils/query';
-import { request } from 'umi';
-import { api } from '../api'
-export interface Props {
-
-}
-/**群发策略列表 */
-// export async function getMpMsgGroupSendStrategy(params?: { date?: string, state?: number, appId?: string, pageNum: number, pageSize: number }) {
-//   return request(`${api}/system/mpMsgGroupSendStrategy${queryStr(params)}`);
-// }
-export async function getMpMsgGroupSendStrategy(params?: { date?: string, state?: number, appId?: string, pageNum: number, pageSize: number }) {
-  let { appId, ...param } = params as any
-  return request(`${api}/system/mpMsgGroupSendStrategy/list`, {
-    method: 'POST',
-    data: { ...param, mpId: appId }
-  });
-}
-/** 新增群发策略*/
-export async function addMpMsgGroupSendStrategy(params: Props) {
-  return request(`${api}/system/mpMsgGroupSendStrategy`, {
-    method: 'POST',
-    data: params,
-  });
-}
-/** 启动禁用*/
-export async function mpMsgGroupSendStrategy(params: { strategyId: number, enabled: boolean }) {
-  const { strategyId, enabled } = params
-  return request(`${api}/system/mpMsgGroupSendStrategy/modifyEnable/${strategyId}/${enabled}`, {
-    method: 'PUT',
-  });
-}
-/**编辑群发策略 */
-export async function editMpMsgGroupSendStrategy(params: any) {
-  const { strategyId, ...param } = params
-  return request(`${api}/system/mpMsgGroupSendStrategy/${strategyId}`, {
-    method: 'PUT',
-    data: param,
-  });
-}
-/**预览 */
-export async function preview(params: any) {
-  let { mpId, fansId, msgType, ...param } = params
-  return request(`${api}/system/mpMsgGroupSendStrategy/preview/${mpId}/${fansId}/${msgType}`, {
-    method: 'POST',
-    data: param,
-  });
-}
-/** 本地素材预览 */
-export async function localPreviewApi({ sysMediaId, mpId, fansId }: { sysMediaId: number, mpId: number, fansId: number }) {
-  return request(`${api}/system/SysMedia/preview/${sysMediaId}/${mpId}/${fansId}`, {
-    method: 'PUT'
-  });
-}
-/**刷新状态 */
-export async function refreshSendResult(id: any) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/refreshSendResult/${id}`, {
-    method: 'POST',
-  });
-}
-/** 删除群发策略*/
-export async function delMpMsgGroupSendStrategy(params: { id: number, list?: any }) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/${params.id}`, {
-    method: 'DELETE',
-    data: params?.list
-  });
-}
-/**获取群发策略详情*/
-export async function getDetails(strategyId: number) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/${strategyId}`)
-}
-/**强行执行群发消息*/
-export async function getRestart(strategyId: number) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/restart/${strategyId}`)
-}
-/**一键重发群发消息*/
-export async function executionNowApi(strategyId: number) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/executionNow/${strategyId}`)
-}
-/** 查询策略执行日志*/
-export async function catLogs(strategyId: number) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/executionLog/${strategyId}`);
-}
-/** 删除策略执行日志*/
-export async function delByLog(logid: any) {
-  return request(`${api}/system/mpMsgGroupSendStrategy/delLog/${logid}`, {
-    method: 'GET',
-  });
-}
-
-/**========================================客服消息 */
-/**导出模板 */
-export async function exportKNewsExcle() {
-  return request(`${api}/system/${encodeURIComponent('客服消息导入模板')}.xlsx`, {
-    method: 'GET',
-    responseType: 'blob',
-  })
-}
-
-/**导入模板批量创建 */
-export async function importKnewsExcle(props: { data: FormDataEntryValue }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/import`, {
-    method: 'POST',
-    body: props.data
-  })
-}
-/**编辑消息 */
-export async function kefuMsgStrategyEdit(params: { strategyId: string }) {
-  let { strategyId, ...props } = params
-  return request(`${api}/system/mp/kefuMsgStrategy/${strategyId}`, {
-    method: 'PUT',
-    data: props,
-  });
-}
-/**新建消息 */
-export async function kefuMsgStrategyAdd(params: Props) {
-  return request(`${api}/system/mp/kefuMsgStrategy`, {
-    method: 'POST',
-    data: params,
-  });
-}
-/**删除消息 */
-export async function kefuMsgStrategyDel(params: { strategyId: string, belongUserId: string }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/${params.strategyId}/${params.belongUserId}`, {
-    method: 'DELETE',
-  });
-}
-/**批量删除消息 */
-export async function kefuMsgStrategyDels(params: { strategyId: string, belongUserId: string }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/batch/${params.strategyId}/${params.belongUserId}`, {
-    method: 'DELETE',
-  });
-}
-/**强制重启 */
-export async function kefuMsgStrategyRestart(params: { strategyId: number, belongUserId: number }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/restart/${params.strategyId}/${params.belongUserId}`, {
-    method: 'put',
-  });
-}
-/**启用暂停客服消息 */
-export async function kefuMsgStrategyOn(params: { enabled: number, strategyId?: string, belongUserId: number }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/${params.strategyId}/${params.belongUserId}/${params.enabled ? 'true' : 'false'}`, {
-    method: 'PUT',
-  });
-}
-/**获取消息列表 */
-export async function kefuMsgStrategyGet(params: any) {
-  return request(`${api}/system/mp/kefuMsgStrategy/listOfPage${queryStr(params)}`);
-}
-/**获取消息列表 */
-export async function kefuMsgStrategyDetail(params: { strategyId: string, belongUserId: number }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/detail/${params.strategyId}/${params.belongUserId}`);
-}
-/**获取执行日志 */
-export async function kefuMsgStrategyDays(params: { strategyId: number, pageNum: number, pageSize: number, mpId?: string, belongUserId: number }) {
-  let { strategyId, ...props } = params
-  return request(`${api}/system/mp/kefuMsgStrategy/execution/logs/${strategyId}/${queryStr(props)}`);
-}
-/**客服消息历史图文 */
-export async function kefuMsgStrategyHistoryNews(params: { pageNum: number, pageSize: number }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/historyNews${queryStr(params)}`);
-}
-/**客服消息预览 */
-export async function sendPreview(params: { fansIds?: string, mpIds: any[] }) {
-  let { fansIds, ...param } = params
-  return request(`${api}/system/mp/kefuMsgStrategy/preview/${param?.mpIds[0]}/${fansIds}`, {
-    method: 'POST',
-    data: param
-  });
-}
-/**立即发送 */
-export async function kefuMsgStrategyExecutionNow(params: { strategyId: string, belongUserId: number }) {
-  return request(`${api}/system/mp/kefuMsgStrategy/executionNow/${params.strategyId}/${params.belongUserId}`);
-}
-
-/**
- *  模板消息
- *  */
-
-/** 获取公众号模板列表 */
-export async function templateMsgApi(params: { mpId: string }) {
-  return request(`${api}/system/mp/templateMsg/list/${params.mpId}`);
-}
-
-/** 模板消息任务列表 */
-export async function listOfPageApi(params: { mpId?: string, taskName?: string, executionStatus?: number, pageNum: number, pageSize: number }) {
-  return request(`${api}/system/mp/templateMsg/strategy/listOfPage`, {
-    method: 'POST',
-    data: params
-  });
-}
-
-/** 同步公众号模板列表 */
-export async function syncTemplateApi(params: { mpId: string }) {
-  return request(`${api}/system/mp/templateMsg/syncTemplate/${params.mpId}`, {
-    method: 'PUT'
-  });
-}
-
-/** 新建模板消息 */
-export async function strategyApi(params: {
-  mpId: string,
-  templateId: number,
-  taskName: string,
-  fansAll: boolean,
-  fansFilterTagType?: number,
-  fansFilterTagids?: any[]
-  contentFields: any[],
-  url?: string,
-  miniprogramAppid?: string,
-  miniprogramPagepath?: string,
-  triggerType: number,
-  sendTime?: string,
-  enabled: boolean,
-  isUrl: boolean,
-  fansFilterSex?: number
-}) {
-  return request(`${api}/system/mp/templateMsg/strategy`, {
-    method: 'POST',
-    data: params
-  });
-}
-
-/** 修改模板消息 */
-export async function modifyStrategyApi(params: {
-  id: number,
-  mpId: string,
-  templateId: number,
-  taskName: string,
-  fansAll: boolean,
-  fansFilterTagType?: number,
-  fansFilterTagids?: any[]
-  contentFields: any[],
-  url?: string,
-  miniprogramAppid?: string,
-  miniprogramPagepath?: string,
-  triggerType: number,
-  sendTime?: string,
-  enabled: boolean,
-  isUrl: boolean,
-  fansFilterSex?: number
-}) {
-  let { id, ...param } = params
-  return request(`${api}/system/mp/templateMsg/strategy/${id}`, {
-    method: 'PUT',
-    data: param
-  });
-}
-
-/** 删除模板消息 */
-export async function temDelApi(params: { id: number }) {
-  return request(`${api}/system/mp/templateMsg/strategy/${params.id}`, {
-    method: 'DELETE'
-  });
-}
-
-/** 模板消息预览 */
-export async function temPreviewApi(params: {
-  mpId: number,
-  fansIds: number,
-  templateId: number,
-  taskName: string,
-  fansAll: boolean,
-  fansFilterTagType?: number,
-  fansFilterTagids?: any[]
-  contentFields: any[],
-  url?: string,
-  miniprogramAppid?: string,
-  miniprogramPagepath?: string,
-  triggerType: number,
-  sendTime?: string,
-  enabled: boolean,
-  isUrl: boolean,
-  fansFilterSex?: number
-}) {
-  let { mpId, fansIds, ...param } = params
-  return request(`${api}/system/mp/templateMsg/preview/${mpId}/${fansIds}`, {
-    method: 'post',
-    data: param
-  });
-}

+ 0 - 21
src/services/operating/qqAuth.ts

@@ -1,21 +0,0 @@
-import { request } from 'umi';
-
-//发起授权QQ广告应用
-export async function postqqauth(params:any) {
-    return request(`http://47.99.157.216:8022/qq/auth`, {
-        method: 'POST',
-        data: params
-    })
-}
-//查询是否有失败的账号
-export async function querErr() {
-    return request(`http://47.99.157.216:8022/qq/queryErr`, {
-        method: 'GET',
-    })
-}
-//删除cookie
-export async function delCookie() {
-    return request(`http://47.99.157.216:8022/qq/delCookie`, {
-        method: 'GET',
-    })
-}