wjx há 2 anos atrás
pai
commit
2ad26b1f62

+ 18 - 1
src/models/useLaunchAdq/useAdAuthorize.ts

@@ -1,12 +1,29 @@
 import { useAjax } from '@/Hook/useAjax'
 import { getAdAccountApi } from '@/services/launchAdq/adAuthorize'
+import { getGroupListApi } from '@/services/launchAdq/subgroup'
 
 
 export default function useAdAuthorize() {
 
     const getAdAccount = useAjax(() => getAdAccountApi(), { formatResult: true })
 
+    /** 所有分组列表 */
+    const getGroupList = useAjax(() => getGroupListApi())
+
+
+    /** 初始话 */
+    const groupListInit = () => {
+        getGroupList.run()
+    }
+
+    const groupRefresh = () => {
+        getGroupList.refresh()
+    }
+
     return {
-        getAdAccount
+        getAdAccount,
+        getGroupList,
+        groupListInit,
+        groupRefresh
     }
 }

+ 2 - 2
src/models/useOperating/useWxGroupList.ts

@@ -3,8 +3,8 @@ import { allOfMember, listGroup, getAllZhMemBerApi, getPicherListApi } from '@/s
 import { useAjax } from '@/Hook/useAjax';
 import { getWxlist } from '@/services/operating/material';
 import { getMpsTimeOut } from '@/services/user';
-import { useModel, history } from 'umi';
-import { Modal, notification } from 'antd';
+import { history } from 'umi';
+import { Modal } from 'antd';
 import { getVersions } from '@/services/login';
 import React from 'react';
 type State = {

+ 99 - 0
src/pages/launchSystemNew/account/addAccountToGroup.tsx

@@ -0,0 +1,99 @@
+import { useAjax } from "@/Hook/useAjax"
+import { getAdAccountApi, getAllUserAccountApi } from "@/services/launchAdq/adAuthorize"
+import { addNewAccountToGroupApi, getAccountListApi, getGroupListApi } from "@/services/launchAdq/subgroup"
+import { PlusOutlined } from "@ant-design/icons"
+import { Button, Form, message, Modal, Select, Transfer } from "antd"
+import React, { useEffect, useState } from "react"
+import { useModel } from "umi"
+
+
+interface Props {
+    onChange?: () => void
+}
+/**
+ * 新增至分组
+ * @param props 
+ * @returns 
+ */
+const AddAccountToGroup: React.FC<Props> = (props) => {
+
+    /*********************************/
+    const { onChange } = props
+    const [form] = Form.useForm();
+    let currGroupId = Form.useWatch('currGroupId', form)
+    const [visible, setVisible] = useState<boolean>(false)
+    const [mockData, setMockData] = useState<{ key: string, title: string }[]>([])
+    const { getGroupList } = useModel('useLaunchAdq.useAdAuthorize')
+
+    const getAccountList = useAjax((params) => getAccountListApi(params))
+    const addNewAccountToGroup = useAjax((params) => addNewAccountToGroupApi(params))
+    const getAllUserAccount = useAjax(() => getAllUserAccountApi())
+    /*********************************/
+
+    useEffect(() => {
+        if (currGroupId) {
+            getAccountList.run(currGroupId).then(res => {
+                console.log(res);
+                form.setFieldsValue({ accountIds: res?.adAccountList?.map((item: { accountId: string }) => item.accountId.toString()) || [] })
+            })
+        }
+    }, [currGroupId])
+
+    const addAccountToGroupHandle = () => {
+        setVisible(true)
+        getAllUserAccount.run().then(res => {
+            setMockData(res?.map((item: { accountId: string, remark: string }) => ({ key: item.accountId.toString(), title: `${item.accountId}${item.remark ? '_' + item.remark : ''}` })))
+        })
+    }
+
+    const handleOk = () => {
+        form.validateFields().then(values => {
+            addNewAccountToGroup.run(values).then(res => {
+                message.success('修改成功')
+                closeHandle()
+                onChange?.()
+            })
+        })
+    }
+
+    const closeHandle = () => {
+        setVisible(false)
+        form.setFieldsValue({ currGroupId: undefined, accountIds: undefined })
+    }
+
+    return <>
+        <Button onClick={addAccountToGroupHandle} type='primary' icon={<PlusOutlined />}>修改分组中账户</Button>
+        {visible && <Modal
+            title='修改分组中账户'
+            visible={visible}
+            onOk={handleOk}
+            onCancel={closeHandle}
+            confirmLoading={addNewAccountToGroup.loading}
+        >
+            <Form
+                form={form}
+                labelCol={{ span: 4 }}
+                colon={false}
+                initialValues={{}}
+            >
+                <Form.Item label={<strong>分组</strong>} name='currGroupId' rules={[{ required: true, message: '请选择分组' }]}>
+                    <Select placeholder='请选择分组'>
+                        {getGroupList?.data?.map((item: { groupName: string, groupId: number }) => <Select.Option value={item.groupId} key={item.groupId}>{item.groupName}</Select.Option>)}
+                    </Select>
+                </Form.Item>
+                {currGroupId && <Form.Item label={<strong>账号</strong>} name='accountIds' valuePropName='targetKeys' rules={[{ required: true, message: '请选择账号' }]}>
+                    <Transfer
+                        dataSource={mockData}
+                        showSearch
+                        titles={['未选', '已选']}
+                        oneWay
+                        render={item => item.title}
+                    />
+                </Form.Item>}
+            </Form>
+        </Modal>}
+    </>
+}
+
+
+export default React.memo(AddAccountToGroup)

+ 95 - 0
src/pages/launchSystemNew/account/appointPut.tsx

@@ -0,0 +1,95 @@
+import { useAjax } from "@/Hook/useAjax"
+import { cutPutApi } from "@/services/operating/accountyyb"
+import { Form, message, Modal, Select } from "antd"
+import React, { useEffect, useState } from "react"
+
+
+interface Props {
+    allOfMember: any
+    onChange?: () => void
+    onClose?: () => void
+    visible?: boolean,
+    value?: any
+}
+
+/**
+ * 指派
+ * @param props 
+ * @returns 
+ */
+const AppointPut: React.FC<Props> = (props) => {
+    /*******************************/
+    const { onChange, onClose, visible, allOfMember, value } = props
+    const [userAll, setUserAll] = useState([])
+
+    const [form] = Form.useForm();
+    const cutPut = useAjax((params) => cutPutApi(params))
+    /*******************************/
+
+    useEffect(() => {
+        if (value && Object.keys(value).length > 0) {
+            form.setFieldsValue({ putUserId: value.putUserId })
+        }
+    }, [value])
+
+    /** 获取组员 */
+    useEffect(() => {
+        (async function () {
+            let res = allOfMember?.data || await allOfMember.run()
+            if (res?.data) {
+                let useAll: any = []
+                res?.data?.forEach((item: { key: { userId: any; nickName: any; }; value: any[]; }) => {
+                    let obj = {
+                        key: item.key.userId,
+                        label: item.key.nickName
+                    }
+                    if (item?.value) {
+                        obj['childrenarr'] = item?.value?.map(item => {
+                            return { key: item.accountId + '_' + item.id, label: item?.remark ? item.accountId + '_' + item?.remark : item.accountId }
+                        })
+                    }
+                    useAll.push(obj)
+                })
+                setUserAll(useAll)
+            }
+        })()
+    }, [])
+
+    const handleOk = () => {
+        form.validateFields().then(values => {
+            cutPut.run({ ...values, accountIds: [value.accountId] }).then(res => {
+                message.success('指派成功')
+                onChange?.()
+            })
+        })
+    }
+
+    return <Modal
+        title="指派"
+        visible={visible}
+        onOk={handleOk}
+        onCancel={() => onClose?.()}
+        confirmLoading={cutPut.loading}
+    >
+        <Form
+            form={form}
+            labelCol={{ span: 4 }}
+            colon={false}
+            initialValues={{}}
+        >
+            <Form.Item label={<strong>组员</strong>} name='putUserId' rules={[{ required: true, message: '请选择分组' }]}>
+                <Select
+                    placeholder='请选择组员'
+                    showSearch
+                    filterOption={(input: string, option: any) => {
+                        return option.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
+                    }}
+                >
+                    {userAll?.map((item: { key: string, label: number }) => <Select.Option value={item.key} key={item.key}>{item.label}</Select.Option>)}
+                </Select>
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(AppointPut)

+ 129 - 0
src/pages/launchSystemNew/account/changeRecord.tsx

@@ -0,0 +1,129 @@
+import Tables from "@/components/Tables";
+import { DatePicker, Drawer, Form, Input, Modal, Select } from "antd";
+import moment from "moment";
+import React, { useCallback, useEffect, useState } from "react";
+import { useModel } from "umi";
+import { columnsCrGdt } from "./tablesConfig"
+
+type Props = {
+    data?: { name: number, id: number } | null,
+    visible?: boolean,
+    onChange?: () => void,
+    onClose?: () => void
+}
+function ChangeRecord(props: Props) {
+
+    const { data, visible, onClose } = props
+    const { getGdtChangeRecord, editAccountChangeRecord, editGdtChangeRecord, getResource } = useModel('useOperating.useAccountyyb')
+    const [accountQueryForm, setAccountQueryForm] = useState<{ quickAppAccountId: number, pageNum: number, pageSize: number }>({ quickAppAccountId: data?.id as number, pageNum: 1, pageSize: 20 })
+    const [gdtQueryForm, setGdtQueryForm] = useState<{ gdtAccountId: number, pageNum: number, pageSize: number }>({ gdtAccountId: data?.name as number, pageNum: 1, pageSize: 20 })
+    const [editTitle, setEditTitle] = useState<string>('编辑')
+    const [form] = Form.useForm()
+    const [editData, setEditData] = useState<{ recordId: number, putResourceId: number | undefined, resourceNames: string, beginTime: any, endTime: any } | null>(null)
+    const [editVisible, setEditVisible] = useState<boolean>(false)
+
+    useEffect(() => {
+        getList()
+    }, [accountQueryForm, gdtQueryForm])
+
+    const getList = () => {
+        getGdtChangeRecord.run(gdtQueryForm)
+    }
+
+    // 分页
+    const pageChange = useCallback((page: string | number, pageSize?: string | number) => {
+        setGdtQueryForm({ ...gdtQueryForm, pageNum: page as number, pageSize: pageSize as number })
+    }, [accountQueryForm, gdtQueryForm])
+
+    // 编辑
+    const editHandle = useCallback((data: any) => {
+        const { beginTime, endTime, id, putResourceName } = data
+        setEditData({ beginTime: moment(beginTime), endTime: endTime ? moment(endTime) : null, recordId: id, putResourceId: undefined, resourceNames: putResourceName })
+        setEditTitle('编辑 ' + putResourceName)
+        setEditVisible(true)
+        setTimeout(() => {
+            form.resetFields()
+        }, 100)
+    }, [editData, editTitle, editVisible, form])
+
+    // 搜索资源
+    const handleSearch = (value: string) => {
+        getResource.run({ resourceName: value, resourceType: 0 })
+    }
+
+    const handleOk = async () => {
+        form.submit()
+        let { resourceNames, ...data1 }  = await form.validateFields()
+        let proms = { ...data1, beginTime: moment(data1.beginTime).format('YYYY-MM-DD') + ' 00:00:00' }
+        if (data1.endTime) {
+            proms.endTime = moment(data1.endTime).format('YYYY-MM-DD')
+        }
+        editGdtChangeRecord.run({ ...proms, recordId: editData?.recordId }).then(res => {
+            if(res) {
+                setEditData(null);
+                setEditVisible(false);
+                getGdtChangeRecord.refresh()
+            }
+        })
+    }
+
+    console.log('editData---->', editData)
+
+    return <div>
+
+        <Drawer title={data?.name + ' 变更记录'} placement="right" width={1200} onClose={() => { onClose && onClose() }} visible={visible}>
+            <Tables
+                columns={columnsCrGdt(editHandle)}
+                dataSource={getGdtChangeRecord?.data?.records}
+                total={getGdtChangeRecord?.data?.total}
+                loading={getGdtChangeRecord?.loading}
+                pageChange={pageChange}
+                sizeChange={pageChange}
+                current={getGdtChangeRecord?.data?.current}
+                pageSize={getGdtChangeRecord?.data?.size}
+                size={'small'}
+                scroll={{ x: 1100 }}
+            />
+        </Drawer>
+
+        {editVisible && <Modal title={editTitle} visible={editVisible} onOk={handleOk} onCancel={() => { setEditData(null); form.resetFields(); setEditVisible(false); }} confirmLoading={editAccountChangeRecord.loading || editGdtChangeRecord.loading}>
+            <Form
+                name="basic"
+                form={form}
+                labelCol={{ span: 5 }}
+                wrapperCol={{ span: 19 }}
+                autoComplete="off"
+                initialValues={{ ...editData }}
+            >
+                <Form.Item label="开始时间" name="beginTime" rules={[{ type: 'object' as const, required: true, message: '请选择时间!' }]}>
+                    <DatePicker />
+                </Form.Item>
+                <Form.Item label="结束时间" name="endTime">
+                    <DatePicker />
+                </Form.Item>
+                <Form.Item label="当前投放信息" name="resourceNames">
+                    <Input.TextArea autoSize disabled />
+                </Form.Item>
+                <Form.Item label="投放信息" name="putResourceId" rules={[{ type: 'number', required: true, message: '请选择投放信息!' }]}>
+                    <Select
+                        showSearch
+                        placeholder="选择投放信息"
+                        defaultActiveFirstOption={false}
+                        showArrow={false}
+                        filterOption={false}
+                        onSearch={handleSearch}
+                        notFoundContent={null}
+                    >
+                        {getResource?.data?.map((item: { id: number, resourceName: string }) => <Select.Option key={item.id} value={item.id}>{item.resourceName}</Select.Option>)}
+                    </Select>
+                </Form.Item>
+
+            </Form>
+
+        </Modal>}
+
+    </div>
+}
+
+
+export default React.memo(ChangeRecord)

+ 69 - 0
src/pages/launchSystemNew/account/checkAccount.tsx

@@ -0,0 +1,69 @@
+import { DatePicker, Form, Input, Modal, Select } from "antd";
+import moment from "moment";
+import React from "react";
+import { useModel } from "umi";
+
+interface Props {
+    value?: any,
+    visible?: boolean,
+    onChange?: () => void,
+    onClose?: () => void
+}
+function CheckAccount(props: Props) {
+    const { value = {}, visible = false, onChange, onClose } = props
+    const { userId } = useModel('useOperating.useUser', model => ({ userId: model.state.selectdUserId }))
+    const { getResource, checkGdtAccountGdt } = useModel('useOperating.useAccountyyb')
+    const [form] = Form.useForm()
+    const handleOk = async () => {
+        form.submit()
+        let data = await form.validateFields()
+        let { accountIds, resourceNames, ...data1 } = data
+        let proms = { ...data1, beginTime: moment(data.beginTime).format('YYYY-MM-DD'), userId, gdtAccountIds: accountIds }
+        checkGdtAccountGdt.run(proms).then(res => {
+            if (res) {
+                onChange && onChange()
+            }
+        })
+    }
+
+    // 搜索资源
+    const handleSearch = (value: string) => {
+        getResource.run({ resourceName: value, resourceType: 0})
+    }
+
+    return <Modal title={`${'GDT'}切号`} visible={visible} onOk={handleOk} onCancel={() => { onClose && onClose() }} confirmLoading={checkGdtAccountGdt.loading}>
+        <Form
+            name="basic"
+            form={form}
+            labelCol={{ span: 5 }}
+            wrapperCol={{ span: 19 }}
+            autoComplete="off"
+            initialValues={{ ...value }}
+        >
+            <Form.Item label="账号ID" name="accountIds" rules={[{ type: 'string', required: true, message: '请输入账号!' }]}>
+                <Input.TextArea autoSize placeholder="请输入账号ID(id1,id2,id3)" disabled />
+            </Form.Item>
+            <Form.Item label="当前投放信息" name="resourceNames">
+                <Input.TextArea autoSize disabled />
+            </Form.Item>
+            <Form.Item label="投放信息" name="putResourceId" rules={[{ type: 'number', required: true, message: '请选择投放信息!' }]}>
+                <Select
+                    showSearch
+                    placeholder="选择投放信息"
+                    defaultActiveFirstOption={false}
+                    showArrow={false}
+                    filterOption={false}
+                    onSearch={handleSearch}
+                    notFoundContent={null}
+                >
+                    {getResource?.data?.map((item: { id: number, resourceName: string }) => <Select.Option key={item.id} value={item.id}>{item.resourceName}</Select.Option>)}
+                </Select>
+            </Form.Item>
+            <Form.Item label="开始时间" name="beginTime" rules={[{ type: 'object' as const, required: true, message: '请选择时间!' }]}>
+                <DatePicker />
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(CheckAccount)

+ 72 - 0
src/pages/launchSystemNew/account/divideIntoGroups.tsx

@@ -0,0 +1,72 @@
+import { useAjax } from "@/Hook/useAjax"
+import { addAccountToGroupApi, delAccountToGroupApi } from "@/services/launchAdq/subgroup"
+import { getArrDifference } from "@/utils/utils"
+import { UsergroupAddOutlined } from "@ant-design/icons"
+import { Button, Checkbox, message, Popover, Spin, Tooltip } from "antd"
+import React, { useEffect, useState } from "react"
+import { useModel } from "umi"
+
+
+interface Props {
+    groupIds: number[],
+    accountId: number,
+    getAdAccountList?: any
+}
+/**
+ * 账号分组至xxx
+ * @param props 
+ */
+const DivideIntoGroups: React.FC<Props> = (props) => {
+
+    /********************************/
+    const { groupIds = [], accountId, getAdAccountList } = props
+    const { getGroupList } = useModel('useLaunchAdq.useAdAuthorize')
+    const [visible, setVisible] = useState<boolean>(false);
+
+    const addAccountToGroup = useAjax((params) => addAccountToGroupApi(params))
+    const delAccountToGroup = useAjax((params) => delAccountToGroupApi(params))
+    /********************************/
+
+    const handleVisibleChange = (newOpen: boolean) => {
+        setVisible(newOpen)
+    }
+
+    const onChange = (checkedValues: any[]) => {
+        let newGroupid = getArrDifference(checkedValues, groupIds)
+        if (newGroupid.length > 0) {
+            if (checkedValues.length > groupIds.length) {  // 新增
+                addAccountToGroup.run({ currGroupId: newGroupid[0], accountIds: [accountId] }).then(res => {
+                    getAdAccountList.refresh()
+                })
+            } else {  // 删除
+                delAccountToGroup.run({ currGroupId: newGroupid[0], accountIds: [accountId] }).then(res => {
+                    getAdAccountList.refresh()
+                })
+            }
+        }
+    }
+
+    return <Popover
+        content={<Spin spinning={delAccountToGroup.loading || addAccountToGroup.loading}>
+            <Checkbox.Group style={{ width: '100%' }} value={groupIds} onChange={onChange}>
+                <ul className="dig_ul">
+                    {getGroupList?.data?.map((item: { groupName: string, groupId: number }) => <li className="dig_ul__li" key={item.groupId}>
+                        <Checkbox value={item.groupId}>{item.groupName}</Checkbox>
+                    </li>)}
+                </ul>
+            </Checkbox.Group>
+        </Spin>}
+        title="选择分组"
+        trigger="click"
+        visible={visible}
+        overlayClassName="dig"
+        onVisibleChange={handleVisibleChange}
+    >
+        <Tooltip title="分组">
+            <Button size="small" style={{ color: '#eb2f96' }} onClick={() => setVisible(true)}><UsergroupAddOutlined /></Button>
+        </Tooltip>
+    </Popover>
+}
+
+
+export default React.memo(DivideIntoGroups)

+ 5 - 18
src/pages/launchSystemNew/account/groupLeft.tsx

@@ -3,10 +3,11 @@ import { addGroupApi, delGroupApi, editGroupApi, getGroupListApi } from "@/servi
 import { DeleteOutlined, FormOutlined, PlusOutlined } from "@ant-design/icons"
 import { Button, Input, message, Popconfirm, Space, Spin } from "antd"
 import React, { useEffect, useRef, useState } from "react"
+import { useModel } from "umi"
 import './index.less'
 
 /**
- * 分组管理Left
+ * 分组管理Left 菜单
  */
 interface Props {
     onChange?: (groupId?: number) => void
@@ -21,10 +22,10 @@ const GroupLeft: React.FC<Props> = (props) => {
     const [groupData, setGroupData] = useState<{ groupName: string, remark?: string, groupId?: number }>({ groupName: '' }) // 分组添加
     const [selectAccData, setSelectAccData] = useState<{ id: number, mpName: string }[]>([])  // 选中
     const [groupId, setGroupId] = useState<number>(value || 0)
+    const { getGroupList } = useModel('useLaunchAdq.useAdAuthorize')
 
     const addGroup = useAjax((params) => addGroupApi(params))
     const editGroup = useAjax((params) => editGroupApi(params))
-    const getGroupList = useAjax(() => getGroupListApi())
     const delGroup = useAjax((params) => delGroupApi(params))
     /*************************/
 
@@ -43,11 +44,6 @@ const GroupLeft: React.FC<Props> = (props) => {
         }
     }, [inputRef, isNewGrouping])
 
-    /** 获取分组 */
-    useEffect(() => {
-        getGroupList.run()
-    }, [])
-
     /** 新增修改分组 */
     const addEditHandle = () => {
         if (groupData?.groupName) {
@@ -100,10 +96,6 @@ const GroupLeft: React.FC<Props> = (props) => {
                             <div style={{ width: 30 }} className="stop">组名</div>
                             <Input placeholder="输入分组名称(最多10个字)" className="stop" maxLength={10} ref={inputRef} onChange={(e) => { setGroupData({ ...groupData, groupName: e.target.value }) }} value={groupData?.groupName} />
                         </Space>
-                        {/* <Space className="stop">
-                            <div style={{ width: 70 }} className="stop">分组备注:</div>
-                            <Input placeholder="请输入分组备注(最多10个字)" className="stop" maxLength={10} onChange={(e) => { setGroupData({ ...groupData, remark: e.target.value }) }} value={groupData?.remark} />
-                        </Space> */}
                         <div style={{ display: 'flex', justifyContent: 'flex-end' }} className="stop">
                             <Space className="stop">
                                 <Button size="small" className="stop" onClick={() => { setIsNewGrouping(false); setGroupData({ groupName: '' }) }}>取消</Button>
@@ -117,21 +109,17 @@ const GroupLeft: React.FC<Props> = (props) => {
                 <div className="groupLeft_content_item">
                     <div className={`con ${groupId === 0 ? 'select' : ''}`} onClick={() => { setGroupId(0); onChange?.(undefined); setSelectAccData([]) }}>
                         <div className="left">
-                            <div className="title">默认分组</div>
+                            <div className="title">全部</div>
                         </div>
                     </div>
                 </div>
-                {getGroupList?.data?.map((item: { groupName: string, groupId: number }, index: number) => <div className="groupLeft_content_item" key={item.groupId || index}>
+                {getGroupList && getGroupList?.data?.map((item: { groupName: string, groupId: number }, index: number) => <div className="groupLeft_content_item" key={item.groupId || index}>
                     {groupData?.groupId && groupData?.groupId === item?.groupId ? <div className="edit stop">
                         <Space direction="vertical" className="stop">
                             <Space className="stop">
                                 <div style={{ width: 40 }} className="stop">组名</div>
                                 <Input placeholder="输入分组名称(最多10个字)" className="stop" maxLength={10} ref={inputRef} onChange={(e) => { setGroupData({ ...groupData, groupName: e.target.value }) }} value={groupData?.groupName} />
                             </Space>
-                            {/* <Space className="stop">
-                                <div style={{ width: 70 }} className="stop">分组备注:</div>
-                                <Input placeholder="请输入分组备注(最多10个字)" className="stop" maxLength={10} onChange={(e) => { setGroupData({ ...groupData, remark: e.target.value }) }} value={groupData?.remark} />
-                            </Space> */}
                             <div style={{ display: 'flex', justifyContent: 'flex-end' }} className="stop">
                                 <Space className="stop">
                                     <Button size="small" className="stop" onClick={() => { setIsNewGrouping(false); setGroupData({ groupName: '' }) }}>取消</Button>
@@ -142,7 +130,6 @@ const GroupLeft: React.FC<Props> = (props) => {
                     </div> : <div className={`con ${groupId === item.groupId ? 'select' : ''}`} onClick={() => { setGroupId(item.groupId); onChange?.(item.groupId); setSelectAccData([]) }} key={item.groupId || index}>
                         <div className="left">
                             <div className="title">{item.groupName}</div>
-                            {/* {item?.remark && <div className="subTitle">{item?.remark}</div>} */}
                         </div>
                         <div className="right">
                             <Space>

+ 23 - 0
src/pages/launchSystemNew/account/index.less

@@ -136,4 +136,27 @@
     }
 
   }
+}
+
+
+.dig {
+
+  &_ul {
+    padding: 0;
+    margin-bottom: 0;
+
+    &__li {
+      padding: 4px 16px;
+      box-sizing: border-box;
+      cursor: pointer;
+
+      &:hover {
+        color: #1890ff;
+      }
+    }
+  }
+
+  .ant-popover-inner-content {
+    padding: 0 0 8px 0;
+  }
 }

+ 133 - 18
src/pages/launchSystemNew/account/index.tsx

@@ -1,6 +1,6 @@
 
 import HocError from '@/Hoc/HocError'
-import { Col, Modal, Row, Input, message, Space, Tabs } from 'antd'
+import { Col, Modal, Row, Input, message, Space, Tabs, Button } from 'antd'
 import React, { useCallback, useEffect, useState } from 'react'
 import { columnsMp } from './tableConfig'
 import { useAjax } from '@/Hook/useAjax'
@@ -8,13 +8,21 @@ import { getAdAccountListApi, GetAdAccountParams, putAdAccountApi } from '@/serv
 import style from './index.less'
 import TableData from '../components/TableData'
 import GroupLeft from './groupLeft'
-import { MenuFoldOutlined, MenuUnfoldOutlined } from '@ant-design/icons'
+import { MenuFoldOutlined, MenuUnfoldOutlined, SwapOutlined } from '@ant-design/icons'
 import TeamMembers from '../components/teamMembers'
+import { getAdAccountAllOfMember } from '@/services/launchAdq/adq'
+import AddAccountToGroup from './addAccountToGroup'
+import { delAccountToGroupApi } from '@/services/launchAdq/subgroup'
+import { useModel } from 'umi'
+import ChangeRecord from './changeRecord'
+import CheckAccount from './checkAccount'
+import AppointPut from './appointPut'
 
 /** 投放管理 */
 const AdAuthorize: React.FC = () => {
 
     /*************************/
+    const { groupListInit } = useModel('useLaunchAdq.useAdAuthorize')
     const [queryForm, setQueryForm] = useState<GetAdAccountParams>({ pageNum: 1, pageSize: 20 })
     const [remarkData, set_remarkData] = useState<{ visible: boolean, remark: string, data: any }>({
         visible: false,
@@ -23,17 +31,50 @@ const AdAuthorize: React.FC = () => {
     })
     const [activeKey, setActiveKey] = useState<string>('1')
     const [showLeft, setShowLeft] = useState<boolean>(false)
+    const [crShow, setCrShow] = useState<boolean>(false) // 变更记录控制
+    const [crData, setCrData] = useState<{ name: number, id: number } | null>(null)
+    const [checkAccShow, setCheckAccShow] = useState<boolean>(false)
+    const [data, setData] = useState<{
+        putResourceId?: number | undefined,
+        beginTime?: string | undefined,
+        gdtAccountId?: number,
+        accountIds?: string,
+        accountId?: string,
+        gdtAccountIds?: string,
+        advertiserId?: string,
+        accountName?: string,
+        account?: string,
+        accountPassword?: string,
+        quickAppAccountIds?: string
+        resourceNames?: string
+    } | undefined>(undefined)
+    const [selectAccData, setSelectAccData] = useState<any[]>([])
+    const [puShow, setPuShow] = useState<boolean>(false)
+    const [puData, setPuData] = useState<any>()
+
     const putRemark = useAjax((adAccountId: any, remark: any) => putAdAccountApi(adAccountId, remark))
+    const delAccountToGroup = useAjax((params) => delAccountToGroupApi(params))
     const getAdAccountList = useAjax((params) => getAdAccountListApi(params), { formatResult: true })
+    const allOfMember = useAjax(() => getAdAccountAllOfMember(), { formatResult: true })
     /*************************/
 
+    useEffect(() => {
+        groupListInit()
+    }, [])
+
     useEffect(() => {
         getList()
     }, [queryForm])
 
-    /** 获取账号列表 */ 
+    /** 获取账号列表 */
     const getList = () => {
-        getAdAccountList.run(queryForm)
+        let params = JSON.parse(JSON.stringify(queryForm))
+        if (params.accountIds) {
+            params.accountIds = params.accountIds.split(/[\,\,]/)
+        } else {
+            delete params?.accountIds
+        }
+        getAdAccountList.run(params)
     }
 
     const remark = () => {
@@ -51,18 +92,48 @@ const AdAuthorize: React.FC = () => {
         set_remarkData({ ...remarkData, visible: true, data, remark: data.remark })
     }, [remarkData])
 
-    return <div style={{ height: '100%' }}>
+    /** 移除分组里账号 */
+    const del = (groupId: number, accountId: number) => {
+        delAccountToGroup.run({ currGroupId: groupId, accountIds: [accountId] }).then(res => {
+            message.success('移出成功')
+            getAdAccountList.refresh()
+        })
+    }
+
+    /** 切号 */
+    const checkAccount = (value: any[]) => {
+        let ids = value?.map((item: any) => item.id)
+        setData({ resourceNames: value?.map((item: any) => item.putResourceName).toString(), accountIds: value?.map((item: any) => item.accountId).toString(), gdtAccountIds: ids.toString(), putResourceId: undefined, beginTime: undefined })
+        setCheckAccShow(true);
+    }
+
+    /** 变更记录 */
+    const changeRecord = (name: number, id: number) => {
+        setCrData({ name, id })
+        setCrShow(true)
+    }
+
+    /** 指派投手 */
+    const putUserHandle = (data: any) => {
+        setPuData(data)
+        setPuShow(true)
+    }
 
+    return <div style={{ height: '100%' }}>
         <Tabs
             tabBarStyle={{ marginBottom: 1 }}
             activeKey={activeKey}
             type="card"
             onChange={(activeKey) => {
+                let newQueryForm = JSON.parse(JSON.stringify(queryForm))
+                delete newQueryForm?.groupId
+                delete newQueryForm?.putUserId
                 if (activeKey !== 'contract') {
                     setActiveKey(activeKey)
                 } else {
                     setShowLeft(!showLeft)
                 }
+                setQueryForm(newQueryForm)
             }}
         >
             <Tabs.TabPane tab='我的' key='1' />
@@ -71,36 +142,80 @@ const AdAuthorize: React.FC = () => {
         </Tabs>
 
         <div className={style.manage}>
-            {!showLeft && activeKey === '1' && <GroupLeft onChange={(groupId) => setQueryForm({ ...queryForm, groupId })} value={queryForm?.groupId}/>}
-            {!showLeft && activeKey === '2' && <TeamMembers onChange={(putUserId) => setQueryForm({ ...queryForm, putUserId })} value={queryForm?.putUserId}/>}
-            
+            {!showLeft && activeKey === '1' && <GroupLeft onChange={(groupId) => setQueryForm({ ...queryForm, groupId, pageNum: 1 })} value={queryForm?.groupId} />}
+            {!showLeft && activeKey === '2' && <TeamMembers allOfMember={allOfMember} onChange={(putUserId) => setQueryForm({ ...queryForm, putUserId, pageNum: 1 })} value={queryForm?.putUserId} />}
+
             <div className={style.manage__left} style={showLeft ? { width: '100%' } : { width: 'calc(100% - 200px)' }}>
                 <TableData
                     ajax={getAdAccountList}
                     dataSource={getAdAccountList?.data?.data?.records}
                     loading={getAdAccountList?.loading}
-                    columns={() => columnsMp(edit)}
+                    columns={() => columnsMp(edit, del, checkAccount, changeRecord, putUserHandle, queryForm?.groupId, getAdAccountList)}
                     total={getAdAccountList?.data?.data?.total}
                     page={getAdAccountList?.data?.data?.current}
                     pageSize={getAdAccountList?.data?.data?.size}
                     size="small"
                     scroll={{ y: 600 }}
                     leftChild={<Space>
-                        {/* <Input placeholder="广告主ID" style={{ width: 150 }} allowClear onChange={(e) => {
-                            let value = e.target.value
-                            if (value) {
-                                let newArr = tableData?.filter(item => String(item.accountId).includes(value))
-                                setTableData(newArr)
+                        <Input.TextArea
+                            placeholder="广告账号, 多个以,隔开(id1,id2)"
+                            allowClear
+                            style={{ minWidth: 200 }}
+                            rows={1}
+                            value={queryForm?.accountIds}
+                            onChange={(e) => {
+                                setQueryForm({ ...queryForm, accountIds: e.target.value })
+                            }}
+                        />
+                        <Button onClick={getList} type='primary' loading={getAdAccountList.loading}>搜索</Button>
+                        <AddAccountToGroup onChange={() => getAdAccountList.refresh()} />
+                        {selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { checkAccount(selectAccData) }}>批量切号</Button>}
+                    </Space>}
+                    rowSelection={{
+                        selectedRowKeys: selectAccData?.map((item: any) => item.id?.toString()),
+                        onSelect: (record: { id: number, mpName: string }, selected: boolean) => {
+                            if (selected) {
+                                selectAccData.push({ ...record })
+                                setSelectAccData([...selectAccData])
                             } else {
-                                setTableData(getAdAccount?.data?.data)
+                                let newSelectAccData = selectAccData.filter((item: { id: number }) => item.id !== record.id)
+                                setSelectAccData([...newSelectAccData])
                             }
-                        }} /> */}
-                        {/* <Button onClick={getList} type='primary'>搜索</Button> */}
-                    </Space>}
+                        },
+                        onSelectAll: (selected: boolean, selectedRows: { id: number }[], changeRows: { id: number }[]) => {
+                            if (selected) {
+                                let newSelectAccData = [...selectAccData]
+                                changeRows.forEach((item: { id: number }) => {
+                                    let index = newSelectAccData.findIndex((ite: { id: number }) => ite.id === item.id)
+                                    if (index === -1) {
+                                        newSelectAccData.push({ ...item })
+                                    }
+                                })
+                                setSelectAccData([...newSelectAccData])
+                            } else {
+                                let newSelectAccData = selectAccData.filter((item: { id: number }) => {
+                                    let index = changeRows.findIndex((ite: { id: number }) => ite.id === item.id)
+                                    if (index !== -1) {
+                                        return false
+                                    } else {
+                                        return true
+                                    }
+                                })
+                                setSelectAccData([...newSelectAccData])
+                            }
+                        }
+                    }}
                 />
             </div>
         </div>
 
+        {/* 变更记录 */}
+        {crShow && <ChangeRecord visible={crShow} data={crData} onClose={() => { setCrShow(false); setCrData(null) }} />}
+        {/* 切号 */}
+        {checkAccShow && <CheckAccount value={data} visible={checkAccShow} onChange={() => { getList(); setCheckAccShow(false); setSelectAccData([]) }} onClose={() => { setCheckAccShow(false) }} />}
+        {/* 指派 */}
+        {puShow && <AppointPut value={puData} visible={puShow} onClose={() => { setPuShow(false) }} allOfMember={allOfMember} onChange={() => { setPuShow(false); getAdAccountList.refresh() }} />}
+
         {remarkData.visible && <Modal
             visible={remarkData.visible}
             title='编辑账户'

+ 70 - 17
src/pages/launchSystemNew/account/tableConfig.tsx

@@ -1,8 +1,10 @@
 import { FundStatusEnum } from "@/services/launchAdq/enum"
-import { Badge, Space, Tooltip } from "antd"
+import { EditOutlined, FileSearchOutlined, SwapOutlined, UploadOutlined, UserSwitchOutlined } from "@ant-design/icons"
+import { Badge, Button, Popconfirm, Space, Tooltip } from "antd"
 import React from "react"
+import DivideIntoGroups from "./divideIntoGroups"
 import './index.less'
-export function columnsMp(edit:(params: any)=>void): any {
+export function columnsMp(edit: (params: any) => void, del: (groupId: number, accountId: number) => void, checkAccount: (value: any[]) => void, changeRecord: (accountId: number, id: number) => void, putUserHandle: (data: any) => void, groupId?: number, getAdAccountList?: any): any {
     return [
         {
             title: 'ID',
@@ -10,7 +12,7 @@ export function columnsMp(edit:(params: any)=>void): any {
             key: 'id',
             align: 'center',
             width: 55,
-            fixed:'left'
+            fixed: 'left'
         },
         {
             title: '广告主ID',
@@ -18,7 +20,7 @@ export function columnsMp(edit:(params: any)=>void): any {
             key: 'accountId',
             align: 'center',
             width: 75,
-            fixed:'left'
+            fixed: 'left'
         },
         {
             title: '类型',
@@ -30,12 +32,42 @@ export function columnsMp(edit:(params: any)=>void): any {
                 return <span>{a == 0 ? '微信' : 'QQ'}</span>
             }
         },
+        {
+            title: '拥有者',
+            dataIndex: 'authorizationUserName',
+            key: 'authorizationUserName',
+            width: 70,
+            align: 'center',
+            ellipsis: true,
+            render: (a: any, b: any) => {
+                return <span>{a || '-1'}</span>
+            }
+        },
+        {
+            title: '投手',
+            dataIndex: 'putUserInfo',
+            key: 'putUserInfo',
+            width: 70,
+            align: 'center',
+            ellipsis: true,
+            render: (a: any, b: any) => {
+                return <span>{a?.nickname || '-1'}</span>
+            }
+        },
+        {
+            title: '投放信息',
+            dataIndex: 'putResourceName',
+            key: 'putResourceName',
+            width: 110,
+            align: 'center',
+            ellipsis: true,
+        },
         {
             title: '备注',
             dataIndex: 'remark',
             key: 'remark',
             width: 200,
-            ellipsis:true,
+            ellipsis: true,
         },
         // {
         //     title: '公众号信息',
@@ -80,7 +112,7 @@ export function columnsMp(edit:(params: any)=>void): any {
             align: 'center',
             render: (a: any) => {
                 return <Tooltip title={a}>
-                    <div className="name-wrapper">{ a }</div>
+                    <div className="name-wrapper">{a}</div>
                 </Tooltip>
             }
         },
@@ -89,9 +121,9 @@ export function columnsMp(edit:(params: any)=>void): any {
             dataIndex: 'enabled',
             key: 'enabled',
             align: 'center',
-            width:60,
+            width: 60,
             render: (a: any, b: any) => {
-                return  <Badge status={a ? "processing" :"error" } text={a? '是' : '否'} />
+                return <Badge status={a ? "processing" : "error"} text={a ? '是' : '否'} />
             }
         },
         {
@@ -99,23 +131,23 @@ export function columnsMp(edit:(params: any)=>void): any {
             dataIndex: 'createTime',
             key: 'createTime',
             align: 'center',
-            width: 120
+            width: 140
         },
         {
             title: '日限额(分)',
             dataIndex: 'dailyBudget',
             key: 'dailyBudget',
             align: 'center',
-            width: 100
+            width: 80
         },
         {
             title: '资金状态',
             dataIndex: 'fundStatus',
             key: 'fundStatus',
             align: 'center',
-            width:100,
-            render:(a: string | number)=>{
-             return FundStatusEnum[a]
+            width: 80,
+            render: (a: string | number) => {
+                return FundStatusEnum[a]
             }
         },
         {
@@ -123,11 +155,32 @@ export function columnsMp(edit:(params: any)=>void): any {
             dataIndex: 'cz',
             key: 'cz',
             align: 'center',
-            width: 80,
-            fixed:'right',
-            render:(a: any,b: any)=>{
+            width: 180,
+            fixed: 'right',
+            render: (a: any, b: any) => {
                 return <Space>
-                    <a onClick={()=>{edit(b)}}>备注</a>
+                    <Tooltip title="备注">
+                        <Button size="small" style={{ color: '#52c41a' }} onClick={() => edit(b)} icon={<EditOutlined />}></Button>
+                    </Tooltip>
+                    <Tooltip title="切号">
+                        <Button size="small" style={{ color: '#ea5506' }} onClick={() => checkAccount([b])} icon={<SwapOutlined />}></Button>
+                    </Tooltip>
+                    <Tooltip title="变更记录">
+                        <Button size="small" style={{ color: '#4d5aaf' }} onClick={() => changeRecord(b?.accountId, b?.id)} icon={<FileSearchOutlined />}></Button>
+                    </Tooltip>
+                    <Tooltip title="指派">
+                        <Button size="small" style={{ color: '#0eb83a' }} onClick={() => putUserHandle(b)} icon={<UserSwitchOutlined />}></Button>
+                    </Tooltip>
+                    {groupId ? <Popconfirm
+                        title={`是否把${b?.accountId}移出该分组?`}
+                        onConfirm={() => { del(groupId, b?.accountId) }}
+                        okText="是"
+                        cancelText="否"
+                    >
+                        <Tooltip title="移出分组">
+                            <Button size="small" style={{ color: 'red' }}><UploadOutlined /></Button>
+                        </Tooltip>
+                    </Popconfirm> : <DivideIntoGroups groupIds={b?.groupIds} getAdAccountList={getAdAccountList} accountId={b?.accountId}/>}
                 </Space>
             }
         },

+ 71 - 0
src/pages/launchSystemNew/account/tablesConfig.tsx

@@ -0,0 +1,71 @@
+import { EditOutlined } from "@ant-design/icons"
+import { Button, Col, Row } from "antd"
+import React from "react"
+
+// 变更记录
+const columnsCrGdt = (editHandle: (data: any) => void) => {
+    return [
+        {
+            title: '开始时间',
+            dataIndex: 'beginTime',
+            key: 'beginTime',
+            align: 'center',
+            width: 140,
+            fixed: 'left',
+        },
+        {
+            title: '结束时间',
+            dataIndex: 'endTime',
+            key: 'endTime',
+            align: 'center',
+            fixed: 'left',
+            width: 140
+        },
+        {
+            title: '操作人',
+            dataIndex: 'createName',
+            key: 'createName',
+            align: 'center',
+            width: 80,
+            ellipsis: true,
+            render: (a: any) => {
+                return <span>{a || '<空>'}</span>
+            }
+        },
+        {
+            title: '资源名称',
+            dataIndex: 'putResourceName',
+            key: 'putResourceName',
+            width: 140,
+            ellipsis: true,
+            align: 'center',
+            render: (a: any, b: any) => {
+                return <span>{a || '<空>'}</span>
+            }
+        },
+        {
+            title: '资源标识',
+            dataIndex: 'putResourceKey',
+            key: 'putResourceKey',
+            ellipsis: true,
+            width: 200,
+            render: (a: any, b: any) => {
+                return <span>{a || '<空>'}</span>
+            }
+        },
+        {
+            title: '操作',
+            dataIndex: 'cz',
+            key: 'cz',
+            render: (a: string, b: any) => (
+                <Row gutter={[10, 0]}>
+                    <Col><Button type="link" size="small" style={{ fontSize: 12 }} icon={<EditOutlined />} onClick={() => { editHandle(b) }}>编辑</Button></Col>
+                </Row>
+            )
+        }
+    ]
+}
+
+export {
+    columnsCrGdt
+}

+ 2 - 11
src/pages/launchSystemNew/components/teamMembers/index.tsx

@@ -1,5 +1,3 @@
-import { useAjax } from "@/Hook/useAjax"
-import { getAdAccountAllOfMember } from "@/services/launchAdq/adq"
 import { IdcardFilled } from "@ant-design/icons"
 import { Menu, Select, Spin } from "antd"
 import React, { useEffect, useState } from "react"
@@ -9,6 +7,7 @@ import './index.less'
 interface Props {
     onChange?: (id?: number) => void
     value?: number
+    allOfMember: any
 }
 /**
  * 选择组员左菜单
@@ -16,15 +15,13 @@ interface Props {
 const TeamMembers: React.FC<Props> = (props) => {
 
     /*************************/
-    const { onChange, value } = props
+    const { onChange, value, allOfMember } = props
     const [userAll, setUserAll] = useState([])
 
     const userInfo = useModel('@@initialState', model => model.initialState?.currentUser)
     const [userId, setUserId] = useState<any>(userInfo?.userId?.toString())
-    const allOfMember = useAjax(() => getAdAccountAllOfMember(), { formatResult: true })
     /*************************/
 
-
     useEffect(() => {
         onChange?.(userId)
     }, [userId])
@@ -60,12 +57,6 @@ const TeamMembers: React.FC<Props> = (props) => {
 
     }, [])
 
-    useEffect(() => {
-
-    }, [])
-    console.log('allOfMember--->', allOfMember);
-
-
     /** 初始跳转到自己的名称 */
     useEffect(() => {
         if (userAll?.length > 0 && userId) {

+ 12 - 1
src/services/launchAdq/adAuthorize.ts

@@ -9,7 +9,7 @@ export interface GetAdAccountParams {
     pageNum: number,
     pageSize: number,
     groupId?: number,
-    accountIds?: number[]
+    accountIds?: string[] | string
     putUserId?: number
 }
 export async function getAdAccountListApi(data: GetAdAccountParams) {
@@ -28,6 +28,17 @@ export async function getAdAccountApi() {
         method: 'GET',
     });
 }
+
+/**
+ * 返回自己所有账号
+ * @returns 
+ */
+export async function getAllUserAccountApi() {
+    return request(api + '/adq/adAccount/allOfOwnerUser', {
+        method: 'GET',
+    });
+}
+
 /**
  * 获取账号列表
  * @returns 

+ 0 - 8
src/services/launchAdq/adq.ts

@@ -7,14 +7,6 @@ import { api } from '../api';
 export async function getAdAccountAllOfMember() {
   return request(api + '/adq/adAccount/allOfMember');
 }
-// export async function get_allOfMember() {
-//   return fetch(api + '/adq/adAccount/allOfMember',{
-//     headers:{
-//       "content-Type":"application/json;charset=UTF-8",
-//       "Authorization": `Bearer ${sessionStorage.getItem("Admin-Token")}`
-//     }
-//   }).then(res=>res.json())
-// }
 
 /**
  * 获取ADQ账号列表

+ 13 - 0
src/services/launchAdq/subgroup.ts

@@ -62,6 +62,7 @@ export async function getAccountListApi(groupId: number) {
 export interface AddAccountToGroupProps {
     accountIds: number[],
     currGroupId?: number,
+    newGroupId?: number,
 }
 export async function addAccountToGroupApi(data: AddAccountToGroupProps) {
     return request(api + `/adq/group/account/add`, {
@@ -70,6 +71,18 @@ export async function addAccountToGroupApi(data: AddAccountToGroupProps) {
     })
 }
 
+/**
+ * 新增账号到分组
+ * @param data 
+ * @returns 
+ */
+export async function addNewAccountToGroupApi(data: AddAccountToGroupProps) {
+    return request(api + `/adq/group/account/addNew`, {
+        method: 'POST',
+        data
+    })
+}
+
 /**
  * 移动账号到新分组
  * @param data 

+ 14 - 6
src/services/operating/accountyyb.ts

@@ -10,17 +10,17 @@ export interface gdtAccountProps {
   putResourceId?: number
 }
 export async function getGdtAccountApi(params: gdtAccountProps) {
-  let { userId, pageNum, pageSize,  accountIds, putResourceId } = params
+  let { userId, pageNum, pageSize, accountIds, putResourceId } = params
   return request(api + `/erp/gdtAccount/list/${userId}`, {
     method: 'POST',
-    data: { pageNum, pageSize,  accountIds, putResourceId }
+    data: { pageNum, pageSize, accountIds, putResourceId }
   });
 }
 
 /** 变更记录 */
 export async function getGdtChangeRecordApi(params: { gdtAccountId: number, pageNum: number, pageSize: number }) {
   let { gdtAccountId, ...param } = params
-  return request(api + `/erp/gdtAccount/gdtChangeRecord/${gdtAccountId}`, {
+  return request(api + `/adq/adAccount/sysChangeRecord/${gdtAccountId}`, {
     method: 'POST',
     data: param
   });
@@ -29,7 +29,7 @@ export async function getGdtChangeRecordApi(params: { gdtAccountId: number, page
 /** 变更记录修改 */
 export async function editGdtChangeRecordApi(params: { recordId: number, putResourceId: number, beginTime: string, endTime: string }) {
   let { recordId, ...param } = params
-  return request(api + `/erp/gdtAccount/gdtChangeRecordModify/${recordId}`, {
+  return request(api + `/adq/adAccount/sysChangeRecordModify/${recordId}`, {
     method: 'PUT',
     data: param
   });
@@ -71,7 +71,7 @@ export interface checkGdtAccountProps {
 }
 export async function checkGdtAccountGdtApi(params: { gdtAccountIds: string, putResourceId: any, beginTime: any }) {
   let { gdtAccountIds, ...param } = params
-  return request(api + `/erp/gdtAccount/checkBatch/${gdtAccountIds}`, {
+  return request(api + `/adq/adAccount/checkBatch/${gdtAccountIds}`, {
     method: 'PUT',
     data: param,
   });
@@ -100,7 +100,7 @@ export async function getQuickAppAccountApi(params: QuickAppAccout) {
     data: param
   });
 }
-/**变更记录 */ 
+/**变更记录 */
 export async function getAccountChangeRecordApi(params: { quickAppAccountId: number, pageNum: number, pageSize: number }) {
   let { quickAppAccountId, ...param } = params
   return request(api + `/erp/quickAppAccount/accountChangeRecord/${quickAppAccountId}`, {
@@ -205,4 +205,12 @@ export async function getKyyListApi(params: KyyListProps) {
  */
 export async function getResourceOfUserApi({ userId, resourceType }: { userId: number, resourceType: 10 | 0 }) {
   return request(`${api}/erp/resourceOfUser/${userId}/${resourceType}`)
+}
+
+
+// 切换投手
+export async function cutPutApi({ accountIds, putUserId }: { accountIds: number, putUserId: number }) {
+  return request(`${api}/adq/adAccount/configPutUser/${accountIds}/${putUserId}`, {
+    method: 'PUT'
+  })
 }

+ 13 - 0
src/utils/utils.ts

@@ -173,4 +173,17 @@ export const randomString = (flag: boolean, min: number, max: number) => {
     str += arr[pos];
   }
   return str;
+}
+
+
+/**
+ * 找2个数组不同元素
+ * @param arr1 
+ * @param arr2 
+ * @returns 
+ */
+export const getArrDifference = (arr1: any[], arr2: any[]) => {
+  return arr1.concat(arr2).filter((v, i, arr) => {
+    return arr.indexOf(v) === arr.lastIndexOf(v);
+  });
 }