Pārlūkot izejas kodu

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

wjx 2 gadi atpakaļ
vecāks
revīzija
f97a6ba000

+ 2 - 2
config/proxy.ts

@@ -10,8 +10,8 @@
  export default {
   dev: {
     '/api/': {
-      target: 'http://test.api.zanxiangwl.com',
-      // target: 'http://api.zanxiangwl.com',
+      // target: 'http://test.api.zanxiangwl.com/api',
+      target: 'http://api.zanxiangwl.com',
       changeOrigin: true,
       pathRewrite: { '/api': '' },
     },

+ 36 - 4
src/pages/adMonitor/adMonitorList/index.tsx

@@ -1,5 +1,6 @@
-import { Tabs } from "antd"
-import React, { useState } from "react"
+import Ad from "@/pages/launchSystemNew/adq/ad"
+import { Card, Select, Tabs } from "antd"
+import React, { useEffect, useState } from "react"
 import { useModel } from "umi"
 import Monitor from "./monitor"
 import PlanList from "./planList"
@@ -9,8 +10,13 @@ const AdMonitorList: React.FC = () => {
     // 变量开始
     const [tab, setTab] = useState<string>('monitor')  // tab切换
     const { getPlanList, getPlanDetailList, getAllPlanList } = useModel('useAdMonitor.useMonitor')
+    const [userId, setUserId] = useState(localStorage.getItem("userId") as string)
+    const { getPicherList } = useModel('useOperating.useWxGroupList')
     // 变量结束
-
+    // 获取投手
+    useEffect(() => {
+        !getPicherList.data && getPicherList.run()
+    }, [])
     return <div className="adMonitorList">
         <Tabs activeKey={tab} className="adMonitorListTab" size="small" type="card" onChange={(activeKey: string) => {
             if (activeKey === 'monitor') {
@@ -23,8 +29,34 @@ const AdMonitorList: React.FC = () => {
         }}>
             <Tabs.TabPane tab="今日起量广告监控" key="monitor" />
             <Tabs.TabPane tab="广告列表" key="list" />
+            <Tabs.TabPane tab="广告列表2" key="list2" />
         </Tabs>
-        {tab === 'monitor' ? <Monitor onChange={() => { setTab('list') }} /> : tab === 'list' ? <PlanList /> : null}
+        {tab === 'monitor' ? <Monitor onChange={() => { setTab('list') }} /> : tab === 'list' ? <PlanList /> : <Card><Ad userId={userId}  Ts={()=>{
+            return <Select
+            showSearch
+            value={userId ? Number(userId) : undefined}
+            style={{ minWidth: 180, maxWidth: 250 }}
+            maxTagCount={1}
+            allowClear
+            placeholder="请选择投手"
+            // disabled={queryForm?.adgroup || queryForm?.accountId?.length > 0}
+            onChange={(value) => {
+                    setUserId(value?.toString() || '')
+            }}
+            filterOption={(input, option) =>
+                (option?.children as any).toLowerCase().indexOf(input.toLowerCase()) >= 0
+            }
+        >
+            {getPicherList?.data?.map((item: { nickname: string, userId: number }, index: number) =>
+                <Select.Option
+                    value={item.userId}
+                    key={item.userId + '' + index}
+                >
+                    {item.nickname}
+                </Select.Option>
+            )}
+        </Select>
+        }}/></Card>}
     </div>
 }
 

+ 1 - 1
src/pages/adMonitor/adMonitorList/tablePlanListConfig.tsx

@@ -543,7 +543,7 @@ function columnsMonitor(details: (id: number) => void) {
                 align: 'center',
                 width: 90,
                 render: (a: any, b: any) => {
-                    return <a style={{ color: '#1890ff' }} onClick={() => window.open(`https://ad.qq.com/atlas/${b?.accountId}/admanage/adgroup?query={%22operation_status%22:[%22CALCULATE_STATUS_EXCLUDE_DEL%22],%22system_status%22:[],%22search_name%22:%2${b.adgroupId}%22}`)} target="_blank">腾讯广告</a>
+                    return <a style={{ color: '#1890ff' }} onClick={() => window.open(`https://ad.qq.com/atlas/${b?.accountId}/admanage/adgroup?query={%22operation_status%22:[%22CALCULATE_STATUS_EXCLUDE_DEL%22],%22system_status%22:[],%22search_name%22:%22${b.adgroupId}%22}`)} target="_blank">腾讯广告</a>
                 }
             }
         ]

+ 7 - 3
src/pages/launchSystemNew/account/index.tsx

@@ -8,7 +8,8 @@ import { getAdAccountListApi, GetAdAccountParams, putAdAccountApi } from '@/serv
 import style from './index.less'
 import TableData from '../components/TableData'
 import GroupLeft from './groupLeft'
-import { MenuFoldOutlined, MenuUnfoldOutlined, SwapOutlined } from '@ant-design/icons'
+import QQAuth from './qqAuto'
+import { MenuFoldOutlined, MenuUnfoldOutlined, PlusOutlined, SwapOutlined } from '@ant-design/icons'
 import TeamMembers from '../components/teamMembers'
 import { getAdAccountAllOfMember, getErpUserAll } from '@/services/launchAdq/adq'
 import AddAccountToGroup from './addAccountToGroup'
@@ -20,7 +21,7 @@ import AppointPut from './appointPut'
 
 /** 投放管理 */
 const AdAuthorize: React.FC = () => {
-
+    let [visible, setVisible] = useState(false)
     /*************************/
     const { groupListInit } = useModel('useLaunchAdq.useAdAuthorize')
     const userInfo = useModel('@@initialState', model => model.initialState?.currentUser)
@@ -128,6 +129,7 @@ const AdAuthorize: React.FC = () => {
             tabBarStyle={{ marginBottom: 1 }}
             activeKey={activeKey}
             type="card"
+            // tabBarExtraContent={<Button type='primary' onClick={()=>setVisible(true)}><PlusOutlined />广告账号授权</Button>}
             onChange={(activeKey) => {
                 if (activeKey !== 'contract') {
                     let newQueryForm = JSON.parse(JSON.stringify(queryForm))
@@ -177,6 +179,7 @@ const AdAuthorize: React.FC = () => {
                         />
                         <Button onClick={getList} type='primary' loading={getAdAccountList.loading}>搜索</Button>
                         <AddAccountToGroup onChange={() => getAdAccountList.refresh()} />
+                        <Button type='primary' onClick={() => setVisible(true)}><PlusOutlined />广告账号授权</Button>
                         {switchType === 'account' ?
                             (selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { checkAccount(selectAccData) }}>批量切号</Button>) :
                             (selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { putUserHandle(selectAccData) }}>批量指派投放助理</Button>)}
@@ -226,7 +229,8 @@ const AdAuthorize: React.FC = () => {
                 />
             </div>
         </div>
-
+        {/* 广告授权 */}
+        {visible && <QQAuth qqVisible={visible} callBack={() => setVisible(false)} />}
         {/* 变更记录 */}
         {crShow && <ChangeRecord visible={crShow} data={crData} onClose={() => { setCrShow(false); setCrData(null) }} />}
         {/* 切号 */}

+ 159 - 0
src/pages/launchSystemNew/account/qqAuto.tsx

@@ -0,0 +1,159 @@
+import { useCallback, useState } from "react"
+import React from 'react'
+import { Col, Row, Radio, Input, Button, message, Space, Image, Modal, Popconfirm } from "antd";
+let name = {
+    0: '小说账号失败列表:',
+    1: '游戏账号失败列表:',
+}
+var time: any = null
+let api= "http://47.99.157.216:8023"
+// let api= "http://127.0.0.1:8023"
+function QQAuth(props: { qqVisible: boolean, callBack: () => void }) {
+    const { qqVisible, callBack } = props
+    let [visible, setVisible] = useState(false)
+    let [loading,setLoading]=useState(false)
+    let [codeUrl, setCodeUrl] = useState('')
+    let [err, setErr] = useState({})
+    let [data, setData] = useState({
+        userId: localStorage.getItem('userId'),
+        adAppType: 0,
+        users: [],
+        callbackPage: 'http%3A%2F%2Ferp.zanxiangnet.com%2FadCode',
+        authorization: `Bearer ${sessionStorage.getItem('Admin-Token')}`
+    })
+    let adAppIdonChange = useCallback((checkedValue) => {
+        setData({ ...data, adAppType: checkedValue })
+    }, [data])
+    let submit = useCallback(() => {
+        if (data.users.some(user => isNaN(user))) {
+            message.error('账号请使用数字!!!!!!')
+            return
+        }
+        setLoading(true)
+        fetch(api+'/qq/auth', {
+            method: 'POST',
+            headers: {
+                "content-type": "application/json",
+            },
+            body: JSON.stringify(data)
+        }).then(res => res.json()).then(r => {
+            if (r?.data?.codeImgUrl) {
+                setCodeUrl(r?.data?.codeImgUrl)
+                setVisible(true)
+                let n=0
+                time = setInterval(() => {
+                    if(n< 60){
+                        n+=1
+                        fetch(`${api}/qq/isOk?userId=${localStorage.getItem('userId')}`, {
+                            method: 'GET'
+                        }).then(res => res.json()).then(r => {
+                            if (r.data) {
+                                setVisible(false)
+                                setCodeUrl("")
+                                clearInterval(time)
+                                setLoading(false)
+                            }
+                        })
+                    }else{
+                        message.error('扫码超时请重新扫码!')
+                        setVisible(false)
+                        setCodeUrl("")
+                        clearInterval(time)
+                        setLoading(false)
+                    }
+                   
+                }, 1000)
+            } else {
+                message.success('已经开始授权,稍后自行查看结果!')
+                setLoading(false)
+            }
+            console.log(r)
+        })
+    }, [data])
+    let query = () => {
+        fetch(`${api}/qq/queryErr?userId=${localStorage.getItem('userId')}`, {
+            method: 'GET'
+        }).then(res => res.json()).then(r => {
+            console.log(r)
+            setErr(r.data)
+        })
+    }
+    let del = () => {
+        fetch(`${api}/qq/delCookie?userId=${localStorage.getItem('userId')}`, {
+            method: 'GET'
+        }).then(res => res.json()).then(r => {
+            console.log(r)
+            message.success('清理成功!!!!请重新扫码授权登录!!!')
+        })
+    }
+    let userIdChange = useCallback((e) => {
+        let value = e.target.value
+        let arr = value.split(/,|,/)
+        let newArr = arr?.map((str: string) => Number(str.replace(/\s/ig, '')))
+        setData({ ...data, users: newArr })
+    }, [data])
+    return <Modal
+        visible={qqVisible}
+        footer={null}
+        width={800}
+        onCancel={callBack}
+        maskClosable={false}
+    >
+        <div>
+            <Row>
+                <Col span='24'>
+                    <Row>
+                        <Col span={3}><h3>平台选择:</h3></Col>
+                        <Col span={20}>
+                            <Radio.Group style={{ width: '100%' }} onChange={adAppIdonChange} defaultValue={data.adAppType}>
+                                <Radio value={0}>小说</Radio>
+                                <Radio value={1}>游戏</Radio>
+                            </Radio.Group>
+                        </Col>
+                    </Row>
+                </Col>
+                <Col span='24'>
+                    <Row>
+                        <Col span={3}><h3>账号ID:</h3></Col>
+                        <Col span={20}> <Input.TextArea placeholder='多个账号请以,号隔开例:123456,222333,444444' rows={5} onChange={userIdChange} allowClear></Input.TextArea></Col>
+                    </Row>
+                </Col>
+            </Row>
+            <Row style={{ display: 'flex', justifyContent: 'center', marginTop: 20 }}>
+                <Space>
+                    <Button type='primary' onClick={submit} loading={loading}>提交</Button>
+                    <Button type='default' onClick={query} >查询授权失败账号</Button>
+                    <Popconfirm title={'清除账号状态将清除所有失败记录,并清空上一次扫码授权状态!'} onConfirm={del} >
+                        <Button type='primary' danger >清除账号状态</Button>
+                    </Popconfirm>
+
+                </Space>
+            </Row>
+            <Row>
+                {
+                    Object.keys(err).map((key, i) => {
+                        return <Col key={i} span={24}>
+                            <div>
+                                <h4>{name[key]}</h4>
+                                <p>{err[key]?.join()}</p>
+                            </div>
+                        </Col>
+                    })
+                }
+            </Row>
+            <Modal
+                visible={visible}
+                footer={null}
+                width={200}
+                onCancel={() => setVisible(false)}
+                maskClosable={false}
+            >
+                <Image
+                    style={{ width: 150 }}
+                    src={codeUrl} />
+            </Modal>
+        </div>
+    </Modal>
+
+}
+export default QQAuth

+ 21 - 14
src/pages/launchSystemNew/adq/ad/index.tsx

@@ -16,10 +16,11 @@ import EarlyWarning from '@/components/EarlyWarning'
 import SetEarlyWarning from '@/components/EarlyWarning/setEarlyWarning'
 
 type Props = {
-    accountId: string,
-    adAccountId: string,
+    accountId?: string,
+    adAccountId?: string,
     userId: string,
-    queryParmas: {
+    Ts?: any,
+    queryParmas?: {
         accountId?: string,//账户ID
         campaignId?: string,//计划ID
         adgroupId?: string,//广告ID
@@ -27,7 +28,7 @@ type Props = {
         pageId?: string,//落地页ID
         targetingId?: string,//定向ID}
     },
-    tableIdClick: (props: {
+    tableIdClick?: (props: {
         activeKey: string, parma: {
             accountId?: string,//账户ID
             campaignId?: string,//计划ID
@@ -42,7 +43,7 @@ type Props = {
 const Ad: React.FC<Props> = (props) => {
 
     /***********************/
-    let { accountId, adAccountId, userId, tableIdClick, queryParmas } = props
+    let { accountId, adAccountId, userId, tableIdClick, queryParmas, Ts } = props
     const [selectedRows, setSelectedRows] = useState<any[]>([])
     const [update, setUpdate] = useState<{ visible: boolean, title: string }>({ visible: false, title: '' })
     const [model, setModel] = useState(true)
@@ -72,14 +73,14 @@ const Ad: React.FC<Props> = (props) => {
     /************************/
 
     useEffect(() => {
-        let { accountId, campaignId, adgroupId, ...obj } = queryParmas
-        let new_queryParmas = {
-            ...obj,
-            accountIdList: accountId ? [accountId] : [],
-            campaignIdList: campaignId ? [campaignId] : [],
-            adgroupIdList: adgroupId ? [adgroupId] : []
-        }
-        getList({ pageNum: 1, pageSize: 20, ...new_queryParmas, accountIdList: accountId ? [accountId] : [] })
+        // let { accountId, campaignId, adgroupId, ...obj } = queryParmas
+        // let new_queryParmas = {
+        //     ...obj,
+        //     accountIdList: accountId ? [accountId] : [],
+        //     campaignIdList: campaignId ? [campaignId] : [],
+        //     adgroupIdList: adgroupId ? [adgroupId] : []
+        // }
+        getList({ pageNum: 1, pageSize: 20 })
     }, [accountId, userId, queryParmas])
 
     // 获取列表
@@ -167,6 +168,7 @@ const Ad: React.FC<Props> = (props) => {
         putAdqAdgroupsSyncBatchApi.run({ adgroupIds: selectedRows?.map(item => item.adgroupId) }).then(res => {
             if (res) {
                 message.success('同步成功!')
+                listAjax.refresh()
             }
         })
     }, [selectedRows])
@@ -205,6 +207,9 @@ const Ad: React.FC<Props> = (props) => {
         {/* 复制广告 */}
         {copyData.visible && <Copy selectedRows={selectedRows} {...copyData} onClose={() => setCopyData({ visible: false })} onChange={() => { setCopyData({ visible: false }); listAjax.refresh(); setSelectedRows([]) }} />}
         <Row gutter={[6, 6]} align='middle' style={{ marginBottom: 15 }}>
+            <Col>
+                {Ts && Ts()}
+            </Col>
             <Col>
                 <Input
                     placeholder='广告账号'
@@ -358,7 +363,7 @@ const Ad: React.FC<Props> = (props) => {
         </Row>
         <TableData
             isCard={false}
-            columns={() => tableConfig(onChange, details, handleSave, tableIdClick)}
+            columns={() => tableConfig(onChange, details, handleSave)}
             ajax={listAjax}
             syncAjax={sync}
             fixed={{ left: 2, right: 4 }}
@@ -451,6 +456,8 @@ const Ad: React.FC<Props> = (props) => {
             onChange={(props: any) => {
                 let { sortData, pagination } = props
                 let { current, pageSize } = pagination
+                // console.log(pagination)
+                // console.log({...queryFrom, pageNum: current, pageSize })
                 set_queryFrom({ ...queryFrom, pageNum: current, pageSize })
                 getList({ ...queryFrom, pageNum: current, pageSize })
             }}

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

@@ -13,7 +13,7 @@ function tableConfig(
     onChange: () => void,
     details: (data: any) => void,
     handleSave: (data: any) => void,
-    tableIdClick: (props: {
+    tableIdClick?: (props: {
         activeKey: string,
         parma: {
             accountId?: string,//账户ID

+ 4 - 4
src/pages/launchSystemNew/adq/log/index.tsx

@@ -6,14 +6,14 @@ import TableData from "../../components/TableData"
 import tableConfig from "./tableConfig"
 
 type Props = {
-    accountId: string,
-    adAccountId: string,
+    accountId?: string,
+    adAccountId?: string,
     userId: string,
-    queryParmas: {
+    queryParmas?: {
         accountId?: string,//账户ID
         adgroupId?: string,//广告ID
     },
-    tableIdClick: (props: {
+    tableIdClick?: (props: {
         activeKey: string, parma: {
             accountId?: string,//账户ID
             campaignId?: string,//计划ID

+ 1 - 1
src/pages/launchSystemNew/adq/log/tableConfig.tsx

@@ -5,7 +5,7 @@ import React from "react"
 
 
 
-function tableConfig(tableIdClick: (props: {
+function tableConfig(tableIdClick?: (props: {
     activeKey: string, parma: {
         accountId?: string,//账户ID
         campaignId?: string,//计划ID

+ 2 - 2
src/services/api.ts

@@ -1,5 +1,5 @@
-export let api: any = process.env.NODE_ENV === 'development' ? 'api' : 'http://test.api.zanxiangwl.com'
-// export let api: any = process.env.NODE_ENV === 'development' ? 'api' : 'http://api.zanxiangwl.com'
+// export let api: any = process.env.NODE_ENV === 'development' ? 'api' : 'http://test.api.zanxiangwl.com/api'
+export let api: any = process.env.NODE_ENV === 'development' ? 'api' : 'http://api.zanxiangwl.com'
 export let dataApi: any = process.env.NODE_ENV === 'development' ? 'dapi' : `http://data.zanxiangnet.com`
 export let wxApi: any = process.env.NODE_ENV === 'development' ? 'wxapi' : `https://report.zanxiangwl.com`
 export let launchApi: any = `http://192.168.7.175:8018`