Bladeren bron

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

shenwu 2 jaren geleden
bovenliggende
commit
d44bbdca30
31 gewijzigde bestanden met toevoegingen van 1487 en 426 verwijderingen
  1. 75 0
      src/components/Tables/EditableCell.tsx
  2. 20 0
      src/components/Tables/EditableRow.tsx
  3. 47 88
      src/components/Tables/index.less
  4. 46 33
      src/components/Tables/index.tsx
  5. 18 1
      src/models/useLaunchAdq/useAdAuthorize.ts
  6. 2 2
      src/models/useOperating/useWxGroupList.ts
  7. 99 0
      src/pages/launchSystemNew/account/addAccountToGroup.tsx
  8. 95 0
      src/pages/launchSystemNew/account/appointPut.tsx
  9. 127 0
      src/pages/launchSystemNew/account/changeRecord.tsx
  10. 69 0
      src/pages/launchSystemNew/account/checkAccount.tsx
  11. 72 0
      src/pages/launchSystemNew/account/divideIntoGroups.tsx
  12. 22 27
      src/pages/launchSystemNew/account/groupLeft.tsx
  13. 24 2
      src/pages/launchSystemNew/account/index.less
  14. 170 31
      src/pages/launchSystemNew/account/index.tsx
  15. 71 20
      src/pages/launchSystemNew/account/tableConfig.tsx
  16. 71 0
      src/pages/launchSystemNew/account/tablesConfig.tsx
  17. 131 121
      src/pages/launchSystemNew/adq/ad/index.tsx
  18. 1 3
      src/pages/launchSystemNew/adq/ad/tableConfig.tsx
  19. 12 2
      src/pages/launchSystemNew/adq/ad/updateAd.tsx
  20. 21 0
      src/pages/launchSystemNew/adq/ad/updateAdName.tsx
  21. 56 21
      src/pages/launchSystemNew/adq/adAccount/index.tsx
  22. 14 28
      src/pages/launchSystemNew/adq/adAccount/tableConfig.tsx
  23. 24 24
      src/pages/launchSystemNew/adq/index.tsx
  24. 6 4
      src/pages/launchSystemNew/components/TableData/index.tsx
  25. 17 0
      src/pages/launchSystemNew/components/teamMembers/index.less
  26. 113 0
      src/pages/launchSystemNew/components/teamMembers/index.tsx
  27. 13 1
      src/services/launchAdq/adAuthorize.ts
  28. 11 12
      src/services/launchAdq/adq.ts
  29. 13 0
      src/services/launchAdq/subgroup.ts
  30. 14 6
      src/services/operating/accountyyb.ts
  31. 13 0
      src/utils/utils.ts

+ 75 - 0
src/components/Tables/EditableCell.tsx

@@ -0,0 +1,75 @@
+import { Form, FormInstance, Input, InputRef } from "antd";
+import React, { useContext, useEffect, useRef, useState } from "react";
+import './index.less'
+
+export const EditableContext = React.createContext<FormInstance<any> | null>(null);
+
+interface Item {
+    key: string;
+    name: string;
+    age: string;
+    address: string;
+}
+interface EditableCellProps {
+    title: React.ReactNode;
+    editable: boolean;
+    children: React.ReactNode;
+    dataIndex: keyof Item;
+    record: Item;
+    handleSave: (record: Item) => void;
+}
+const EditableCell: React.FC<EditableCellProps> = ({
+    title,
+    editable,
+    children,
+    dataIndex,
+    record,
+    handleSave,
+    ...restProps
+}) => {
+    const [editing, setEditing] = useState(false);
+    const inputRef = useRef<InputRef>(null);
+    const form = useContext(EditableContext)!;
+
+    useEffect(() => {
+        if (editing) {
+            inputRef.current!.focus();
+        }
+    }, [editing]);
+
+    const toggleEdit = () => {
+        setEditing(!editing);
+        form.setFieldsValue({ [dataIndex]: record[dataIndex] });
+    };
+
+    const save = async () => {
+        try {
+            const values = await form.validateFields();
+            if (values?.adgroupName !== (record as any)?.adgroupName) {
+                handleSave({ ...record, ...values });
+            }
+            toggleEdit();
+        } catch (errInfo) {
+            console.log('Save failed:', errInfo);
+        }
+    };
+
+    let childNode = children;
+
+    if (editable) {
+        childNode = editing ? (<Form.Item
+            style={{ margin: 0 }}
+            name={dataIndex}
+            rules={[{ required: true, message: `${title} is required.` }]}
+        >
+            <Input ref={inputRef} onPressEnter={save} onBlur={save} />
+        </Form.Item>) : (<div className="editable-cell-value-wrap ellipsisText" onClick={toggleEdit}>
+            {children}
+        </div>);
+    }
+
+    return <td {...restProps}>{childNode}</td>;
+};
+
+
+export default React.memo(EditableCell)

+ 20 - 0
src/components/Tables/EditableRow.tsx

@@ -0,0 +1,20 @@
+import { Form } from "antd";
+import React from "react";
+import './index.less'
+import { EditableContext } from "./EditableCell";
+
+interface EditableRowProps {
+    index: number;
+}
+const EditableRow: React.FC<EditableRowProps> = ({ index, ...props }) => {
+    const [form] = Form.useForm();
+    return (
+        <Form form={form} component={false}>
+            <EditableContext.Provider value={form}>
+                <tr {...props} />
+            </EditableContext.Provider>
+        </Form>
+    );
+};
+
+export default React.memo(EditableRow)

+ 47 - 88
src/components/Tables/index.less

@@ -1,95 +1,54 @@
-.unfollow{
+.unfollow {
     background-color: #fafafa;
 }
 
-.ant-table-row.expanded>.ant-table-cell{
+.ant-table-row.expanded>.ant-table-cell {
     padding: 5px 16px !important;
 }
-.ant-table-row.error{
+
+.ant-table-row.error {
     background-color: #ffe9e9;
 }
-// .react-resizable {
-//     position: relative;
-//   }
-//   .react-resizable-handle {
-//     position: absolute;
-//     width: 20px;
-//     height: 20px;
-//     background-repeat: no-repeat;
-//     background-origin: content-box;
-//     box-sizing: border-box;
-//     background-image: url('data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA2IDYiIHN0eWxlPSJiYWNrZ3JvdW5kLWNvbG9yOiNmZmZmZmYwMCIgeD0iMHB4IiB5PSIwcHgiIHdpZHRoPSI2cHgiIGhlaWdodD0iNnB4Ij48ZyBvcGFjaXR5PSIwLjMwMiI+PHBhdGggZD0iTSA2IDYgTCAwIDYgTCAwIDQuMiBMIDQgNC4yIEwgNC4yIDQuMiBMIDQuMiAwIEwgNiAwIEwgNiA2IEwgNiA2IFoiIGZpbGw9IiMwMDAwMDAiLz48L2c+PC9zdmc+');
-//     background-position: bottom right;
-//     padding: 0 3px 3px 0;
-//   }
-//   .react-resizable-handle-sw {
-//     bottom: 0;
-//     left: 0;
-//     cursor: sw-resize;
-//     transform: rotate(90deg);
-//   }
-//   .react-resizable-handle-se {
-//     bottom: 0;
-//     right: 0;
-//     cursor: se-resize;
-//   }
-//   .react-resizable-handle-nw {
-//     top: 0;
-//     left: 0;
-//     cursor: nw-resize;
-//     transform: rotate(180deg);
-//   }
-//   .react-resizable-handle-ne {
-//     top: 0;
-//     right: 0;
-//     cursor: ne-resize;
-//     transform: rotate(270deg);
-//   }
-//   .react-resizable-handle-w,
-//   .react-resizable-handle-e {
-//     top: 50%;
-//     margin-top: -10px;
-//     cursor: ew-resize;
-//   }
-//   .react-resizable-handle-w {
-//     left: 0;
-//     transform: rotate(135deg);
-//   }
-//   .react-resizable-handle-e {
-//     right: 0;
-//     transform: rotate(315deg);
-//   }
-//   .react-resizable-handle-n,
-//   .react-resizable-handle-s {
-//     left: 50%;
-//     margin-left: -10px;
-//     cursor: ns-resize;
-//   }
-//   .react-resizable-handle-n {
-//     top: 0;
-//     transform: rotate(225deg);
-//   }
-//   .react-resizable-handle-s {
-//     bottom: 0;
-//     transform: rotate(45deg);
-//   }
-  .ellipsisText{
-      overflow: hidden;
-      text-overflow: ellipsis;
-      white-space: nowrap;
-      display: block;
-  }
-  .components-table-resizable-column .react-resizable{
-      position: relative;
-      background-clip: padding-box;
-  }
-  .components-table-resizable-column .react-resizable-handle{
-      position:absolute;
-      width: 10px;
-      height: 100%;
-      bottom: 0;
-      right: -9px;
-      cursor:col-resize;
-      z-index: 1;
-      border-left: white 1px solid;
-  }
+
+.editable-cell {
+    position: relative;
+}
+
+.editable-cell-value-wrap {
+    padding: 5px;
+    cursor: pointer;
+    box-sizing: border-box;
+}
+
+.editable-cell-value-wrap:hover {
+    padding: 5px;
+    box-shadow: 0 0 0 1px #d9d9d9;
+    border-radius: 4px;
+}
+
+[data-theme='dark'] .editable-cell-value-wrap:hover {
+    box-shadow: 0 0 0 1px #d9d9d9;
+}
+
+.ellipsisText {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+    display: block;
+}
+
+.components-table-resizable-column .react-resizable {
+    position: relative;
+    background-clip: padding-box;
+}
+
+.components-table-resizable-column .react-resizable-handle {
+    position: absolute;
+    width: 10px;
+    height: 100%;
+    bottom: 0;
+    right: -9px;
+    cursor: col-resize;
+    z-index: 1;
+    border-left: white 1px solid;
+}

+ 46 - 33
src/components/Tables/index.tsx

@@ -1,18 +1,26 @@
-import React, { ReactNode ,useEffect, useRef, useState} from 'react'
+import React, { ReactNode, useEffect, useRef, useState } from 'react'
 import { Table, Tag, message } from 'antd';
 import { Excle } from '@/utils/Excle'
 import style from './index.less'
 import './index.less'
 import { Resizable } from 'react-resizable'
 import { SortOrder } from 'antd/lib/table/interface';
+import EditableRow from './EditableRow';
+import EditableCell from './EditableCell';
 
+export interface DataType {
+    key: React.Key;
+    name: string;
+    age: string;
+    address: string;
+}
 
 const ResizableHeader = (props: { [x: string]: any; onResize: any; width: any }) => {
     const { onResize, width, ...restProps } = props;
     if (!width) {
         return <th {...restProps} />
     }
-    return <Resizable width={width} height={0} onResize={onResize} draggableOpts={{enableUserSelectHack:false}}>
+    return <Resizable width={width} height={0} onResize={onResize} draggableOpts={{ enableUserSelectHack: false }}>
         <th {...restProps} />
     </Resizable>
 }
@@ -52,15 +60,16 @@ interface Props {
     showHeader?: 1,
     hideOnSinglePage?: boolean,
     className?: string,
-    handelResize?:(columns:any)=>void//当表头被拖动改变宽度时回调设置对应的本地保存
+    handelResize?: (columns: any) => void//当表头被拖动改变宽度时回调设置对应的本地保存
     sortDirections?: SortOrder[],
     isShowTotal?: boolean,  // 是否展示总计
-    myKey?:any,//自定义要用哪个值做key
+    myKey?: any,//自定义要用哪个值做key
+    handleSave?: (row: DataType) => void
 }
 
 function Tables(props: Props) {
     // //导出数据
-    let { columns, dataSource, excle, total,handelResize, rowSelection, onRow, isShowTotal = true, hideOnSinglePage, rowClassName, className, expandedRowRender, scroll, summary, showHeader, bordered, size = 'small', onChange, sortDirections, pagination,myKey, ...prop } = props
+    let { columns, dataSource, excle, total, handelResize, rowSelection, onRow, isShowTotal = true, hideOnSinglePage, handleSave, rowClassName, className, expandedRowRender, scroll, summary, showHeader, bordered, size = 'small', onChange, sortDirections, pagination, myKey, ...prop } = props
     let handleExcle = () => {
         if (dataSource.length < 1) {
             message.error('请先搜索再导出');
@@ -77,32 +86,47 @@ function Tables(props: Props) {
     }
     let ww = document.body.clientWidth < 415
     // 拖动宽逻辑
-    const [cols,setCols] = useState<any>(columns)
+    const [cols, setCols] = useState<any>(columns)
     const colsRef = useRef<any[]>([])
-    const components={
-        header:{
-            cell:ResizableHeader
+    const components = {
+        header: {
+            cell: ResizableHeader
+        },
+        body: {
+            row: EditableRow,
+            cell: EditableCell
         }
     }
-    useEffect(()=>{
+
+    useEffect(() => {
         setCols(columns)
-    },[columns])
-    const handleResize=(index:any)=>(e:any,{size}:any)=>{
-        const nextColumns=[...cols]
-        nextColumns[index]={
+    }, [columns])
+
+    const handleResize = (index: any) => (e: any, { size }: any) => {
+        const nextColumns = [...cols]
+        nextColumns[index] = {
             ...nextColumns[index],
-            width:size.width
+            width: size.width
         }
         setCols(nextColumns)
         handelResize && handelResize(nextColumns)
     }
-    colsRef.current = (cols||[]).map((col:any,index:any)=>({
+
+    colsRef.current = (cols || []).map((col: any, index: any) => ({
         ...col,
-        onHeaderCell:(column:any)=>({
-            width:column.width,
-            onResize:handleResize(index)
-        })
+        onHeaderCell: (column: any) => ({
+            width: column.width,
+            onResize: handleResize(index)
+        }),
+        onCell: (record: DataType) => ({
+            record,
+            editable: col.editable,
+            dataIndex: col.dataIndex,
+            title: col.title,
+            handleSave: (row: DataType) => { handleSave?.(row) },
+        }),
     }))
+
     return <div className='components-table-resizable-column'>
         {
             excle && <Tag color='#f50' style={{ margin: '10px 0', float: 'right' }} onClick={handleExcle}><a>导出数据</a></Tag>
@@ -120,7 +144,7 @@ function Tables(props: Props) {
             scroll={scroll ? { ...scroll, scrollToFirstRowOnChange: true } : undefined}
             size={size}
             rowKey={(a: any) => {
-                if(myKey){
+                if (myKey) {
                     return JSON.stringify(a[myKey])
                 }
                 return (JSON.stringify(a?.id) || JSON.stringify(a?.key))
@@ -131,16 +155,6 @@ function Tables(props: Props) {
                     onClick: onRow?.onClick && onRow?.onClick.bind('', record) || undefined,
                 }
             }}
-            // rowClassName={(record: any) => {
-            //     if (rowClassName && record[rowClassName as string] === 2) {
-            //         return style.unfollow
-            //     }
-            //     if (rowClassName && !record[rowClassName as string]) {
-            //         return style.unfollow
-            //     }
-            // }
-            // }
-            // rowClassName={rowClassName}
             summary={summary}
             className={className}
             expandable={expandedRowRender ? {
@@ -178,8 +192,7 @@ function Tables(props: Props) {
                         return style.unfollow
                     }
                 } : rowClassName
-            }
-            }
+            }}
         />
     </div>
 }

+ 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)

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

@@ -0,0 +1,127 @@
+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') }
+        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()
+            }
+        })
+    }
+
+    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)

+ 22 - 27
src/pages/launchSystemNew/account/groupLeft.tsx

@@ -3,30 +3,38 @@ 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
+    value?: number
 }
 const GroupLeft: React.FC<Props> = (props) => {
 
     /*************************/
+    const { onChange, value } = props
     const [isNewGrouping, setIsNewGrouping] = useState<boolean>(false);  // 是否新增分组
     const inputRef = useRef<any>(null);
     const [groupData, setGroupData] = useState<{ groupName: string, remark?: string, groupId?: number }>({ groupName: '' }) // 分组添加
     const [selectAccData, setSelectAccData] = useState<{ id: number, mpName: string }[]>([])  // 选中
-    const [queryForm, setQueryForm] = useState<{ groupId?: number, pageNum: number, pageSize: number }>({ pageNum: 1, pageSize: 20 })
-    const { groupId = 0 } = queryForm
+    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))
     /*************************/
 
+    useEffect(() => {
+        if (value) {
+            setGroupId(value || 0)
+        }
+    }, [value])
+
     /** 点击新增处理聚焦 */
     useEffect(() => {
         if (isNewGrouping && inputRef?.current) {
@@ -36,11 +44,6 @@ const GroupLeft: React.FC<Props> = (props) => {
         }
     }, [inputRef, isNewGrouping])
 
-    /** 获取分组 */
-    useEffect(() => {
-        getGroupList.run()
-    }, [])
-
     /** 新增修改分组 */
     const addEditHandle = () => {
         if (groupData?.groupName) {
@@ -65,12 +68,13 @@ const GroupLeft: React.FC<Props> = (props) => {
     }
 
     /** 删除分组 */
-    const delGroupHandle = (groupId: number) => {
-        delGroup.run({ groupId }).then(res => {
+    const delGroupHandle = (id: number) => {
+        delGroup.run({ groupId: id }).then(res => {
             message.success('删除成功')
             getGroupList.refresh()
-            if (queryForm.groupId === groupId) {
-                setQueryForm({ ...queryForm, groupId: 0 })
+            if (groupId === id) {
+                setGroupId(0)
+                onChange?.(undefined)
             }
         })
     }
@@ -92,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>
@@ -107,23 +107,19 @@ const GroupLeft: React.FC<Props> = (props) => {
             </div>}
             <Spin spinning={getGroupList.loading}>
                 <div className="groupLeft_content_item">
-                    <div className={`con ${groupId === 0 ? 'select' : ''}`} onClick={() => { setQueryForm({ ...queryForm, groupId: 0 }); setSelectAccData([]) }}>
+                    <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>
@@ -131,10 +127,9 @@ const GroupLeft: React.FC<Props> = (props) => {
                                 </Space>
                             </div>
                         </Space>
-                    </div> : <div className={`con ${groupId === item.groupId ? 'select' : ''}`} onClick={() => { setQueryForm({ ...queryForm, groupId: item.groupId, pageNum: 1 }); setSelectAccData([]) }} key={item.groupId || index}>
+                    </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>

+ 24 - 2
src/pages/launchSystemNew/account/index.less

@@ -10,7 +10,6 @@
   text-overflow: ellipsis;
   white-space: nowrap;
 }
-
 .boxCol {
   display: flex;
 
@@ -26,7 +25,7 @@
 }
 
 .manage {
-  height: 100%;
+  height: calc(100% - 42px);
   display: flex;
   justify-content: flex-start;
 
@@ -137,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;
+  }
 }

+ 170 - 31
src/pages/launchSystemNew/account/index.tsx

@@ -1,42 +1,83 @@
 
 import HocError from '@/Hoc/HocError'
-import { Col, Modal, Row, Input, message, Space } 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 { useModel } from 'umi'
 import { useAjax } from '@/Hook/useAjax'
-import { getAdAccountListApi, putAdAccountApi } from '@/services/launchAdq/adAuthorize'
+import { getAdAccountListApi, GetAdAccountParams, putAdAccountApi } from '@/services/launchAdq/adAuthorize'
 import style from './index.less'
 import TableData from '../components/TableData'
 import GroupLeft from './groupLeft'
+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 { getAdAccount } = useModel('useLaunchAdq.useAdAuthorize')
-    const [tableData, setTableData] = useState<any[]>([])
+    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,
         remark: '',
         data: null
     })
+    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(() => {
-        getList()
+        groupListInit()
     }, [])
+
+    useEffect(() => {
+        getList()
+    }, [queryForm])
+
+    /** 获取账号列表 */
     const getList = () => {
-        // 获取账号列表
-        getAdAccount.run().then(res => {
-            if (res) {
-                setTableData(() => res?.data || [])
-            }
-        })
+        let params = JSON.parse(JSON.stringify(queryForm))
+        if (params.accountIds) {
+            params.accountIds = params.accountIds.split(/[\,\,]/)
+        } else {
+            delete params?.accountIds
+        }
+        getAdAccountList.run(params)
     }
-    const remark = useCallback(() => {
+
+    const remark = () => {
         if (remarkData.remark && remarkData.data) {
             putRemark.run(remarkData.data.id, remarkData.remark).then(res => {
                 set_remarkData({ ...remarkData, visible: false, remark: '', data: null })
@@ -46,43 +87,141 @@ const AdAuthorize: React.FC = () => {
             message.error('请输入备注!')
         }
 
-    }, [getAdAccount, remarkData])
+    }
     const edit = useCallback((data) => {
         set_remarkData({ ...remarkData, visible: true, data, remark: data.remark })
     }, [remarkData])
 
+    /** 移除分组里账号 */
+    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%' }}>
-        {/* <div className={style.manage}> */}
-            {/* <GroupLeft /> */}
-            <div>
+        <Tabs
+            tabBarStyle={{ marginBottom: 1 }}
+            activeKey={activeKey}
+            type="card"
+            onChange={(activeKey) => {
+                if (activeKey !== 'contract') {
+                    let newQueryForm = JSON.parse(JSON.stringify(queryForm))
+                    delete newQueryForm?.groupId
+                    delete newQueryForm?.putUserId
+                    setQueryForm(newQueryForm)
+                    setActiveKey(activeKey)
+                } else {
+                    setShowLeft(!showLeft)
+                }
+            }}
+        >
+            <Tabs.TabPane tab='我的' key='1' />
+            <Tabs.TabPane tab='组员' key='2' />
+            <Tabs.TabPane tab={showLeft ? <MenuUnfoldOutlined /> : <MenuFoldOutlined />} key='contract' />
+        </Tabs>
+
+        <div className={style.manage}>
+            {!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={getAdAccount}
-                    dataSource={tableData}
-                    loading={getAdAccount?.loading}
-                    columns={() => columnsMp(edit)}
+                    ajax={getAdAccountList}
+                    dataSource={getAdAccountList?.data?.data?.records}
+                    loading={getAdAccountList?.loading}
+                    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> */}
+        </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='编辑账户'
             onCancel={() => { set_remarkData({ ...remarkData, visible: false, data: null }) }}
             onOk={remark}
+            confirmLoading={putRemark.loading}
         >
             <Row gutter={[20, 20]}>
                 <Col span={24} className={style.boxCol}><strong>广告主ID:</strong><span>{remarkData?.data.accountId}</span></Col>

+ 71 - 20
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,15 +12,15 @@ export function columnsMp(edit:(params: any)=>void): any {
             key: 'id',
             align: 'center',
             width: 55,
-            fixed:'left'
+            fixed: 'left'
         },
         {
             title: '广告主ID',
             dataIndex: 'accountId',
             key: 'accountId',
             align: 'center',
-            width: 75,
-            fixed:'left'
+            width: 80,
+            fixed: 'left'
         },
         {
             title: '类型',
@@ -30,13 +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: 'memo',
             key: 'memo',
             align: 'center',
             width: 100,
-            fixed: 'left',
             ellipsis: true,
         },
         {
@@ -45,7 +76,6 @@ export function columnsMp(edit:(params: any)=>void): any {
             key: 'remark',
             align: 'center',
             width: 100,
-            fixed: 'left',
             ellipsis: true,
         },
         // {
@@ -87,11 +117,11 @@ export function columnsMp(edit:(params: any)=>void): any {
             title: '行业ID',
             dataIndex: 'systemIndustryId',
             key: 'systemIndustryId',
-            width: 100,
+            width: 105,
             align: 'center',
             render: (a: any) => {
                 return <Tooltip title={a}>
-                    <div className="name-wrapper">{ a }</div>
+                    <div className="name-wrapper">{a}</div>
                 </Tooltip>
             }
         },
@@ -100,9 +130,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 ? '是' : '否'} />
             }
         },
         {
@@ -110,23 +140,23 @@ export function columnsMp(edit:(params: any)=>void): any {
             dataIndex: 'createTime',
             key: 'createTime',
             align: 'center',
-            width: 120
+            width: 150
         },
         {
             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]
             }
         },
         {
@@ -134,11 +164,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
+}

+ 131 - 121
src/pages/launchSystemNew/adq/ad/index.tsx

@@ -5,10 +5,11 @@ import { Col, Row, Input, Select, message, Space, Button, Popconfirm, Switch, no
 import React, { useEffect, useCallback, useState } from 'react'
 import TableData from '../../components/TableData'
 import tableConfig from './tableConfig'
-import { putAdqAdgroupsSync, getAdqAdgroupsList, delListAdqAdgroupsApi, newEditAdqAdgroupsDataApi } from '@/services/launchAdq/adq'
+import { putAdqAdgroupsSync, getAdqAdgroupsList, delListAdqAdgroupsApi, newEditAdqAdgroupsDataApi, editAdqAdgroupsDataApi } from '@/services/launchAdq/adq'
 import { CopyOutlined, DeleteOutlined, FieldTimeOutlined, PauseCircleOutlined, PlayCircleOutlined, TransactionOutlined } from '@ant-design/icons'
 import UpdateAd from './updateAd'
 import Copy from './copy'
+import { DataType } from '@/components/Tables'
 
 type Props = {
     accountId: string,
@@ -42,7 +43,7 @@ const Ad: React.FC<Props> = (props) => {
     const [update, setUpdate] = useState<{ visible: boolean, title: string }>({ visible: false, title: '' })
     const [model, setModel] = useState(true)
     const [copyData, setCopyData] = useState<{ visible: boolean }>({ visible: false })
-    const [queryFrom,set_queryFrom]=useState<{
+    const [queryFrom, set_queryFrom] = useState<{
         pageNum: number;
         pageSize: number;
         accountIdList?: any[];
@@ -51,25 +52,26 @@ const Ad: React.FC<Props> = (props) => {
         promotedObjectType?: string;
         isDeleted?: boolean
         campaignIdList?: any[]
-        statusList?:any[],
-        memoList?:any[]
-        remarkList?:any[]
-    }>({pageNum:1,pageSize:20})
+        statusList?: any[],
+        memoList?: any[]
+        remarkList?: any[]
+    }>({ pageNum: 1, pageSize: 20 })
     const listAjax = useAjax((params) => getAdqAdgroupsList(params), { formatResult: true })
     const syncAjax = useAjax((adAccountId) => putAdqAdgroupsSync(adAccountId))
     const delListAdqAdgroups = useAjax((params) => delListAdqAdgroupsApi(params))
     const editAdqAdgroupsData = useAjax((params) => newEditAdqAdgroupsDataApi(params))
+    const editAdqAdgroups = useAjax((params) => editAdqAdgroupsDataApi(params))
     /************************/
 
     useEffect(() => {
-        let {accountId,campaignId,adgroupId,...obj} = queryParmas
+        let { accountId, campaignId, adgroupId, ...obj } = queryParmas
         let new_queryParmas = {
             ...obj,
-            accountIdList:accountId?[accountId]:[],
-            campaignIdList:campaignId?[campaignId]:[],
-            adgroupIdList:adgroupId?[adgroupId]:[]
+            accountIdList: accountId ? [accountId] : [],
+            campaignIdList: campaignId ? [campaignId] : [],
+            adgroupIdList: adgroupId ? [adgroupId] : []
         }
-        getList({ pageNum: 1, pageSize: 20, ...new_queryParmas,accountIdList:accountId?[accountId]:[] })
+        getList({ pageNum: 1, pageSize: 20, ...new_queryParmas, accountIdList: accountId ? [accountId] : [] })
     }, [accountId, userId, queryParmas])
 
     // 获取列表
@@ -82,9 +84,9 @@ const Ad: React.FC<Props> = (props) => {
         promotedObjectType?: string;
         isDeleted?: boolean
         campaignIdList?: any[]
-        statusList?:any[],
-        memoList?:any[]
-        remarkList?:any[]
+        statusList?: any[],
+        memoList?: any[]
+        remarkList?: any[]
     }) => {
         if (!params.adgroupName || params.adgroupName !== listAjax?.params[0]?.adgroupName) {
             !params.adgroupName && delete params.adgroupName
@@ -160,6 +162,13 @@ const Ad: React.FC<Props> = (props) => {
         setCopyData({ visible: true })
     }
 
+    const handleSave = (row: any) => {
+        editAdqAdgroups.run({ adgroupIds: [row.adgroupId], adgroupName: row.adgroupName }).then(res => {
+            message.success('修改广告名称成功')
+            listAjax.refresh()
+        })
+    }
+
     return <div>
         {/* 修改广告 */}
         {update.visible && <UpdateAd
@@ -186,6 +195,7 @@ const Ad: React.FC<Props> = (props) => {
             page={listAjax?.data?.data?.current}
             pageSize={listAjax?.data?.data?.size}
             myKey={'adgroupId'}
+            handleSave={handleSave}
             leftChild={<Space direction='vertical'>
                 <Row gutter={[10, 10]} align='middle'>
                     <Col>
@@ -195,37 +205,37 @@ const Ad: React.FC<Props> = (props) => {
                             style={{ width: 150 }}
                             onBlur={(e) => {
                                 let value = e.target.value
-                                let arr:any = []
-                                if(value){
-                                    value = value.replace(/[,,\s]/g,',')
-                                    arr = value.split(',').filter(a=>a)
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter(a => a)
                                 }
-                                set_queryFrom({...queryFrom,accountIdList: arr})
-                                getList({ ...queryFrom,pageNum: 1,  accountIdList: arr })
+                                set_queryFrom({ ...queryFrom, accountIdList: arr })
+                                getList({ ...queryFrom, pageNum: 1, accountIdList: arr })
                             }}
                             onKeyDownCapture={(e: any) => {
                                 let key = e.key
                                 if (key === 'Enter') {
                                     let value = e.target.value
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,accountIdList: arr})
-                                    getList({...queryFrom, pageNum: 1, accountIdList: arr })
+                                    set_queryFrom({ ...queryFrom, accountIdList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, accountIdList: arr })
                                 }
                             }}
                             onChange={(e) => {
                                 let value = e.target.value
                                 if (!value) {
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,accountIdList: arr})
-                                    getList({...queryFrom, pageNum: 1,  accountIdList: arr })
+                                    set_queryFrom({ ...queryFrom, accountIdList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, accountIdList: arr })
                                 }
                             }}
                         />
@@ -237,22 +247,22 @@ const Ad: React.FC<Props> = (props) => {
                             style={{ width: 150 }}
                             onBlur={(e) => {
                                 let value = e.target.value
-                                set_queryFrom({...queryFrom,adgroupName: value })
-                                getList({ ...queryFrom,pageNum: 1, adgroupName: value })
+                                set_queryFrom({ ...queryFrom, adgroupName: value })
+                                getList({ ...queryFrom, pageNum: 1, adgroupName: value })
                             }}
                             onKeyDownCapture={(e: any) => {
                                 let key = e.key
                                 if (key === 'Enter') {
                                     let value = e.target.value
-                                    set_queryFrom({...queryFrom,adgroupName: value })
-                                    getList({ ...queryFrom,pageNum: 1,  adgroupName: value })
+                                    set_queryFrom({ ...queryFrom, adgroupName: value })
+                                    getList({ ...queryFrom, pageNum: 1, adgroupName: value })
                                 }
                             }}
                             onChange={(e) => {
                                 let value = e.target.value
                                 if (!value) {
-                                    set_queryFrom({...queryFrom,adgroupName: value })
-                                    getList({...queryFrom, pageNum: 1,  adgroupName: value })
+                                    set_queryFrom({ ...queryFrom, adgroupName: value })
+                                    getList({ ...queryFrom, pageNum: 1, adgroupName: value })
                                 }
                             }}
                         />
@@ -264,37 +274,37 @@ const Ad: React.FC<Props> = (props) => {
                             style={{ width: 150 }}
                             onBlur={(e) => {
                                 let value = e.target.value
-                                let arr:any = []
-                                if(value){
-                                    value = value.replace(/[,,\s]/g,',')
-                                    arr = value.split(',').filter((a: any)=>a)
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter((a: any) => a)
                                 }
-                                set_queryFrom({...queryFrom,adgroupIdList: arr  })
-                                getList({...queryFrom, pageNum: 1,  adgroupIdList: arr })
+                                set_queryFrom({ ...queryFrom, adgroupIdList: arr })
+                                getList({ ...queryFrom, pageNum: 1, adgroupIdList: arr })
                             }}
                             onKeyDownCapture={(e: any) => {
                                 let key = e.key
                                 if (key === 'Enter') {
                                     let value = e.target.value
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,adgroupIdList: arr  })
-                                    getList({...queryFrom, pageNum: 1,  adgroupIdList: arr })
+                                    set_queryFrom({ ...queryFrom, adgroupIdList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, adgroupIdList: arr })
                                 }
                             }}
                             onChange={(e) => {
                                 let value = e.target.value
                                 if (!value) {
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,adgroupIdList: arr  })
-                                    getList({...queryFrom, pageNum: 1,  adgroupIdList: arr })
+                                    set_queryFrom({ ...queryFrom, adgroupIdList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, adgroupIdList: arr })
                                 }
                             }}
                         />
@@ -306,37 +316,37 @@ const Ad: React.FC<Props> = (props) => {
                             style={{ width: 150 }}
                             onBlur={(e) => {
                                 let value = e.target.value
-                                let arr:any = []
-                                if(value){
-                                    value = value.replace(/[,,\s]/g,',')
-                                    arr = value.split(',').filter((a: any)=>a)
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter((a: any) => a)
                                 }
-                                set_queryFrom({...queryFrom,campaignIdList: arr  })
-                                getList({ ...queryFrom,pageNum: 1,  campaignIdList: arr })
+                                set_queryFrom({ ...queryFrom, campaignIdList: arr })
+                                getList({ ...queryFrom, pageNum: 1, campaignIdList: arr })
                             }}
                             onKeyDownCapture={(e: any) => {
                                 let key = e.key
                                 if (key === 'Enter') {
                                     let value = e.target.value
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,campaignIdList: arr  })
-                                    getList({ ...queryFrom,pageNum: 1,  campaignIdList: arr })
+                                    set_queryFrom({ ...queryFrom, campaignIdList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, campaignIdList: arr })
                                 }
                             }}
                             onChange={(e) => {
                                 let value = e.target.value
                                 if (!value) {
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,campaignIdList: arr  })
-                                    getList({ ...queryFrom,pageNum: 1,  campaignIdList: arr })
+                                    set_queryFrom({ ...queryFrom, campaignIdList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, campaignIdList: arr })
                                 }
                             }}
                         />
@@ -351,8 +361,8 @@ const Ad: React.FC<Props> = (props) => {
                             }
                             allowClear
                             onChange={(value: any) => {
-                                set_queryFrom({...queryFrom,promotedObjectType: value  })
-                                getList({ ...queryFrom,pageNum: 1,  promotedObjectType: value })
+                                set_queryFrom({ ...queryFrom, promotedObjectType: value })
+                                getList({ ...queryFrom, pageNum: 1, promotedObjectType: value })
                             }}
                         >
                             {Object.keys(PromotedObjectType).map(key => {
@@ -370,8 +380,8 @@ const Ad: React.FC<Props> = (props) => {
                             }
                             allowClear
                             onChange={(value: any) => {
-                                set_queryFrom({...queryFrom,isDeleted: value  })
-                                getList({ ...queryFrom,pageNum: 1,  isDeleted: value })
+                                set_queryFrom({ ...queryFrom, isDeleted: value })
+                                getList({ ...queryFrom, pageNum: 1, isDeleted: value })
                             }}
                         >
                             <Select.Option value={true}>已删除</Select.Option>
@@ -389,13 +399,13 @@ const Ad: React.FC<Props> = (props) => {
                             }
                             allowClear
                             onChange={(value: any) => {
-                                set_queryFrom({...queryFrom,statusList: value  })
-                                getList({...queryFrom, pageNum: 1,  statusList: value })
+                                set_queryFrom({ ...queryFrom, statusList: value })
+                                getList({ ...queryFrom, pageNum: 1, statusList: value })
                             }}
                         >
                             {
-                                Object.keys(AdStatusEnum).map(key=>{
-                                    return  <Select.Option value={key} key={key}>{AdStatusEnum[key]}</Select.Option>
+                                Object.keys(AdStatusEnum).map(key => {
+                                    return <Select.Option value={key} key={key}>{AdStatusEnum[key]}</Select.Option>
                                 })
                             }
                         </Select>
@@ -407,37 +417,37 @@ const Ad: React.FC<Props> = (props) => {
                             style={{ width: 150 }}
                             onBlur={(e) => {
                                 let value = e.target.value
-                                let arr:any = []
-                                if(value){
-                                    value = value.replace(/[,,\s]/g,',')
-                                    arr = value.split(',').filter(a=>a)
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter(a => a)
                                 }
-                                set_queryFrom({...queryFrom,memoList: arr  })
-                                getList({...queryFrom, pageNum: 1,  memoList: arr })
+                                set_queryFrom({ ...queryFrom, memoList: arr })
+                                getList({ ...queryFrom, pageNum: 1, memoList: arr })
                             }}
                             onKeyDownCapture={(e: any) => {
                                 let key = e.key
                                 if (key === 'Enter') {
                                     let value = e.target.value
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,memoList: arr  })
-                                    getList({...queryFrom, pageNum: 1,  memoList: arr })
+                                    set_queryFrom({ ...queryFrom, memoList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, memoList: arr })
                                 }
                             }}
                             onChange={(e) => {
                                 let value = e.target.value
                                 if (!value) {
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,memoList: arr  })
-                                    getList({...queryFrom, pageNum: 1, memoList: arr })
+                                    set_queryFrom({ ...queryFrom, memoList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, memoList: arr })
                                 }
                             }}
                         />
@@ -449,37 +459,37 @@ const Ad: React.FC<Props> = (props) => {
                             style={{ width: 150 }}
                             onBlur={(e) => {
                                 let value = e.target.value
-                                let arr:any = []
-                                if(value){
-                                    value = value.replace(/[,,\s]/g,',')
-                                    arr = value.split(',').filter(a=>a)
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter(a => a)
                                 }
-                                set_queryFrom({...queryFrom,remarkList: arr  })
-                                getList({...queryFrom, pageNum: 1,  remarkList: arr })
+                                set_queryFrom({ ...queryFrom, remarkList: arr })
+                                getList({ ...queryFrom, pageNum: 1, remarkList: arr })
                             }}
                             onKeyDownCapture={(e: any) => {
                                 let key = e.key
                                 if (key === 'Enter') {
                                     let value = e.target.value
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,remarkList: arr  })
-                                    getList({...queryFrom, pageNum: 1,  remarkList: arr })
+                                    set_queryFrom({ ...queryFrom, remarkList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, remarkList: arr })
                                 }
                             }}
                             onChange={(e) => {
                                 let value = e.target.value
                                 if (!value) {
-                                    let arr:any = []
-                                    if(value){
-                                        value = value.replace(/[,,\s]/g,',')
-                                        arr = value.split(',').filter((a: any)=>a)
+                                    let arr: any = []
+                                    if (value) {
+                                        value = value.replace(/[,,\s]/g, ',')
+                                        arr = value.split(',').filter((a: any) => a)
                                     }
-                                    set_queryFrom({...queryFrom,remarkList: arr  })
-                                    getList({...queryFrom, pageNum: 1,  remarkList: arr })
+                                    set_queryFrom({ ...queryFrom, remarkList: arr })
+                                    getList({ ...queryFrom, pageNum: 1, remarkList: arr })
                                 }
                             }}
                         />
@@ -490,7 +500,7 @@ const Ad: React.FC<Props> = (props) => {
                         <Switch checkedChildren="普通模式" unCheckedChildren="深度优化" checked={model} onChange={(checked) => { setModel(checked); setSelectedRows([]) }} style={model ? {} : { background: '#67c23a' }} />
                     </Col>
                     {model ? <>
-                        <Col><Button type='primary' style={{ background: '#1890ff' }} icon={<FieldTimeOutlined />} disabled={selectedRows.length === 0} onClick={editScheduling}>修改排期出价</Button></Col>
+                        <Col><Button type='primary' style={{ background: '#1890ff' }} icon={<FieldTimeOutlined />} disabled={selectedRows.length === 0} onClick={editScheduling}>修改排期出价名称</Button></Col>
                         <Col><Button type='primary' style={{ background: '#1890ff' }} icon={<CopyOutlined />} disabled={selectedRows.length === 0} onClick={copyHandle}>批量复制</Button></Col>
                         <Col><Button type='primary' style={{ background: '#67c23a', borderColor: '#67c23a' }} loading={editAdqAdgroupsData.loading} icon={<PlayCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus('play')}>启动广告</Button></Col>
                         <Col><Button type='primary' style={{ background: '#e6a23c', borderColor: '#e6a23c' }} loading={editAdqAdgroupsData.loading} icon={<PauseCircleOutlined />} disabled={selectedRows.length === 0} onClick={() => adStatus('suspend')}>暂停广告</Button></Col>
@@ -527,8 +537,8 @@ const Ad: React.FC<Props> = (props) => {
             onChange={(props: any) => {
                 let { sortData, pagination } = props
                 let { current, pageSize } = pagination
-                set_queryFrom({...queryFrom,pageNum:current,pageSize})
-                getList({...queryFrom, pageNum: current, pageSize })
+                set_queryFrom({ ...queryFrom, pageNum: current, pageSize })
+                getList({ ...queryFrom, pageNum: current, pageSize })
             }}
         />
     </div>

+ 1 - 3
src/pages/launchSystemNew/adq/ad/tableConfig.tsx

@@ -98,9 +98,7 @@ function tableConfig(
             key: 'adgroupName',
             width: 280,
             ellipsis: true,
-            render: (a: string) => {
-                return <a style={{ wordBreak: 'break-all' }} onClick={() => { copy(a) }}>{a}</a>
-            }
+            editable: true
         },
         {
             title: '推广目标类型',

+ 12 - 2
src/pages/launchSystemNew/adq/ad/updateAd.tsx

@@ -48,6 +48,7 @@ const UpdateAd: React.FC<Props> = ({ title = '修改广告', visible, onChange,
             let adgroupsUpdateDatetimeDTO = {}  // 排期
             let adgroupsUpdateBidAmountDTO = {} // 出价
             let deepConversionSpec = {} // ROI
+            let data = {}
             if (timeSeriesType === 'allDayLong') {
                 newValues.timeSeries = getTimeSeriesList()
             }
@@ -88,11 +89,14 @@ const UpdateAd: React.FC<Props> = ({ title = '修改广告', visible, onChange,
                             adgroupsUpdateBidAmountDTO['bidStrategy'] = newValues.bidStrategy
                             adgroupsUpdateBidAmountDTO['bidAmount'] = newValues.bidAmount * 100
                             break
+                        case 'adgroupName':
+                            data['adgroupName'] = newValues.adgroupName
+                            break
                     }
                 })
             }
-            // console.log('params--->', adgroupsUpdateDatetimeDTO);
-            editAdqAdgroupsData.run({ adgroupIds: selectedRows.map((item: { adgroupId: number }) => item.adgroupId), adgroupsUpdateDatetimeDTO, adgroupsUpdateBidAmountDTO, deepConversionSpec }).then(res => {
+            
+            editAdqAdgroupsData.run({ adgroupIds: selectedRows.map((item: { adgroupId: number }) => item.adgroupId), adgroupsUpdateDatetimeDTO, adgroupsUpdateBidAmountDTO, deepConversionSpec, ...data }).then(res => {
                 if (res) {
                     message.success(`修改操作完成.结果请在操作记录查询!`)//成功: ${res.success},失败: ${res.fail}
                     if (res?.fail) {
@@ -154,6 +158,7 @@ const UpdateAd: React.FC<Props> = ({ title = '修改广告', visible, onChange,
                                 </Tooltip>}
                             </Space>
                         </Checkbox>
+                        <Checkbox value="adgroupName">广告名称</Checkbox>
                     </Checkbox.Group>
                 </Form.Item>
                 {field?.includes('dateType') && <>
@@ -218,6 +223,11 @@ const UpdateAd: React.FC<Props> = ({ title = '修改广告', visible, onChange,
                         <Input placeholder={`输入价格 元`} style={{ width: 300 }} />
                     </Form.Item>
                 </>}
+                {field?.includes('adgroupName') && <>
+                    <Form.Item label={<strong>广告名称</strong>} name='adgroupName' rules={[{ required: true, message: '请输入广告名称' }]}>
+                        <Input placeholder={`请输入广告名称`} style={{ width: 300 }} />
+                    </Form.Item>
+                </>}
             </> : <>
                 <Form.Item label={<strong>深度优化方式</strong>} name='optimizationMode' rules={[{ required: true, message: '请选择深度优化方式' }]}>
                     <Radio.Group disabled>

+ 21 - 0
src/pages/launchSystemNew/adq/ad/updateAdName.tsx

@@ -0,0 +1,21 @@
+import React from "react"
+
+
+
+
+interface Props {
+
+}
+const updateAdName: React.FC<Props> = (props) => {
+
+    /*******************************/
+    const {} = props
+    /*******************************/
+
+    return <div>
+
+    </div>
+}
+
+
+export default React.memo(updateAdName)

+ 56 - 21
src/pages/launchSystemNew/adq/adAccount/index.tsx

@@ -1,6 +1,6 @@
 
 import { useAjax } from '@/Hook/useAjax'
-import {  Row,  message } from 'antd'
+import { Row, message, Input } from 'antd'
 import React, { useEffect, useState, useCallback } from 'react'
 import TableData from '../../components/TableData'
 import tableConfig from './tableConfig'
@@ -28,28 +28,26 @@ type Props = {
         }
     }) => void
 }
-function AdAccount(props:Props) {
-    let { accountId, adAccountId, userId,tableIdClick } = props
-    let [selectedRowKeys,setSelectedRowKeys]=useState<any[]>([])
+function AdAccount(props: Props) {
+    let { adAccountId, userId } = props
+    let [selectedRowKeys, setSelectedRowKeys] = useState<any[]>([])
+    const [queryForm, setQueryForm] = useState<{
+        pageNum: number;
+        pageSize: number;
+        accountIds?: string;
+        adcreativeName?: string;
+    }>({pageNum: 1, pageSize: 20})
     // api方法
     const listAjax = useAjax((params) => getAdqAdAccountList(params), { formatResult: true })
     const syncAjax = useAjax((params) => putAdqAdAccountSyncByIds(params))
     console.log('创意=====》')
     useEffect(() => {
-        getList({ pageNum: 1, pageSize: 20 })
-    }, [accountId, userId])
+        getList()
+    }, [queryForm, userId])
     // 获取列表
-    const getList = useCallback((params: {
-        pageNum: number;
-        pageSize: number;
-        accountId?: string;
-        adcreativeName?: string;
-    }) => {
-        if (!params.adcreativeName || params.adcreativeName !== listAjax?.params[0]?.adcreativeName) {
-            !params.adcreativeName && delete params.adcreativeName
-            listAjax.run({ ...params, userId, accountIds:accountId?[accountId]:null })
-        }
-    }, [accountId, userId, listAjax])
+    const getList = useCallback(() => {
+        listAjax.run({ ...queryForm, userId })
+    }, [queryForm, userId, listAjax])
     // 同步 
     const sync = useCallback(() => {
         if (selectedRowKeys?.length === 0) {
@@ -61,21 +59,58 @@ function AdAccount(props:Props) {
             res ? message.success('同步成功!') : message.error('同步失败!')
 
         })
-    }, [adAccountId, listAjax,selectedRowKeys])
+    }, [adAccountId, listAjax, selectedRowKeys])
     return <div>
         <TableData
             isCard={false}
-            columns={()=>tableConfig(tableIdClick)}
+            columns={() => tableConfig()}
             ajax={listAjax}
             syncAjax={sync}
             dataSource={listAjax?.data?.data?.records}
             loading={listAjax?.loading || syncAjax?.loading}
-            scroll={{ y:550 }}
+            scroll={{ y: 550 }}
             total={listAjax?.data?.data?.total}
             page={listAjax?.data?.data?.current}
             pageSize={listAjax?.data?.data?.size}
             leftChild={<>
                 <Row gutter={[10, 10]}>
+                    <Input
+                        placeholder='广告账号'
+                        allowClear
+                        style={{ width: 150 }}
+                        onBlur={(e) => {
+                            let value = e.target.value
+                            let arr: any = []
+                            if (value) {
+                                value = value.replace(/[,,\s]/g, ',')
+                                arr = value.split(',').filter(a => a)
+                            }
+                            setQueryForm({ ...queryForm, accountIds: arr })
+                        }}
+                        onKeyDownCapture={(e: any) => {
+                            let key = e.key
+                            if (key === 'Enter') {
+                                let value = e.target.value
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter((a: any) => a)
+                                }
+                                setQueryForm({ ...queryForm, accountIds: arr })
+                            }
+                        }}
+                        onChange={(e) => {
+                            let value = e.target.value
+                            if (!value) {
+                                let arr: any = []
+                                if (value) {
+                                    value = value.replace(/[,,\s]/g, ',')
+                                    arr = value.split(',').filter((a: any) => a)
+                                }
+                                setQueryForm({ ...queryForm, accountIds: arr })
+                            }
+                        }}
+                    />
                 </Row>
             </>}
             rowSelection={{
@@ -86,7 +121,7 @@ function AdAccount(props:Props) {
             onChange={(props: any) => {
                 let { sortData, pagination } = props
                 let { current, pageSize } = pagination
-                getList({ pageNum: current, pageSize })
+                setQueryForm({ ...queryForm, pageNum: current, pageSize })
             }}
         />
     </div>

+ 14 - 28
src/pages/launchSystemNew/adq/adAccount/tableConfig.tsx

@@ -1,38 +1,24 @@
-import {  FundStatusEnum, } from '@/services/launchAdq/enum'
+import { FundStatusEnum, } from '@/services/launchAdq/enum'
 import React from 'react'
 import { Badge } from 'antd'
-function tableConfig(tableIdClick: (props: {
-    activeKey: string,
-    parma: {
-        accountId?: string,//账户ID
-        campaignId?: string,//计划ID
-        adgroupId?: string,//广告ID
-        adcreativeId?: string,//创意ID
-        pageId?: string,//落地页ID
-        targetingId?: string,//定向ID
-    }
-}) => void):any{
+import { copy } from '@/utils/utils'
+function tableConfig(): any {
     return [
         {
             title: 'ID',
             dataIndex: 'id',
             key: 'id',
             align: 'center',
-            width:50,
-            render:(a:string)=>{
-                return <a>{a}</a>
-            }
+            width: 50
         },
         {
             title: '账号ID',
             dataIndex: 'accountId',
             key: 'accountId',
             align: 'center',
-            width:90,
-            render:(a:string)=>{
-                return <a onClick={() => {
-                    tableIdClick({ activeKey: '1', parma: { accountId: a } })
-                }}>{a}</a>
+            width: 90,
+            render: (a: string) => {
+                return <a onClick={() => { copy(a) }}>{a}</a>
             }
         },
         {
@@ -58,26 +44,26 @@ function tableConfig(tableIdClick: (props: {
             dataIndex: 'balance',
             key: 'balance',
             align: 'center',
-            width:150,
+            width: 150,
         },
         {
             title: '资金状态',
             dataIndex: 'fundStatus',
             key: 'fundStatus',
             align: 'center',
-            width:130,
-           render:(a: string | number)=>{
-            return FundStatusEnum[a]
-           } 
+            width: 130,
+            render: (a: string | number) => {
+                return FundStatusEnum[a]
+            }
         },
         {
             title: '是否有效',
             dataIndex: 'enabled',
             key: 'enabled',
             align: 'center',
-            width:130,
+            width: 130,
             render: (a: any, b: any) => {
-                return  <Badge status={a ? "processing" :"error" } text={a? '是' : '否'} />
+                return <Badge status={a ? "processing" : "error"} text={a ? '是' : '否'} />
             }
         },
     ]

+ 24 - 24
src/pages/launchSystemNew/adq/index.tsx

@@ -179,31 +179,31 @@ function Adq() {
         <div className={style.right} style={!hide ? { width: 'calc(100% - 150px)' } : { width: '100%' }}>
             <div className={style.hiddenBtn}><Button size='small' type="primary" onClick={() => setHide(!hide)} icon={!hide ? <MenuFoldOutlined /> : <MenuUnfoldOutlined />} /></div>
             <Card>
-                <Tabs activeKey={activeKey} type="card" onChange={(activeKey) => { setActiveKey(activeKey) }} tabBarExtraContent={
-                    <Select
-                        placeholder='广点通账号'
-                        style={{ minWidth: 200 }}
-                        showSearch
-                        allowClear
-                        onChange={(value: any) => {
-                            let accountId = ''
-                            let adAccountId = ''
-                            if (value) {
-                                let arr = value.split('_')
-                                accountId = arr[0]
-                                adAccountId = arr[1]
-                            }
-                            setIds({ accountId, adAccountId })
-                        }}
-                        value={idS.accountId ? idS.accountId + '_' + idS.adAccountId : null}
-                    >
-                        {
-                            selectedArr?.map((item: any) => {
-                                return <Select.Option value={item.key} key={item.key}>{item.label}</Select.Option>
-                            })
+                <Tabs activeKey={activeKey} type="card" onChange={(activeKey) => { setActiveKey(activeKey) }} tabBarExtraContent={<>
+                    {/* <Select
+                    placeholder='广点通账号'
+                    style={{ minWidth: 200 }}
+                    showSearch
+                    allowClear
+                    onChange={(value: any) => {
+                        let accountId = ''
+                        let adAccountId = ''
+                        if (value) {
+                            let arr = value.split('_')
+                            accountId = arr[0]
+                            adAccountId = arr[1]
                         }
-                    </Select>
-                }>
+                        setIds({ accountId, adAccountId })
+                    }}
+                    value={idS.accountId ? idS.accountId + '_' + idS.adAccountId : null}
+                >
+                    {
+                        selectedArr?.map((item: any) => {
+                            return <Select.Option value={item.key} key={item.key}>{item.label}</Select.Option>
+                        })
+                    }
+                </Select> */}
+                </>}>
                     {
                         tabsConfig?.map(item => {
                             return <TabPane tab={item.tab} key={item.key} >

+ 6 - 4
src/pages/launchSystemNew/components/TableData/index.tsx

@@ -1,5 +1,5 @@
 import CustomListModel from '@/components/CustomList'
-import Tables from '@/components/Tables'
+import Tables, { DataType } from '@/components/Tables'
 import { quanpin } from '@/utils/fullScreen'
 import { FullscreenExitOutlined, FullscreenOutlined, RedoOutlined, SettingOutlined, SyncOutlined } from '@ant-design/icons'
 import { Button, Card, Col, Row, Space, Spin, Tooltip, } from 'antd'
@@ -47,10 +47,11 @@ interface Prosp {
     bodyStyle?: any
     gutter?: any
     isCard?: boolean
+    handleSave?: (row: DataType) => void
 }
 
 function TableData(props: Prosp) {
-    const { isZj, scroll, columns, title, dataSource, expandedRowRender, className, isCard = true, leftChild, page = undefined, rowSelection = false, pageSize = undefined, size = 'small', fixed = { left: 0, right: 1 }, total = 0, loading = false, onChange, config, configName, ajax, syncAjax, hoverable = true, myKey, gutter = [0, 20] } = props
+    const { isZj, scroll, columns, title, dataSource, expandedRowRender, className, isCard = true, leftChild, handleSave, page = undefined, rowSelection = false, pageSize = undefined, size = 'small', fixed = { left: 0, right: 1 }, total = 0, loading = false, onChange, config, configName, ajax, syncAjax, hoverable = true, myKey, gutter = [0, 20] } = props
     const { state: userState } = useModel('useOperating.useUser')
     const { isFell } = userState
     const [visible, setVisible] = useState<boolean>(false)
@@ -252,7 +253,7 @@ function TableData(props: Prosp) {
                 </Row>
             </Card> : <Row gutter={gutter}>
                 {header}
-                <Tab {...{ size, newColumns, handelResize, className, isZj, rowSelection, columns, loading, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
+                <Tab {...{ size, newColumns, handelResize, className, isZj, rowSelection, columns, loading, handleSave, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
             </Row>}
         </Col>
     </Row >
@@ -263,7 +264,7 @@ function TableData(props: Prosp) {
 
 /**表格 */
 const Tab = React.memo((props: any) => {
-    const { size, newColumns, className, handelResize, columns, scroll, loading, rowSelection, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey } = props
+    const { size, newColumns, className, handelResize, columns, scroll, loading, handleSave, rowSelection, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey } = props
     return < Col span={24} >
         <div className={`${style[size]} ${className ? style[className] : ''} `}>
             {dataSource || !ajax?.loading ? <Tables
@@ -285,6 +286,7 @@ const Tab = React.memo((props: any) => {
                 rowSelection={rowSelection}
                 handelResize={((columns: any) => handelResize(columns))}
                 myKey={myKey}
+                handleSave={handleSave}
             /> : <div className={style.example}>
                 <Spin />
             </div>}

+ 17 - 0
src/pages/launchSystemNew/components/teamMembers/index.less

@@ -0,0 +1,17 @@
+.teamMembers {
+    width: 200px;
+    height: 100%;
+    background-color: #fff;
+    overflow: hidden;
+    overflow-y: auto;
+
+    >.menus {
+        width: 100%;
+        height: calc(100% - 32px);
+        overflow: hidden;
+    }
+
+    ul::-webkit-scrollbar {
+        width: 0 !important;
+    }
+}

+ 113 - 0
src/pages/launchSystemNew/components/teamMembers/index.tsx

@@ -0,0 +1,113 @@
+import { IdcardFilled } from "@ant-design/icons"
+import { Menu, Select, Spin } from "antd"
+import React, { useEffect, useState } from "react"
+import { useModel } from "umi"
+import './index.less'
+
+interface Props {
+    onChange?: (id?: number) => void
+    value?: number
+    allOfMember: any
+}
+/**
+ * 选择组员左菜单
+ */
+const TeamMembers: React.FC<Props> = (props) => {
+
+    /*************************/
+    const { onChange, value, allOfMember } = props
+    const [userAll, setUserAll] = useState([])
+
+    const userInfo = useModel('@@initialState', model => model.initialState?.currentUser)
+    const [userId, setUserId] = useState<number | undefined>(userInfo?.userId ? Number(userInfo?.userId) : undefined)
+    /*************************/
+
+    // useEffect(() => {
+    //     onChange?.(userId)
+    // }, [userId])
+
+    useEffect(() => {
+        if (value) {
+            setUserId(value)
+        }
+    }, [value])
+
+    /** 获取组员 */
+    useEffect(() => {
+        (async function () {
+            let res = allOfMember?.data || await allOfMember.run()
+            if (res?.data) {
+                let useAll: any = []
+                res?.data?.forEach((item: { key: { userId: number; nickName: any; }; value: any[]; }) => {
+                    let obj = {
+                        key: item.key.userId,
+                        label: item.key.nickName,
+                        icon: <IdcardFilled />,
+                    }
+                    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)
+            }
+        })()
+
+    }, [])
+
+    /** 初始跳转到自己的名称 */
+    useEffect(() => {
+        if (userAll?.length > 0 && userId) {
+            let topEq = userAll?.findIndex((item: any) => item.key == userId)
+            let em: any = document.getElementById('myMenus')
+            if (em) em.scrollTop = (52 - 4) * topEq
+        }
+    }, [userId, userAll])
+
+    return <div className="teamMembers">
+        <Select
+            placeholder='名称搜索'
+            style={{ width: '100%' }}
+            showSearch
+            value={userId ? Number(userId) : undefined}
+            filterOption={(input: any, option: any) => {
+                return (option!?.children as unknown as string)?.toLowerCase()?.includes(input?.toLowerCase())
+            }}
+            loading={allOfMember.loading}
+            onChange={(value: any) => {
+                if (value) {
+                    setUserId(value)
+                }
+                onChange?.(value ? value : undefined)
+            }}
+        >
+            {userAll.map((item: any) => {
+                return <Select.Option value={Number(item.key)} key={item.key}>{item.label}</Select.Option>
+            })}
+        </Select>
+        <Spin className="menus" spinning={allOfMember.loading}>
+            <Menu
+                id='myMenus'
+                theme='light'
+                onClick={(e: any) => {
+                    setUserId(e.key ? Number(e.key) : undefined)
+                    onChange?.(e.key)
+                }}
+                selectedKeys={userId ? [userId.toString()] : undefined}
+                mode="inline"
+                items={userAll}
+                style={{
+                    overflowY: 'auto',
+                    height: 'calc(100vh - 190px)',
+                    overflowX: 'hidden'
+                }}
+            />
+        </Spin>
+
+    </div>
+}
+
+
+export default React.memo(TeamMembers)

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

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

+ 11 - 12
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账号列表
@@ -128,20 +120,26 @@ export async function delAdqAdgroupsApi({ adAccountId, adgroupId }: { adAccountI
 }
 
 export interface EditAdqAdgroupsProps {
-  adgroupIds: number[],   // 广告组id列表
-  adgroupsUpdateBidAmountDTO?: { // 出价
+  /** 广告组id列表 */
+  adgroupIds: number[],
+  /** 广告名称 */ 
+  adgroupName?: string,
+  /** 出价 */
+  adgroupsUpdateBidAmountDTO?: {
     bidAmount: number,  // 出价
     bidMode: string,    // 出价方式
     bidStrategy: string,// 出价策略
     optimizationGoal: string,  // 出价目标
   },
-  adgroupsUpdateDatetimeDTO?: { // 排期
+  /** 排期 */
+  adgroupsUpdateDatetimeDTO?: {
     beginDate: string,
     endDate?: string,
     firstDayBeginTime?: string,
     timeSeries?: string
   },
-  deepConversionSpec?: { // 深度优化
+  /** 深度优化 */
+  deepConversionSpec?: {
     deepConversionType: string,
     deepConversionBehaviorSpec?: {
       bidAmount: number,
@@ -156,6 +154,7 @@ export interface EditAdqAdgroupsProps {
       goal: string
     }
   },
+  /** 启停状态 */
   configuredStatus?: string
 }
 export async function editAdqAdgroupsDataApi(data: EditAdqAdgroupsProps) {

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