Jelajahi Sumber

Merge branch 'develop' of http://git.zanxiangnet.com/wjx/ad-manage

wjx 8 bulan lalu
induk
melakukan
389231a7ad
100 mengubah file dengan 27 tambahan dan 14905 penghapusan
  1. 0 115
      src/components/ActionModal/index.less
  2. 0 82
      src/components/ActionModal/index.tsx
  3. 0 205
      src/components/ActionModal/left.tsx
  4. 0 109
      src/components/ActionModal/more.less
  5. 0 301
      src/components/ActionModal/more.tsx
  6. 0 203
      src/components/ActionModal/selectLeft.tsx
  7. 0 30
      src/components/Alink/index.less
  8. 0 166
      src/components/Alink/index.tsx
  9. 0 26
      src/components/CityCascader/index.tsx
  10. 0 36
      src/components/ColorPicker/index.less
  11. 0 55
      src/components/ColorPicker/index.tsx
  12. 0 43
      src/components/DatePicker/index.tsx
  13. 0 71
      src/components/DebounceSelect/index.tsx
  14. 0 246
      src/components/Editor/AudioUploader.js
  15. 0 265
      src/components/Editor/Box/TEditor.tsx
  16. 0 32
      src/components/Editor/Box/UEditor.tsx
  17. 0 149
      src/components/Editor/Box/editorPlugin.tsx
  18. 0 25
      src/components/Editor/Box/index.less
  19. 0 516
      src/components/Editor/Box/index.tsx
  20. 0 22
      src/components/Editor/Button.js
  21. 0 25
      src/components/Editor/Input.js
  22. 0 24
      src/components/Editor/Label.js
  23. 0 101
      src/components/Editor/Link.js
  24. 0 57
      src/components/Editor/Modal.js
  25. 0 472
      src/components/Editor/ReactUeditor.js
  26. 0 22
      src/components/Editor/Select.js
  27. 0 45
      src/components/Editor/Tag.js
  28. 0 38
      src/components/Editor/Upload.js
  29. 0 247
      src/components/Editor/VideoUploader.js
  30. 0 1
      src/components/Editor/index.d.ts
  31. 0 3
      src/components/Editor/index.js
  32. 0 20
      src/components/Editor/utils.js
  33. 0 38
      src/components/Expression/index.less
  34. 0 79
      src/components/Expression/index.tsx
  35. 0 23
      src/components/FansSelect/index.less
  36. 0 681
      src/components/FansSelect/index.tsx
  37. 0 89
      src/components/FileBox/components/fileModal/index.tsx
  38. 0 47
      src/components/FileBox/components/fileModal/sortModal.tsx
  39. 0 120
      src/components/FileBox/components/imgModal/index.tsx
  40. 0 211
      src/components/FileBox/components/newsModal/index.less
  41. 0 54
      src/components/FileBox/components/newsModal/index.tsx
  42. 0 158
      src/components/FileBox/components/newsModal/left.tsx
  43. 0 130
      src/components/FileBox/components/newsModal/right.tsx
  44. 0 106
      src/components/FileBox/components/syncModal/index.less
  45. 0 313
      src/components/FileBox/components/syncModal/index.tsx
  46. 0 15
      src/components/FileBox/components/tree/index.less
  47. 0 83
      src/components/FileBox/components/tree/index.tsx
  48. 0 354
      src/components/FileBox/index.less
  49. 0 567
      src/components/FileBox/index.tsx
  50. 0 211
      src/components/FileBoxAD/components/newsModal/index.less
  51. 0 54
      src/components/FileBoxAD/components/newsModal/index.tsx
  52. 0 158
      src/components/FileBoxAD/components/newsModal/left.tsx
  53. 0 130
      src/components/FileBoxAD/components/newsModal/right.tsx
  54. 2 2
      src/components/FileBoxAD/index.tsx
  55. 0 166
      src/components/Formitem/index.less
  56. 0 403
      src/components/Formitem/index.tsx
  57. 0 60
      src/components/Formitem/type.ts
  58. 0 186
      src/components/GroupWxTabs/gzhMangae.tsx
  59. 0 34
      src/components/GroupWxTabs/index.less
  60. 0 220
      src/components/GroupWxTabs/index.tsx
  61. 0 220
      src/components/GroupWxTabs/kyyBox.tsx
  62. 0 366
      src/components/GroupWxTabs/wx.tsx
  63. 0 156
      src/components/GroupWxTabs/yyb.tsx
  64. 0 23
      src/components/HeaderSearch/index.less
  65. 0 102
      src/components/HeaderSearch/index.tsx
  66. 0 60
      src/components/ImgPreview/index.less
  67. 0 34
      src/components/ImgPreview/index.tsx
  68. 0 40
      src/components/InputSearch/index.tsx
  69. 0 110
      src/components/MaterialModal/db.less
  70. 0 268
      src/components/MaterialModal/graphic.less
  71. 0 81
      src/components/MaterialModal/index.less
  72. 0 182
      src/components/MaterialModal/index.tsx
  73. 0 409
      src/components/MaterialModal/modalBox.tsx
  74. 0 104
      src/components/MaterialModal/mphnews.less
  75. 0 110
      src/components/MaterialModal/mpnews.less
  76. 0 471
      src/components/MaterialModal/msgWxGraphicListModal.tsx
  77. 0 102
      src/components/MaterialModal/msgWxLeft.tsx
  78. 0 97
      src/components/MaterialModal/previewLocalModal.tsx
  79. 0 359
      src/components/MaterialModal/previewModal.tsx
  80. 0 250
      src/components/MaterialModal/smModalBox.tsx
  81. 0 136
      src/components/MaterialModal/synthetic.less
  82. 0 148
      src/components/MaterialModal/synthetic.tsx
  83. 0 334
      src/components/MaterialModal/text.less
  84. 0 443
      src/components/MaterialModal/textModal.tsx
  85. 0 6
      src/components/MaterialModal/updata.less
  86. 0 227
      src/components/MaterialModal/updata.tsx
  87. 0 291
      src/components/MaterialModal/wxGraphicListModal.tsx
  88. 0 239
      src/components/MaterialModal/wxGraphicModal.tsx
  89. 0 101
      src/components/MaterialModal/wxHistorBD.tsx
  90. 0 188
      src/components/MaterialModal/wxModalBox.tsx
  91. 0 157
      src/components/MaterialModal/wxMpnews.tsx
  92. 0 125
      src/components/NoticeIcon/NoticeIcon.tsx
  93. 0 103
      src/components/NoticeIcon/NoticeList.less
  94. 0 112
      src/components/NoticeIcon/NoticeList.tsx
  95. 0 35
      src/components/NoticeIcon/index.less
  96. 0 158
      src/components/NoticeIcon/index.tsx
  97. 0 19
      src/components/RegExpInput/index.less
  98. 0 35
      src/components/RegExpInput/index.tsx
  99. 25 42
      src/components/RightContent/AvatarDropdown.tsx
  100. 0 18
      src/components/TagSelect/index.less

+ 0 - 115
src/components/ActionModal/index.less

@@ -1,115 +0,0 @@
-.ico {
-    -webkit-animation: Tada 3s both infinite;
-    -moz-animation: Tada 3s both infinite;
-    -ms-animation: Tada 3s both infinite;
-    animation: Tada 3s both infinite;
-  }
-  .colud {
-    display: flex;
-    flex-flow: row nowrap;
-    > div:nth-child(2) {
-      flex: 1;
-    }
-    span.ant-checkbox {
-      display: none;
-    }
-  }
-  .box {
-    > span {
-      &:first-child {
-        display: none;
-      }
-    }
-  }
-  .card_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;
-    }
-    &::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);
-    }
-  }
-  @keyframes Tada {
-    0% {
-      transform: scale(1);
-      transform: scale(1);
-    }
-  
-    70%,
-    73% {
-      transform: scale(0.9) rotate(-3deg);
-      transform: scale(0.9) rotate(-3deg);
-    }
-  
-    77%,
-    83%,
-    90%,
-    97% {
-      transform: scale(1.1) rotate(3deg);
-      transform: scale(1.1) rotate(3deg);
-    }
-  
-    80%,
-    87%,
-    93% {
-      transform: scale(1.1) rotate(-3deg);
-      transform: scale(1.1) rotate(-3deg);
-    }
-  
-    100% {
-      transform: scale(1) rotate(0);
-      transform: scale(1) rotate(0);
-    }
-  }
-  .card_box {
-    > div {
-      padding: 10px;
-    }
-  }
-  .disabled{
-    position: relative;
-    &::before{
-      position: absolute;
-      content: '';
-      width: 100%;
-      height: 100%;
-      display: block;
-      left: 0;
-      top:0;
-      bottom: 0;
-      right: 0;
-      background-color: rgba(199,199,199,.1);
-    }
-    div{
-      color: #a9a9a9;
-    }
-  }
-  .img{
-    width: 25px;
-    height: 25px;
-    margin-right: 5px;
-  }

+ 0 - 82
src/components/ActionModal/index.tsx

@@ -1,82 +0,0 @@
-import { Avatar, Card, Col, Radio, Row, Modal, Button, Space } from 'antd'
-import Meta from 'antd/lib/card/Meta'
-import React, { useCallback } from 'react'
-import { useModel } from 'umi'
-import Left from './left'
-import style from './index.less'
-import NoFoundPage from '@/pages/empty'
-/**本地保存并群发选择公众号弹窗*/
-type Props = {
-    visible: boolean,
-    hideWx: (cancel: boolean) => void
-}
-let ActionModal = (props: Props) => {
-    const { visible, hideWx } = props
-    const { state, actionWx } = useModel('useOperating.useWxGroupList')
-    //关闭弹窗
-    let handleCancel = useCallback((cancel: boolean) => {
-        if (state.actionWX) {
-            hideWx(cancel)
-        }
-    }, [state])
-    //选中事件
-    let action = useCallback((wx: any) => {
-        actionWx(wx)
-    }, [])
-    return <>
-        {
-            state?.actionWX ? <Modal
-                title="选择公众号"
-                width={740}
-                open={visible}
-                keyboard={false}
-                maskClosable={false}
-                closable={false}
-                footer={<>
-                    <Space>
-                        <Button type='primary' onClick={() => { handleCancel(true) }}>取消</Button>
-                        <Button type='primary' onClick={() => { handleCancel(false) }}>确定</Button>
-                    </Space>
-                </>}
-            >
-                <Row className={style.colud}>
-                    <Col>
-                        <Left />
-                    </Col>
-                    <Col>
-                        <Card style={{ height: '100%', overflowY: 'auto' }} title='分组' bodyStyle={{ maxHeight: 473, overflowY: 'auto' }}>
-                            <Radio.Group style={{ width: '100%' }} >
-                                <Row gutter={[10, 0]}>
-                                    {
-                                        state?.mpAccounts?.map((item: any) => {
-                                            return <Col key={item.id}>
-                                                <Radio value={item} className={style.box} disabled={item?.verifyTypeInfo === -1}>
-                                                    <Card
-                                                        onClick={() => { action(item) }}
-                                                        hoverable={item?.verifyTypeInfo !== -1}
-                                                        className={`${item.appid === state?.actionWX?.appid ? style.card_action : undefined} ${style.card_box} ${item?.verifyTypeInfo === -1 ? style.disabled : ''}`}
-                                                    >
-                                                        <Meta
-                                                            style={{ display: 'flex', alignItems: 'center' }}
-                                                            avatar={
-                                                                <Avatar src={item?.headImg || localStorage?.bookImg} />
-                                                            }
-                                                            title={item.nickName}
-
-                                                        />
-                                                    </Card>
-                                                </Radio>
-                                            </Col>
-                                        })
-                                    }
-                                </Row>
-                            </Radio.Group>
-                        </Card>
-                    </Col>
-                </Row>
-            </Modal > : <NoFoundPage />
-        }
-    </>
-}
-
-export default ActionModal

+ 0 - 205
src/components/ActionModal/left.tsx

@@ -1,205 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react'
-import { Menu, Select, Tabs } from 'antd'
-import { QrcodeOutlined } from '@ant-design/icons';
-import { useModel } from 'umi';
-import style from './index.less'
-const { Option } = Select
-interface Props {
-    default?: string,
-    height?: number | string,
-    type?: boolean,
-    isHideMyGroup?: boolean
-}
-function LeftPage(props: Props) {
-    const { isHideMyGroup = false } = props
-    const [selectedKeys, setSelectedKeys] = useState<string[]>([]) //选中自己的菜单
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>([]) //选中组员的菜单
-    const { getWxGroupAll, actionMp, actionWx, getAllOfMember, state, dispatch } = useModel('useOperating.useWxGroupList', model => ({ getWxGroupAll: model.getDataList, ...model }))
-    const { dispatch: userDispatch, initUserId } = useModel('useOperating.useUser')
-    const { tabsKey, actionArr, actionWX } = state
-    let bWith = document.body.clientWidth < 700
-    //自己menuitem点击
-    let menuItemClick = (e: any) => {
-        checkData(e.key, '', tabsKey)
-    };
-    //组员menuitem点击
-    let crewMenuItemClick = (e: any) => {
-        checkData(e.key, '', tabsKey)
-    };
-    //tabs选中
-    let tabsChange = useCallback((key: string) => {
-        dispatch({ type: 'setTabsKey', params: { tabsKey: key } })
-        if (key === '自己') {
-            initUserId()
-            checkData(selectedKeys[0], '', key)
-        } else {
-            checkData(crewSelectedKeys[0], '', key)
-        }
-    }, [selectedKeys, crewSelectedKeys])
-    //搜索
-    let inputChange = (v: any) => {
-        if (v) {
-            let [name, key] = v?.split('_')
-            checkData(key, name, tabsKey)
-        }
-    }
-    //设置选中的数据
-    let checkData = useCallback((key: string, ikey?: string, tabsKey?: string) => {
-        if (tabsKey === '自己') {
-            initUserId()
-            setSelectedKeys([key])
-            getWxGroupAll?.data?.forEach((item: any) => {
-                if (item.groupName === key) {//选中组
-                    actionMp(item?.mpAccounts)
-                    item?.mpAccounts?.forEach((wx: any) => {
-                        if (wx.nickName && wx.nickName === ikey) {//选中微信
-                            actionWx(wx)
-                        }
-                    })
-                }
-            })
-        } else {
-            setCrewSelectedKeys([key])
-            getAllOfMember?.data?.forEach((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                if (item?.key?.nickname + item?.key?.userId === key) {//选中组
-                    actionMp(item.value)
-                    handelUserId(item?.key?.userId, item?.key?.nickname)
-                    item?.value?.forEach((wx: any) => {
-                        if (wx?.nickName && wx?.nickName === ikey) {//选中微信
-                            actionWx(wx)
-                        }
-                    })
-                }
-            })
-        }
-    }, [getWxGroupAll, getAllOfMember])
-    useEffect(() => {
-        if (tabsKey === '自己') {
-            initUserId()
-            if (actionWX && getWxGroupAll?.data) {
-                getWxGroupAll?.data?.forEach((item: any, index: number) => {
-                    item?.mpAccounts?.forEach((mp: { appid: string }) => {
-                        if (mp.appid === actionWX.appid) {
-                            checkData(item['groupName'], '', tabsKey)
-                        }
-                    })
-                })
-            } else {
-                let action = true
-                getWxGroupAll?.data?.forEach((item: any, index: number) => {
-                    if (action && item['mpAccounts']?.length > 0) {
-                        action = false
-                        checkData(getWxGroupAll?.data[index]['groupName'], '', tabsKey)
-                    }
-                })
-            }
-        } else {
-            if (actionWX && getAllOfMember?.data) {
-                getAllOfMember?.data?.forEach((item: { key: { nickname: string, userId: number }, value: any[] }, index: number) => {
-                    item?.value?.forEach((mp: { appid: string }) => {
-                        if (mp?.appid === actionWX.appid) {
-                            checkData(item?.key?.nickname + item?.key?.userId, '', tabsKey)
-                        }
-                    })
-                })
-            } else {
-                let action = true
-                getAllOfMember?.data?.forEach((item: { key: { nickname: string, userId: number }, value: any[] }, index: number) => {
-                    if (action && item['userMpAccounts']?.length > 0) {
-                        action = false
-                        checkData(getAllOfMember?.data[index]?.key?.nickname + getAllOfMember?.data[index]['key']['userId'], '', tabsKey)
-                    }
-                })
-            }
-        }
-    }, [getWxGroupAll?.data, getAllOfMember?.data, tabsKey])
-    //选中角色
-    let handelUserId = useCallback((userId, name) => {
-        userDispatch({ type: 'setUserId', params: { userId: userId?.toString(), name } })
-    }, [])
-    return <div>
-        <Tabs type='card' activeKey={tabsKey} onChange={tabsChange} tabBarStyle={{ marginBottom: 0 }}>
-            <Tabs.TabPane tab='自己' key='自己'>
-                {!isHideMyGroup && <div style={{ width: `${bWith ? '100%' : 200}` }}>
-                    <Select style={{ minWidth: 150 }} placeholder="输入搜索公众号" onChange={inputChange} showArrow showSearch allowClear>
-                        {
-                            getWxGroupAll?.data?.map((item: any) => {
-                                return item?.mpAccounts?.map((list: any) => {
-                                    return <Option key={list.nickName + '_' + item.groupName} value={item.nickName} disabled={list?.verifyTypeInfo === -1}>
-                                        <img src={list?.headImg || localStorage?.bookImg} className={style.img} />  {list.nickName}
-                                    </Option>
-                                })
-                            })
-                        }
-                    </Select>
-                </div>
-                }
-                {!isHideMyGroup && <Menu
-                    onClick={menuItemClick}
-                    style={{ width: `${bWith ? '100%' : 200}`, height: props.height ? props.height : `${bWith ? '40' : 'calc(100vh - 390px)'} `, overflowY: 'auto', overflowX: 'hidden', borderRight: 0, backgroundColor: 'transparent' }}
-                    selectedKeys={selectedKeys}
-                    mode={"inline"}
-                >
-                    {
-                        props?.default && <Menu.Item key="all" icon={<QrcodeOutlined />}>全部公众号材料</Menu.Item>
-                    }
-                    {
-                        getWxGroupAll?.data?.map((item: any) => {
-                            return <Menu.Item
-                                key={item?.groupName}
-                            >
-                                <p style={{ margin: 0 }}>
-                                    {item?.mpAccounts?.some((mp: { appid: string }) => actionArr?.some((arr: { appid: string }) => mp.appid === arr.appid)) ? <i style={{ fontStyle: 'normal', color: 'red' }}>*</i> : ''}
-                                    {item?.groupName}
-                                    <span style={{ color: '#999' }}>({item?.mpAccounts?.length || 0})</span>
-                                </p>
-                            </Menu.Item >
-                        })
-                    }
-                </Menu>}
-            </Tabs.TabPane>
-            {
-                getAllOfMember?.data?.length > 0 && <Tabs.TabPane tab='组员' key='组员'>
-                    <div style={{ width: `${bWith ? '100%' : 200}` }}>
-                        <Select style={{ minWidth: 150 }} placeholder="输入搜索公众号" onChange={inputChange} showArrow showSearch allowClear>
-                            {
-                                getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                                    return item?.value?.map((list: any) => {
-                                        return <Option key={item?.key?.nickname + '_' + list?.id} value={list?.nickName + '_' + item?.key?.nickname + item?.key?.userId} disabled={list?.verifyTypeInfo === -1}>
-                                            <img src={list?.headImg || localStorage?.bookImg} className={style.img} /> {list?.nickName}
-                                        </Option>
-                                    })
-                                })
-                            }
-                        </Select>
-                    </div>
-                    <Menu
-                        onClick={crewMenuItemClick}
-                        style={{ width: `${bWith ? '100%' : 200}`, height: props.height ? props.height : `${bWith ? '40' : 'calc(100vh - 390px)'} `, overflowY: 'auto', overflowX: 'hidden', borderRight: 0, backgroundColor: 'transparent' }}
-                        selectedKeys={crewSelectedKeys}
-                        mode={"inline"}
-                    >
-                        {
-                            props?.default && <Menu.Item key="all" icon={<QrcodeOutlined />}>全部公众号材料</Menu.Item>
-                        }
-                        {
-                            getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                                return <Menu.Item
-                                    key={item?.key?.nickname + item?.key?.userId}
-                                >
-                                    <p onClick={() => { handelUserId(item?.key?.userId?.toString(), item?.key?.nickname) }} style={{ margin: 0 }}>
-                                        {item?.value?.some((mp: { appid: string }) => actionArr?.some((arr: { appid: string }) => mp.appid === arr.appid)) ? <i style={{ fontStyle: 'normal', color: 'red' }}>*</i> : ''}
-                                        {item?.key?.nickname}
-                                        <span style={{ color: '#999' }}>({item?.value?.length})</span>
-                                    </p>
-                                </Menu.Item >
-                            })
-                        }
-                    </Menu>
-                </Tabs.TabPane>
-            }
-        </Tabs>
-    </div >
-}
-
-export default LeftPage

+ 0 - 109
src/components/ActionModal/more.less

@@ -1,109 +0,0 @@
-.ico {
-  -webkit-animation: Tada 3s both infinite;
-  -moz-animation: Tada 3s both infinite;
-  -ms-animation: Tada 3s both infinite;
-  animation: Tada 3s both infinite;
-}
-.colud {
-  display: flex;
-  flex-flow: row nowrap;
-  > div:nth-child(2) {
-    flex: 0;
-  }
-  > div:nth-child(3) {
-    flex: 1;
-  }
-  span.ant-checkbox {
-    display: none;
-  }
-}
-.box {
-  > span {
-    &:first-child {
-      display: none;
-    }
-    &:last-child {
-      display: inline-block;
-    }
-  }
-}
-.card_title {
-  font-size: 12px;
-  color: #999;
-  display: block;
-}
-.card_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: 12px solid #4abe84;
-    border-top-color: transparent;
-    border-left-color: transparent;
-  }
-  &::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);
-  }
-}
-@keyframes Tada {
-  0% {
-    transform: scale(1);
-    transform: scale(1);
-  }
-
-  70%,
-  73% {
-    transform: scale(0.9) rotate(-3deg);
-    transform: scale(0.9) rotate(-3deg);
-  }
-
-  77%,
-  83%,
-  90%,
-  97% {
-    transform: scale(1.1) rotate(3deg);
-    transform: scale(1.1) rotate(3deg);
-  }
-
-  80%,
-  87%,
-  93% {
-    transform: scale(1.1) rotate(-3deg);
-    transform: scale(1.1) rotate(-3deg);
-  }
-
-  100% {
-    transform: scale(1) rotate(0);
-    transform: scale(1) rotate(0);
-  }
-}
-.card_box {
-  > div {
-    padding: 10px;
-  }
-}
-.item_img {
-  width: 25px;
-  border-radius: 2px;
-  margin-right: 5px;
-  background-color: #efefef;
-}

+ 0 - 301
src/components/ActionModal/more.tsx

@@ -1,301 +0,0 @@
-import { Button, Card, Checkbox, Col, Row } from 'antd'
-import Modal from 'antd/lib/modal/Modal'
-import React, { useCallback, useEffect, useState } from 'react'
-import { useModel } from 'umi'
-import Left from '@/components/ActionModal/left'
-import SelectLeft from '@/components/ActionModal/selectLeft'
-import style from './more.less'
-import NoFoundPage from '@/pages/empty'
-type Props = {
-    visible: boolean,
-    hideWx: () => void,
-    ok: (arr: any[]) => void,
-    defaultDtat: any[],
-    isSelect?: boolean
-}
-//更多选择弹窗
-let MoreModal = (props: Props) => {
-    const { visible, hideWx, ok, defaultDtat, isSelect = false } = props
-    const { mpAccounts, actionWX, dispatch, actionArr, getDataList, getAllOfMember } = useModel('useOperating.useWxGroupList',
-        models => ({
-            mpAccounts: models.state.mpAccounts,
-            actionWX: models.state.actionWX,
-            dispatch: models.dispatch,
-            actionArr: models.state.actionArr,
-            getDataList: models.getDataList,
-            getAllOfMember: models.getAllOfMember
-        }))
-    const [groupSyncWx, setGroupSyncWx] = useState<any[]>([])//当前组未选中的微信
-    const [selectState, setSelectState] = useState<{ isAll: boolean, isChecked: boolean }>({ isAll: false, isChecked: false })
-    const { syncWx, sync, graphicMaterialEdit } = useModel('useOperating.useMaterialContent', model => ({
-        syncWx: model.syncWx,
-        sync: model.sync,
-        graphicMaterialEdit: model.graphicMaterialEdit,
-    }))
-    //全选
-    let allSelect = useCallback(() => {
-        let isGroupWx: any[] = []//选中的数据
-        let newActionArr: any[] = []
-        let fiterMp: any[] = []
-        mpAccounts?.forEach((mp: { id: number, verifyTypeInfo: number }) => {
-            if (mp?.verifyTypeInfo !== -1) {//过滤未认证
-                fiterMp.push(mp)
-            }
-            actionArr?.forEach((wx: { id: number }) => {
-                if (wx.id === mp.id) {
-                    isGroupWx.push(wx)
-                }
-            })
-        })
-        if (isGroupWx?.length === fiterMp?.length || isGroupWx?.length === fiterMp?.length - groupSyncWx?.length) {//清空
-            newActionArr = actionArr?.filter((wx: { id: number }) => {
-                if (isGroupWx.every((groupwx: { id: number }) => wx.id !== groupwx.id)) {
-                    return wx
-                }
-                return
-            })
-            setSelectState({ isAll: false, isChecked: false })
-            dispatch({ type: 'setActionArr', params: { actionArr: newActionArr } })
-        } else {//全选
-            newActionArr = actionArr?.filter((wx: { id: number }) => {
-                if (isGroupWx.every((groupwx: { id: number }) => wx.id !== groupwx.id)) {
-                    return wx
-                }
-                return
-            })
-            newActionArr = [...newActionArr, ...fiterMp]
-            setSelectState({ isAll: false, isChecked: true })
-            dispatch({ type: 'setActionArr', params: { actionArr: newActionArr } })
-        }
-    }, [selectState, mpAccounts, actionArr, actionWX, groupSyncWx])
-    //反选
-    let returnSelct = useCallback(() => {
-        let isGroupWx: any[] = []
-        let returnWx: any[] = []
-        let newActionArr: any[] = []
-        let fiterMp: any[] = []
-        mpAccounts?.forEach((mp: { id: number, verifyTypeInfo: number }) => {
-            if (mp?.verifyTypeInfo !== -1) {//过滤未认证
-                fiterMp.push(mp)
-            }
-            actionArr?.forEach((wx: { id: number }) => {
-                if (wx.id === mp.id) {
-                    isGroupWx.push(wx)
-                }
-            })
-        })
-        returnWx = fiterMp?.filter((mp: { id: number }) => {
-            if (isGroupWx.every((wx: { id: number }) => mp.id !== wx.id)) {
-                return mp
-            }
-            return
-        })
-        newActionArr = actionArr?.filter((wx: { id: number }) => {
-            if (isGroupWx.every((groupwx: { id: number }) => wx.id !== groupwx.id)) {
-                return wx
-            }
-            return
-        })
-        if (returnWx.length !== 0 && groupSyncWx.length !== returnWx.length) {//假如选中个数的大于0
-            setSelectState({ isAll: true, isChecked: true })
-        } else {//假如等于0
-            setSelectState({ isAll: false, isChecked: false })
-        }
-        if (returnWx.length === fiterMp.length && groupSyncWx.length === 0) {
-            setSelectState({ isAll: false, isChecked: true })//假如反选值与当前组的个数一样证明全选
-        }
-        newActionArr = [...newActionArr, ...returnWx]
-        dispatch({ type: 'setActionArr', params: { actionArr: newActionArr } })
-    }, [selectState, mpAccounts, actionArr, actionWX, groupSyncWx])
-    //每次切换组检测全选状态
-    useEffect(() => {
-        let isGroupWx: any[] = []
-        let groupSyncWx: any[] = []
-        mpAccounts?.forEach((mp: { id: number }) => {
-            actionArr?.forEach((wx: { id: number }) => {
-                if (wx.id === mp.id) {
-                    isGroupWx.push(wx)
-                }
-            })
-        })
-        setGroupSyncWx(groupSyncWx)
-        // }
-        if (isGroupWx?.length === mpAccounts?.length) {
-            setSelectState({ isAll: false, isChecked: true })
-        } else {
-            setSelectState({ isAll: true, isChecked: true })
-        }
-        if (isGroupWx?.length === 0) {
-            setSelectState({ isAll: false, isChecked: false })
-        }
-    }, [mpAccounts, actionArr])
-    //关闭弹窗
-    let handleCancel = useCallback(() => {
-        dispatch({ type: 'setActionArr', params: { actionArr: [] } })
-        hideWx()
-    }, [])
-    //确定
-    let handleOk = useCallback(() => {
-        ok(actionArr)
-        dispatch({ type: 'setActionArr', params: { actionArr: [] } })
-    }, [actionArr])
-    //选中事件
-    let action = useCallback((item: any) => {
-        let isGroupWx: any[] = []//选中的数据
-        if (actionArr?.some((obj: { appid: number }) => obj.appid === item.appid)) {//删除
-            let newArr = actionArr?.filter((obj: { appid: number }) => obj.appid !== item.appid)
-            mpAccounts?.forEach((mp: { id: number }) => {
-                newArr?.forEach((wx: { id: number }) => {
-                    if (wx.id === mp.id) {
-                        isGroupWx.push(wx)
-                    }
-                })
-            })
-            if (isGroupWx.length === 0) {//假如为空
-                setSelectState({ isAll: false, isChecked: false })
-            } else {
-                setSelectState({ isAll: true, isChecked: true })
-            }
-            dispatch({ type: 'setActionArr', params: { actionArr: newArr } })
-        } else {//添加
-            let arr = [...actionArr, item]
-            if (mpAccounts?.every((mp: { id: number }) => arr?.some((wx: { id: number }) => mp.id === wx.id))) {//假如全部存在全选
-                setSelectState({ isAll: false, isChecked: true })
-            } else {
-                setSelectState({ isAll: true, isChecked: true })
-            }
-            dispatch({ type: 'setActionArr', params: { actionArr: arr } })
-        }
-    }, [actionArr, mpAccounts])
-    useEffect(() => {
-        let newArr: any[] = []
-        if (getDataList?.data) {
-            getDataList?.data?.forEach((data: { mpAccounts: any }) => {
-                if(data?.mpAccounts){
-                    newArr = [...data?.mpAccounts]
-                }
-            })
-        }
-
-        if (getAllOfMember?.data) {
-            getAllOfMember?.data?.forEach((data: { value: any }) => {
-                data?.value?.forEach((mp: { id: number }) => {
-                    if (newArr.every((arr: { id: number }) => mp?.id !== arr.id)) {
-                        newArr.push(mp)
-                    }
-                })
-            })
-        }
-    }, [getDataList?.data, getAllOfMember?.data, isSelect])
-    //编辑回填
-    useEffect(() => {
-        if (defaultDtat.length > 0) {
-            dispatch({ type: 'setActionArr', params: { actionArr: defaultDtat } })
-        }
-    }, [defaultDtat])
-    return <>
-        <Modal
-            title="批量选择公众号"
-            width={1040}
-            open={visible}
-            onOk={handleOk}
-            onCancel={handleCancel}
-            okText='确定'
-            cancelText='取消'
-            destroyOnClose
-            confirmLoading={syncWx.loading || sync.loading || graphicMaterialEdit.loading}
-        >
-            {
-                actionWX ? <Row className={style.colud}  >
-                    <Col >
-                      {isSelect ? <SelectLeft /> : <Left />}
-                        {/* <Left /> */}
-                    </Col>
-                    <Col>
-                        <Card
-                            style={{ height: '420px', overflow: 'hidden', minWidth: 290 }}
-                            title={
-                                <>
-                                    <span style={{ marginRight: 10 }}>组下成员</span>
-                                    <Checkbox
-                                        indeterminate={selectState.isAll}
-                                        onChange={allSelect}
-                                        checked={selectState.isChecked}
-                                    >
-                                        <span style={{ fontSize: 12, color: '#999' }}>全选</span>
-                                    </Checkbox>
-                                    <Button size='small' onClick={returnSelct}>反选</Button>
-                                </>
-                            }
-                            bodyStyle={{ height: 350, overflowY: 'auto' }}
-                        >
-                            <Checkbox.Group style={{ width: '100%', }} >
-                                <Row gutter={[10, 0]}>
-                                    {
-
-                                        mpAccounts?.map((item: any) => {
-                                            let isAction: any = actionArr?.some((obj: any) => obj?.appid === item?.appid)
-                                            return <Col key={item.id} span={24}>
-                                                <Checkbox value={item} className={style.box} onClick={() => action(item)} disabled={item?.verifyTypeInfo === -1}>
-                                                    <div
-                                                        className={`${isAction ? style.card_action : undefined} ${style.card_box}`}
-                                                    >
-                                                        <div
-                                                            style={{ display: 'flex', alignItems: 'center' }}
-                                                        >
-                                                            <img src={item?.headImg || localStorage?.bookImg} className={style.item_img} />
-                                                            {item.nickName}
-                                                        </div>
-                                                    </div>
-                                                </Checkbox>
-                                            </Col>
-                                        })
-                                    }
-                                </Row>
-                            </Checkbox.Group>
-                        </Card>
-                    </Col>
-                    <Col>
-                        <Card
-                            style={{ height: 420, overflow: 'hidden', minWidth: 280 }}
-                            title={
-                                <>
-                                    <span style={{ marginRight: 10 }}>已勾选</span>
-                                    <Button size='small' onClick={() => { dispatch({ type: 'setActionArr', params: { actionArr: [] } }) }}>清空</Button>
-                                </>
-                            }
-                            bodyStyle={{ height: 350, overflowY: 'auto' }}
-                        >
-                            <Checkbox.Group style={{ width: '100%' }} >
-                                <Row gutter={[10, 0]}>
-                                    {
-
-                                        actionArr?.map((item: any) => {
-                                            let isAction: any = actionArr?.some((obj: any) => obj?.appid === item?.appid)
-                                            return <Col key={item.id}>
-                                                <Checkbox value={item} className={style.box} onClick={() => action(item)}>
-                                                    <div
-                                                        className={`${isAction ? style.card_action : undefined} ${style.card_box}`}
-                                                    >
-                                                        <div
-                                                            style={{ display: 'flex', alignItems: 'center' }}
-                                                        >
-                                                            <img src={item?.headImg || localStorage?.bookImg} className={style.item_img} />
-                                                            {item.nickName}
-                                                        </div>
-                                                    </div>
-                                                </Checkbox>
-                                            </Col>
-                                        })
-                                    }
-                                </Row>
-                            </Checkbox.Group>
-                        </Card>
-                    </Col>
-                </Row> : <NoFoundPage />
-            }
-        </Modal >
-    </>
-}
-
-export default MoreModal

+ 0 - 203
src/components/ActionModal/selectLeft.tsx

@@ -1,203 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react'
-import { Menu, Select, Tabs } from 'antd'
-import { QrcodeOutlined } from '@ant-design/icons';
-import { useModel } from 'umi';
-import style from './index.less'
-const { Option } = Select
-interface Props {
-    default?: string,
-    height?: number | string,
-    type?: boolean
-}
-function LeftPage(props: Props) {
-    const [selectedKeys, setSelectedKeys] = useState<string[]>([]) //选中自己的菜单
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>([]) //选中组员的菜单
-    const { getWxGroupAll, actionMp, actionWx, getAllOfMember, state, dispatch } = useModel('useOperating.useWxGroupList', model => ({ getWxGroupAll: model.getDataList, ...model }))
-    const { userId, dispatch: userDispatch, } = useModel('useOperating.useUser', model => ({ userId: model.state.selectdUserId, dispatch: model.dispatch }))
-    const { tabsKey, actionArr } = state
-    let bWith = document.body.clientWidth < 700
-    //自己menuitem点击
-    let menuItemClick = (e: any) => {
-        checkData(e.key, '', tabsKey)
-    };
-    //组员menuitem点击
-    let crewMenuItemClick = (e: any) => {
-        checkData(e.key, '', tabsKey)
-    };
-    //tabs选中
-    let tabsChange = useCallback((key: string) => {
-        dispatch({ type: 'setTabsKey', params: { tabsKey: key } })
-        if (key === '自己') {
-            checkData(selectedKeys[0], '', key)
-        } else {
-            checkData(crewSelectedKeys[0], '', key)
-        }
-    }, [selectedKeys, crewSelectedKeys])
-    //搜索
-    let inputChange = (v: any) => {
-        if (v) {
-            let [name, key] = v.split('_')
-            checkData(key, name, tabsKey)
-        }
-    }
-    //设置选中的数据
-    let checkData = useCallback((key: string, ikey?: string, tabsKey?: string) => {
-        if (tabsKey === '自己') {
-            setSelectedKeys([key])
-            getWxGroupAll?.data?.forEach((item: any) => {
-                if (item.groupName === key) {//选中组
-                    actionMp(item?.mpAccounts)
-                    item?.mpAccounts?.forEach((wx: any) => {
-                        if (wx.nickName === ikey) {//选中微信
-                            actionWx(wx)
-                        }
-                    })
-                }
-            })
-        } else {
-            setCrewSelectedKeys([key])
-            getAllOfMember?.data?.forEach((item: {key: {nickname: string, userId: number}, value: any[]}) => {
-                if (item?.key?.nickname + item?.key?.userId === key) {//选中组
-                    actionMp(item.value)
-                    handelUserId(item?.key?.userId, item?.key?.nickname)
-                    item?.value?.forEach((wx: any) => {
-                        if (wx.nickName === ikey) {//选中微信
-                            actionWx(wx)
-                        }
-                    })
-                }
-            })
-        }
-    }, [getWxGroupAll, getAllOfMember])
-    useEffect(() => {
-        actionMp([])
-        if (tabsKey === '自己') {
-            if (getWxGroupAll?.data) {
-                let action = true
-                console.log(getWxGroupAll?.data)
-                getWxGroupAll?.data?.forEach((item: any, index: number) => {
-                    if (action && item['mpAccounts']?.length > 0) {
-                        action = false
-                        checkData(getWxGroupAll?.data[index]['groupName'], '', tabsKey)
-                    }
-                })
-            }
-        } else {
-            if (getAllOfMember?.data) {
-                let action = true
-                getAllOfMember?.data?.forEach((item: any, index: number) => {
-                    if (action && item['value']?.length > 0 && item.userId == userId) {
-                        action = false
-                        checkData(getAllOfMember?.data[index]['nickName'] + getAllOfMember?.data[index]['userId'], '', tabsKey)
-                    }
-                })
-            }
-        }
-    }, [getWxGroupAll?.data, getAllOfMember?.data, tabsKey])
-    //选中角色
-    let handelUserId = useCallback((userId, name) => {
-        userDispatch({ type: 'setUserId', params: { userId: userId?.toString(), name } })
-    }, [])
-    return <div>
-        <Tabs type='card' activeKey={tabsKey} onChange={tabsChange} tabBarStyle={{ marginBottom: 0 }}>
-            {tabsKey === '自己' && <Tabs.TabPane tab='自己' key='自己'>
-                <div style={{ width: `${bWith ? '100%' : 200}` }}>
-                    <Select style={{ minWidth: 150 }} placeholder="输入搜索公众号" onChange={inputChange} showArrow showSearch allowClear>
-                        {
-                            getWxGroupAll?.data?.map((item: any) => {
-                                return item?.mpAccounts?.map((list: any) => {
-                                    return <Option key={list.nickName + '_' + item.groupName} value={item.nickName} disabled={list?.verifyTypeInfo === -1}>
-                                        <img src={list?.headImg || localStorage?.bookImg} className={style.img} />  {list.nickName}
-                                    </Option>
-                                })
-                            })
-                        }
-                    </Select>
-                </div>
-                <Menu
-                    onClick={menuItemClick}
-                    style={{ width: `${bWith ? '100%' : 200}`, height: props.height ? props.height : `${bWith ? '40' : 'calc(100vh - 390px)'} `, overflowY: 'auto', overflowX: 'hidden', borderRight: 0, backgroundColor: 'transparent' }}
-                    selectedKeys={selectedKeys}
-                    mode={"inline"}
-                >
-                    {
-                        props?.default && <Menu.Item key="all" icon={<QrcodeOutlined />}>全部公众号材料</Menu.Item>
-                    }
-                    {
-                        getWxGroupAll?.data?.map((item: any) => {
-                            return <Menu.Item
-                                key={item?.groupName}
-                            >
-                                <p>
-                                    {item?.mpAccounts?.some((mp: { appid: string }) => actionArr?.some((arr: { appid: string }) => mp.appid === arr.appid)) ? <i style={{ fontStyle: 'normal', color: 'red' }}>*</i> : ''}
-                                    {item?.groupName}
-                                    <span style={{ color: '#999' }}>({item?.mpAccounts?.length || 0})</span>
-                                </p>
-                            </Menu.Item >
-                        })
-                    }
-                </Menu>
-            </Tabs.TabPane>}
-            {
-                getAllOfMember?.data?.length > 0 && tabsKey === '组员' && <Tabs.TabPane tab='组员' key='组员'>
-                    <div style={{ width: `${bWith ? '100%' : 200}` }}>
-                        <Select style={{ minWidth: 150 }} placeholder="输入搜索公众号" onChange={inputChange} showArrow showSearch allowClear>
-                            {
-                                getAllOfMember?.data?.map((item: any) => {
-                                    if (item.userId == userId) {
-                                        return item?.userMpAccounts?.map((list: any) => {
-                                            return <Option key={item?.nickName + '_' + list?.id} value={list?.nickName + '_' + item?.nickName + item?.userId} disabled={list?.verifyTypeInfo === -1}>
-                                                <img src={list?.headImg || localStorage?.bookImg} className={style.img} /> {list?.nickName}
-                                            </Option>
-                                        })
-                                    }
-                                })
-                            }
-                        </Select>
-                    </div>
-                    <Menu
-                        onClick={crewMenuItemClick}
-                        style={{ width: `${bWith ? '100%' : 200}`, height: props.height ? props.height : `${bWith ? '40' : 'calc(100vh - 390px)'} `, overflowY: 'auto', overflowX: 'hidden', borderRight: 0, backgroundColor: 'transparent' }}
-                        selectedKeys={crewSelectedKeys}
-                        mode={"inline"}
-                    >
-                        {
-                            props?.default && <Menu.Item key="all" icon={<QrcodeOutlined />}>全部公众号材料</Menu.Item>
-                        }
-                        {/* {
-                            getAllOfMember?.data?.map((item: any) => {
-                                if (item?.userId == userId) {
-                                    return <Menu.Item
-                                        key={item?.nickName + item?.userId}
-                                    >
-                                        <p>
-                                            {item?.userMpAccounts?.some((mp: { appid: string }) => actionArr?.some((arr: { appid: string }) => mp.appid === arr.appid)) ? <i style={{ fontStyle: 'normal', color: 'red' }}>*</i> : ''}
-                                            {item?.nickName}
-                                            <span style={{ color: '#999' }}>({item?.userMpAccounts?.length})</span>
-                                        </p>
-                                    </Menu.Item >
-                                }
-                                return
-                            })
-                        } */}
-                        {
-                            getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                                return <Menu.Item
-                                    key={item?.key?.nickname + item?.key?.userId}
-                                >
-                                    <p onClick={() => { handelUserId(item?.key?.userId?.toString(), item?.key?.nickname) }}>
-                                        {item?.value?.some((mp: { appid: string }) => actionArr?.some((arr: { appid: string }) => mp.appid === arr.appid)) ? <i style={{ fontStyle: 'normal', color: 'red' }}>*</i> : ''}
-                                        {item?.key?.nickname}
-                                        <span style={{ color: '#999' }}>({item?.value?.length})</span>
-                                    </p>
-                                </Menu.Item >
-                            })
-                        }
-                    </Menu>
-                </Tabs.TabPane>
-            }
-        </Tabs>
-    </div >
-}
-
-export default LeftPage

+ 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 - 166
src/components/Alink/index.tsx

@@ -1,166 +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 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} 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
-            open={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>
-            </Row>
-        </Modal>
-    </div>
-}
-
-export default Alink

+ 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 - 36
src/components/ColorPicker/index.less

@@ -1,36 +0,0 @@
-.color {
-    width: 20px;
-    height: 20px;
-    border-radius: 2px;
-}
-.swatch{
-    padding: 5px;
-    background: #fff;
-    border-radius: 1px;
-    box-shadow: 0 0 0 1px rgba(0,0,0,.1);
-    display: inline-block;
-    cursor: pointer;
-    margin-top: 8px;
-} 
-.colorPicker{
-    position: relative;
-}
-.popover{
-    position: absolute;
-    top: 45px;
-    left: 0;
-    z-index: 100;
-    .cover{
-        position: fixed;
-        top: 0;
-        left: 0;
-        bottom: 0;
-        right: 0;
-    }
-    .sketchPicker{
-        position: absolute;
-    }
-}
-.swatch .color{
-    border: 1px solid rgb(199, 199, 199);
-}

+ 0 - 55
src/components/ColorPicker/index.tsx

@@ -1,55 +0,0 @@
-import React, { useCallback, useEffect, useState } from "react"
-import { SketchPicker } from 'react-color'
-import style from './index.less'
-type props = {
-    onColor: (color: string) => void,
-    defaultColor?: string,
-    value?: string,
-}
-
-const ColorPicker = (props: props) => {
-    let { onColor, defaultColor = "#000000", value } = props
-    const [displayColorPicker, setDisplayColorPicker] = useState<boolean>(false)
-    const [color, setColor] = useState<any>(defaultColor)
-
-    const handleClick = useCallback(() => {
-        setDisplayColorPicker(!displayColorPicker)
-    }, [])
-
-    const handleClose = useCallback(() => {
-        setDisplayColorPicker(false)
-    }, [])
-
-    const handleChange = useCallback((e: any) => {
-        setColor(e.hex)
-        onColor(e.hex)
-    }, [color])
-
-    useEffect(() => {
-        onColor(color)
-    }, [])
-
-    useEffect(() => {
-        if (value) {
-            setColor(value)
-            onColor(value)
-        }
-    }, [value])
-    
-    return <>
-        <div className={style.colorPicker}>
-            <div className={style.swatch} onClick={handleClick}>
-                <div className={style.color} style={{ backgroundColor: color }} />
-            </div>
-            {
-                displayColorPicker ? <div className={style.popover}>
-                    <div className={style.cover} onClick={handleClose} />
-                    <SketchPicker color={color} onChange={handleChange} className={style.sketchPicker} />
-                </div> : null
-            }
-
-        </div>
-    </>
-}
-
-export default React.memo(ColorPicker)

+ 0 - 43
src/components/DatePicker/index.tsx

@@ -1,43 +0,0 @@
-import React from 'react'
-import { DatePicker, Space } from 'antd';
-import moment from 'moment';
-
-const { RangePicker } = DatePicker;
-interface Props {
-    model: 'RangePicker' | 'DatePicker',
-    DatePickerChange: (moment: any, formatString: [string, string] | string) => void,
-    allowClear?: boolean,
-    className?: string,
-    showTime?: boolean,
-    scope?: { num: number, unit: 'day' | 'week' | 'month' | 'year' },//自定义时间跨度
-    date?: any,
-    before?: number,//截止日期以今天为底的前几天填数字
-    isDisabledDate?: boolean,//是否开启时间限制
-    placeholder?: any,
-    style?: { width: number | string }
-}
-
-function DatePickePage(props: Props) {
-    let { model, DatePickerChange, scope, before, isDisabledDate = true, allowClear = false, ...prop } = props
-    const disabledDate = (current: any) => {
-        let tppday = before ? current && current > moment(new Date()).subtract(before, 'day') : current && current > moment().endOf('day') //最晚日期
-        let isScope = false
-        if (scope) {
-            isScope = current && current < moment().subtract(scope?.num, scope?.unit)//可选日期
-        }
-        return tppday || isScope;
-    };
-    return <>
-        <Space direction="vertical" size={12}>
-            {
-                model === 'RangePicker' ?
-                    <RangePicker {...prop} onChange={(mo: any, str: any) => {
-                        DatePickerChange(mo, str)
-                    }} disabledDate={disabledDate} value={props?.date && props?.date?.every((s: string) => s !== '') ? [moment(props.date[0]), moment(props.date[1])] : undefined} allowClear={allowClear} /> :
-                    <DatePicker onChange={DatePickerChange} {...prop} disabledDate={isDisabledDate ? disabledDate : undefined} allowClear={true} value={props.date ? moment(props.date) : undefined} />
-            }
-        </Space>
-    </>
-}
-export default DatePickePage
-

+ 0 - 71
src/components/DebounceSelect/index.tsx

@@ -1,71 +0,0 @@
-import { Select, Spin } from 'antd';
-import type { SelectProps } from 'antd/es/select';
-import debounce from 'lodash/debounce';
-import React, { useMemo, useRef, useState } from 'react';
-
-export interface DebounceSelectProps<ValueType = any>
-    extends Omit<SelectProps<ValueType | ValueType[]>, 'options' | 'children'> {
-    fetchOptions: (search: string) => Promise<ValueType[]>;
-    debounceTimeout?: number;
-}
-
-function DebounceSelect<
-    ValueType extends { key?: string; label: React.ReactNode; value: string | number } = any,
-    >({ fetchOptions, debounceTimeout = 800, ...props }: DebounceSelectProps<ValueType>) {
-    const [fetching, setFetching] = useState(false);
-    const [options, setOptions] = useState<ValueType[]>([]);
-    const fetchRef = useRef(0);
-
-    const debounceFetcher = useMemo(() => {
-        const loadOptions = (value: string) => {
-            fetchRef.current += 1;
-            const fetchId = fetchRef.current;
-            setOptions([]);
-            setFetching(true);
-
-            fetchOptions(value).then(newOptions => {
-                if (fetchId !== fetchRef.current) {
-                    // for fetch callback order
-                    return;
-                }
-
-                setOptions(newOptions);
-                setFetching(false);
-            });
-        };
-
-        return debounce(loadOptions, debounceTimeout);
-    }, [fetchOptions, debounceTimeout]);
-
-    return (
-        <Select
-            labelInValue
-            filterOption={false}
-            onSearch={debounceFetcher}
-            notFoundContent={fetching ? <Spin size="small" /> : null}
-            {...props}
-            options={options}
-        />
-    );
-}
-interface UserValue {
-    label: string;
-    value: string;
-}
-
-async function fetchUserList(username: string): Promise<UserValue[]> {
-    console.log('fetching user', username);
-
-    return fetch('https://randomuser.me/api/?results=5')
-        .then(response => response.json())
-        .then(body =>
-            body.results.map(
-                (user: { name: { first: string; last: string }; login: { username: string } }) => ({
-                    label: `${user.name.first} ${user.name.last}`,
-                    value: user.login.username,
-                }),
-            ),
-        );
-}
-
-export {DebounceSelect,fetchUserList}

+ 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 - 265
src/components/Editor/Box/TEditor.tsx

@@ -1,265 +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 mp_miniprogram = html?.match(/(<mp-miniprogram .*>\s?<\/mp-miniprogram>)/)
-        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>/)
-        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)
-        })
-        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])
-    // 腾讯图片出去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)
-            }
-        }
-    }, [])
-    // console.log('value======>',value)
-    return <>
-        <Editor
-            apiKey='wkn1n49be4rmnjq9h33nzp15z9n9v5jn2n4dr3kav8bx7y4y'
-
-            // 初始化
-            onInit={(evt, editor) => {
-                editorRef.current = editor
-                setLoding(false)
-                isOk(editor);
-                // 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,//输入地址时的自动完成
-                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',//工具换行
-                paste_webkit_styles: 'all',
-                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) => {
-                    editorRef.current.insertContent(props)
-                    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 - 516
src/components/Editor/Box/index.tsx

@@ -1,516 +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 } = 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) => {
-                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})
-        if (sid !== actionId ) {
-            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)
-        }
-    }, [actionId, dataArr,  sid])
-    //编辑回填
-    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 - 38
src/components/Expression/index.less

@@ -1,38 +0,0 @@
-.expression {
-  width: 400px;
-  overflow: hidden;
-  display: flex;
-  position: relative;
-  padding-bottom: 10px;
-  .box {
-    width: 400px;
-    display: flex;
-    flex-flow: row wrap;
-    flex-shrink: 0;
-    transition: all .5s;
-    > span {
-      font-size: 20px;
-      padding: 5px;
-      cursor: pointer;
-    }
-  }
-  .bottom {
-    position: absolute;
-    bottom: 0px;
-    width: 100%;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-  .yd {
-    width: 10px;
-    height: 10px;
-    border-radius: 50%;
-    background-color: #efefef;
-    margin-right: 5px;
-    cursor: pointer;
-  }
-  .action{
-      background-color: yellowgreen;
-  }
-}

+ 0 - 79
src/components/Expression/index.tsx

@@ -1,79 +0,0 @@
-import { MehOutlined } from '@ant-design/icons'
-import { Popover } from 'antd'
-import style from './index.less'
-import React, { useCallback, useState } from 'react'
-const arr1 = [
-    "😄", "😊", "😃", "😉", "😍", "😘", "😚", "😳", "😁", "😌", "😜", "😝", "😒", "😏",
-    "😓", "😔", "😞", "😖", "😥", "😰", "😨", "😣", "😢", "😭", "😂", "😲", "😱", "😠",
-    "😡", "😪", "😷", "👿", "👽", "❤️", "💔", "💘", "✨", "🌟", "❕", "❔", "💤", "💦",
-    "🎵", "🔥", "💩", "👍", "👎", "👊", "✌️", "👆", "👇", "👉", "👈", "☝️"
-]
-const arr2 = [
-    "💪", "💏", "💑", "👦", "👧", "👩", "👨", "👼", "💀", "👄", "☀", "☔", "☁", "⛄",
-    "🌙", "⚡", "🌊", "🐱", "🐶", "🐭", "🐹", "🐰", "🐺", "🐸", "🐯", "🐨", "🐻", "🐷",
-    "🐮", "🐗", "🐵", "🐴", "🐍", "🐦", "🐔", "🐧", "🐛", "🐙", "🐠", "🐳", "🐬", "🌹",
-    "🌺", "🌴", "🌵", "💝", "🎃", "👻", "🎅", "🎄", "🎁", "🔔", "🎉", "🎈"
-]
-const arr3 = [
-    "💿", "📷", "🎥", "💻", "📺", "☎", "🔓", "🔒", "🔑", "🔨", "💡", "📫", "🛀", "💰",
-    "💣", "🔫", "💊", "🏈", "🏀", "⚽", "⚾", "⛳", "🏆", "👾", "🎤", "🎸", "👙", "👑",
-    "🌂", "👜", "💄", "💍", "💎", "☕", "🍺", "🍻", "🍸", "🍔", "🍟", "🍝", "🍣", "🍜",
-    "🍳", "🍦", "🎂", "🍎", "✈", "🚀", "🚲", "🚄", "⚠", "🏁", "🚹", "🚺"
-]
-const arr4 = ["⭕", "❌", "©", "®", "™"]
-type Props = {
-    getStr: (str: string, range: Range) => void//回调传回选中表情和最后光标位置
-    range: Range//文本光标节点
-}
-function Expression(props: Props) {
-    const [eq, setEq] = useState<number>(0)//当前页
-    const [left, setLeft] = useState<number>(0)//偏移
-    const [isShow, setIsShow] = useState<boolean>(false)//弹窗
-    //显示关闭弹窗
-    const exit = useCallback(() => {
-        setIsShow(!isShow)
-    }, [isShow])
-    //点击表情
-    const handelClick = useCallback((str: string) => {
-        props.getStr(str, props.range)
-        setIsShow(false)
-    }, [props.range])
-    //点击翻页
-    const handelAction = useCallback((eq: number) => {
-        setEq(eq)
-        setLeft(eq * 400)
-    }, [])
-    return <div>
-        <Popover
-            content={
-                <div className={style.expression} >
-                    {
-                        [arr1, arr2, arr3, arr4].map((item: string[], index: number) => {
-                            return <div key={index} className={style.box} style={{ transform: `translateX(-${left}px)` }} >
-                                {
-                                    item.map((em: string, index: number) => {
-                                        return <span key={index} onClick={() => handelClick(em)}>{em}</span>
-                                    })
-                                }
-                            </div>
-                        })
-                    }
-                    <div className={style.bottom}>
-                        {
-                            [0, 1, 2, 3].map((item) => {
-                                return <span className={`${style.yd} ${eq === item ? style.action : undefined}`} key={item} onClick={() => handelAction(item)} />
-                            })
-                        }
-                    </div>
-                </div>
-            }
-            trigger="click"
-            open={isShow}
-            onOpenChange={exit}
-        >
-            <MehOutlined onClick={exit} />
-        </Popover>
-    </div>
-}
-
-export default Expression

+ 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 - 89
src/components/FileBox/components/fileModal/index.tsx

@@ -1,89 +0,0 @@
-import WxSelect from '@/components/WxSelect'
-import { Input, InputNumber, Modal, Tag } from 'antd'
-import React, { useMemo } from 'react'
-import { useModel } from 'umi'
-/**新建文件夹,修改非图文素材名称 */
-function FileModal(props: { isAll?: boolean }) {
-    const { isAll } = props
-    const { state, set, fileOk, nameOk, offEditFile } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    const { fileVisible, actionItem, fileName, sort, videoDescription, videoTitle } = state
-    const { state: { selectWx }, initSelectWx } = useModel('useOperating.useWxGroupList')//公众号筛选
-    const title = useMemo(() => {
-        if (actionItem?.folder) {
-            return '编辑文件夹'
-        }
-        switch (actionItem?.fileType) {
-            case 'image':
-                return '编辑图片';
-            case 'voice':
-                return '编辑音频';
-            case 'video':
-                return '编辑视频';
-        }
-        return '新建文件夹'
-    }, [actionItem])
-    console.log(state)
-    return <Modal
-        open={fileVisible}
-        destroyOnClose
-        onOk={(e) => { actionItem ? nameOk(selectWx) : fileOk(e, undefined, selectWx); initSelectWx() }}
-        onCancel={() => { offEditFile(); initSelectWx() }}
-        width={400}
-        title={title}
-        closable={false}
-    >
-        <Tag color='warning'>数值越大越靠前</Tag>
-        <div style={{ display: 'flex', flexFlow: 'row', marginBottom: 10, alignItems: 'center', marginTop: 10 }}>
-            <label style={{ width: '15%' }}>排序:</label>
-            <InputNumber
-                style={{ width: '100%' }}
-                value={sort}
-                placeholder='请输入序号, 数值越大越靠前'
-                onChange={(e) => {
-                    set({ sort: e || 0 })
-                }}
-            />
-        </div>
-
-        {
-            actionItem?.fileType === 'video' ? <div>
-                <div style={{ display: 'flex', flexFlow: 'row', marginBottom: 10, alignItems: 'center' }}>
-                    <label style={{ width: '15%' }}>名称:</label>
-                    <Input
-                        value={videoTitle}
-                        allowClear
-                        placeholder='请输入名称'
-                        onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                            set({ videoTitle: event.target.value })
-                        }}
-                    /></div>
-                <div style={{ display: 'flex', flexFlow: 'row', alignItems: 'center' }}>
-                    <label style={{ width: '15%' }}>描述:</label>
-                    <Input.TextArea
-                        placeholder='请输入描述内容'
-                        allowClear
-                        value={videoDescription}
-                        onChange={(event: React.ChangeEvent<HTMLTextAreaElement>) => {
-                            set({ videoDescription: event.target.value })
-                        }}
-                    />
-                </div>
-                <WxSelect />
-            </div> : <>
-                <div style={{ display: 'flex', flexFlow: 'row', marginBottom: 10, alignItems: 'center' }}>
-                    <label style={{ width: '15%' }}>名称:</label>
-                    <Input
-                        value={fileName}
-                        allowClear
-                        placeholder='请输入名称'
-                        onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
-                            set({ fileName: event.target.value })
-                        }}
-                    />
-                </div>
-                <WxSelect />
-            </>
-        }
-    </Modal>
-}
-export default React.memo(FileModal)

+ 0 - 47
src/components/FileBox/components/fileModal/sortModal.tsx

@@ -1,47 +0,0 @@
-import { InputNumber, Modal, Tag } from 'antd'
-import React, { useEffect, useState } from 'react'
-import { useModel } from 'umi'
-
-
-interface Props {
-    isAll?: boolean
-}
-function SortModal(props: Props) {
-    const { isAll } = props
-    const { state, offEditFile, configSort, list, set } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    const { sortVisible, actionItem } = state
-    const [sort, setSort] = useState<number>(0)
-
-    useEffect(() => {
-        setSort(actionItem?.sort || 0)
-    }, [actionItem?.sort])
-
-    const sortHandle = () => {
-        configSort.run({ sysMediaId: actionItem?.id, sort: sort }).then(res => {
-            if (res) {
-                list?.refresh()
-                set({ sortVisible: false, actionItem: null })
-            }
-        })
-    }
-
-    return <Modal
-        open={sortVisible}
-        width={400}
-        title={'编辑排序'}
-        closable={false}
-        onOk={sortHandle}
-        onCancel={() => { offEditFile() }}
-    >
-        <Tag color='warning'>数值越大越靠前</Tag>
-        <InputNumber
-            style={{ width: '100%', marginTop: 10 }}
-            value={sort}
-            placeholder='请输入序号, 数值越大越靠前'
-            onChange={(e) => {
-                setSort(e || 0)
-            }} 
-        />
-    </Modal>
-}
-export default SortModal

+ 0 - 120
src/components/FileBox/components/imgModal/index.tsx

@@ -1,120 +0,0 @@
-import React, { useCallback, useState } from 'react'
-import { Modal } from 'antd'
-import FormItem from '@/components/Formitem'
-import { FormConfig } from '@/components/Formitem/type'
-import { useModel } from 'umi'
-import WxSelect from '@/components/WxSelect'
-/**新建非图文素材 */
-let ImgModal = React.memo((props: { isAll?: boolean }) => {
-    const { isAll } = props
-    const [fromsubmit, setFromsubmit] = useState<() => Promise<any>>()//存放from提交事件
-    const callback = useCallback((fnc: () => Promise<any>) => { setFromsubmit(fnc) }, [])//回调获取from提交事件
-    const { state, typeEnum, fileOk, offEditFile } = useModel(isAll ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    const { imgVisrible, fileType, actionItem } = state
-    const { state: { selectWx }, initSelectWx} = useModel('useOperating.useWxGroupList')//公众号筛选
-    return <Modal
-        title={(actionItem ? '编辑' : '新建') + typeEnum[fileType as keyof typeof typeEnum]}
-        open={imgVisrible}
-        onOk={(e) => { fileOk(e, fromsubmit, selectWx);initSelectWx() }}
-        onCancel={()=>{
-            offEditFile();
-            initSelectWx()
-        }}
-        destroyOnClose
-        maskClosable={false}
-    >
-        <FormItem
-            formConfig={config(typeEnum[fileType as keyof typeof typeEnum])}
-            flow='column'
-            getFormSubmit={callback}
-            defaultProps={{ sort: 0 }}
-            isAll={isAll}
-        />
-        <WxSelect />
-    </Modal>
-})
-export default ImgModal
-let config: (name: string,) => FormConfig[] = (name) => {
-    let videoArr: FormConfig[] = [
-        {
-            label: name + '名称',
-            tag: 'input',
-            name: 'videoTitle',
-            width: 200,
-        },
-        
-        {
-            label: name + '描述',
-            tag: 'TextArea',
-            name: 'videoDescription',
-            width: 300,
-        },
-        {
-            label: '排序',
-            tag: 'inputNumber',
-            name: 'sort',
-            width: 200,
-        },
-        {
-            label: '上传' + name,
-            tag: 'inputFile',
-            name: 'file',
-            required: true,
-            message: '请上传文件'
-        }
-    ]
-    let imgArr: FormConfig[] = [
-        {
-            label: name + '名称',
-            tag: 'input',
-            name: 'fileName',
-            width: 200,
-        },
-        {
-            label: '排序',
-            tag: 'inputNumber',
-            name: 'sort',
-            width: 200,
-        },
-        {
-            label: '上传' + name,
-            tag: 'imgCrop',
-            name: 'file',
-            required: true,
-            message: '请上传文件'
-        }
-    ]
-    let arr: FormConfig[] = [
-        {
-            label: name + '名称',
-            tag: 'input',
-            name: 'fileName',
-            width: 200,
-        },
-        {
-            label: '排序',
-            tag: 'inputNumber',
-            name: 'sort',
-            width: 200,
-        },
-        {
-            label: '上传' + name,
-            tag: 'inputFile',
-            name: 'file',
-            required: true,
-            message: '请上传文件'
-        }
-    ]
-    if (name === '编辑') {
-        return [
-            {
-                label: name + '名称',
-                tag: 'input',
-                name: 'fileName',
-                width: 200
-            },
-        ]
-    }
-    return name === '视频' ? videoArr : name === '图片' ? imgArr : arr
-}
-

+ 0 - 211
src/components/FileBox/components/newsModal/index.less

@@ -1,211 +0,0 @@
-.left {
-  width: 100%;
-  .left_top {
-    display: flex;
-    justify-content: left;
-    align-items: center;
-    padding: 10px;
-    border-bottom: 1px solid #efefef;
-    font-weight: 500;
-  }
-  .left_ul {
-    height: calc(100vh - 150px);
-    overflow-y: auto;
-    > ul {
-      display: flex;
-      flex-flow: column;
-      padding: 10px;
-      overflow-y: auto;
-      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);
-    }
-  }
-}
-.right_fb {
-  height: calc(100vh - 112px);
-  overflow-y: scroll;
-  > div {
-    width: 100%;
-    display: flex;
-    flex-flow: column;
-  }
-  .upload {
-    border: 1px dashed #d8d8d8;
-    border-radius: 3px;
-    cursor: pointer;
-    margin: 10px 0;
-    position: relative;
-    img {
-      object-fit: cover;
-      width: 100%;
-      height: 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);
-    }
-  }
-  .min {
-    width: 88px;
-    height: 88px;
-  }
-  .max {
-    width: 220px;
-    height: 95px;
-  }
-  .right_textArea {
-    span:last-child {
-      float: right;
-      text-align: right;
-    }
-  }
-}
-.box {
-  border: 1px solid #efefef;
-  height: 100%;
-  > div {
-    &:nth-child(1) {
-      border-right: 1px solid #efefef;
-    }
-    &:last-child {
-      padding: 0 10px;
-      border-left: 1px solid #efefef;
-    }
-  }
-}
-.title1 {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 200px;
-}
-.title {
-  width: 100%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}

+ 0 - 54
src/components/FileBox/components/newsModal/index.tsx

@@ -1,54 +0,0 @@
-import React, { useImperativeHandle, useState } from 'react'
-import { Col, Drawer, Row } from 'antd'
-import style from './index.less'
-import Left from './left'
-import Right from './right'
-import Editor from '@/components/Editor/Box'
-import { useModel } from 'umi'
-//isWx是否是微信用来判断调用不同的接口逻辑默认不是
-const DrawerPage = React.forwardRef((props: any, ref) => {
-    const { styleRight = '', isAll = true, callback = null } = props
-    const [visible, setVisible] = useState<boolean>(false)//抽屉
-    const [isEdit, setIsEdit] = useState<boolean>(false)//是否编辑
-    const [editId, setEditId] = useState<string>('')//编辑的ID
-    const { drawerDispatch, actionData } = useModel('useOperating.useMaterialDrawer', model => ({ drawerDispatch: model.dispatch, actionData: model.state.actionData }))
-    //映射ref方法
-    useImperativeHandle(ref, () => ({
-        showDrawer,
-    }))
-    //抽屉显示
-    let showDrawer = (props?: any) => {
-        setEditId(props?.editId || '')
-        setIsEdit(props?.isEdit || false)//设置是否编辑
-        setVisible(true)//开启弹窗
-        localStorage.setItem('collapsed', '1')
-    };
-    //抽屉关闭
-    let onClose = () => {
-        // isEdit ? drawerDispatch({ type: 'initData' }) : drawerDispatch({ type: 'action', params: { actionId: 1 } })//编辑取消后清空数据
-        drawerDispatch({ type: 'initData' })
-        setVisible(false)//关闭抽屉
-        setIsEdit(false)//设回flase以免新建关闭后销毁数据
-        localStorage.setItem('collapsed', '0')
-    };
-    return <Drawer
-        placement="right"
-        closable={false}
-        onClose={onClose}
-        open={visible}
-        getContainer={false}
-        width='90%'
-        destroyOnClose
-        style={styleRight ? { right: styleRight } : {}}
-    >
-        <Row className={style.box}>
-            <Col flex='1'><Left isWx={props?.isWx} /></Col>
-            <Col flex='3'>{visible && <Editor onClose={onClose} editId={editId} editData={actionData?.dataArr} syncNews={props?.syncNews} isWx={props?.isWx} isShowWx={props?.isShowWx} isAll={isAll} callback={callback}/>}</Col>
-            <Col flex='1'><Right isShowWx={props?.isShowWx} /></Col>
-        </Row>
-    </Drawer>
-})
-
-export default DrawerPage
-
-

+ 0 - 158
src/components/FileBox/components/newsModal/left.tsx

@@ -1,158 +0,0 @@
-import React, { useCallback, useState } from 'react'
-import style from './index.less'
-import { ArrowDownOutlined, ArrowUpOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'
-import { Avatar, Input, message, Modal, Space } from 'antd'
-import { useModel } from 'umi'
-import { exportMediaByUrl1 } from '@/services/operating/material'
-const Left = React.memo((props: { isWx?: boolean }) => {
-    const { isWx } = props
-    const { drawerState: { dataArr, actionId }, dispatch } = useModel('useOperating.useMaterialDrawer', model => ({ drawerState: model.state, dispatch: model.dispatch }))
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const { ueditorRef } = useModel('useOperating.useMaterialDrawer', model => ({ ueditorRef: model.state.ueditorRef }))
-    const [showNews, setShowNews] = useState<boolean>(false)//导入文章
-    const [newsUrl, setNewsUrl] = useState<string>('')//文章地址
-
-    //导入文章
-    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}的地址错误,请输入正确的文章地址!`)
-            }
-        })
-        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, thumbMediaUrl, title } = r.data
-                            contentSourceUrl = contentSourceUrl.replace(/['"]*/g, '')
-                            content = content.replace('data-src', 'src').replace(/\<mpvoice[\s\S]*\<\/mpvoice\>/ig, '')
-                            index === 0 && ueditorRef?.setContent(content, false)
-                            arr.push({ menuId: actionId + index, content, contentSourceUrl, digest, thumbMediaUrl, title })
-                        }
-                    })
-                    arr = arr.sort((a: { menuId: number }, b: { menuId: number }) => { return a.menuId - b.menuId })
-                    dispatch({ type: 'importNews', params: { data: { dataArrs: arr, actionId } } })
-                }
-            }).catch(err => { console.log(err) })
-            setShowNews(false)
-        }
-    }, [newsUrl, actionId, ueditorRef])
-    return <div className={style.left}>
-        {
-            isWx && <div className={style.left_top}>
-                <Space>
-                    <Avatar src={actionWX?.headImg || "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"} />
-                    <span>{actionWX?.nickName}</span>
-                </Space>
-            </div>
-        }
-        <div className={style.left_ul}>
-            <ul>
-                {
-                    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.thumbMediaUrl || item.thumbUrl || '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.thumbMediaUrl || item.thumbUrl || '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>
-                    })
-                }
-            </ul>
-            {
-                dataArr?.length < 8 && <span onClick={() => dispatch({ type: 'addDataArr' })} ><PlusOutlined />新建</span>
-            }
-            <span onClick={() => { setShowNews(true) }} style={{ marginTop: 10 }}><PlusOutlined />导入文章</span>
-            <Modal
-                open={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>
-    </div>
-})
-export default Left

+ 0 - 130
src/components/FileBox/components/newsModal/right.tsx

@@ -1,130 +0,0 @@
-import React, { useCallback, useMemo, useState } from 'react'
-import { Divider, Input, InputNumber, Tabs, Tag } from 'antd'
-import style from './index.less'
-import { PlusOutlined } from '@ant-design/icons';
-import SmMaterialModal from '@/components/MaterialModal/smModalBox';
-import { useModel } from 'umi';
-import WxSelect from '@/components/WxSelect';
-const { TabPane } = Tabs;
-
-let Right = React.memo((props: any) => {
-    const { drawerDispatch, drawerState: { actionId, dataArr, sort } } = useModel('useOperating.useMaterialDrawer', model => ({
-        drawerDispatch: model.dispatch,
-        drawerState: model.state
-    }))
-    const { show, hide, state: { visible } } = useModel('useOperating.useMaterialModal')
-    const [digest, setDigest] = useState<string>('') //摘要
-    const [authorStr, setAuthor] = useState<string>('') //作者
-    const [contentSourceUrlStr, setContentSourceUrl] = useState<string>('') //原文链接
-
-    //点击上传打开弹窗获取数据
-    let upload = useCallback(() => {
-        show()
-    }, [])
-    //跟随选择更新图片
-    const defaultValue: any = useMemo(() => {
-        let obj = {}
-        dataArr.forEach((item: any) => {
-            if (item.menuId === actionId) {
-                setDigest(item.digest || '')
-                setAuthor(item.author || '')
-                setContentSourceUrl(item.contentSourceUrl || '')
-                obj = item
-            }
-        })
-        return obj
-    }, [dataArr, actionId, sort])
-    //字数并插入dataArr
-    let strLeng = useCallback((v: React.ChangeEvent<HTMLTextAreaElement>) => {
-        drawerDispatch({ type: 'pushData', params: { menuId: actionId, digest: v.target.value, } })
-        setDigest(v.target.value)
-    }, [actionId])
-    //作者插入
-    let author = useCallback((v: React.ChangeEvent<HTMLInputElement>) => {
-        drawerDispatch({ type: 'pushData', params: { menuId: actionId, author: v.target.value, } })
-        setAuthor(v.target.value)
-    }, [actionId])
-    //原文链接插入
-    let contentSourceUrl = useCallback((v: React.ChangeEvent<HTMLTextAreaElement>) => {
-        drawerDispatch({ type: 'pushData', params: { menuId: actionId, contentSourceUrl: v.target.value } })
-        setContentSourceUrl(v.target.value)
-    }, [actionId])
-    return <>
-        <Tabs type="line">
-            <TabPane tab="发布" key="1" className={style.right_fb}>
-                <div className={style.right_img}>
-                    {
-                        actionId === 1 ? <span>封面(建议尺寸900*500像素)</span> : <span>封面(建议尺寸200*200像素)</span>
-                    }
-                    <span
-                        className={`${style.upload} ${actionId === 1 ? style.max : style.min}`}
-                        onClick={upload}
-                    >
-                        {
-                            (defaultValue?.thumbMediaUrl || defaultValue?.thumbUrl) && <img src={defaultValue?.thumbMediaUrl || defaultValue?.thumbUrl} alt="" />
-                        }
-                        <span className={`${style.add} ${(defaultValue?.thumbMediaUrl || defaultValue?.thumbUrl) && style.pos}`}>
-                            <PlusOutlined style={{ fontSize: 16 }} />
-                            上传封面
-                        </span>
-                    </span>
-                    {/* <span><Switch checkedChildren="开启" unCheckedChildren="关闭" defaultChecked={false} />封面显示在正文</span> */}
-                </div>
-                <Divider dashed />
-                <div className={style.right_textArea}>
-                    <span>摘要(选填)</span>
-                    <Input.TextArea rows={5} allowClear maxLength={120} onChange={strLeng} value={digest} />
-                    <span>{digest.length}/120</span>
-                </div>
-                <Divider dashed />
-                <div className={style.right_author}>
-                    <span>作者(选填)</span>
-                    <Input allowClear onChange={author} value={authorStr} />
-                </div>
-                <Divider dashed />
-                <div className={style.right_src}>
-                    <span>原文链接(必填)</span>
-                    <Input.TextArea rows={2} placeholder='请勿添加其他公众号的主页链接' allowClear onChange={contentSourceUrl} value={contentSourceUrlStr} />
-                </div>
-                <div className={style.right_src} style={{ marginTop: 10 }}>
-                    <span>排序(必填)<Tag color='warning'>数值越大越靠前</Tag></span>
-                    <InputNumber
-                        style={{ width: '100%' }}
-                        value={sort}
-                        placeholder='请输入序号, 数值越大越靠前'
-                        onChange={(e: number) => {
-                            drawerDispatch({ type: 'setSort', params: { sort: e } })
-                        }}
-                    />
-                </div>
-                <div>
-                    <WxSelect />
-                </div>
-            </TabPane>
-        </Tabs>
-        {
-            visible && <SmMaterialModal
-                visible={visible}
-                onCancel={hide}
-                title='选择图片'
-                onOk={(props: any) => {
-                    console.log(props)
-                    let obj: any = {}
-                    if (props?.mediaId) {
-                        obj.wxMediaId = props?.id
-                        obj.thumbUrl = props?.url
-                    } else {
-                        obj.thumbUrl = props?.url
-                    }
-                    drawerDispatch({ type: 'pushData', params: { menuId: actionId, thumbMediaUrl: props.url, ...obj } })
-                    hide()
-                }}
-                mediaType={1}
-                isShowWx={props?.isShowWx}
-                isAllData
-                noFile={false}
-            />
-        }
-    </>
-})
-export default Right

+ 0 - 106
src/components/FileBox/components/syncModal/index.less

@@ -1,106 +0,0 @@
-.ico {
-  -webkit-animation: Tada 3s both infinite;
-  -moz-animation: Tada 3s both infinite;
-  -ms-animation: Tada 3s both infinite;
-  animation: Tada 3s both infinite;
-}
-.colud {
-  display: flex;
-  flex-flow: row nowrap;
-  > div:nth-child(2) {
-    flex: 1;
-  }
-  span.ant-checkbox {
-    display: none;
-  }
-}
-.box {
-  > span {
-    &:first-child {
-      display: none;
-    }
-    &:last-child{
-      display: inline-block;
-    }
-  }
-}
-.card_title{
-  font-size: 12px;
-  color: #999;
-  display: block;
-}
-.card_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: 12px solid #4abe84;
-    border-top-color: transparent;
-    border-left-color: transparent;
-  }
-  &::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);
-  }
-}
-@keyframes Tada {
-  0% {
-    transform: scale(1);
-    transform: scale(1);
-  }
-
-  70%,
-  73% {
-    transform: scale(0.9) rotate(-3deg);
-    transform: scale(0.9) rotate(-3deg);
-  }
-
-  77%,
-  83%,
-  90%,
-  97% {
-    transform: scale(1.1) rotate(3deg);
-    transform: scale(1.1) rotate(3deg);
-  }
-
-  80%,
-  87%,
-  93% {
-    transform: scale(1.1) rotate(-3deg);
-    transform: scale(1.1) rotate(-3deg);
-  }
-
-  100% {
-    transform: scale(1) rotate(0);
-    transform: scale(1) rotate(0);
-  }
-}
-.card_box {
-  > div {
-    padding: 10px;
-  }
-}
-.item_img {
-  width: 25px;
-  border-radius: 2px;
-  margin-right: 5px;
-  background-color: #efefef;
-}

+ 0 - 313
src/components/FileBox/components/syncModal/index.tsx

@@ -1,313 +0,0 @@
-import { Button, Card, Checkbox, Col, Row, Spin } from 'antd'
-import Modal from 'antd/lib/modal/Modal'
-import React, { useCallback, useEffect, useImperativeHandle, useState } from 'react'
-import { useModel } from 'umi'
-import Left from '@/components/ActionModal/left'
-import style from './index.less'
-import NoFoundPage from '@/pages/empty'
-type Props = {
-}
-let SyncModal = React.forwardRef((props: Props, ref) => {
-    //映射ref
-    useImperativeHandle(ref, () => ({
-        show
-    }))
-    const { mpAccounts, actionWX, dispatch, actionArr, getDataList, getAllOfMember } = useModel('useOperating.useWxGroupList',
-        models => ({
-            mpAccounts: models.state.mpAccounts,
-            actionWX: models.state.actionWX,
-            dispatch: models.dispatch,
-            actionArr: models.state.actionArr,
-            getDataList: models.getDataList,
-            getAllOfMember: models.getAllOfMember
-        }))
-    const { sync } = useModel('useOperating.useBdMedia')
-    const [visible, setVisible] = useState<boolean>(false)//显示隐藏
-    const [groupSyncWx, setGroupSyncWx] = useState<any[]>([])//当前组未选中的微信
-    const [selectState, setSelectState] = useState<{ isAll: boolean, isChecked: boolean }>({ isAll: false, isChecked: false })
-    const [sysMediaId, setSysMediaId] = useState<any>()
-
-    //全选
-    let allSelect = useCallback(() => {
-        let isGroupWx: any[] = []//选中的数据
-        let newActionArr: any[] = []
-        let fiterMp: any[] = []
-        mpAccounts?.forEach((mp: { id: number, verifyTypeInfo: number }) => {
-            if (mp?.verifyTypeInfo !== -1) {//过滤未认证
-                fiterMp.push(mp)
-            }
-            actionArr?.forEach((wx: { id: number }) => {
-                if (wx.id === mp.id) {
-                    isGroupWx.push(wx)
-                }
-            })
-        })
-        if (isGroupWx?.length === fiterMp?.length || isGroupWx?.length === fiterMp?.length - groupSyncWx?.length) {//清空
-            newActionArr = actionArr?.filter((wx: { id: number }) => {
-                if (isGroupWx.every((groupwx: { id: number }) => wx.id !== groupwx.id)) {
-                    return wx
-                }
-                return
-            })
-            setSelectState({ isAll: false, isChecked: false })
-            dispatch({ type: 'setActionArr', params: { actionArr: newActionArr } })
-        } else {//全选
-            newActionArr = actionArr?.filter((wx: { id: number }) => {
-                if (isGroupWx.every((groupwx: { id: number }) => wx.id !== groupwx.id)) {
-                    return wx
-                }
-                return
-            })
-            newActionArr = [...newActionArr, ...fiterMp]
-            setSelectState({ isAll: false, isChecked: true })
-            dispatch({ type: 'setActionArr', params: { actionArr: newActionArr } })
-        }
-    }, [selectState, mpAccounts, actionArr, actionWX, groupSyncWx])
-    //反选
-    let returnSelct = useCallback(() => {
-        let isGroupWx: any[] = []
-        let returnWx: any[] = []
-        let newActionArr: any[] = []
-        let fiterMp: any[] = []
-        mpAccounts?.forEach((mp: { id: number, verifyTypeInfo: number }) => {
-            if (mp?.verifyTypeInfo !== -1) {//过滤未认证
-                fiterMp.push(mp)
-            }
-            actionArr?.forEach((wx: { id: number }) => {
-                if (wx.id === mp.id) {
-                    isGroupWx.push(wx)
-                }
-            })
-        })
-        returnWx = fiterMp?.filter((mp: { id: number }) => {
-            if (isGroupWx.every((wx: { id: number }) => mp.id !== wx.id)) {
-                return mp
-            }
-            return
-        })
-        newActionArr = actionArr?.filter((wx: { id: number }) => {
-            if (isGroupWx.every((groupwx: { id: number }) => wx.id !== groupwx.id)) {
-                return wx
-            }
-            return
-        })
-        if (returnWx.length !== 0 && groupSyncWx.length !== returnWx.length) {//假如选中个数的大于0
-            setSelectState({ isAll: true, isChecked: true })
-        } else {//假如等于0
-            setSelectState({ isAll: false, isChecked: false })
-        }
-        if (returnWx.length === fiterMp.length && groupSyncWx.length === 0) {
-            setSelectState({ isAll: false, isChecked: true })//假如反选值与当前组的个数一样证明全选
-        }
-        newActionArr = [...newActionArr, ...returnWx]
-        dispatch({ type: 'setActionArr', params: { actionArr: newActionArr } })
-    }, [selectState, mpAccounts, actionArr, actionWX, groupSyncWx])
-    //每次切换组检测全选状态
-    useEffect(() => {
-        let isGroupWx: any[] = []
-        let groupSyncWx: any[] = []
-        mpAccounts?.forEach((mp: { id: number }) => {
-            actionArr?.forEach((wx: { id: number }) => {
-                if (wx.id === mp.id) {
-                    isGroupWx.push(wx)
-                }
-            })
-        })
-        setGroupSyncWx(groupSyncWx)
-        // }
-        if (isGroupWx?.length === mpAccounts?.length) {
-            setSelectState({ isAll: false, isChecked: true })
-        } else {
-            setSelectState({ isAll: true, isChecked: true })
-        }
-        if (isGroupWx?.length === 0) {
-            setSelectState({ isAll: false, isChecked: false })
-        }
-    }, [mpAccounts, actionArr])
-    //弹窗传参接受
-    let show = useCallback((param: { sysMediaId: number }) => {
-        setSysMediaId(param?.sysMediaId)
-        setVisible(true)
-    }, [])
-    //关闭弹窗
-    let handleCancel = useCallback(() => {
-        dispatch({ type: 'setActionArr', params: { actionArr: [] } })
-        setVisible(false)
-    }, [])
-    //确定同步
-    let handleOk = useCallback(() => {
-        if (!actionWX) {
-            return
-        }
-        let mpIds: any[] = []//新建同步
-        actionArr?.forEach((item: any) => {//选中的微信号循环处理
-            mpIds.push(item.id)
-        })
-        sync.run({ mpIds, sysMediaId: sysMediaId }).then((res: any) => {
-            console.log(res)
-            handleCancel()
-        })
-    }, [actionArr, sysMediaId])
-    //选中事件
-    let action = useCallback((item: any) => {
-        let isGroupWx: any[] = []//选中的数据
-        if (actionArr?.some((obj: { appid: number }) => obj.appid === item.appid)) {//删除
-            let newArr = actionArr?.filter((obj: { appid: number }) => obj.appid !== item.appid)
-            mpAccounts?.forEach((mp: { id: number }) => {
-                newArr?.forEach((wx: { id: number }) => {
-                    if (wx.id === mp.id) {
-                        isGroupWx.push(wx)
-                    }
-                })
-            })
-            if (isGroupWx.length === 0) {//假如为空
-                setSelectState({ isAll: false, isChecked: false })
-            } else {
-                setSelectState({ isAll: true, isChecked: true })
-            }
-            dispatch({ type: 'setActionArr', params: { actionArr: newArr } })
-        } else {//添加
-            let arr = [...actionArr, item]
-            if (mpAccounts?.every((mp: { id: number }) => arr?.some((wx: { id: number }) => mp.id === wx.id))) {//假如全部存在全选
-                setSelectState({ isAll: false, isChecked: true })
-            } else {
-                setSelectState({ isAll: true, isChecked: true })
-            }
-            dispatch({ type: 'setActionArr', params: { actionArr: arr } })
-        }
-    }, [actionArr, mpAccounts])
-    useEffect(() => {
-        let newArr: any[] = []
-        if (getDataList?.data) {
-            getDataList?.data?.forEach((data: { mpAccounts: any }) => {
-                if(data?.mpAccounts){
-                    newArr = [...data?.mpAccounts]
-                }
-            })
-        }
-        if (getAllOfMember?.data) {
-            getAllOfMember?.data?.forEach((data: { userMpAccounts: any }) => {
-                data?.userMpAccounts?.forEach((mp: { id: number }) => {
-                    if (newArr.every((arr: { id: number }) => mp?.id !== arr.id)) {
-                        newArr.push(mp)
-                    }
-                })
-            })
-        }
-    }, [getDataList?.data, getAllOfMember?.data,])
-    //配合左侧搜索改变公众号帮助选中
-    useEffect(() => {
-        if (actionWX) {
-            action(actionWX)
-        }
-    }, [actionWX])
-    return <>
-        <Modal
-            title="选择公众号同步"
-            width={1040}
-            open={visible}
-            onOk={handleOk}
-            onCancel={handleCancel}
-            okText='确定'
-            cancelText='取消'
-            destroyOnClose
-            confirmLoading={sync?.loading}
-        >
-            <Spin tip='Loading...同步素材较慢,请耐心等待,可关闭窗口不影响其他操作' spinning={sync?.loading}
-            >
-                {
-                    actionWX ? <Row className={style.colud}  >
-                        <Col >
-                            <Left />
-                        </Col>
-                        <Col>
-                            <Card
-                                style={{ height: '420px', overflow: 'hidden', minWidth: 290 }}
-                                title={
-                                    <>
-                                        <span style={{ marginRight: 10 }}>组下成员</span>
-                                        <Checkbox
-                                            indeterminate={selectState.isAll}
-                                            onChange={allSelect}
-                                            checked={selectState.isChecked}
-                                        >
-                                            <span style={{ fontSize: 12, color: '#999' }}>全选</span>
-                                        </Checkbox>
-                                        <Button size='small' onClick={returnSelct}>反选</Button>
-                                    </>
-                                }
-                                bodyStyle={{ height: 350, overflowY: 'auto' }}
-                            >
-                                <Checkbox.Group style={{ width: '100%', }} >
-                                    <Row gutter={[10, 0]}>
-                                        {
-
-                                            mpAccounts?.map((item: any) => {
-                                                let isAction: any = actionArr?.some((obj: any) => obj?.appid === item?.appid)
-                                                return <Col key={item.id} span={24}>
-                                                    <Checkbox value={item} className={style.box} onClick={() => action(item)} >
-                                                        <div
-                                                            className={`${isAction ? style.card_action : undefined} ${style.card_box}`}
-                                                        >
-                                                            <div
-                                                                style={{ display: 'flex', alignItems: 'center' }} /**data?.syncVo?.some((obj:{appId:string}) => obj.appId === item.appid) ? {} :  */
-                                                            // description="This is the description"
-                                                            >
-                                                                <img src={item?.headImg || localStorage?.bookImg} className={style.item_img} />
-                                                                {item.nickName}
-                                                            </div>
-                                                        </div>
-                                                    </Checkbox>
-                                                </Col>
-                                            })
-                                        }
-                                    </Row>
-                                </Checkbox.Group>
-                            </Card>
-                        </Col>
-                        <Col>
-                            <Card
-                                style={{ height: 420, overflow: 'hidden', minWidth: 280 }}
-                                title={
-                                    <>
-                                        <span style={{ marginRight: 10 }}>已勾选</span>
-                                        <Button size='small' onClick={() => { dispatch({ type: 'setActionArr', params: { actionArr: [] } }) }}>清空</Button>
-                                    </>
-                                }
-                                bodyStyle={{ height: 350, overflowY: 'auto' }}
-                            >
-                                <Checkbox.Group style={{ width: '100%' }} >
-                                    <Row gutter={[10, 0]}>
-                                        {
-
-                                            actionArr?.map((item: any) => {
-                                                let isAction: any = actionArr?.some((obj: any) => obj?.appid === item?.appid)
-                                                return <Col key={item.id}>
-                                                    <Checkbox value={item} className={style.box} onClick={() => action(item)}>
-                                                        <div
-                                                            className={`${isAction ? style.card_action : undefined} ${style.card_box}`}
-                                                        >
-                                                            <div
-                                                                style={{ display: 'flex', alignItems: 'center' }} /**data?.syncVo?.some((obj:{appId:string}) => obj.appId === item.appid) ? {} :  */
-                                                            // description="This is the description"
-                                                            >
-                                                                <img src={item?.headImg || localStorage?.bookImg} className={style.item_img} />
-                                                                {item.nickName}
-                                                            </div>
-                                                        </div>
-                                                    </Checkbox>
-                                                </Col>
-                                            })
-                                        }
-                                    </Row>
-                                </Checkbox.Group>
-                            </Card>
-                        </Col>
-                    </Row> : <NoFoundPage />
-                }
-            </Spin>
-        </Modal >
-    </>
-})
-
-export default SyncModal

+ 0 - 15
src/components/FileBox/components/tree/index.less

@@ -1,15 +0,0 @@
-.tree{
-    // min-width: 199px;
-    border-right: 1px solid #efefef;
-    height: calc(100vh - 200px);
-    margin-right: 5px;
-    overflow-x:auto;
-    overflow-y: auto;
-    >div{
-        // width: 350px;
-    }
-    img{
-        width: 15px;
-        margin-right: 5px;
-    }
-}

+ 0 - 83
src/components/FileBox/components/tree/index.tsx

@@ -1,83 +0,0 @@
-import { Tree } from 'antd'
-import React, { useMemo, useCallback, useState } from 'react'
-import style from './index.less'
-const fileImg = require('../../../../../public/file.png')
-function TreeBox(props: { data: any[], belongUser: any }): any {
-    const [item, setItem] = useState<any>('')
-    const [actionId, setActionId] = useState<any>('')//拖动选中的当前文件夹ID
-    const [hoverId, setHoverId] = useState<any>('')//hoverId
-    const [expandedKeys, setExpandedKeys] = useState<any>([])
-    let arr = useMemo(() => {
-        let keys: any[] = []
-        let menuArr = [
-            {
-                id: 0,
-                title: props.belongUser == 1 ? '个人本地' : '公共本地',
-                icon: <img src={fileImg} />,
-                childMedias: props?.data
-            }
-        ]
-        function handle(arr: any[]) {
-            let newArr = arr?.map((item) => {
-                if (Array.isArray(item.childMedias)) {
-                    let children: any[] = handle(item.childMedias)
-                    keys.push(item.id)
-                    return { ...item, children, icon: <img src={fileImg} />, key: item.id }
-                } else {
-                    return { ...item, icon: <img src={fileImg} />, key: item.id }
-                }
-            })
-            return newArr
-        }
-        let newArr = menuArr?.map((item) => {
-            if (Array.isArray(item.childMedias)) {
-                let children: any[] = handle(item.childMedias)
-                keys.push(item.id)
-                return { ...item, children, icon: <img src={fileImg} />, key: item.id }
-            } else {
-                return { ...item, icon: <img src={fileImg} />, key: item.id }
-            }
-        })
-        setExpandedKeys(keys)
-        return newArr
-    }, [props.data, props.belongUser])
-    // 点击树
-    const treeClick = useCallback((selectedKeys, e) => {
-        setItem(e.selectedNodes[0])
-    }, [])
-    return [<div className={`${style.tree}`} id='tree'>
-        <Tree
-            treeData={arr}
-            showIcon
-            draggable
-            blockNode
-            defaultExpandAll={true}
-            autoExpandParent={true}
-            expandedKeys={expandedKeys}
-            onExpand={(expandedKeys) => {
-                setExpandedKeys(expandedKeys)
-            }}
-            onSelect={treeClick}
-            onDragStart={(info) => {
-                info.event.preventDefault()
-            }}
-            titleRender={(nodeData: any) => {
-                return <span
-                    style={hoverId === nodeData.id ? { color: 'red', backgroundColor: '#efefef', display: 'inline-block', width: 'calc(100% - 24px)' } : { display: 'inline-block', width: 'calc(100% - 24px)' }}
-                    onDrop={() => {
-                        if (nodeData.id !== actionId) {
-                            setActionId(nodeData.id)
-                        }
-                    }}
-                >{nodeData.title}</span>
-            }}
-            allowDrop={(info: any) => {
-                if (info?.dropNode?.id !== hoverId) {
-                    setHoverId(info?.dropNode?.id)
-                }
-                return false
-            }}
-        />
-    </div>, item, actionId, setActionId, setHoverId]
-}
-export default TreeBox

+ 0 - 354
src/components/FileBox/index.less

@@ -1,354 +0,0 @@
-.files {
-  width: 100%;
-  height: calc(100vh - 240px);
-  overflow-y: auto;
-  position: relative;
-}
-.flex_box_img {
-  width: 100px;
-  cursor: pointer;
-}
-.flex_box {
-  width: 200px;
-  height: 200px;
-  display: flex;
-  justify-content: center;
-  flex-flow: column;
-  align-items: center;
-  padding: 10px 0;
-  position: relative;
-  &:hover {
-    background-color: #c5d8f0;
-    border-radius: 5px;
-    border: 1px solid #c5d8f0;
-    box-sizing: border-box;
-    .select {
-      display: flex;
-      background-color: #7cc6ee;
-    }
-  }
-}
-.flex_box_name {
-  width: 85%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  cursor: pointer;
-  text-align: center;
-  &:hover {
-    color: #1890ff;
-  }
-}
-.flex_box_id {
-  width: 85%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  cursor: pointer;
-  text-align: center;
-  &:hover {
-    color: #1890ff;
-  }
-}
-.rt {
-  margin: 0 5px;
-  color: #c5d8f3;
-}
-.path {
-  margin-bottom: 15px;
-  //   margin-top: 10px;
-}
-.path_color {
-  color: #09aaff;
-  cursor: pointer;
-}
-.file_news_content {
-  width: 100%;
-  columns:300px 5;
-  column-gap: 20px;
-  > div {
-    width: 100%;
-    break-inside: avoid;
-    margin-bottom: 20px;
-    display: flex;
-    justify-content: center;
-  }
-}
-.file_content {
-  width: 100%;
-  // columns:200px 7;
-  // column-gap: 20px;
-  display: flex;
-  flex-wrap: wrap;
-  gap: 2px;
-  > div {
-    width: 200px;
-    break-inside: avoid;
-    display: flex;
-    justify-content: center;
-  }
-}
-.select {
-  position: absolute;
-  left: 5px;
-  top: 5px;
-  border-radius: 50%;
-  width: 21px;
-  height: 21px;
-  display: none;
-  justify-content: center;
-  align-items: center;
-  cursor: pointer;
-  > span {
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-}
-.select_btn {
-  margin-bottom: 10px;
-  > span {
-    color: #09aaff;
-    cursor: pointer;
-  }
-}
-.image_box,
-.video_box,
-.audio_box {
-  width: 200px;
-  height: 200px;
-  display: flex;
-  justify-content: center;
-  flex-flow: column;
-  align-items: center;
-  padding: 10px 20px;
-  position: relative;
-  img {
-    height: 100px;
-    width: 130px;
-    object-fit: contain;
-  }
-  audio {
-  }
-  &:hover {
-    background-color: #c5d8f0;
-    border-radius: 5px;
-    border: 1px solid #c5d8f0;
-    box-sizing: border-box;
-    .select {
-      display: flex;
-      background-color: #7cc6ee;
-    }
-  }
-}
-
-.menu {
-  position: fixed;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  flex-flow: column;
-  z-index: 999;
-  list-style: none;
-  padding: 15px 0;
-  min-width: 100px;
-  margin: 0;
-  border: 1px solid #dde0e4;
-  border-radius: 5px;
-  box-shadow: 0 0 8px #ccc;
-  background-color: #fff;
-  > li {
-    cursor: pointer;
-    height: 30px;
-    line-height: 30px;
-    padding: 0 10px;
-    text-align: center;
-    width: 100%;
-    &:hover {
-      background-color: #a4d9f5;
-    }
-  }
-}
-.add {
-  position: absolute;
-  left: 0;
-  top: 0;
-  height: 100%;
-  width: 100%;
-  background-color: rgba(0, 0, 0, 0.6);
-  color: #fff;
-  font-size: 30px;
-  display: none;
-  align-items: center;
-  justify-content: center;
-}
-.news_box {
-  width: 280px;
-  display: flex;
-  justify-content: center;
-  flex-flow: column;
-  align-items: center;
-  padding: 15px 30px;
-  box-sizing: border-box;
-  position: relative;
-  > div {
-    height: 60px;
-    display: flex;
-    flex-flow: row;
-    align-items: center;
-    position: relative;
-    box-sizing: border-box;
-    width: 100%;
-    justify-content: space-between;
-    margin-top: 2px;
-    &:hover {
-      > p {
-        display: flex;
-        cursor: pointer;
-      }
-    }
-    div {
-      order: 2;
-    }
-    img {
-      object-fit: cover;
-      width: 50px;
-      height: 50px;
-    }
-    span {
-      display: -webkit-box;
-      -webkit-box-orient: vertical;
-      -webkit-line-clamp: 2;
-      overflow: hidden;
-      order: 1;
-      height: 40px;
-      width: 75%;
-    }
-    &:nth-child(2) {
-      position: relative;
-      height: 120px;
-      overflow: hidden;
-      img {
-        object-fit: cover;
-        width: 100%;
-        height: 120px;
-      }
-      > span {
-        position: absolute;
-        bottom: 0;
-        left: 0;
-        height: 20px;
-        background-color: rgba(0, 0, 0, 0.6);
-        color: #fff;
-        line-height: 20px;
-        overflow: hidden;
-        text-overflow: ellipsis;
-        white-space: nowrap;
-        display: inline-block;
-        width: 100%;
-        box-sizing: border-box;
-      }
-    }
-  }
-  &:hover {
-    background-color: #c5d8f0;
-    border-radius: 5px;
-    // border: 1px solid #c5d8f0;
-    box-sizing: border-box;
-    .select {
-      display: flex;
-      background-color: #7cc6ee;
-    }
-  }
-}
-.knews_box {
-  width: 300px;
-  display: flex;
-  justify-content: center;
-  flex-flow: column;
-  align-items: center;
-  padding: 15px 30px;
-  box-sizing: border-box;
-  position: relative;
-  height: 200px;
-  > div {
-    display: flex;
-    justify-content: space-between;
-    width: 100%;
-    background-color: #f0f5f7;
-    padding: 10px;
-    border-radius: 5px;
-    height: 95px;
-    box-sizing: border-box;
-    img{
-      width: 50px;
-      height: 50px;
-      margin-top: 25px;
-      object-fit: cover;
-    }
-    span{
-      font-weight: 500;
-      margin-bottom: 5px;
-    }
-    p{
-      font-size: 12px;
-      overflow: hidden;
-      text-overflow: ellipsis;
-      display: -webkit-box;
-      -webkit-line-clamp: 2;
-      -webkit-box-orient: vertical;
-      color: #999;
-      padding-top: 10px;
-      width: 160px;
-    }
-  }
-  &:hover {
-    background-color: #c5d8f0;
-    border-radius: 5px;
-    // border: 1px solid #c5d8f0;
-    box-sizing: border-box;
-    .select {
-      display: flex;
-      background-color: #7cc6ee;
-    }
-  }
-}
-.flex_box_font {
-}
-
-.action {
-  background-color: #c5d8f0;
-  border-radius: 5px;
-  // border: 1px solid #90d8ff;
-  box-sizing: border-box;
-  .select {
-    background-color: #09aaff;
-    display: flex;
-  }
-  &:hover {
-    background-color: #c5d8f0;
-    border-radius: 5px;
-    // border: 1px solid #90d8ff;
-    box-sizing: border-box;
-    .select {
-      display: flex;
-      background-color: #09aaff;
-    }
-  }
-}
-.pagination {
-  width: 100%;
-  display: flex;
-  align-items: center;
-  justify-content: center;
-  margin-bottom: 10px;
-}
-.wxSelect{
-  position: absolute;
-  top:0;
-  right: 20px;
-  width: 200px;
-  >div{
-    margin-top: 0 !important;
-  }
-}

+ 0 - 567
src/components/FileBox/index.tsx

@@ -1,567 +0,0 @@
-import useCopy from "@/Hook/useCopy"
-import React, { useCallback, useEffect, useState } from "react"
-import { Button, Col, Image, message, Pagination, Popconfirm, Row, Space, Spin } from 'antd'
-import style from './index.less'
-import { DeleteOutlined, EditOutlined, PlusCircleOutlined, SyncOutlined } from "@ant-design/icons"
-import Synthetic from "../MaterialModal/synthetic"
-import FileModal from './components/fileModal'
-import { useModel } from "umi"
-import ImgModal from "./components/imgModal"
-import MsgWxGraphicListModal from '@/components/MaterialModal/msgWxGraphicListModal'
-import filePng from '../../../public/file.png'
-import Updata from "../MaterialModal/updata"
-import WxSelect from "../WxSelect"
-import TreeBox from "./components/tree"
-import SortModal from "./components/fileModal/sortModal"
-import PreviewLocalModal from "@/components/MaterialModal/previewLocalModal"
-
-interface News {
-    id: number,
-    sysMediaId: number,
-    sortIndex: number,
-    title: string,
-    thumbUrl: string,
-    author: string,
-    digest: string,
-    showCoverPic: boolean,
-    content: string,//内容只在调取详情时获取
-    contentSourceUrl: string,//文章地址
-    needOpenComment: boolean,
-    onlyFansCanComment: boolean
-}
-interface Item {
-    id: number,
-    folder: boolean,//是否是文件夹
-    fileType: 'video' | 'image' | 'news' | 'voice' | 'knews',//类型
-    number: string,//编号
-    title: string,//名称
-    url: string,//链接
-    belongType: string,//所属类型
-    createTime: string,//创建时间
-    description: string,//k图文描述
-    news?: News[]//图文内容
-    knewsThumbUrl: string, // 图片链接
-    knewsThumbId: number,//本地图片ID
-    knewsThumbInfo: any,//k客服详情
-    videoTitle: string,//视频标题
-}
-interface Props {
-    showDrawer?: (props?: any) => void,//图文素材弹窗事件
-    showSync?: (props?: any) => void,//同步弹窗事件
-    isAll?: boolean,//是否允许全选默认开启
-    height?: any,//当使用为弹窗组件时设置高度以免太高
-    noFile?: boolean,//是否禁止选择文件夹
-    isBd?: boolean,//是否强制使用本地数据
-}
-function FlieBox(props: Props) {
-
-    const { showDrawer, showSync, isAll = true, height, noFile = false, isBd } = props
-    const { addData } = useModel('useOperating.useSynthetic')
-    const { dispatch } = useModel('useOperating.useMaterialDrawer')
-    const { state, set, dels, list, get, onFile, allFile, delPupOn, delPupOff, changeClickFile, editFile, fileClick, treeClick, pathClick, getList, knewsOk, edit_media_folder, get_folder_tree } = useModel(isAll || isBd ? 'useOperating.useBdMedia' : 'useOperating.useBdMediaPup')
-    const { fileVisible, belongUser, selectFile, delPupId, xy, rightClickPup, path, publicPath, parentId, imgVisrible, fileType, knewsVisrible, knewsdefaultData, sortVisible } = state
-    const { copy } = useCopy()
-    const [updataVisible, setUpdataVisible] = useState<boolean>(false)
-    const fileImg = require('../../../public/file.png')
-    const { dispatch: dDispatch, getWxlists, initSelectWx } = useModel('useOperating.useWxGroupList')//公众号筛选
-    const [moveId, setMoveId] = useState<any>('')//移动的素材ID
-    const [treeEl, item, folderId, setActionId, setHoverId] = TreeBox({ data: get_folder_tree.data, belongUser })
-    const [previewShow, setPreviewShow] = useState<boolean>(false)  // 预览弹窗控制
-    const [previewId, setPreviewId] = useState<number>() // 要预览的ID
-
-    /**复制编号 */
-    const copyId = useCallback((e: React.MouseEvent<HTMLSpanElement, MouseEvent>, value: string) => {
-        e.stopPropagation()//阻止冒泡传递到文件夹被点击事件
-        copy(value)
-    }, [])
-    /**全局右键菜单 */
-    const Menu = useCallback((props: { isItem?: boolean }) => {
-        if (props.isItem && isAll) {
-            return <ul style={{ top: xy?.y, left: xy?.x }} className={style.menu} >
-                {
-                    isAll && <li onClick={allFile}>全选/反选</li>
-                }
-                <li onClick={(e) => { delPupOn(rightClickPup.id); onFile(e, rightClickPup, isAll, true) }}> 删除</li>
-                {
-                    !rightClickPup?.folder && <li onClick={() => {
-                        setPreviewShow(true)
-                        setPreviewId(rightClickPup?.id)
-                    }}>预览</li>
-                }
-                {
-                    !rightClickPup?.folder && <li onClick={() => {
-                        showSync && showSync({ sysMediaId: rightClickPup?.id })
-                    }}>同步</li>
-                }
-                <li onClick={() => {
-                    getWxlists.run(rightClickPup?.id).then((res: any) => {//获取当前素材关联的公众号列表
-                        if (res) {
-                            dDispatch({ type: 'selectWx', params: { selectWx: res?.map((item: any) => item.id) } })
-                        }
-                    })
-                    switch (fileType) {
-                        case 'news':
-                            if (rightClickPup?.folder) {//是文件夹
-                                editFile()
-                            } else {
-                                get.run(rightClickPup?.id).then((res: any) => {//请求详情接口获取详情内容
-                                    if (res) {
-                                        dispatch({ type: 'actionData', params: { data: { dataArr: res?.news, actionId: 1, sort: res?.sort } } })//设置编辑器的内容
-                                        showDrawer && showDrawer({ isEdit: true, editId: rightClickPup?.id })//开启新建素材弹窗
-                                        localStorage.setItem('collapsed', '1')//左侧菜单缩进
-                                    }
-                                })
-                            }
-                            break;
-                        case 'knews':
-                            if (rightClickPup?.folder) {//是文件夹
-                                editFile()
-                            } else {
-                                set({ knewsVisrible: true })
-                            }
-                            break;
-                        default://编辑非图文素材
-                            editFile()
-                    }
-                }}>编辑</li>
-                <li onClick={() => { set({ actionItem: rightClickPup, sortVisible: true }) }}>编辑排序</li>
-                <li onClick={() => { set({ fileVisible: true }) }}>新建文件夹</li>
-                <li onClick={() => {
-                    switch (fileType) {
-                        case 'news':
-                            showDrawer && showDrawer()
-                            break;
-                        case 'knews':
-                            set({ knewsVisrible: true, knewsdefaultData: null })
-                            break;
-                        default:
-                            set({ imgVisrible: true })
-                    }
-                }}>新建素材</li>
-                {
-                    (fileType !== 'knews' && fileType !== 'news') && <li onClick={() => { setUpdataVisible(true) }}>批量新增素材</li>
-                }
-                {
-                    isAll && <li onClick={dels}>删除选中文件</li>
-                }
-            </ul>
-        }
-        return <ul style={{ top: xy?.y, left: xy?.x }} className={style.menu}>
-            {
-                isAll && <li onClick={allFile}>全选/反选</li>
-            }
-            {
-
-            }
-            {//防止K图文无限嵌套创建判断
-                (isAll !== false || fileType !== 'knews') ? <li onClick={() => { set({ fileVisible: true }) }}>新建文件夹</li> : <li>此处无法新建操作</li>
-            }
-            {
-                (isAll !== false || fileType !== 'knews') && <li onClick={() => {
-                    switch (fileType) {
-                        case 'news':
-                            showDrawer && showDrawer()
-                            break;
-                        case 'knews':
-                            set({ knewsVisrible: true, knewsdefaultData: null })
-                            break;
-                        default:
-                            set({ imgVisrible: true })
-                    }
-                }}>新建素材</li>
-            }
-            {
-                (fileType !== 'knews' && fileType !== 'news') && <li onClick={() => { setUpdataVisible(true) }}>批量新增素材</li>
-            }
-            {
-                isAll && <li onClick={dels}>删除选中文件</li>
-            }
-        </ul>
-    }, [xy, rightClickPup, allFile, fileType, showDrawer, previewShow, previewId])
-    /**鼠标右键 */
-    const rightMenu = useCallback((e: any, isItem?: any) => {
-        e.stopPropagation()
-        e.preventDefault()
-        let x = e.clientX;
-        let y = e.clientY;
-        set({ xy: { x, y } })
-        if (isItem) {
-            set({ rightClickPup: isItem })
-            if (!isItem?.folder && isItem?.fileType === 'knews') {
-                set({
-                    knewsdefaultData: {//客服消息编辑回填弹窗中的内容预先存放
-                        newsList: [
-                            {
-                                title: isItem?.title,
-                                knewsThumbUrl: isItem?.knewsThumbUrl,
-                                knewsLink: isItem?.knewsLink,
-                                description: isItem?.description,
-                                knewsThumbInfo: isItem?.knewsThumbInfo,
-                                knewsThumbId: isItem?.knewsThumbId,
-                                sort: isItem?.sort || 0
-                            }
-                        ]
-                    }
-                })
-            }
-        } else {
-            set({ rightClickPup: { id: 'all' } })
-        }
-        return false;
-    }, [])
-    /**左键点击页面隐藏菜单 */
-    useEffect(() => {
-        function fnc(e: any) {
-            set({ rightClickPup: { id: '' } })
-        }
-        document.addEventListener('click', fnc)
-        return () => {
-            document.removeEventListener('click', fnc)
-        }
-    }, [])
-    /**合成器添加内容 */
-    const addNews = useCallback((news: any) => {
-        console.log(news)
-        addData(news)
-    }, [])
-    // /**切换个人|公共|父目录ID变化清空选中的文件*/
-    useEffect(() => {
-        set({ selectFile: [] })
-        if (belongUser == '1' && path) {//处理切换个人|公共时保留路径层级的请求
-            set({ parentId: path[path?.length - 1]?.id || null })
-        }
-        if (belongUser == '0' && publicPath) {
-            set({ parentId: publicPath[publicPath?.length - 1]?.id || null })
-        }
-    }, [belongUser, parentId, path?.length, publicPath?.length])
-    /**卸载组件处理 */
-    useEffect(() => {
-        return () => {
-            set({ parentId: null })
-        }
-    }, [])
-    /**获取目录树*/
-    useEffect(() => {
-        // if (isBd) {
-        get_folder_tree.run({ belongUser, fileType })
-        // }
-    }, [isAll, isBd, fileType, belongUser])
-    // 点击目录树进入对应目录
-    useEffect(() => {
-        if (item) {
-            let { icon, children, ...arg } = item
-            treeClick(arg)
-        }
-    }, [item])
-    // 拖动事件配置
-    const moveConfig = useCallback((item) => {
-        return {
-            draggable: true,
-            onDragStart: (ev: any) => {
-                let img = document.createElement('img')
-                img.src = fileImg;
-                ev.dataTransfer.setDragImage(img, 0, 0)
-                setMoveId(item.id)
-            },
-            onDragEnd: (e: any) => {
-                if (folderId !== '' && moveId !== '') {
-                    edit_media_folder.run({ sysMediaId: moveId, folderId }).then(res => {
-                        message.success('操作成功')
-                        list.refresh()
-                    })
-                }
-                setActionId('')
-                setHoverId('')
-                setMoveId('')
-            },
-        }
-    }, [folderId, moveId])
-    return <div style={{ display: 'flex', flexFlow: 'row' }}>
-        {
-            get_folder_tree?.data?.length > 0 && <div style={{ flexShrink: 0 }}>
-                {treeEl}
-            </div>
-        }
-        <div style={{ flexShrink: 1 }}>
-            <div className={style.files} onContextMenu={rightMenu} style={height ? { height } : {}}>
-                {/* 关联公众号筛选 */}
-                <div className={style.wxSelect}>
-                    <WxSelect mode={1} isAll={isAll} />
-                </div>
-                {/*合成器 refD?.current?.showDrawer() */}
-                {fileType === 'news' && isAll && <Synthetic show={() => { showDrawer && showDrawer() }} />}
-                {/* 层级路径 */}
-                <div className={style.path} >
-                    {//存在渲染个人本地路径不存在执行公共本地
-                        belongUser == '1' && path?.map((item: { title: string }, index: number) => {
-                            return <span key={index} onClick={() => { pathClick({ ...item, index }) }} >
-                                <span className={path?.length !== index + 1 ? style.path_color : ''}>{item?.title}</span>
-                                {path?.length !== index + 1 && <span className={style.rt} >{'>'}</span>}
-                            </span>
-                        })
-                    }
-                    {
-                        belongUser == '0' && publicPath?.map((item: { title: string }, index: number) => {
-                            return <span key={index} onClick={() => { pathClick({ ...item, index }) }} >
-                                <span className={publicPath?.length !== index + 1 ? style.path_color : ''}>{item?.title}</span>
-                                {publicPath?.length !== index + 1 && <span className={style.rt} >{'>'}</span>}
-                            </span>
-                        })
-                    }
-                </div>
-                {/* 内容 */}
-                <div className={(fileType === 'news' || fileType === 'knews') ? style.file_news_content : style.file_content} >
-                    {
-                        list?.data?.records?.map((item: Item) => {
-                            if (item.folder) {
-                                {/* 文件夹模板 */ }
-                                return <Popconfirm
-                                    title="确定要删除吗?"
-                                    onConfirm={() => { dels(item) }}
-                                    okText="是"
-                                    cancelText="否"
-                                    onCancel={delPupOff}
-                                    visible={delPupId === item.id}
-                                    key={item.id}
-                                >
-                                    <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading}>
-                                        <div
-                                            className={`${style.flex_box} ${selectFile?.some((id: number) => id === item.id) ? style.action : ''}`}
-                                            onContextMenu={(e) => { rightMenu(e, item) }}
-                                            onClick={(e) => { changeClickFile(e, item, isAll, noFile) }}
-                                            onDragStart={(e: any) => {
-                                                e.preventDefault()
-                                            }}
-                                        >
-                                            <span className={`${style.select}`} onClick={(e) => { changeClickFile(e, item, isAll, noFile) }}>
-                                                <span role="img" aria-label="check" style={{ color: '#fff' }}><svg viewBox="64 64 896 896" focusable="false" data-icon="check" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path></svg></span>
-                                            </span>
-                                            <img src={fileImg}
-                                                className={style.flex_box_img}
-                                                onClick={(e: any) => { e.stopPropagation(); fileClick(item) }}
-                                                onDragOver={(ev) => {
-                                                    ev.preventDefault()
-                                                }}
-                                                onDrop={() => {
-                                                    if (item.id !== folderId) {
-                                                        setActionId(item.id)
-                                                    }
-                                                }}
-                                            />
-                                            <span className={style.flex_box_name} >{item?.title}</span>
-                                            <span className={style.flex_box_id} onClick={(e) => { copyId(e, item?.number) }} >{item?.number}</span>
-                                        </div>
-                                    </Spin>
-                                </Popconfirm>
-                            } else if (item.fileType === 'news') {
-                                {/* 图文模板 */ }
-                                return <Popconfirm
-                                    title="确定要删除吗?"
-                                    onConfirm={() => { dels(item.id) }}
-                                    okText="是"
-                                    cancelText="否"
-                                    onCancel={delPupOff}
-                                    visible={delPupId === item.id}
-                                    key={item.id}
-                                >
-                                    <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading}>
-                                        <div
-                                            className={`${style.news_box} ${selectFile?.some((id: number) => id === item.id) ? style.action : ''}`}
-                                            onContextMenu={(e) => { rightMenu(e, item) }}
-                                            onClick={(e) => { changeClickFile(e, item, isAll) }}
-                                            {...moveConfig(item)}
-                                        >
-                                            <span className={`${style.select}`} onClick={(e) => { changeClickFile(e, item, isAll) }}>
-                                                <span role="img" aria-label="check" style={{ color: '#fff' }}><svg viewBox="64 64 896 896" focusable="false" data-icon="check" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path></svg></span>
-                                            </span>
-                                            {
-                                                item?.news?.map((news: News) => {
-                                                    return <div key={news?.id}>
-                                                        <Image src={news?.thumbUrl} onClick={(e) => { e.stopPropagation() }} />
-                                                        <span className={style.news_box_font}>{news?.title}</span>
-                                                        <p className={style.add} onClick={(e) => { e.stopPropagation(); addNews(news) }}><PlusCircleOutlined /></p>
-                                                    </div>
-                                                })
-                                            }
-                                            <span className={style.flex_box_id} onClick={(e) => { copyId(e, item?.number) }} >{item?.number}</span>
-                                            <span>
-                                                <Space>
-                                                    <Button
-                                                        type='text'
-                                                        size='small'
-                                                        onClick={(e) => {
-                                                            e.stopPropagation();
-                                                            getWxlists.run(item?.id).then((res: any) => {//获取当前素材关联的公众号列表
-                                                                if (res) {
-                                                                    dDispatch({ type: 'selectWx', params: { selectWx: res?.map((item: any) => item.id) } })
-                                                                }
-                                                            })
-                                                            if (item?.folder) {//是文件夹
-                                                                editFile()
-                                                            } else {
-                                                                get.run(item?.id).then((res: any) => {//请求详情接口获取详情内容
-                                                                    if (res) {
-                                                                        let news = res?.news?.map((item: any, index: number) => {
-                                                                            return { ...item, menuId: index + 1 }
-                                                                        })
-                                                                        dispatch({ type: 'actionData', params: { data: { dataArr: news, actionId: 1, sort: res?.sort } } })//设置编辑器的内容
-                                                                        showDrawer && showDrawer({ isEdit: true, editId: item?.id })//开启新建素材弹窗
-                                                                        localStorage.setItem('collapsed', '1')//左侧菜单缩进
-                                                                    }
-                                                                })
-                                                            }
-                                                        }}
-                                                    >
-                                                        <EditOutlined />
-                                                    </Button>
-                                                    <Button
-                                                        type='text'
-                                                        size='small'
-                                                        onClick={(e) => {
-                                                            e.stopPropagation();
-                                                            showSync && showSync({ sysMediaId: item?.id })
-                                                        }}
-                                                    >
-                                                        <SyncOutlined />
-                                                    </Button>
-                                                    <Button
-                                                        type='text'
-                                                        size='small'
-                                                        onClick={(e) => {
-                                                            e.stopPropagation();
-                                                            delPupOn(item.id); onFile(e, item, isAll, true)
-                                                        }}
-                                                    >
-                                                        <DeleteOutlined />
-                                                    </Button>
-                                                </Space>
-                                            </span>
-                                        </div>
-                                    </Spin>
-                                </Popconfirm>
-                            } if (item.fileType === 'knews') {
-                                {/* K图文模板 */ }
-                                return <Popconfirm
-                                    title="确定要删除吗?"
-                                    onConfirm={() => { dels(item.id) }}
-                                    okText="是"
-                                    cancelText="否"
-                                    onCancel={delPupOff}
-                                    visible={delPupId === item.id}
-                                    key={item.id}
-                                >
-                                    <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading}>
-                                        <div
-                                            className={`${style.knews_box} ${selectFile?.some((id: number) => id === item.id) ? style.action : ''}`}
-                                            onContextMenu={(e) => { rightMenu(e, item) }}
-                                            onClick={(e) => { changeClickFile(e, item, isAll) }}
-                                            {...moveConfig(item)}
-                                        >
-                                            <span className={`${style.select}`} onClick={(e) => { changeClickFile(e, item, isAll) }}>
-                                                <span role="img" aria-label="check" style={{ color: '#fff' }}><svg viewBox="64 64 896 896" focusable="false" data-icon="check" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path></svg></span>
-                                            </span>
-                                            <div >
-                                                <div>
-                                                    <span className={style.news_box_font}>{item?.title}</span>
-                                                    <p>{item?.description}</p>
-                                                </div>
-                                                <Image src={item?.knewsThumbId ? item?.knewsThumbInfo?.folder ? filePng : item?.knewsThumbInfo?.url : item?.knewsThumbUrl} onClick={(e) => { e.stopPropagation() }} />
-                                            </div>
-                                            <span className={style.flex_box_id} onClick={(e) => { copyId(e, item?.number) }} >{item?.number}</span>
-                                        </div>
-                                    </Spin>
-                                </Popconfirm>
-                            } else {
-                                {/* 图片模板 ,视频模板,音频模板*/ }
-                                let El = item.fileType === 'image' ?
-                                    <Image src={item.url} onClick={(e) => { e.stopPropagation() }}
-                                    /> :
-                                    item.fileType === 'video' ?
-                                        <video src={item.url} style={{ width: 130, height: 100 }} controls />
-                                        :
-                                        <audio src={item.url} controls style={{ width: 150 }} />
-                                return <Popconfirm
-                                    title="确定要删除吗?"
-                                    onConfirm={() => { dels(item.id) }}
-                                    okText="是"
-                                    cancelText="否"
-                                    onCancel={delPupOff}
-                                    visible={delPupId === item.id}
-                                    key={item.id}
-                                >
-                                    <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading}>
-                                        <div
-                                            className={`${style.image_box} ${selectFile?.some((id: number) => id === item.id) ? style.action : ''}`}
-                                            onContextMenu={(e) => { rightMenu(e, item) }}
-                                            onClick={(e) => { changeClickFile(e, item, isAll) }}
-                                            {...moveConfig(item)}
-                                        >
-                                            <span className={`${style.select}`} onClick={(e) => { changeClickFile(e, item, isAll) }}>
-                                                <span role="img" aria-label="check" style={{ color: '#fff' }}><svg viewBox="64 64 896 896" focusable="false" data-icon="check" width="1em" height="1em" fill="currentColor" aria-hidden="true"><path d="M912 190h-69.9c-9.8 0-19.1 4.5-25.1 12.2L404.7 724.5 207 474a32 32 0 00-25.1-12.2H112c-6.7 0-10.4 7.7-6.3 12.9l273.9 347c12.8 16.2 37.4 16.2 50.3 0l488.4-618.9c4.1-5.1.4-12.8-6.3-12.8z"></path></svg></span>
-                                            </span>
-                                            {El}
-                                            <span className={style.flex_box_name} onClick={(e) => { copyId(e, item?.url) }}>{item?.videoTitle || item?.title}</span>
-                                            <span className={style.flex_box_id} onClick={(e) => { copyId(e, item?.number) }} >{item?.number}</span>
-                                        </div>
-                                    </Spin>
-                                </Popconfirm>
-                            }
-                            return null
-                        })
-                    }
-                </div>
-                {/* 鼠标右键菜单 */}
-                {rightClickPup.id ? rightClickPup.id === 'all' ? <Menu /> : <Menu isItem /> : null}
-                {/* 新建文件弹窗 */}
-                {fileVisible && <FileModal isAll={isAll} />}
-                {/* 编辑排序 */}
-                {sortVisible && <SortModal isAll={isAll} />}
-                {/* 新建非图文 */}
-                {imgVisrible && <ImgModal isAll={isAll} />}
-                {/* 批量新建素材 */}
-                {updataVisible && <Updata mediaType={fileType === 'image' ? '1' : fileType === 'video' ? '3' : '2'} callBcak={setUpdataVisible} type={1} isAll={isAll} />}
-                {/* 新建客服消息模板 */}
-                {
-                    knewsVisrible && <MsgWxGraphicListModal
-                        title={'K-图文'}
-                        visible={knewsVisrible || false}
-                        onCancel={() => {
-                            // dispatchMate({ type: 'initData', params: { data: { dataArr: [{ menuId: 1 }] } } }) //设置成默认
-                            set({ knewsVisrible: false })
-                            initSelectWx()
-                            return
-                        }}
-                        isKnews={true}
-                        onOK={(props) => { knewsOk(props) }}
-                        defaultData={knewsdefaultData}
-                        tooltipTxt='只支持单图文'
-                        historyType={1}
-                        ImportBtShow={1}
-                        isProhibitMs={true}
-                        msgType={1}
-                    />
-                }
-            </div>
-            {
-                list?.data?.records?.length > 0 && <div className={style.pagination}>
-                    {/* 分页 */}
-                    <Pagination
-                        showSizeChanger
-                        onChange={(page: number, pageSize?: number) => {
-                            getList({ pageSize, pageNum: page })
-                        }}
-                        onShowSizeChange={(current: number, size: number) => {
-                            getList({ pageSize: size, pageNum: current })
-                        }}
-                        current={list?.data?.current}
-                        defaultPageSize={20}
-                        total={list?.data?.total}
-                    />
-                </div>
-            }
-        </div>
-
-        {previewShow && <PreviewLocalModal visible={previewShow} onClose={() => setPreviewShow(false)} previewId={previewId} />}
-    </div>
-}
-export default React.memo(FlieBox)

+ 0 - 211
src/components/FileBoxAD/components/newsModal/index.less

@@ -1,211 +0,0 @@
-.left {
-  width: 100%;
-  .left_top {
-    display: flex;
-    justify-content: left;
-    align-items: center;
-    padding: 10px;
-    border-bottom: 1px solid #efefef;
-    font-weight: 500;
-  }
-  .left_ul {
-    height: calc(100vh - 150px);
-    overflow-y: auto;
-    > ul {
-      display: flex;
-      flex-flow: column;
-      padding: 10px;
-      overflow-y: auto;
-      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);
-    }
-  }
-}
-.right_fb {
-  height: calc(100vh - 112px);
-  overflow-y: scroll;
-  > div {
-    width: 100%;
-    display: flex;
-    flex-flow: column;
-  }
-  .upload {
-    border: 1px dashed #d8d8d8;
-    border-radius: 3px;
-    cursor: pointer;
-    margin: 10px 0;
-    position: relative;
-    img {
-      object-fit: cover;
-      width: 100%;
-      height: 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);
-    }
-  }
-  .min {
-    width: 88px;
-    height: 88px;
-  }
-  .max {
-    width: 220px;
-    height: 95px;
-  }
-  .right_textArea {
-    span:last-child {
-      float: right;
-      text-align: right;
-    }
-  }
-}
-.box {
-  border: 1px solid #efefef;
-  height: 100%;
-  > div {
-    &:nth-child(1) {
-      border-right: 1px solid #efefef;
-    }
-    &:last-child {
-      padding: 0 10px;
-      border-left: 1px solid #efefef;
-    }
-  }
-}
-.title1 {
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-  width: 200px;
-}
-.title {
-  width: 100%;
-  overflow: hidden;
-  text-overflow: ellipsis;
-  white-space: nowrap;
-}

+ 0 - 54
src/components/FileBoxAD/components/newsModal/index.tsx

@@ -1,54 +0,0 @@
-import React, { useImperativeHandle, useState } from 'react'
-import { Col, Drawer, Row } from 'antd'
-import style from './index.less'
-import Left from './left'
-import Right from './right'
-import Editor from '@/components/Editor/Box'
-import { useModel } from 'umi'
-//isWx是否是微信用来判断调用不同的接口逻辑默认不是
-const DrawerPage = React.forwardRef((props: any, ref) => {
-    const { styleRight = '', isAll = true, callback = null } = props
-    const [visible, setVisible] = useState<boolean>(false)//抽屉
-    const [isEdit, setIsEdit] = useState<boolean>(false)//是否编辑
-    const [editId, setEditId] = useState<string>('')//编辑的ID
-    const { drawerDispatch, actionData } = useModel('useOperating.useMaterialDrawer', model => ({ drawerDispatch: model.dispatch, actionData: model.state.actionData }))
-    //映射ref方法
-    useImperativeHandle(ref, () => ({
-        showDrawer,
-    }))
-    //抽屉显示
-    let showDrawer = (props?: any) => {
-        setEditId(props?.editId || '')
-        setIsEdit(props?.isEdit || false)//设置是否编辑
-        setVisible(true)//开启弹窗
-        localStorage.setItem('collapsed', '1')
-    };
-    //抽屉关闭
-    let onClose = () => {
-        // isEdit ? drawerDispatch({ type: 'initData' }) : drawerDispatch({ type: 'action', params: { actionId: 1 } })//编辑取消后清空数据
-        drawerDispatch({ type: 'initData' })
-        setVisible(false)//关闭抽屉
-        setIsEdit(false)//设回flase以免新建关闭后销毁数据
-        localStorage.setItem('collapsed', '0')
-    };
-    return <Drawer
-        placement="right"
-        closable={false}
-        onClose={onClose}
-        open={visible}
-        getContainer={false}
-        width='90%'
-        destroyOnClose
-        style={styleRight ? { right: styleRight } : {}}
-    >
-        <Row className={style.box}>
-            <Col flex='1'><Left isWx={props?.isWx} /></Col>
-            <Col flex='3'>{visible && <Editor onClose={onClose} editId={editId} editData={actionData?.dataArr} syncNews={props?.syncNews} isWx={props?.isWx} isShowWx={props?.isShowWx} isAll={isAll} callback={callback}/>}</Col>
-            <Col flex='1'><Right isShowWx={props?.isShowWx} /></Col>
-        </Row>
-    </Drawer>
-})
-
-export default DrawerPage
-
-

+ 0 - 158
src/components/FileBoxAD/components/newsModal/left.tsx

@@ -1,158 +0,0 @@
-import React, { useCallback, useState } from 'react'
-import style from './index.less'
-import { ArrowDownOutlined, ArrowUpOutlined, DeleteOutlined, PlusOutlined } from '@ant-design/icons'
-import { Avatar, Input, message, Modal, Space } from 'antd'
-import { useModel } from 'umi'
-import { exportMediaByUrl1 } from '@/services/operating/material'
-const Left = React.memo((props: { isWx?: boolean }) => {
-    const { isWx } = props
-    const { drawerState: { dataArr, actionId }, dispatch } = useModel('useOperating.useMaterialDrawer', model => ({ drawerState: model.state, dispatch: model.dispatch }))
-    const { actionWX } = useModel('useOperating.useWxGroupList', model => ({ actionWX: model.state.actionWX }))
-    const { ueditorRef } = useModel('useOperating.useMaterialDrawer', model => ({ ueditorRef: model.state.ueditorRef }))
-    const [showNews, setShowNews] = useState<boolean>(false)//导入文章
-    const [newsUrl, setNewsUrl] = useState<string>('')//文章地址
-
-    //导入文章
-    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}的地址错误,请输入正确的文章地址!`)
-            }
-        })
-        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, thumbMediaUrl, title } = r.data
-                            contentSourceUrl = contentSourceUrl.replace(/['"]*/g, '')
-                            content = content.replace('data-src', 'src').replace(/\<mpvoice[\s\S]*\<\/mpvoice\>/ig, '')
-                            index === 0 && ueditorRef?.setContent(content, false)
-                            arr.push({ menuId: actionId + index, content, contentSourceUrl, digest, thumbMediaUrl, title })
-                        }
-                    })
-                    arr = arr.sort((a: { menuId: number }, b: { menuId: number }) => { return a.menuId - b.menuId })
-                    dispatch({ type: 'importNews', params: { data: { dataArrs: arr, actionId } } })
-                }
-            }).catch(err => { console.log(err) })
-            setShowNews(false)
-        }
-    }, [newsUrl, actionId, ueditorRef])
-    return <div className={style.left}>
-        {
-            isWx && <div className={style.left_top}>
-                <Space>
-                    <Avatar src={actionWX?.headImg || "https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png"} />
-                    <span>{actionWX?.nickName}</span>
-                </Space>
-            </div>
-        }
-        <div className={style.left_ul}>
-            <ul>
-                {
-                    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.thumbMediaUrl || item.thumbUrl || '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.thumbMediaUrl || item.thumbUrl || '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>
-                    })
-                }
-            </ul>
-            {
-                dataArr?.length < 8 && <span onClick={() => dispatch({ type: 'addDataArr' })} ><PlusOutlined />新建</span>
-            }
-            <span onClick={() => { setShowNews(true) }} style={{ marginTop: 10 }}><PlusOutlined />导入文章</span>
-            <Modal
-                open={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>
-    </div>
-})
-export default Left

+ 0 - 130
src/components/FileBoxAD/components/newsModal/right.tsx

@@ -1,130 +0,0 @@
-import React, { useCallback, useMemo, useState } from 'react'
-import { Divider, Input, InputNumber, Tabs, Tag } from 'antd'
-import style from './index.less'
-import { PlusOutlined } from '@ant-design/icons';
-import SmMaterialModal from '@/components/MaterialModal/smModalBox';
-import { useModel } from 'umi';
-import WxSelect from '@/components/WxSelect';
-const { TabPane } = Tabs;
-
-let Right = React.memo((props: any) => {
-    const { drawerDispatch, drawerState: { actionId, dataArr, sort } } = useModel('useOperating.useMaterialDrawer', model => ({
-        drawerDispatch: model.dispatch,
-        drawerState: model.state
-    }))
-    const { show, hide, state: { visible } } = useModel('useOperating.useMaterialModal')
-    const [digest, setDigest] = useState<string>('') //摘要
-    const [authorStr, setAuthor] = useState<string>('') //作者
-    const [contentSourceUrlStr, setContentSourceUrl] = useState<string>('') //原文链接
-
-    //点击上传打开弹窗获取数据
-    let upload = useCallback(() => {
-        show()
-    }, [])
-    //跟随选择更新图片
-    const defaultValue: any = useMemo(() => {
-        let obj = {}
-        dataArr.forEach((item: any) => {
-            if (item.menuId === actionId) {
-                setDigest(item.digest || '')
-                setAuthor(item.author || '')
-                setContentSourceUrl(item.contentSourceUrl || '')
-                obj = item
-            }
-        })
-        return obj
-    }, [dataArr, actionId, sort])
-    //字数并插入dataArr
-    let strLeng = useCallback((v: React.ChangeEvent<HTMLTextAreaElement>) => {
-        drawerDispatch({ type: 'pushData', params: { menuId: actionId, digest: v.target.value, } })
-        setDigest(v.target.value)
-    }, [actionId])
-    //作者插入
-    let author = useCallback((v: React.ChangeEvent<HTMLInputElement>) => {
-        drawerDispatch({ type: 'pushData', params: { menuId: actionId, author: v.target.value, } })
-        setAuthor(v.target.value)
-    }, [actionId])
-    //原文链接插入
-    let contentSourceUrl = useCallback((v: React.ChangeEvent<HTMLTextAreaElement>) => {
-        drawerDispatch({ type: 'pushData', params: { menuId: actionId, contentSourceUrl: v.target.value } })
-        setContentSourceUrl(v.target.value)
-    }, [actionId])
-    return <>
-        <Tabs type="line">
-            <TabPane tab="发布" key="1" className={style.right_fb}>
-                <div className={style.right_img}>
-                    {
-                        actionId === 1 ? <span>封面(建议尺寸900*500像素)</span> : <span>封面(建议尺寸200*200像素)</span>
-                    }
-                    <span
-                        className={`${style.upload} ${actionId === 1 ? style.max : style.min}`}
-                        onClick={upload}
-                    >
-                        {
-                            (defaultValue?.thumbMediaUrl || defaultValue?.thumbUrl) && <img src={defaultValue?.thumbMediaUrl || defaultValue?.thumbUrl} alt="" />
-                        }
-                        <span className={`${style.add} ${(defaultValue?.thumbMediaUrl || defaultValue?.thumbUrl) && style.pos}`}>
-                            <PlusOutlined style={{ fontSize: 16 }} />
-                            上传封面
-                        </span>
-                    </span>
-                    {/* <span><Switch checkedChildren="开启" unCheckedChildren="关闭" defaultChecked={false} />封面显示在正文</span> */}
-                </div>
-                <Divider dashed />
-                <div className={style.right_textArea}>
-                    <span>摘要(选填)</span>
-                    <Input.TextArea rows={5} allowClear maxLength={120} onChange={strLeng} value={digest} />
-                    <span>{digest.length}/120</span>
-                </div>
-                <Divider dashed />
-                <div className={style.right_author}>
-                    <span>作者(选填)</span>
-                    <Input allowClear onChange={author} value={authorStr} />
-                </div>
-                <Divider dashed />
-                <div className={style.right_src}>
-                    <span>原文链接(必填)</span>
-                    <Input.TextArea rows={2} placeholder='请勿添加其他公众号的主页链接' allowClear onChange={contentSourceUrl} value={contentSourceUrlStr} />
-                </div>
-                <div className={style.right_src} style={{ marginTop: 10 }}>
-                    <span>排序(必填)<Tag color='warning'>数值越大越靠前</Tag></span>
-                    <InputNumber
-                        style={{ width: '100%' }}
-                        value={sort}
-                        placeholder='请输入序号, 数值越大越靠前'
-                        onChange={(e: number) => {
-                            drawerDispatch({ type: 'setSort', params: { sort: e } })
-                        }}
-                    />
-                </div>
-                <div>
-                    <WxSelect />
-                </div>
-            </TabPane>
-        </Tabs>
-        {
-            visible && <SmMaterialModal
-                visible={visible}
-                onCancel={hide}
-                title='选择图片'
-                onOk={(props: any) => {
-                    console.log(props)
-                    let obj: any = {}
-                    if (props?.mediaId) {
-                        obj.wxMediaId = props?.id
-                        obj.thumbUrl = props?.url
-                    } else {
-                        obj.thumbUrl = props?.url
-                    }
-                    drawerDispatch({ type: 'pushData', params: { menuId: actionId, thumbMediaUrl: props.url, ...obj } })
-                    hide()
-                }}
-                mediaType={1}
-                isShowWx={props?.isShowWx}
-                isAllData
-                noFile={false}
-            />
-        }
-    </>
-})
-export default Right

+ 2 - 2
src/components/FileBoxAD/index.tsx

@@ -361,7 +361,7 @@ function FlieBox(props: Props) {
                                     okText="是"
                                     cancelText="否"
                                     onCancel={delPupOff}
-                                    visible={delPupId === item.id}
+                                    open={delPupId === item.id}
                                     key={item.id}
                                 >
                                     <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading}>
@@ -490,7 +490,7 @@ function FlieBox(props: Props) {
                                     okText="是"
                                     cancelText="否"
                                     onCancel={delPupOff}
-                                    visible={delPupId === item.id}
+                                    open={delPupId === item.id}
                                     key={item.id}
                                 >
                                     <Spin tip='正在请求素材详情,请耐心等待...' spinning={get?.loading} data-id={item.id}>

+ 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
-                                    open={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 - 186
src/components/GroupWxTabs/gzhMangae.tsx

@@ -1,186 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react'
-import { Menu, Select, Tabs } from 'antd'
-import { MenuFoldOutlined, MenuUnfoldOutlined, QrcodeOutlined, UserOutlined } from '@ant-design/icons';
-import { useModel } from 'umi';
-import style from './index.less'
-const { Option } = Select
-interface Props {
-    default?: string,
-    height?: number | string,
-    type?: boolean,
-    isHideMyGroup?: boolean,
-    children?: JSX.Element,
-}
-function LeftPage(props: Props) {
-    const { isHideMyGroup = false } = props
-    const [isShow, setIsShow] = useState<boolean>(true)
-    const [selectedKeys, setSelectedKeys] = useState<string[]>([]) //选中自己的菜单
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>([]) //选中组员的菜单
-    const { getWxGroupAll, actionMp, actionWx, getAllOfMember, state, dispatch } = useModel('useOperating.useWxGroupList', model => ({ getWxGroupAll: model.getDataList, ...model }))
-    const { dispatch: userDispatch, initUserId } = useModel('useOperating.useUser')
-    const { tabsKey, actionArr, actionWX } = state
-    let bWith = document.body.clientWidth < 700
-    //自己menuitem点击
-    let menuItemClick = (e: any) => {
-        checkData(e.key, '', tabsKey)
-    };
-    //组员menuitem点击
-    let crewMenuItemClick = (e: any) => {
-        checkData(e.key, '', tabsKey)
-    };
-    //tabs选中
-    let tabsChange = useCallback((key: string) => {
-        if (key === 'btn1') return
-        if (key === 'btn') {
-            console.log(1, tabsKey)
-            if (tabsKey === '组员') {
-                setIsShow(!isShow)
-            }
-            return
-        }
-        dispatch({ type: 'setTabsKey', params: { tabsKey: key } })
-        if (key === '自己') {
-            initUserId()
-            checkData(selectedKeys[0], '', key)
-        } else {
-            checkData(crewSelectedKeys[0], '', key)
-        }
-    }, [selectedKeys, crewSelectedKeys, isShow])
-    //搜索
-    let inputChange = (v: any) => {
-        if (v) {
-            let [name, key] = v?.split('_')
-            checkData(key, name, tabsKey)
-        }
-    }
-    //设置选中的数据
-    let checkData = useCallback((key: string, ikey?: string, tabsKey?: string) => {
-        if (tabsKey === '自己') {
-            initUserId()
-            setSelectedKeys([key])
-            getWxGroupAll?.data?.forEach((item: any) => {
-                if (item.groupName === key) {//选中组
-                    actionMp(item?.mpAccounts)
-                    item?.mpAccounts?.forEach((wx: any) => {
-                        if (wx.nickName === ikey) {//选中微信
-                            actionWx(wx)
-                        }
-                    })
-                }
-            })
-        } else {
-            setCrewSelectedKeys([key])
-            getAllOfMember?.data?.forEach((item: any) => {
-                if (item.nickName + item.userId === key) {//选中组
-                    actionMp(item.userMpAccounts)
-                    handelUserId(item.userId, item.nickName)
-                    item?.userMpAccounts?.forEach((wx: any) => {
-                        if (wx.nickName === ikey) {//选中微信
-                            actionWx(wx)
-                        }
-                    })
-                }
-            })
-        }
-    }, [getWxGroupAll, getAllOfMember])
-    useEffect(() => {
-        if (tabsKey === '自己') {
-            initUserId()
-            if (actionWX && getWxGroupAll?.data) {
-                getWxGroupAll?.data?.forEach((item: any, index: number) => {
-                    item?.mpAccounts?.forEach((mp: { appid: string }) => {
-                        if (mp.appid === actionWX.appid) {
-                            checkData(item['groupName'], '', tabsKey)
-                        }
-                    })
-                })
-            } else {
-                let action = true
-                getWxGroupAll?.data?.forEach((item: any, index: number) => {
-                    if (action && item['mpAccounts']?.length > 0) {
-                        action = false
-                        checkData(getWxGroupAll?.data[index]['groupName'], '', tabsKey)
-                    }
-                })
-            }
-        } else {
-            if (actionWX && getAllOfMember?.data) {
-                getAllOfMember?.data?.forEach((item: any, index: number) => {
-                    item?.userMpAccounts?.forEach((mp: { appid: string }) => {
-                        if (mp.appid === actionWX.appid) {
-                            checkData(item['nickName'] + item['userId'], '', tabsKey)
-                        }
-                    })
-                })
-            } else {
-                let action = true
-                getAllOfMember?.data?.forEach((item: any, index: number) => {
-                    if (action && item['userMpAccounts'].length > 0) {
-                        action = false
-                        checkData(getAllOfMember?.data[index]['nickName'] + getAllOfMember?.data[index]['userId'], '', tabsKey)
-                    }
-                })
-            }
-        }
-    }, [getWxGroupAll?.data, getAllOfMember?.data, tabsKey])
-    //选中角色
-    let handelUserId = useCallback((userId, name) => {
-        userDispatch({ type: 'setUserId', params: { userId: userId?.toString(), name } })
-    }, [])
-    return <div>
-        <Tabs type='card' activeKey={tabsKey} onChange={tabsChange} tabBarStyle={{ marginBottom: 0 }}>
-            <Tabs.TabPane tab={<span><UserOutlined />自己</span>} key='自己' >
-                {props.children}
-            </Tabs.TabPane>
-            {
-                getAllOfMember?.data?.length > 0 && <Tabs.TabPane tab='组员' key='组员'>
-                    <div className={style.group}>
-                        {
-                            isShow && <div style={{ width: `${bWith ? '100%' : 200}` }}>
-                                <Select style={{ minWidth: 150 }} placeholder="输入搜索公众号" onChange={inputChange} showArrow showSearch allowClear>
-                                    {
-                                        getAllOfMember?.data?.map((item: any) => {
-                                            return item?.userMpAccounts?.map((list: any) => {
-                                                return <Option key={item?.nickName + '_' + list?.id} value={list?.nickName + '_' + item?.nickName + item?.userId} disabled={list?.verifyTypeInfo === -1}>
-                                                    <img src={list?.headImg || localStorage?.bookImg} className={style.img} /> {list?.nickName}
-                                                </Option>
-                                            })
-                                        })
-                                    }
-                                </Select>
-                                <Menu
-                                    onClick={crewMenuItemClick}
-                                    style={{ width: `${bWith ? '100%' : 200}`, height: props.height ? props.height : `${bWith ? '40' : 'calc(100vh - 390px)'} `, overflowY: 'auto', overflowX: 'hidden', borderRight: 0, backgroundColor: 'transparent' }}
-                                    selectedKeys={crewSelectedKeys}
-                                    mode={"inline"}
-                                >
-                                    {
-                                        props?.default && <Menu.Item key="all" icon={<QrcodeOutlined />}>全部公众号材料</Menu.Item>
-                                    }
-                                    {
-                                        getAllOfMember?.data?.map((item: any) => {
-                                            return <Menu.Item
-                                                key={item?.nickName + item?.userId}
-                                            >
-                                                <p onClick={() => { handelUserId(item?.userId?.toString(), item?.nickName) }}>
-                                                    {item?.userMpAccounts?.some((mp: { appid: string }) => actionArr?.some((arr: { appid: string }) => mp.appid === arr.appid)) ? <i style={{ fontStyle: 'normal', color: 'red' }}>*</i> : ''}
-                                                    {item?.nickName}
-                                                    <span style={{ color: '#999' }}>({item?.userMpAccounts?.length})</span>
-                                                </p>
-                                            </Menu.Item >
-                                        })
-                                    }
-                                </Menu>
-                            </div>
-                        }
-
-                        {props.children}
-                    </div>
-                </Tabs.TabPane>
-            }
-            <Tabs.TabPane tab={<span>{isShow ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />}</span>} key='btn' />
-        </Tabs>
-    </div >
-}
-
-export default LeftPage

+ 0 - 34
src/components/GroupWxTabs/index.less

@@ -1,34 +0,0 @@
-.tabs{
-    margin-bottom: 0;
-    // background-color: #f8f8f8;
-    >div{
-        margin-bottom: 0 !important;
-        &::before{
-            border-bottom:0px !important;
-        }
-    }
-}
-.img{
-    width: 25px;
-    border-radius: 2px;
-}
-.group{
-    display: flex;
-    justify-content: space-between;
-    >div{
-        &:first-child{
-            width: 178px;
-        }
-        &:last-child{
-            width: 100%;
-            overflow-x: auto;
-            flex: 1;
-        }
-    }
-}
-.item_img {
-    width: 25px;
-    border-radius: 2px;
-    margin-right: 5px;
-    background-color: #efefef;
-  }

+ 0 - 220
src/components/GroupWxTabs/index.tsx

@@ -1,220 +0,0 @@
-import { Input, Menu, Select, Tabs } from 'antd'
-import React, { useCallback, useEffect, useState } from 'react'
-import style from './index.less'
-import { useModel, history } from 'umi'
-import { MenuFoldOutlined, MenuUnfoldOutlined, UsergroupAddOutlined, UserOutlined } from '@ant-design/icons'
-
-function GroupWxTabs(props: { children?: JSX.Element, height?: string | number, isFadminQTab?: boolean, isUserSelect?: boolean, allowClear?: boolean }) {
-    let { isFadminQTab = false, isUserSelect = false, allowClear = true } = props // isFadminQTab 非Admin 不展示选择人 isUserSelect 是否展示搜索人员
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>([]) //选中组员的菜单
-    const { getAllOfMember, state: usesState, dispatch: useDispatch, actionGroupWx } = useModel('useOperating.useWxGroupList')
-    const { tabsKey } = usesState
-    const { dispatch, initUserId, state: { selectdUserId } } = useModel('useOperating.useUser')
-    const { state: { pitcher }, dispatch: tableDispatch, getUserAjax } = useModel('useData.useTableData')
-    const { dispatch: dataDispatch } = useModel('useData.useDataCenter')
-    const [isShow, setIsShow] = useState<boolean>(true)
-    const { currentUser }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser }))
-    const [qTab, setQTab] = useState<boolean>(false)
-
-    useEffect(() => {
-        if (isUserSelect) {
-            getUserAjax.run({ user_id: currentUser.userId == 1 ? selectdUserId : currentUser.userId })
-        }
-    }, [isUserSelect, selectdUserId, currentUser])
-    useEffect(() => {
-        if (isFadminQTab && currentUser.userId !== 1) {
-            setQTab(true)
-        }
-    }, [isFadminQTab, currentUser.userId])
-    //组员与自己的切换
-    const onChange = (key: string) => {
-        if (key === 'btn1') return
-        if (key === 'btn') {
-            if (tabsKey === '组员') {
-                setIsShow(!isShow)
-            }
-            return
-        }
-        useDispatch({ type: 'setTabsKey', params: { tabsKey: key } })
-        tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-        dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-        if (key === '自己') {
-            initUserId()
-            setIsShow(true)
-        } else {
-            /**当切换为组员的时候自动选中第一个有绑定公众号的组员 */
-            let ok = true
-            getAllOfMember?.data?.forEach((item: { key: { userId: number, nickname: string }, value: any[] }) => {
-                if (ok && item?.value?.length > 0) {
-                    ok = false
-                    setCrewSelectedKeys([item?.key?.nickname + item?.key?.userId])
-                    dispatch({ type: 'setUserId', params: { userId: item?.key?.userId.toString(), name: item?.key?.nickname } })
-                }
-            })
-            if (ok) {
-                dispatch({ type: 'setUserId', params: { userId: getAllOfMember?.data[0]?.key?.userId?.toString(), name: getAllOfMember?.data[0]?.key?.nickname } })
-            }
-        }
-        return () => {
-            initUserId()
-        }
-    }
-
-    //选中的成员改变全局userId请求获取数据
-    const itemChange = (key: string, option: any) => {
-        if (key) {
-            setCrewSelectedKeys([option.children + key])
-            dispatch({ type: 'setUserId', params: { userId: key.toString(), name: option.children } })
-            tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-            dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-        } else {
-            setCrewSelectedKeys([])
-            dispatch({ type: 'setUserId', params: { userId: '', name: '' } })
-            tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-            dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-        }
-    }
-    //组员menuitem点击
-    let crewMenuItemClick = (e: any) => {
-        setCrewSelectedKeys([e.key])
-    };
-    //选中角色
-    let handelUserId = useCallback((userId, name) => {
-        dispatch({ type: 'setUserId', params: { userId: userId?.toString(), name } })
-        tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-        dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-    }, [])
-    //获取当前角色下的公众号
-    useEffect(() => {
-        actionGroupWx(selectdUserId)//获取当前角色下的公众号
-    }, [selectdUserId])
-    //更改背景色
-    useEffect(() => {
-        let path = history.location.pathname.split('/')[1]
-        if (path === 'operatePage') {
-            localStorage.setItem('bg', 'light')
-        }
-        if (path === 'dataStatistics') {
-            localStorage.setItem('bg', 'dark')
-        }
-    }, [history])
-
-    return <>
-        {
-            !qTab ?
-                <Tabs onChange={onChange} className={style.tabs} type='card' activeKey={tabsKey} >
-                    <Tabs.TabPane tab={<span><UserOutlined />自己</span>} key='自己' >
-                        {props.children}
-                    </Tabs.TabPane>
-                    {
-                        getAllOfMember?.data?.length > 0 && <>
-                            <Tabs.TabPane tab={<span><UsergroupAddOutlined />组员</span>} key='组员'>
-                                <div className={style.group}>
-                                    {
-                                        isShow && <div>
-                                            <Select
-                                                showSearch
-                                                style={{ width: 178 }}
-                                                placeholder="输入组员名称"
-                                                optionFilterProp="children"
-                                                onChange={itemChange}
-                                                allowClear={allowClear}
-                                                value={crewSelectedKeys?.join()?.replace(/[\w]/ig, '')}
-                                                filterOption={(input, option) =>
-                                                    option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                                                }
-                                            >
-                                                {
-                                                    getAllOfMember?.data?.map((user: { key: { userId: number, nickname: string } }, index: number) => {
-                                                        return <Select.Option value={user?.key?.userId} key={user?.key?.userId + index}>{user?.key?.nickname}</Select.Option>
-                                                    })
-                                                }
-                                            </Select>
-                                            <Menu
-                                                onClick={crewMenuItemClick}
-                                                style={{
-                                                    width: 178,
-                                                    height: props?.height ? props.height : 'calc(100vh - 400px)',
-                                                    overflowY: `auto`,
-                                                    overflowX: 'hidden',
-                                                    borderRight: 0,
-                                                    backgroundColor: 'transparent'
-                                                }}
-                                                selectedKeys={crewSelectedKeys}
-                                                mode={"inline"}
-                                            >
-                                                {
-                                                    getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                                                        return <Menu.Item
-                                                            key={item?.key?.nickname + item?.key?.userId}
-                                                        >
-                                                            <p onClick={() => {
-                                                                handelUserId(item?.key?.userId?.toString(), item?.key?.nickname)
-                                                            }} style={{ margin: 0 }}>
-                                                                {item?.key?.nickname}
-                                                                <span style={{ color: '#999' }}>({item?.value?.length})</span>
-                                                            </p>
-                                                        </Menu.Item >
-                                                    })
-                                                }
-                                            </Menu>
-                                        </div>
-                                    }
-                                    {props.children}
-                                </div>
-                            </Tabs.TabPane>
-                            <Tabs.TabPane tab={<span>{isShow ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />}</span>} key='btn' />
-                            {
-                                isUserSelect && <Tabs.TabPane tab={<Select
-                                    style={{ width: 150 }}
-                                    placeholder="输入搜索投手"
-                                    // onChange={isShow ? (v: any) => { inputChange(v, isOk) } : (v: any) => { inputChange(v, true) }}
-                                    onChange={(value: any) => { tableDispatch({ type: 'setState', params: { pitcher: value } }) }}
-                                    showArrow
-                                    showSearch
-                                    allowClear
-                                    value={pitcher}
-                                >
-                                    {
-                                        getUserAjax?.data?.data?.map((list: any, eq: number) => {
-                                            return <Select.Option key={list?.user_id} value={list?.nick_name}>
-                                                {list?.nick_name}
-                                            </Select.Option>
-                                        })
-                                    })
-                                </Select>} key='btn1' />
-                            }
-                        </>
-                    }
-                </Tabs>
-                :
-                <>
-                    <div style={{ padding: '8px 16px', backgroundColor: '#FFF', display: 'inline-block' }}>
-                        {
-                            isUserSelect && <Select
-                                style={{ width: 150 }}
-                                placeholder="输入搜索投手"
-                                // onChange={isShow ? (v: any) => { inputChange(v, isOk) } : (v: any) => { inputChange(v, true) }}
-                                onChange={(value: any) => { tableDispatch({ type: 'setState', params: { pitcher: value } }) }}
-                                showArrow
-                                showSearch
-                                allowClear
-                                value={pitcher}
-                            >
-                                {
-                                    getUserAjax?.data?.data?.map((list: any, eq: number) => {
-                                        return <Select.Option key={list?.user_id} value={list?.nick_name}>
-                                            {list?.nick_name}
-                                        </Select.Option>
-                                    })
-                                })
-                            </Select>
-                        }
-                    </div>
-                    {props.children}
-                </>
-        }
-    </>
-}
-
-export default GroupWxTabs

+ 0 - 220
src/components/GroupWxTabs/kyyBox.tsx

@@ -1,220 +0,0 @@
-import {  Menu, Select, Tabs } from 'antd'
-import React, { ReactNode, useCallback, useEffect, useState } from 'react'
-import style from './index.less'
-import { useModel, history } from 'umi'
-import { MenuFoldOutlined, MenuUnfoldOutlined, UsergroupAddOutlined, UserOutlined } from '@ant-design/icons'
-
-function GroupKyyBoxTabs(props: { children?: JSX.Element, height?: string | number, isFadminQTab?: boolean, isUserSelect?: boolean, allowClear?: boolean, tabBarExtraContent?: ReactNode | {left?: ReactNode, right?: ReactNode} }) {
-    let { isFadminQTab = false, isUserSelect = false, allowClear = true, tabBarExtraContent } = props // isFadminQTab 非Admin 不展示选择人 isUserSelect 是否展示搜索人员
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>([]) //选中组员的菜单
-    const { getAllOfMember, state: usesState, dispatch: useDispatch, actionGroupWx } = useModel('useOperating.useWxGroupList')
-    const { tabsKey } = usesState
-    const { dispatch, initUserId, state: { selectdUserId } } = useModel('useOperating.useUser')
-    const { state: { pitcher }, dispatch: tableDispatch, getUserAjax } = useModel('useData.useTableData')
-    const { dispatch: dataDispatch } = useModel('useData.useDataCenter')
-    const [isShow, setIsShow] = useState<boolean>(true)
-    const { currentUser }: any = useModel('@@initialState', model => ({ currentUser: model.initialState?.currentUser }))
-    const [qTab, setQTab] = useState<boolean>(false)
-
-    useEffect(() => {
-        if (isUserSelect) {
-            getUserAjax.run({ user_id: currentUser.userId == 1 ? selectdUserId : currentUser.userId })
-        }
-    }, [isUserSelect, selectdUserId, currentUser])
-    useEffect(() => {
-        if (isFadminQTab && currentUser.userId !== 1) {
-            setQTab(true)
-        }
-    }, [isFadminQTab, currentUser.userId])
-    //组员与自己的切换
-    const onChange = (key: string) => {
-        if (key === 'btn1') return
-        if (key === 'btn') {
-            if (tabsKey === '组员') {
-                setIsShow(!isShow)
-            }
-            return
-        }
-        useDispatch({ type: 'setTabsKey', params: { tabsKey: key } })
-        tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-        dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-        if (key === '自己') {
-            initUserId()
-            setIsShow(true)
-        } else {
-            /**当切换为组员的时候自动选中第一个有绑定公众号的组员 */
-            let ok = true
-            getAllOfMember?.data?.forEach((item: { key: { userId: number, nickname: string }, value: any[] }) => {
-                if (ok && item?.value?.length > 0) {
-                    ok = false
-                    setCrewSelectedKeys([item?.key?.nickname + item?.key?.userId])
-                    dispatch({ type: 'setUserId', params: { userId: item?.key?.userId.toString(), name: item?.key?.nickname } })
-                }
-            })
-            if (ok) {
-                dispatch({ type: 'setUserId', params: { userId: getAllOfMember?.data[0]?.key?.userId?.toString(), name: getAllOfMember?.data[0]?.key?.nickname } })
-            }
-        }
-        return () => {
-            initUserId()
-        }
-    }
-
-    //选中的成员改变全局userId请求获取数据
-    const itemChange = (key: string, option: any) => {
-        if (key) {
-            setCrewSelectedKeys([option.children + key])
-            dispatch({ type: 'setUserId', params: { userId: key.toString(), name: option.children } })
-            tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-            dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-        } else {
-            setCrewSelectedKeys([])
-            dispatch({ type: 'setUserId', params: { userId: '', name: '' } })
-            tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-            dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-        }
-    }
-    //组员menuitem点击
-    let crewMenuItemClick = (e: any) => {
-        setCrewSelectedKeys([e.key])
-    };
-    //选中角色
-    let handelUserId = useCallback((userId, name) => {
-        dispatch({ type: 'setUserId', params: { userId: userId?.toString(), name } })
-        tableDispatch({ type: 'channel', params: { channel: undefined } })//清空公众号select的值
-        dataDispatch({ type: 'setState', params: { channel: undefined } })//清空公众号select的值
-    }, [])
-    //获取当前角色下的公众号
-    useEffect(() => {
-        actionGroupWx(selectdUserId)//获取当前角色下的公众号
-    }, [selectdUserId])
-    //更改背景色
-    useEffect(() => {
-        let path = history.location.pathname.split('/')[1]
-        if (path === 'operatePage') {
-            localStorage.setItem('bg', 'light')
-        }
-        if (path === 'dataStatistics') {
-            localStorage.setItem('bg', 'dark')
-        }
-    }, [history])
-
-    return <>
-        {
-            !qTab ?
-                <Tabs onChange={onChange} className={style.tabs} type='card' activeKey={tabsKey} tabBarExtraContent={tabBarExtraContent}>
-                    <Tabs.TabPane tab={<span><UserOutlined />自己</span>} key='自己' >
-                        {props.children}
-                    </Tabs.TabPane>
-                    {
-                        getAllOfMember?.data?.length > 0 && <>
-                            <Tabs.TabPane tab={<span><UsergroupAddOutlined />组员</span>} key='组员'>
-                                <div className={style.group}>
-                                    {
-                                        isShow && <div>
-                                            <Select
-                                                showSearch
-                                                style={{ width: 178 }}
-                                                placeholder="输入组员名称"
-                                                optionFilterProp="children"
-                                                onChange={itemChange}
-                                                allowClear={allowClear}
-                                                value={crewSelectedKeys?.join()?.replace(/[\w]/ig, '')}
-                                                filterOption={(input, option) =>
-                                                    option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                                                }
-                                            >
-                                                {
-                                                    getAllOfMember?.data?.map((user: { key: { userId: number, nickname: string } }, index: number) => {
-                                                        return <Select.Option value={user?.key?.userId} key={user?.key?.userId + index}>{user?.key?.nickname}</Select.Option>
-                                                    })
-                                                }
-                                            </Select>
-                                            <Menu
-                                                onClick={crewMenuItemClick}
-                                                style={{
-                                                    width: 178,
-                                                    height: props?.height ? props.height : 'calc(100vh - 400px)',
-                                                    overflowY: `auto`,
-                                                    overflowX: 'hidden',
-                                                    borderRight: 0,
-                                                    backgroundColor: 'transparent'
-                                                }}
-                                                selectedKeys={crewSelectedKeys}
-                                                mode={"inline"}
-                                            >
-                                                {
-                                                    getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                                                        return <Menu.Item
-                                                            key={item?.key?.nickname + item?.key?.userId}
-                                                        >
-                                                            <p onClick={() => {
-                                                                handelUserId(item?.key?.userId?.toString(), item?.key?.nickname)
-                                                            }} style={{ margin: 0 }}>
-                                                                {item?.key?.nickname}
-                                                                <span style={{ color: '#999' }}>({item?.value?.length})</span>
-                                                            </p>
-                                                        </Menu.Item >
-                                                    })
-                                                }
-                                            </Menu>
-                                        </div>
-                                    }
-                                    {props.children}
-                                </div>
-                            </Tabs.TabPane>
-                            <Tabs.TabPane tab={<span>{isShow ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />}</span>} key='btn' />
-                            {
-                                isUserSelect && <Tabs.TabPane tab={<Select
-                                    style={{ width: 150 }}
-                                    placeholder="输入搜索投手"
-                                    // onChange={isShow ? (v: any) => { inputChange(v, isOk) } : (v: any) => { inputChange(v, true) }}
-                                    onChange={(value: any) => { tableDispatch({ type: 'setState', params: { pitcher: value } }) }}
-                                    showArrow
-                                    showSearch
-                                    allowClear
-                                    value={pitcher}
-                                >
-                                    {
-                                        getUserAjax?.data?.data?.map((list: any, eq: number) => {
-                                            return <Select.Option key={list?.user_id} value={list?.nick_name}>
-                                                {list?.nick_name}
-                                            </Select.Option>
-                                        })
-                                    })
-                                </Select>} key='btn1' />
-                            }
-                        </>
-                    }
-                </Tabs>
-                :
-                <>
-                    <div style={{ padding: '8px 16px', backgroundColor: '#FFF', display: 'inline-block' }}>
-                        {
-                            isUserSelect && <Select
-                                style={{ width: 150 }}
-                                placeholder="输入搜索投手"
-                                // onChange={isShow ? (v: any) => { inputChange(v, isOk) } : (v: any) => { inputChange(v, true) }}
-                                onChange={(value: any) => { tableDispatch({ type: 'setState', params: { pitcher: value } }) }}
-                                showArrow
-                                showSearch
-                                allowClear
-                                value={pitcher}
-                            >
-                                {
-                                    getUserAjax?.data?.data?.map((list: any, eq: number) => {
-                                        return <Select.Option key={list?.user_id} value={list?.nick_name}>
-                                            {list?.nick_name}
-                                        </Select.Option>
-                                    })
-                                })
-                            </Select>
-                        }
-                    </div>
-                    {props.children}
-                </>
-        }
-    </>
-}
-
-export default GroupKyyBoxTabs

+ 0 - 366
src/components/GroupWxTabs/wx.tsx

@@ -1,366 +0,0 @@
-import React, { useState, useEffect, useCallback } from 'react'
-import { Menu, Modal, Select, Tabs } from 'antd'
-import style from './index.less'
-import { useModel } from 'umi';
-import { ExclamationCircleOutlined } from '@ant-design/icons';
-const { SubMenu } = Menu;
-const { Option } = Select
-function LeftPage(props: { isOk?: boolean, isShow?: boolean, h?: number, children?: JSX.Element,isDisabled?:boolean }) {
-    const { isOk = true, isShow, h,isDisabled = true } = props
-    const { getWxGroupAll, actionWx, getAllOfMember, state, dispatch } = useModel('useOperating.useWxGroupList', model => ({ getWxGroupAll: model.getDataList, ...model }))
-    const { dispatch: userDispatch, state: usetState, initUserId } = useModel('useOperating.useUser')
-    const { tabsKey, groupAllWx, allWx } = state
-    const [openKeys, setOpenKeys] = useState<string[]>(['']) //自己栏选中展开的菜单
-    const [crewOpenKeys, setCrewOpenKeys] = useState<string[]>(['']) //组员栏选中展开的菜单
-    const [selectedKeys, setSelectedKeys] = useState<string[]>(['']) //自己栏选中的菜单
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>(['']) //组员栏选中的菜单
-    const [visible, setVisible] = useState<boolean>(false)//未保存编辑显示提示窗
-    const [wx, setWx] = useState<any>(null)//提示窗出现后暂存点击的公众号以备逻辑跳转
-    const [wxData, setWxData] = useState<any>({
-        key: '自己',
-        menuItem: null,
-        crewMenuItem: null,
-    })
-    let bWith = document.body.clientWidth < 700
-    //自己menuitem点击
-    let menuItemClick = useCallback((e: any, isOk?: any) => {
-        setWxData({ ...wxData, menuItem: e })
-        if (isOk) {
-            if (e?.keyPath) {
-                setSelectedKeys([e.keyPath[0]])
-                setOpenKeys(['', e.keyPath[1]])
-            }
-        }
-    }, [getWxGroupAll, wxData])
-    /**组员menuitem点击 */
-    let crewMenuItemClick = useCallback((e: any, isOk?: any) => {
-        setWxData({ ...wxData, crewMenuItem: e })
-        if (isOk) {
-            if (e?.keyPath) {
-                setCrewSelectedKeys([e?.keyPath[0]])
-                setCrewOpenKeys([e?.keyPath[1]])
-            }
-        }
-    }, [getAllOfMember, wxData])
-    //自己menu点击
-    let menuClick = useCallback((e: any) => {
-        setOpenKeys(e)
-    }, [getWxGroupAll])
-    /**组员menu点击 */
-    let crewMenuClick = useCallback((e: any) => {
-        setCrewOpenKeys(e)
-    }, [])
-    /**放弃保存 */
-    let outSaver = () => {
-        setVisible(false)
-        tabsChange(wxData.key, true)
-        if (wxData.key === '自己') {
-            if (typeof wxData?.menuItem === 'string') {
-                inputChange(wxData?.menuItem, true)
-            } else {
-                wxData?.menuItem && menuItemClick(wxData?.menuItem, true)
-            }
-
-        } else {
-            if (typeof wxData?.crewMenuItem === 'string') {
-                inputChange(wxData?.crewMenuItem, true)
-            } else {
-                wxData?.crewMenuItem && crewMenuItemClick(wxData?.crewMenuItem, true)
-            }
-        }
-        if (wx) {
-            selectData(wx, true)
-        }
-    }
-
-    //选中微信的数据
-    let selectData = useCallback((wx: any, isOk?: any) => {
-        setWx(wx)
-        if (isOk) {
-            actionWx(wx)
-            setVisible(false)
-        } else {
-            if (!visible) {
-                setVisible(true)
-            }
-        }
-    }, [getAllOfMember, wxData, visible])
-    //tabs选中
-    let tabsChange = useCallback((key: string, isOk?: boolean) => {
-        console.log(111111, key)
-        setWxData({ ...wxData, key })
-        if (isOk) {
-            dispatch({ type: 'setTabsKey', params: { tabsKey: key } })
-            if (key === '自己') {
-                initUserId()
-                if (openKeys[0] && selectedKeys[0]) {
-                    selectGZH(openKeys[1], selectedKeys[0], key)
-                } else {
-                    let ok = true
-                    getWxGroupAll?.data?.forEach((item: any) => {
-                        if (ok && item?.mpAccounts?.length > 0) {
-                            ok = false
-                            actionWx(item?.mpAccounts[0])
-                        }
-                    })
-                }
-
-            } else {
-                if (crewOpenKeys[0] && crewSelectedKeys[0]) {
-                    selectGZH(crewOpenKeys[0], crewSelectedKeys[0], key)
-                } else {
-                    let ok = true
-                    getAllOfMember?.data?.forEach((item: { key: any, value: any[] }) => {
-                        if (ok && item?.value?.length > 0) {
-                            ok = false
-                            actionWx(item?.value[0])
-                        }
-                    })
-                }
-            }
-            setVisible(false)
-        } else {
-            if (!visible) {
-                setVisible(true)
-            }
-
-        }
-    }, [openKeys, selectedKeys, crewOpenKeys, crewSelectedKeys, wxData, visible, getWxGroupAll, getAllOfMember])
-    /*以key筛选公众号 */
-    let selectGZH = (open: string, select: string, tabsKey?: string) => {
-        if (tabsKey === '自己') {
-            if (getWxGroupAll?.data) {//筛选出微信号
-                getWxGroupAll?.data?.forEach((item: any) => {
-                    if (item?.groupName === open) {
-                        item?.mpAccounts?.forEach((obj: any) => {
-                            if (obj?.nickName === select) {
-                                actionWx(obj)//更新当前选中微信号,触发各个组件的数据获取
-                            }
-                        })
-                    }
-                })
-            }
-        } else {
-            if (getAllOfMember?.data) {
-                getAllOfMember?.data?.forEach((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                    if (item?.key?.nickname + item?.key?.userId === open) {
-                        item?.value?.forEach((obj: any) => {
-                            if (obj?.nickName === select) {
-                                userDispatch({ type: 'setUserId', params: { userId: item?.key?.userId } })
-                                actionWx(obj)//更新当前选中微信号,触发各个组件的数据获取
-                            }
-                        })
-                    }
-                })
-            }
-        }
-    }
-    //搜索
-    let inputChange = (v: string, isOk?: boolean) => {
-        console.log(v)
-        if (v) {
-            if (isOk) {
-                let [open, select] = v.split('_') //切换字符串转换成数组
-                if (tabsKey === '自己') {//设置选中key展开的菜单
-                    setOpenKeys([open])
-                    setSelectedKeys([select])
-                } else {
-                    setCrewOpenKeys([open])
-                    setCrewSelectedKeys([select])
-                }
-                userIdset(v)
-                selectGZH(open, select, tabsKey)//已key搜索对应的公众号并发送请求获取数据
-            } else {
-                if (!visible) {
-                    if (tabsKey === '自己') {
-                        setWxData({ ...wxData, menuItem: v })
-                    } else {
-                        setWxData({ ...wxData, crewMenuItem: v })
-                    }
-                    setVisible(true)
-                }
-                userIdset(v)
-            }
-        }
-    }
-    //设置选中的userId
-    const userIdset = useCallback((v?: any) => {
-        if (tabsKey === '自己') {
-            initUserId()
-        } else {
-            let id = typeof v === 'number' ? v : v.replace(/[\u4e00-\u9fa5_]/ig, '')
-            userDispatch({ type: 'setUserId', params: { userId: id } })
-        }
-    }, [tabsKey])
-    //首次加载选中当前选中的tabs有公众号的组或成员中第一个公众号
-    useEffect(() => {
-        if (tabsKey === '自己') {
-            getWxGroupAll?.data?.forEach((item: { mpAccounts?: any[], groupName: string }, index: number) => {
-                item?.mpAccounts?.forEach((wx: { nickName: string }) => {
-                    if (wx?.nickName === state?.actionWX?.nickName) {
-                        setOpenKeys(['', `${item?.groupName}`])
-                        setSelectedKeys([`${wx?.nickName}`])
-                    }
-                })
-            })
-        } else {
-            getAllOfMember?.data?.forEach((item: { key: { nickname: string, userId: number }, value: any[] }, index: number) => {
-                item?.value?.forEach((wx: { nickName: string }) => {
-                    if (wx?.nickName === state?.actionWX?.nickName) {
-                        setCrewOpenKeys([`${item?.key?.nickname + item?.key?.userId}`])
-                        setCrewSelectedKeys([`${wx?.nickName}`])
-                    }
-                })
-            })
-        }
-
-    }, [tabsKey])
-    useEffect(() => {
-        if (visible) {
-            Modal.confirm({
-                title: '有修改未保存!',
-                icon: <ExclamationCircleOutlined />,
-                onOk() {
-                    setVisible(false)
-                },
-                onCancel() {
-                    outSaver()
-                },
-                okText: '去保存修改',
-                cancelText: '放弃修改',
-            });
-        }
-    }, [visible])
-    return <>
-        <Tabs type="card" activeKey={tabsKey} onChange={isShow ? (key: any) => tabsChange(key, isOk) : (key: any) => tabsChange(key, true)} className={style.tabs} >
-            <Tabs.TabPane tab='自己' key='自己'>
-                <div className={style.group}>
-                    <div>
-                        <Select
-                            style={{ width: '100%' }}
-                            placeholder="输入搜索公众号"
-                            onChange={isShow ? (v: any) => { inputChange(v, isOk) } : (v: any) => { inputChange(v, true) }}
-                            showArrow
-                            showSearch
-                            allowClear
-                        >
-                            {
-                                getWxGroupAll?.data?.map((item: any, index: number) => {
-                                    return item?.mpAccounts?.map((list: any, eq: number) => {
-                                        return <Option key={item?.groupName + list?.id} value={item.groupName + '_' + list?.nickName} disabled={isDisabled ? list?.verifyTypeInfo === -1 :false}>
-                                            <img src={list?.headImg || localStorage?.bookImg} className={style.item_img} />{list.nickName}
-                                        </Option>
-                                    })
-                                })
-                            }
-                        </Select>
-                        <Menu
-                            onClick={isShow ? (e: any) => menuItemClick(e, isOk) : (e: any) => menuItemClick(e, true)}
-                            style={{ width: `${bWith ? '100%' : '178px'}`, height: 'calc(100vh - 220px)', overflowY: 'auto', overflowX: 'hidden' }}
-                            openKeys={openKeys}
-                            selectedKeys={selectedKeys}
-                            mode={"inline"}
-                            onOpenChange={menuClick}
-                        >
-                            {
-                                getWxGroupAll?.data?.map((item: any) => {
-                                    return <SubMenu
-                                        key={item?.groupName}
-                                        title={<p>{item?.groupName}<span style={{ color: '#999' }}>({item?.mpAccounts?.length || 0})</span></p>}
-                                    >
-                                        {
-                                            item?.mpAccounts?.map((list: any) => {
-                                                return <Menu.Item
-                                                    key={list?.nickName}
-                                                    onClick={isShow ? () => {
-                                                        selectData(list, isOk)
-                                                        userIdset(item?.userId)
-                                                    } : () => {
-                                                        selectData(list, true)
-                                                        userIdset(item?.userId)
-                                                    }}
-                                                    disabled={isDisabled ? list.verifyTypeInfo === -1 :false}
-                                                >
-                                                    <img src={list?.headImg || localStorage?.bookImg} className={style.item_img} />
-                                                    <span>{list?.nickName}</span>
-                                                </Menu.Item>
-                                            })
-                                        }
-                                    </SubMenu>
-                                })
-                            }
-                        </Menu>
-                    </div>
-                    {props.children}
-                </div>
-            </Tabs.TabPane>
-            {
-                getAllOfMember?.data?.length > 0 && <>
-                    <Tabs.TabPane tab='组员' key='组员'>
-                        <div className={style.group}>
-                            <div >
-                                <Select
-                                    style={{ width: '100%' }}
-                                    placeholder="输入搜索公众号"
-                                    onChange={isShow ? (v: any) => { inputChange(v, isOk) } : (v: any) => { inputChange(v, true) }}
-                                    showArrow
-                                    showSearch
-                                    allowClear
-                                >
-                                    {
-                                        getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }, index: number) => {
-                                            return item?.value?.map((list: any, eq: number) => {
-                                                return <Option key={list?.id + item?.key?.nickname} value={item?.key?.nickname + item?.key?.userId + '_' + list?.nickName} disabled={ isDisabled?list?.verifyTypeInfo === -1:false}>
-                                                    <img src={list?.headImg || localStorage?.bookImg} className={style.item_img} /> {list?.nickName}
-                                                </Option>
-                                            })
-                                        })
-                                    }
-                                </Select>
-                                <Menu
-                                    onClick={isShow ? (e: any) => crewMenuItemClick(e, isOk) : (e: any) => crewMenuItemClick(e, true)}
-                                    style={{ width: `${bWith ? '100%' : '178px'}`, height: 'calc(100vh - 220px)', overflowY: 'auto', overflowX: 'hidden' }}
-                                    openKeys={crewOpenKeys}
-                                    selectedKeys={crewSelectedKeys}
-                                    mode={"inline"}
-                                    onOpenChange={crewMenuClick}
-                                >
-                                    {
-                                        getAllOfMember?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }, eq: number) => {
-                                            return <SubMenu
-                                                key={item?.key?.nickname + item?.key?.userId}
-                                                title={<p>{item?.key?.nickname}<span style={{ color: '#999' }}>({item?.value?.length})</span></p>}
-                                            >
-                                                {
-                                                  crewOpenKeys.some((name) => name === item?.key?.nickname + item?.key?.userId) &&   item?.value?.map((list: any,index:number) => {
-                                                        return <Menu.Item
-                                                            key={eq + '_' + index + '_' + list?.id + '_' + list?.putUserId}
-                                                            onClick={isShow ? () => {
-                                                                selectData(list, isOk)
-                                                                userIdset(item?.key?.userId)
-                                                            } : () => {
-                                                                selectData(list, true)
-                                                                userIdset(item?.key?.userId)
-                                                            }}
-                                                            disabled={isDisabled? list.verifyTypeInfo === -1 :false}
-                                                        >
-                                                            <img src={list?.headImg || localStorage?.bookImg} className={style.item_img} />
-                                                            <span>{list?.nickName}</span>
-                                                        </Menu.Item>
-                                                    })
-                                                }
-                                            </SubMenu>
-                                        })
-                                    }
-                                </Menu>
-                            </div>
-                            {props.children}
-                        </div>
-                    </Tabs.TabPane>
-                </>
-            }
-        </Tabs>
-    </ >
-}
-
-export default LeftPage

+ 0 - 156
src/components/GroupWxTabs/yyb.tsx

@@ -1,156 +0,0 @@
-import { Menu, Select, Tabs } from 'antd'
-import React, { ReactNode, useCallback, useEffect, useState } from 'react'
-import style from './index.less'
-import { useModel, history } from 'umi'
-import { MenuFoldOutlined, MenuUnfoldOutlined, UsergroupAddOutlined, UserOutlined } from '@ant-design/icons'
-
-function GroupYybTabs(props: { children?: JSX.Element, height?: string | number, name?: string, allowClear?: boolean, isShowCount?: boolean, tabBarExtraContent?: ReactNode | { left?: ReactNode, right?: ReactNode } }) {
-    let { allowClear = true, tabBarExtraContent, isShowCount = true, name } = props // isFadminQTab 非Admin 不展示选择人
-    const [crewSelectedKeys, setCrewSelectedKeys] = useState<string[]>([]) //选中组员的菜单
-    const { getAllZhMemBer, state: usesState, dispatch: useDispatch } = useModel('useOperating.useWxGroupList')
-    const { tabsKey1 } = usesState
-    const { dispatch, initUserIdYyb, state: { selectdUserIdYyb, selectdNameYyb } } = useModel('useOperating.useUser')
-    const [isShow, setIsShow] = useState<boolean>(true)
-
-    //获取当前角色下的公众号
-    useEffect(() => {
-        if (selectdNameYyb && selectdUserIdYyb) {
-            setCrewSelectedKeys([selectdNameYyb + selectdUserIdYyb])
-        }
-    }, [selectdNameYyb, selectdUserIdYyb])
-
-    // 特定空的需要重新赋值
-    useEffect(() => {
-        if (name === '账号管理' && tabsKey1 === '组员' && !selectdUserIdYyb) {
-            onChange('组员')
-        }
-    }, [])
-
-    //组员与自己的切换
-    const onChange = (key: string) => {
-        if (key === 'btn1') return
-        if (key === 'btn') {
-            if (tabsKey1 === '组员') {
-                setIsShow(!isShow)
-            }
-            return
-        }
-        useDispatch({ type: 'setTabsKey1', params: { tabsKey1: key } })
-        if (key === '自己') {
-            initUserIdYyb()
-            setIsShow(true)
-        } else {
-            /**当切换为组员的时候自动选中第一个有绑定公众号的组员 */
-            let ok = true
-            getAllZhMemBer?.data?.forEach((item: { key: { userId: number, nickname: string }, value: any[] }) => {
-                if (ok && item?.value?.length > 0) {
-                    ok = false
-                    // setCrewSelectedKeys([item?.key?.nickname + item?.key?.userId])
-                    dispatch({ type: 'setUserIdYyb', params: { userId: item?.key?.userId.toString(), name: item?.key?.nickname } })
-                }
-            })
-            if (ok) {
-                dispatch({ type: 'setUserIdYyb', params: { userId: getAllZhMemBer?.data[0]?.key?.userId?.toString(), name: getAllZhMemBer?.data[0]?.key?.nickname } })
-            }
-        }
-        return () => {
-            initUserIdYyb()
-        }
-    }
-
-    //选中的成员改变全局userId请求获取数据
-    const itemChange = (key: string, option: any) => {
-        if (key) {
-            // setCrewSelectedKeys([option.children + key])
-            dispatch({ type: 'setUserIdYyb', params: { userId: key.toString(), name: option.children } })
-        } else {
-            setCrewSelectedKeys([])
-            dispatch({ type: 'setUserIdYyb', params: { userId: '', name: '' } })
-        }
-    }
-    //组员menuitem点击
-    let crewMenuItemClick = (e: any) => {
-        setCrewSelectedKeys([e.key])
-    };
-    //选中角色
-    let handelUserId = useCallback((userId, name) => {
-        dispatch({ type: 'setUserIdYyb', params: { userId: userId?.toString(), name } })
-    }, [])
-
-    //更改背景色
-    useEffect(() => {
-        let path = history.location.pathname.split('/')[1]
-        if (path === 'operatePage') {
-            localStorage.setItem('bg', 'light')
-        }
-        if (path === 'dataStatistics') {
-            localStorage.setItem('bg', 'dark')
-        }
-    }, [history])
-
-    return <>
-        <Tabs onChange={onChange} className={style.tabs} type='card' activeKey={tabsKey1} tabBarExtraContent={tabBarExtraContent}>
-            <Tabs.TabPane tab={<span><UserOutlined />自己</span>} key='自己' >
-                {props.children}
-            </Tabs.TabPane>
-            {
-                getAllZhMemBer?.data?.length > 0 && <>
-                    <Tabs.TabPane tab={<span><UsergroupAddOutlined />组员</span>} key='组员'>
-                        <div className={style.group}>
-                            {
-                                isShow && <div>
-                                    <Select
-                                        showSearch
-                                        style={{ width: 178 }}
-                                        placeholder="输入组员名称"
-                                        optionFilterProp="children"
-                                        onChange={itemChange}
-                                        allowClear={allowClear}
-                                        value={crewSelectedKeys?.join()?.replace(/[\w]/ig, '')}
-                                        filterOption={(input, option) =>
-                                            option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-                                        }
-                                    >
-                                        {
-                                            getAllZhMemBer?.data?.map((user: { key: { userId: number, nickname: string } }, index: number) => {
-                                                return <Select.Option value={user?.key?.userId} key={user?.key?.userId + index}>{user?.key?.nickname}</Select.Option>
-                                            })
-                                        }
-                                    </Select>
-                                    <Menu
-                                        onClick={crewMenuItemClick}
-                                        style={{
-                                            width: 178,
-                                            height: props?.height ? props.height : 'calc(100vh - 400px)',
-                                            overflowY: `auto`,
-                                            overflowX: 'hidden',
-                                            borderRight: 0,
-                                            backgroundColor: 'transparent'
-                                        }}
-                                        selectedKeys={crewSelectedKeys}
-                                        mode={"inline"}
-                                    >
-                                        {
-                                            getAllZhMemBer?.data?.map((item: { key: { nickname: string, userId: number }, value: any[] }) => {
-                                                return <Menu.Item key={item?.key?.nickname + item?.key?.userId}>
-                                                    <p onClick={() => { handelUserId(item?.key?.userId?.toString(), item?.key?.nickname) }} style={{ margin: 0 }}>
-                                                        {item?.key?.nickname}
-                                                        {isShowCount && <span style={{ color: '#999' }}>({item?.value?.length})</span>}
-                                                    </p>
-                                                </Menu.Item>
-                                            })
-                                        }
-                                    </Menu>
-                                </div>
-                            }
-                            {props.children}
-                        </div>
-                    </Tabs.TabPane>
-                    <Tabs.TabPane tab={<span>{isShow ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />}</span>} key='btn' />
-                </>
-            }
-        </Tabs>
-    </>
-}
-
-export default GroupYybTabs

+ 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(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 as any).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 - 60
src/components/ImgPreview/index.less

@@ -1,60 +0,0 @@
-#imgPreview{
-    position: fixed;
-    width: 100%;
-    height: 100%;
-    z-index: 888;
-    top: 0;
-    left: 0;
-    padding: 40px;
-    box-sizing: border-box;
-
-    &>div.carousel-root{
-        height: 100%;
-        &>.carousel-slider{
-            height: 80%;
-            &>.slider-wrapper{
-                height: 100%;
-                ul.slider{
-                    height: 100%;
-                    li{
-                        height: 100%;
-                        &>div{
-                            height: 100%;
-                            position: relative;
-                            img{
-                                // height: 100%;
-                                // width: auto;
-                                max-height: 100%;
-                                width: auto;
-                                max-width: 1200px;
-                                position: absolute;
-                                top: 50%;
-                                left: 50%;
-                                transform: translate(-50%, -50%);
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        &>.carousel > .thumbs-wrapper .thumbs{
-            text-align: center;
-        }
-    }
-    &>.close{
-        position: absolute;
-        right: 250px;
-        top: 5px;
-        color: #fff;
-        font-size: 24px;
-        z-index: 890;
-    }
-    &>.back{
-        position: absolute;
-        width: 100%;
-        height: 100%;
-        background-color: rgba(0, 0, 0, .7);
-        top: 0;
-        left: 0;
-    }
-}

+ 0 - 34
src/components/ImgPreview/index.tsx

@@ -1,34 +0,0 @@
-import React, { useCallback } from "react"
-import './index.less'
-import "react-responsive-carousel/lib/styles/carousel.min.css";
-import { Carousel } from 'react-responsive-carousel'
-import { CloseOutlined } from "@ant-design/icons";
-import { Button } from "antd";
-
-interface Props {
-    data: string[],
-    show: boolean,
-    hidden: (value: boolean) => void
-}
-
-function ImgPreview (props: Props) {
-    let {data, show = false, hidden} = props
-    const handleHidden = useCallback((e) => {
-        e.stopPropagation()
-        e.preventDefault()
-        hidden(false)
-    },[])
-    return <div id="imgPreview" style={{display: show && data.length > 0 ? 'block' : 'none'}}>
-        <Button type="text" className="close" onClick={(e)=>{handleHidden(e)}}><CloseOutlined /></Button>
-        <div className="back" onClick={(e)=>{handleHidden(e)}}></div>
-        <Carousel>
-            {
-                data?.map((item: string, index: number) => <div key={index}>
-                    <img src={item} />
-                </div>)
-            }
-        </Carousel>
-    </div>
-}
-
-export default React.memo(ImgPreview)

+ 0 - 40
src/components/InputSearch/index.tsx

@@ -1,40 +0,0 @@
-import React from 'react'
-import { Select } from 'antd'
-import { SearchOutlined } from '@ant-design/icons'
-import { SelectValue } from 'antd/lib/select'
-
-interface Props {
-    onChange: (value: SelectValue) => void,
-    onFocus?: (event?: React.FocusEvent<HTMLElement>) => void,
-    onBlur?: (event?: React.FocusEvent<HTMLElement>) => void,
-    onSearch: (value: string) => void,
-    style?: React.CSSProperties,
-    placeholder?: string | React.ReactNode,
-    option: { value: string | number, text: string }[]
-}
-
-let { Option } = Select
-function InputSearch(props: Props) {
-
-    return <Select
-        showSearch
-        suffixIcon={<SearchOutlined />}
-        style={props.style || { width: 200 }}
-        placeholder={props.placeholder}
-        optionFilterProp="children"
-        onChange={props.onChange}
-        onFocus={props.onFocus}
-        onBlur={props.onBlur}
-        onSearch={props.onSearch}
-        filterOption={(input, option) =>
-            option?.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
-        }
-    >
-        {
-            props?.option?.map((option: { value: string | number, text: string }) => {
-                return <Option value={option.value} key={option.value}>{option.text}</Option>
-            })
-        }
-    </Select>
-}
-export default InputSearch

+ 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: any) => {
-        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}
-            open={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: any, 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}
-        open={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 as any)?.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 as any)?.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 as keyof typeof config1]} 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: any = {
-                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}
-        open={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) => {
-                                                    setSort(e || 0)
-                                                }}
-                                            />
-                                        </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
-                open={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} open={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 as any)?.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}
-            open={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}
-        open={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 } 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: any = {
-    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 as any)?.selection ? (document as any)?.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='编辑文字内容'
-        open={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={'新建互动链'}
-                            open={isShow}
-                            onOpenChange={(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
-            open={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
-                open={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}
-        open={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}
-        open={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
-    open={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}
-        open={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 - 157
src/components/MaterialModal/wxMpnews.tsx

@@ -1,157 +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: number, pageSize: number) => {
-        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: any) => {
-        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
-            open={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}
-                        items={[
-                            { label: '个人本地', key: '1' },
-                            { label: '公共本地', key: '0' },
-                        ]}
-                    />
-                    <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: any, 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']}
-      open={visible}
-      onOpenChange={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 - 19
src/components/RegExpInput/index.less

@@ -1,19 +0,0 @@
-.input_box {
-  position: relative;
-  .error {
-    position: absolute;
-    top:5px;
-    right: 5px;
-    color: red;
-    z-index: 1;
-  }
-  .error + input{
-    padding-right: 20px;
-    box-sizing: border-box;
-  }
-  .msg{
-    position: absolute;
-    bottom: -30px;
-    left: 0;
-  }
-}

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

@@ -1,35 +0,0 @@
-import { Input, Space } from 'antd'
-import React, { useCallback } from 'react'
-import style from './index.less'
-type Props = {
-    maxLength?: any,//最大长度
-    rules: { reg: any },//正则
-    callback: (value: string) => void,//回调函数
-    labelWidth?: number,//label宽
-    inputWidth?: number,//input宽
-    labelName?: any,//label名称
-    errorMsg?: string//提示文字
-    defaultValue?: string
-}
-const RegExpInput = (props: Props) => {
-    const ref: any = React.createRef()
-    /**菜单名称输入 */
-    const handelInput = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
-        let value = e.target.value
-        props.callback(value)
-    }, [])
-    return <Space>
-        <label>{props?.labelName}</label>
-        <div className={style.input_box} style={props?.inputWidth ? { width: props.inputWidth } : undefined}>
-            <Input
-                ref={ref}
-                onChange={handelInput}
-                maxLength={props?.maxLength}
-                defaultValue={props.defaultValue}
-                style={{ ...props?.inputWidth ? { width: props?.inputWidth } : {} }}
-            />
-            <span className={style.msg}>{props?.errorMsg}</span>
-        </div>
-    </Space>
-}
-export default RegExpInput

+ 25 - 42
src/components/RightContent/AvatarDropdown.tsx

@@ -8,7 +8,7 @@ import { stringify } from 'querystring';
 import HeaderDropdown from '../HeaderDropdown';
 import styles from './index.less';
 import { useAjax } from '@/Hook/useAjax';
-import {api }from '@/services/api'
+import { api } from '@/services/api'
 import useCopy from '@/Hook/useCopy';
 
 export interface GlobalHeaderRightProps {
@@ -36,7 +36,7 @@ const loginOut = async () => {
 };
 
 const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
-  const {copy} =useCopy()
+  const { copy } = useCopy()
   const selectCompany = useAjax((companyId: number) => selectCompanyApi(companyId), { formatResult: true })
   const { initialState, setInitialState } = useModel('@@initialState');
   const { edit, modifyPassword } = useModel('useOperating.useUser')
@@ -62,10 +62,10 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
         setDialogVisible(() => true)
         return
       }
-      if(key === 'admin'){
-        let token = sessionStorage.getItem('Admin-Token') 
-        window.open(api.includes('test') || api === 'api'?`http://test.zanxiangnet.com/admin/#/login?token=${token}`:`https://mp.zanxiangnet.com/admin/#/login?token=${token}`)
-        return 
+      if (key === 'admin') {
+        let token = sessionStorage.getItem('Admin-Token')
+        window.open(api.includes('test') || api === 'api' ? `http://test.zanxiangnet.com/admin/#/login?token=${token}` : `https://mp.zanxiangnet.com/admin/#/login?token=${token}`)
+        return
       }
       history.push(`/account/${key}`);
     },
@@ -124,40 +124,23 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
     return loading;
   }
 
+  let items = []
+  if (menu) {
+    items.push({ label: '个人中心', key: 'center', icon: <UserOutlined /> })
+    items.push({ label: '个人设置', key: 'settings', icon: <SettingOutlined /> })
+  }
+  if (currentUser?.powerLevel === 999) {
+    items.push({ label: '管理系统', key: 'admin', icon: <SendOutlined /> })
+  }
+  items.push({ label: '切换公司', key: 'company', icon: <SwapOutlined /> })
+  items.push({ label: '修改密码', key: 'edit', icon: <EditOutlined /> })
+  items.push({ label: '退出登录', key: 'logout', icon: <LogoutOutlined /> })
+
   const menuHeaderDropdown = (
-    <Menu className={styles.menu} selectedKeys={[]} onClick={onMenuClick}>
-      {menu && (
-        <Menu.Item key="center">
-          <UserOutlined />
-          个人中心
-        </Menu.Item>
-      )}
-      {menu && (
-        <Menu.Item key="settings">
-          <SettingOutlined />
-          个人设置
-        </Menu.Item>
-      )}
-      {menu && <Menu.Divider />}
-      {
-        currentUser?.powerLevel === 999 && <Menu.Item key="admin">
-          <SendOutlined />
-          管理系统
-        </Menu.Item>
-      }
-      <Menu.Item key="company">
-        <SwapOutlined />
-        切换公司
-      </Menu.Item>
-      <Menu.Item key="edit">
-        <EditOutlined />
-        修改密码
-      </Menu.Item>
-      <Menu.Item key="logout">
-        <LogoutOutlined />
-        退出登录
-      </Menu.Item>
-    </Menu>
+    <Menu
+      items={items}
+      className={styles.menu} selectedKeys={[]} onClick={onMenuClick}
+    />
   );
 
   // 切换公司
@@ -171,9 +154,9 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => {
   return (
     <>
       <HeaderDropdown overlay={menuHeaderDropdown}>
-        <span className={`${styles.action} ${styles.account}`} onClick={()=>{
-          let AdminToken:any = sessionStorage.getItem('Admin-Token')
-            copy(AdminToken)
+        <span className={`${styles.action} ${styles.account}`} onClick={() => {
+          let AdminToken: any = sessionStorage.getItem('Admin-Token')
+          copy(AdminToken)
         }}>
           <Avatar size="small" className={styles.avatar} src={currentUser.avatar || headImg} alt="avatar" />
           <span className={`${styles.name} anticon`}>{currentUser.name}</span>

+ 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;
-    }
-  }
-}

Beberapa file tidak ditampilkan karena terlalu banyak file yang berubah dalam diff ini