wjx hai 1 ano
pai
achega
90800cc66b

+ 0 - 3
src/components/EarlyWarning/ruleAccountLog.tsx

@@ -8,9 +8,6 @@ import { ruleAdLogTableConfig } from "./tableConfig"
 const OperationType = [
     { label: '告警', value: 0 },
     { label: '暂停广告', value: 1 },
-    { label: '启动广告', value: 2 },
-    { label: '增加预算', value: 3 },
-    { label: '减少预算', value: 4 },
     { label: '广告置顶标黄', value: 5 },
     { label: '广告置顶标红', value: 6 }
 ]

+ 1 - 4
src/components/EarlyWarning/ruleLog.tsx

@@ -8,13 +8,10 @@ import { ruleLogTableConfig } from "./tableConfig"
 export const OperationType = [
     { label: '告警', value: 0 },
     { label: '暂停广告', value: 1 },
-    { label: '启动广告', value: 2 },
-    { label: '增加预算', value: 3 },
-    { label: '减少预算', value: 4 },
     { label: '广告置顶标黄', value: 5 },
     { label: '广告置顶标红', value: 6 }
 ]
-export const OperationTypeObj = { 0: '告警', 1: '暂停广告', 2: '启动广告', 3: '增加预算', 4: '减少预算', 5: '广告置顶标黄', 6: '广告置顶标红' }
+export const OperationTypeObj = { 0: '告警', 1: '暂停广告', 5: '广告置顶标黄', 6: '广告置顶标红' }
 
 interface Props {
     ruleName: string,

+ 77 - 0
src/components/EarlyWarning/setEarlyWarningsAccount.tsx

@@ -0,0 +1,77 @@
+import { useAjax } from "@/Hook/useAjax"
+import { configRuleAccountApi } from "@/services/adMonitor/adMonitor"
+import { getSysWarningRuleListApi } from "@/services/adMonitor/earlyWarning"
+import { AlertOutlined } from "@ant-design/icons"
+import { Button, Form, message, Modal, Select } from "antd"
+import React, { useState } from "react"
+
+
+
+interface Props {
+    accountIds: any
+    onChange?: () => void
+}
+const SetEarlyWarningsAccount: React.FC<Props> = (props) => {
+
+    /******************************/
+    const { accountIds, onChange } = props
+    const [visible, setVisible] = useState<boolean>(false)
+    const [form] = Form.useForm();
+    const getSysWarningRuleList = useAjax((params) => getSysWarningRuleListApi(params))
+    const configRuleAccount = useAjax((params) => configRuleAccountApi(params), { formatResult: true })
+    /******************************/
+
+    const openModal = () => {
+        setVisible(true)
+        getSysWarningRuleList.run()
+    }
+
+    const handleOk = () => {
+        form.validateFields().then(values => {
+            configRuleAccount.run({ accountIds, ruleId: values.ruleId }).then(res => {
+                console.log(res)
+                if (res?.data) {
+                    message.success('设置成功')
+                    onChange?.()
+                    setVisible(false)
+                }
+            })
+        })
+    }
+
+    return <>
+        <Button icon={<AlertOutlined />} style={{ padding: 0, color: 'red' }} type="link" onClick={openModal}>设置预警</Button>
+        {visible && <Modal
+            visible={visible}
+            title="预警设置"
+            onOk={handleOk}
+            confirmLoading={configRuleAccount.loading}
+            onCancel={() => setVisible(false)}
+        >
+            <Form
+                form={form}
+                labelCol={{ span: 5 }}
+                colon={false}
+                initialValues={{
+
+                }}
+            >
+                <Form.Item name="ruleId" label={<strong>选择预警规则</strong>} rules={[{ required: true, message: '请选择预警规则' }]}>
+                    <Select
+                        showSearch
+                        allowClear
+                        placeholder="选择预警规则"
+                        filterOption={(input, option) =>
+                            ((option?.label ?? '') as any).toLowerCase().includes(input.toLowerCase())
+                        }
+                    >
+                        {getSysWarningRuleList?.data?.filter((item: any) => !item?.defaultRule)?.map((item: any) => <Select.Option value={item.id} key={item.id}>{item.ruleName}</Select.Option>)}
+                    </Select>
+                </Form.Item>
+            </Form>
+        </Modal>}
+    </>
+}
+
+
+export default React.memo(SetEarlyWarningsAccount)

+ 10 - 0
src/components/Tables/index.less

@@ -51,4 +51,14 @@
     cursor: col-resize;
     z-index: 1;
     border-left: white 1px solid;
+}
+
+
+
+.row_error>td {
+    background-color: rgb(255, 207, 207);
+}
+
+.row_warning>td {
+    background-color: rgb(255, 234, 202);
 }

+ 1 - 12
src/components/Tables/index.tsx

@@ -1,7 +1,6 @@
 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';
@@ -67,7 +66,7 @@ interface Props {
 
 function Tables(props: Props) {
     // //导出数据
-    let { columns, dataSource, excle, total, handelResize, columnWidth, 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, columnWidth, rowSelection, onRow, isShowTotal = true, hideOnSinglePage, className, expandedRowRender, scroll, summary, showHeader, bordered, size = 'small', onChange, sortDirections, pagination, myKey, ...prop } = props
     let handleExcle = () => {
         if (dataSource.length < 1) {
             message.error('请先搜索再导出');
@@ -172,16 +171,6 @@ function Tables(props: Props) {
                 }
             }
             {...prop}
-            {...{
-                rowClassName: typeof rowClassName === 'string' ? (record: any) => {
-                    if (rowClassName && record[rowClassName as string] === 2) {
-                        return style.unfollow
-                    }
-                    if (rowClassName && !record[rowClassName as string]) {
-                        return style.unfollow
-                    }
-                } : rowClassName
-            }}
         />
     </div>
 }

+ 10 - 8
src/pages/adMonitor/adMonitorList/components/FilterQuery.tsx

@@ -23,6 +23,8 @@ interface Props {
  */
 const FilterQuery: React.FC<Props> = ({ onChange }) => {
 
+    const [queryForm, setQueryForm] = useState<any>({})
+
     const queryList: QueryProps[] = [
         {
             lable: '广告创建时间',
@@ -30,12 +32,6 @@ const FilterQuery: React.FC<Props> = ({ onChange }) => {
             type: 'DatePicker',
             value: (params) => <DatePicker.RangePicker {...params} />
         },
-        {
-            lable: '广告名称',
-            name: 'adgroupName',
-            type: 'Input',
-            value: (params) => <Input placeholder="请输入广告名称" {...params} />
-        },
         {
             lable: '最低今日转化数',
             name: 'conversionsCountDayMin',
@@ -124,11 +120,17 @@ const FilterQuery: React.FC<Props> = ({ onChange }) => {
             newAllValue.adCreateTimeMax = moment(newAllValue?.adCreateTime[1]).format('YYYY-MM-DD')
             delete newAllValue?.adCreateTime
         }
-        onChange?.(newAllValue)
+        onChange?.({ ...newAllValue, ...queryForm })
     }
 
     return <div id="filterQueryContent">
         <div style={{ width: '100%', display: 'flex', gap: 8 }}>
+            <Input
+                placeholder="请输入广告名称"
+                allowClear
+                value={queryForm?.adgroupName}
+                onChange={(e) => setQueryForm({ ...queryForm, adgroupName: e.target.value })}
+            />
             <Popover
                 visible={visible}
                 content={<div style={{ width: 500, height: 400, overflowY: 'auto', padding: '10px 16px' }}>
@@ -168,7 +170,7 @@ const FilterQuery: React.FC<Props> = ({ onChange }) => {
             <Button type="primary" onClick={onFinish} icon={<SearchOutlined />}>搜索</Button>
             <Button onClick={() => {
                 form.resetFields();
-                onFinish()
+                setQueryForm({})
             }}>重置</Button>
         </div>
         {filterTrueList.length > 0 && <div className="selectedFilter">

+ 23 - 4
src/pages/adMonitor/adMonitorList/components/TabAd.tsx

@@ -27,7 +27,7 @@ const TabAd: React.FC<Props> = ({ accountId, adgroupId }) => {
     const [logVisible, setLogVisible] = useState<boolean>(false)
     const [ruleId, setrRleId] = useState<number>(0)
     const [ruleName, setrRuleName] = useState<string>('')
-    
+
     const getAdgroupsDetails = useAjax((params) => getAdgroupsDetailsApi(params), { formatResult: true })
     const delAdWarningRule = useAjax((params) => delAdWarningRuleApi(params), { formatResult: true })
     const addAdToRuleBlackList = useAjax((params) => addAdToRuleBlackListApi(params), { formatResult: true })
@@ -138,7 +138,7 @@ const TabAd: React.FC<Props> = ({ accountId, adgroupId }) => {
                     dataSource={data[key]}
                     leftChild={<Space>
                         <strong>{EWTypeEnum[key]}</strong>
-                        {key === 'ADGROUP' && <SetEarlyWarnings  accountId={accountId} adgroupId={adgroupId} onChange={() => getAdgroupsDetails.refresh()}/>}
+                        {key === 'ADGROUP' && <SetEarlyWarnings accountId={accountId} adgroupId={adgroupId} onChange={() => getAdgroupsDetails.refresh()} />}
                     </Space>}
                     loading={getAdgroupsDetails?.loading}
                     total={getAdgroupsDetails?.data?.data?.length}
@@ -146,7 +146,26 @@ const TabAd: React.FC<Props> = ({ accountId, adgroupId }) => {
                 />
             </Card>)
         }
-        return <Empty image={Empty.PRESENTED_IMAGE_SIMPLE} />
+        return <Card
+            hoverable
+            style={{ width: '100%' }}
+            bodyStyle={{ padding: 16 }}
+        >
+            <TableData
+                size="small"
+                isCard={false}
+                columns={() => tableConfigEw('ADGROUP', addBlack, remove, removeBlack, log)}
+                ajax={getAdgroupsDetails}
+                dataSource={[]}
+                leftChild={<Space>
+                    <strong>{EWTypeEnum['ADGROUP']}</strong>
+                    <SetEarlyWarnings accountId={accountId} adgroupId={adgroupId} onChange={() => getAdgroupsDetails.refresh()} />
+                </Space>}
+                loading={getAdgroupsDetails?.loading}
+                total={getAdgroupsDetails?.data?.data?.length}
+                gutter={[0, 10]}
+            />
+        </Card>
     }, [getAdgroupsDetails?.data?.data, getAdgroupsDetails.loading])
 
     return <Space style={{ width: '100%' }} direction="vertical">
@@ -168,7 +187,7 @@ const TabAd: React.FC<Props> = ({ accountId, adgroupId }) => {
         </Card>
         {EWContent}
 
-        {logVisible && <RuleLog ruleName={ruleName} ruleId={ruleId} visible={logVisible} onClose={() => setLogVisible(false)}/>}
+        {logVisible && <RuleLog ruleName={ruleName} ruleId={ruleId} visible={logVisible} onClose={() => setLogVisible(false)} />}
     </Space>
 }
 

+ 5 - 1
src/pages/launchSystemNew/account/index.tsx

@@ -18,6 +18,7 @@ import { useModel } from 'umi'
 import ChangeRecord from './changeRecord'
 import CheckAccount from './checkAccount'
 import AppointPut from './appointPut'
+import SetEarlyWarningsAccount from '@/components/EarlyWarning/setEarlyWarningsAccount'
 
 /** 投放管理 */
 const AdAuthorize: React.FC = () => {
@@ -199,7 +200,10 @@ const AdAuthorize: React.FC = () => {
                         <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={() => { checkAccount(selectAccData) }}>批量切号</Button>
+                                <SetEarlyWarningsAccount onChange={() => { setSelectAccData([]); }} accountIds={selectAccData.map(item => item.accountId)?.toString()}/>
+                            </>) :
                             switchType === 'putUser' ? (selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { putUserHandle(selectAccData) }}>批量指派投放助理</Button>) :
                                 selectAccData?.length > 0 && <Button type="primary" ghost icon={<SwapOutlined />} onClick={() => { setOpenServer(selectAccData) }}>批量配置服务商</Button>
                         }

+ 11 - 0
src/pages/launchSystemNew/account/tableConfig.tsx

@@ -78,6 +78,17 @@ export function columnsMp(edit: (params: any) => void, setOpenServer: (data: any
             width: 100,
             ellipsis: true,
         },
+        {
+            title: '告警名称',
+            dataIndex: 'warningRuleList',
+            key: 'warningRuleList',
+            align: 'center',
+            width: 90,
+            ellipsis: true,
+            render: (a: any[], b: any) => {
+                return a?.length > 0 ? a?.[0]?.ruleName: '--'
+            }
+        },
         // {
         //     title: '公众号信息',
         //     dataIndex: 'wechatAccountName',

+ 17 - 9
src/pages/launchSystemNew/adq/ad/FilterQuery.tsx

@@ -85,12 +85,12 @@ const FilterQuery: React.FC<Props> = ({ onChange, initialValues, queryForm, setQ
             type: 'Input',
             value: (params) => <Input placeholder="请输入广告账号(多个,隔开)" style={{ width: '100%' }} {...params} />
         },
-        {
-            lable: '广告名称',
-            name: 'adgroupName',
-            type: 'Input',
-            value: (params) => <Input placeholder="请输入广告名称" style={{ width: '100%' }} {...params} />
-        },
+        // {
+        //     lable: '广告名称',
+        //     name: 'adgroupName',
+        //     type: 'Input',
+        //     value: (params) => <Input placeholder="请输入广告名称" style={{ width: '100%' }} {...params} />
+        // },
         // {
         //     lable: '广告ID',
         //     name: 'adgroupIdStr',
@@ -280,7 +280,7 @@ const FilterQuery: React.FC<Props> = ({ onChange, initialValues, queryForm, setQ
             <Select
                 showSearch
                 maxTagCount={1}
-                style={{ minWidth: 140 }}
+                style={{ width: 100 }}
                 allowClear
                 mode="multiple"
                 placeholder="请选择投手"
@@ -299,11 +299,18 @@ const FilterQuery: React.FC<Props> = ({ onChange, initialValues, queryForm, setQ
                     </Select.Option>
                 )}
             </Select>
+            <Input
+                placeholder="请输入广告名称"
+                allowClear
+                style={{ width: 140 }}
+                value={queryForm?.adgroupName}
+                onChange={(e) => setQueryForm({ ...queryForm, adgroupName: e.target.value })}
+            />
             <Select
                 placeholder='广告状态'
                 mode="multiple"
                 maxTagCount={1}
-                style={{ minWidth: 140 }}
+                style={{ width: 130 }}
                 showSearch
                 filterOption={(input: any, option: any) =>
                     (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
@@ -321,7 +328,7 @@ const FilterQuery: React.FC<Props> = ({ onChange, initialValues, queryForm, setQ
             <Input placeholder="请输入广告ID(多个,隔开)" style={{ width: 140 }} value={queryForm.adgroupIdStr} onChange={(e) => setQueryForm({ ...queryForm, adgroupIdStr: e.target.value, pageNum: 1 })} />
             <Select
                 placeholder='已删除?'
-                style={{ minWidth: 130 }}
+                style={{ width: 90 }}
                 showSearch
                 allowClear
                 filterOption={(input: any, option: any) =>
@@ -402,6 +409,7 @@ const FilterQuery: React.FC<Props> = ({ onChange, initialValues, queryForm, setQ
             <Button type="primary" onClick={onFinish} icon={<SearchOutlined />}>搜索</Button>
             <Button onClick={() => {
                 form.resetFields();
+                setQueryForm({ pageNum: 1, pageSize: 20, columns: [], isDeleted: false })
                 onFinish()
             }}>重置</Button>
         </div>

+ 40 - 2
src/pages/launchSystemNew/adq/ad/adPlanList.tsx

@@ -3,7 +3,7 @@ import { useAjax } from '@/Hook/useAjax'
 import { Col, Row, message, Space, Button, Switch, notification, Modal, Tooltip, Dropdown, Menu } from 'antd'
 import React, { useEffect, useCallback, useState, useRef } from 'react'
 import TableData from '../../components/TableData'
-import { putAdqAdgroupsSync, delListAdqAdgroupsApi, newEditAdqAdgroupsDataApi, editAdqAdgroupsDataApi, putAdqAdgroupsSyncBatch, putModifyCustomAudienceApi, getPutUserApi } from '@/services/launchAdq/adq'
+import { putAdqAdgroupsSync, delListAdqAdgroupsApi, newEditAdqAdgroupsDataApi, editAdqAdgroupsDataApi, putAdqAdgroupsSyncBatch, putModifyCustomAudienceApi, getPutUserApi, delUserTagApi } from '@/services/launchAdq/adq'
 import { CopyOutlined, DeleteOutlined, DownOutlined, ExclamationCircleOutlined, FieldTimeOutlined, FormOutlined, PauseCircleOutlined, PlayCircleOutlined, QuestionCircleOutlined, SyncOutlined, TransactionOutlined } from '@ant-design/icons'
 import UpdateAd from './updateAd'
 import Copy from './copy'
@@ -19,6 +19,7 @@ import Details from '@/pages/adMonitor/adMonitorList/components/Details'
 import AdExpandedRowRender from './adExpandedRowRender'
 import { useSize } from 'ahooks'
 import RuleAccountLog from '@/components/EarlyWarning/ruleAccountLog'
+import PlanTag from './planTag'
 
 const AdPlanList: React.FC<{ userId: string }> = (props) => {
 
@@ -43,12 +44,16 @@ const AdPlanList: React.FC<{ userId: string }> = (props) => {
     const putModifyCustomAudience = useAjax((params) => putModifyCustomAudienceApi(params))
     const putAdqAdgroupsSyncBatchApi = useAjax((params) => putAdqAdgroupsSyncBatch(params))
     const getPutUser = useAjax((params) => getPutUserApi(params))
+    const delUserTag = useAjax((params) => delUserTagApi(params))
 
     const [logVisible, setLogVisible] = useState<boolean>(false)
     const [adgroupId, setAdgroupId] = useState<string>('')
     const [adgroupName, setAdgroupName] = useState<string>('')
     const [accountIdRule, setAccountIdRule] = useState<string>('')
 
+    const [tagVisible, setTagVisible] = useState<boolean>(false)
+    const [tagData, setTagData] = useState<any>({})
+
     const configName = '广告列表New'
     const ref = useRef(null)
     const size = useSize(ref)
@@ -250,7 +255,31 @@ const AdPlanList: React.FC<{ userId: string }> = (props) => {
         setLogVisible(true)
     }
 
+    const handleTag = (value: any) => {
+        setTagData(value)
+        setTagVisible(true)
+    }
+
+    const delTag = (value: any) => {
+        delUserTag.run({ accountId: value.account_id, adgroupId: value.adgroup_id }).then(res => {
+            if (res) {
+                message.success('删除成功')
+                getAdList.refresh()
+            }
+        })
+    }
+
     return <div>
+        {/* 打标签 */}
+        {tagVisible && <PlanTag
+            visible={tagVisible}
+            data={tagData}
+            onClose={() => setTagVisible(false)}
+            onChange={() => {
+                getAdList.refresh()
+                setTagVisible(false)
+            }}
+        />}
         {/* 修改广告 */}
         {update.visible && <UpdateAd
             {...update}
@@ -278,7 +307,7 @@ const AdPlanList: React.FC<{ userId: string }> = (props) => {
                 refreshData={getList}
                 isCard={false}
                 className='expendTable'
-                columns={() => tablePlanConfig(onChange, details, handleSave, handleSaveDaily, log)}
+                columns={() => tablePlanConfig(onChange, details, handleSave, handleSaveDaily, log, handleTag, delTag)}
                 ajax={getAdList}
                 syncAjax={sync}
                 fixed={{ left: 2, right: 4 }}
@@ -292,6 +321,15 @@ const AdPlanList: React.FC<{ userId: string }> = (props) => {
                 gutter={[0, 10]}
                 config={planAdConfig}
                 configName={configName}
+                rowClassName={(record) => {
+                    if (record?.tag_value === 100) {
+                        return 'row_error'
+                    }else if (record?.tag_value === 90) {
+                        return 'row_warning'
+                    } else {
+                        return ''
+                    }
+                }}
                 leftChild={<Space direction='vertical'>
                     <Row gutter={[10, 10]} align='middle'>
                         <Col>

+ 3 - 2
src/pages/launchSystemNew/adq/ad/index.tsx

@@ -71,7 +71,7 @@ const Ad: React.FC<Props> = (props) => {
         remarkList?: any[]
         optimizationGoal?: string,
         putUserIdList?: number[]
-    }>({ pageNum: 1, pageSize: 20 })
+    }>({ pageNum: 1, pageSize: 20, isDeleted: false })
     const listAjax = useAjax((params) => getAdqAdgroupsList(params), { formatResult: true })
     const syncAjax = useAjax((adAccountId) => putAdqAdgroupsSync(adAccountId))
     const delListAdqAdgroups = useAjax((params) => delListAdqAdgroupsApi(params))
@@ -94,7 +94,7 @@ const Ad: React.FC<Props> = (props) => {
         //     campaignIdList: campaignId ? [campaignId] : [],
         //     adgroupIdList: adgroupId ? [adgroupId] : []
         // }
-        getList({ pageNum: 1, pageSize: 20 })
+        getList({ pageNum: 1, pageSize: 20, isDeleted: false })
     }, [accountId, userId, queryParmas, model])
 
     // 获取列表
@@ -356,6 +356,7 @@ const Ad: React.FC<Props> = (props) => {
                         (option!.children as unknown as string).toLowerCase().includes(input.toLowerCase())
                     }
                     allowClear
+                    value={queryFrom?.isDeleted}
                     onChange={(value: any) => {
                         set_queryFrom({ ...queryFrom, isDeleted: value })
                     }}

+ 65 - 0
src/pages/launchSystemNew/adq/ad/planTag.tsx

@@ -0,0 +1,65 @@
+import { useAjax } from "@/Hook/useAjax"
+import { adUserTagApi } from "@/services/launchAdq/adq"
+import { Form, Input, Modal, Select, message } from "antd"
+import React from "react"
+
+
+
+interface Props {
+    data: any,
+    visible?: boolean
+    onClose?: () => void
+    onChange?: () => void
+}
+const PlanTag: React.FC<Props> = ({ data, visible, onClose, onChange }) => {
+
+    /******************************/
+    const [form] = Form.useForm();
+    const adUserTag = useAjax((params) => adUserTagApi(params))
+    /******************************/
+
+    const handleOk = () => {
+        form.validateFields().then(values => {
+            adUserTag.run({ ...values, accountId: data.account_id, adgroupId: data.adgroup_id }).then(res => {
+                if (res) {
+                    onChange?.()
+                    message.success('打标记成功')
+                }
+            })
+        })
+    }
+
+    return <Modal
+        title={`${data.adgroup_name} 打标记`}
+        visible={visible}
+        onCancel={onClose}
+        onOk={handleOk}
+        confirmLoading={adUserTag.loading}
+    >
+        <Form
+            form={form}
+            labelCol={{ span: 4 }}
+            className='ad_form_style'
+            colon={false}
+            name="DBJ"
+            labelAlign="left"
+            initialValues={{
+
+            }}
+        >
+            <Form.Item label={<strong>类型</strong>} name='tagValue' rules={[{ required: true, message: '请选择打标签类型' }]}>
+                <Select
+                    placeholder={'请选择打标签类型'}
+                >
+                    <Select.Option value={90}>警告</Select.Option>
+                    <Select.Option value={100}>异常</Select.Option>
+                </Select>
+            </Form.Item>
+            <Form.Item label={<strong>备注</strong>} name='tagRemark' rules={[{ required: true, message: '请输入打标签备注' }]}>
+                <Input placeholder="请输入打标签备注"/>
+            </Form.Item>
+        </Form>
+    </Modal>
+}
+
+export default React.memo(PlanTag)

+ 24 - 5
src/pages/launchSystemNew/adq/ad/tablePlanListConfig.tsx

@@ -1,6 +1,6 @@
 import { AdStatusEnum, BidModeEnum, BidStrategyEnum, OptimizationGoalEnum, PromotedObjectType } from '@/services/launchAdq/enum'
 import React from 'react'
-import { Badge, Popover, Space, Statistic } from 'antd'
+import { Badge, Dropdown, Menu, Popover, Space, Statistic } from 'antd'
 import Box from '@/pages/adMonitor/adMonitorList/components/box'
 import SwitchStatus from './switchStatus'
 import TimeSeriesLook from './timeSeriesLook'
@@ -10,12 +10,15 @@ import { copy } from '@/utils/utils'
 import InputUpdate from './inputUpdate'
 import { ColumnsType } from 'antd/lib/table'
 import StatisticNull from '@/components/StatisticNull'
+import { DownOutlined } from '@ant-design/icons'
 function tablePlanConfig(
     onChange: () => void,
     details: (data: any) => void,
     handleSave: (data: any) => void,
     handleSaveDaily: (data: any) => void,
-    log: (data: any) => void
+    log: (data: any) => void,
+    handleTag: (data: any) => void,
+    delTag: (data: any) => void,
 ): ColumnsType<any> {
 
     let adArr: ColumnsType<any> = [
@@ -161,7 +164,6 @@ function tablePlanConfig(
             width: 70,
             align: 'center',
             ellipsis: true,
-            sorter: true,
             render: (a: string, b: { deep_conversion_spec_json: any }) => {
                 if (b?.deep_conversion_spec_json) {
                     return JSON.parse(b?.deep_conversion_spec_json)?.deepConversionWorthSpec?.expectedRoi || '--'
@@ -262,6 +264,17 @@ function tablePlanConfig(
                 return <Box b={b?.creative_preivew} />
             }
         },
+        {
+            title: '标记备注',
+            dataIndex: 'tag_remark',
+            key: 'tag_remark',
+            align: 'center',
+            width: 100,
+            ellipsis: true,
+            render(value, record, index) {
+                return value || '--'
+            },
+        },
         {
             title: '广告详情',
             dataIndex: 'cost_speed',
@@ -279,11 +292,17 @@ function tablePlanConfig(
             title: '操作',
             dataIndex: 'cz',
             key: 'cz',
-            width: 150,
+            width: 130,
             align: 'center',
             render: (a: any, b: any) => {
                 return <Space>
-                    <a onClick={() => log(b)}>告警日志</a>
+                    <Dropdown overlay={<Menu>
+                        <Menu.Item><a onClick={() => log(b)}>告警日志</a></Menu.Item>
+                        <Menu.Item><a onClick={() => handleTag(b)}>打标记</a></Menu.Item>
+                        {b?.tag_value ? <Menu.Item><a style={{ color: 'red' }} onClick={() => delTag(b)}>删除标记</a></Menu.Item> : undefined}
+                    </Menu>}>
+                        <a><Space size={2}>更多 <DownOutlined /></Space></a>
+                    </Dropdown>
                     <a style={{ color: '#1890ff' }} onClick={() => window.open(`https://ad.qq.com/atlas/${b?.account_id}/admanage/adgroup?tab=adgroup&query={%22operation_status%22:[%22CALCULATE_STATUS_EXCLUDE_DEL%22],%22system_status%22:[],%22search_name%22:%22${b.adgroup_id}%22}`)} target="_blank">腾讯广告</a>
                 </Space>
             }

+ 2 - 1
src/pages/launchSystemNew/adq/config.ts

@@ -57,7 +57,8 @@ const planAdConfig = [
             { title: '广告状态', dataIndex: 'status', serverIndex: 'adgroups.status', label: '广告详情', default: 21, width: 70 },
             { title: '创意预览', dataIndex: 'creative_id', serverIndex: 'adgroup_data.creative_id', label: '广告详情', default: 22, width: 70 },
             { title: '广告详情', dataIndex: 'cost_speed', label: '广告详情', default: 23, width: 80 },
-            { title: '操作', dataIndex: 'cz', label: '广告详情', default: 24, width: 136 },
+            { title: '标记备注', dataIndex: 'tag_remark', label: '广告详情', width: 80, serverIndex: 'adgroup_user_tag.tag_remark' },
+            { title: '操作', dataIndex: 'cz', label: '广告详情', default: 24, width: 116 },
         ]
     },
     {

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

@@ -49,11 +49,12 @@ interface Prosp {
     gutter?: any
     isCard?: boolean
     totalData?: any[]
-    refreshData?: () => void
+    refreshData?: () => void,
+    rowClassName?: string | ((record: any, index: any) => string),//样式
 }
 
 function TableData(props: Prosp) {
-    const { isZj, scroll, columns, title, columnWidth, dataSource, totalData = [], refreshData, expandedRowRender, className, isCard = true, leftChild, page = undefined, rowSelection = false, pageSize = undefined, size = 'small', fixed = { left: 0, right: 1 }, total = 0, onChange, config, configName, ajax, syncAjax, hoverable = true, myKey, gutter = [0, 20] } = props
+    const { isZj, scroll, columns, title, columnWidth, rowClassName, dataSource, totalData = [], refreshData, expandedRowRender, className, isCard = true, leftChild, page = undefined, rowSelection = false, pageSize = undefined, size = 'small', fixed = { left: 0, right: 1 }, total = 0, 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)
@@ -267,11 +268,11 @@ function TableData(props: Prosp) {
             >
                 <Row gutter={gutter}>
                     {header}
-                    <Tab {...{ size, newColumns, handelResize, columnWidth, className, isZj, totalData, rowSelection, columns, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
+                    <Tab {...{ size, newColumns, rowClassName, handelResize, columnWidth, className, isZj, totalData, rowSelection, columns, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
                 </Row>
             </Card> : <Row gutter={gutter}>
                 {header}
-                <Tab {...{ size, newColumns, handelResize, className, isZj, columnWidth, totalData, rowSelection, columns, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
+                <Tab {...{ size, newColumns, rowClassName, handelResize, className, isZj, columnWidth, totalData, rowSelection, columns, scroll, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey }} />
             </Row>}
         </Col>
     </Row >
@@ -282,7 +283,7 @@ function TableData(props: Prosp) {
 
 /**表格 */
 const Tab = React.memo((props: any) => {
-    const { size, newColumns, className, handelResize, isZj, columns, scroll, columnWidth, totalData, rowSelection, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey } = props
+    const { size, newColumns, rowClassName, className, handelResize, isZj, columns, scroll, columnWidth, totalData, rowSelection, isFell, page, pageSize, dataSource, onChange, expandedRowRender, total, ajax, myKey } = props
     let ran = Math.ceil(Math.random() * 100)
 
     useEffect(() => {
@@ -342,7 +343,7 @@ const Tab = React.memo((props: any) => {
                 dataSource={dataSource}
                 scroll={scroll ? isFell ? { ...scroll, y: document.body.clientHeight - 300 } : scroll : {}}
                 onChange={(pagination: any, filters: any, sorter: any) => onChange && onChange({ pagination, filters, sortData: sorter })}
-                rowClassName={(record: { color: string }) => style[record['color']]}
+                rowClassName={rowClassName}
                 columnWidth={columnWidth}
                 expandedRowRender={expandedRowRender ? expandedRowRender : undefined}
                 size={size}

+ 12 - 0
src/services/adMonitor/adMonitor.ts

@@ -469,4 +469,16 @@ export async function configAdWarningRuleApi({ accountId, adgroupId, ruleIds }:
     return request(`${api}/adq/sysWarningRule/configRuleAdgroup/${accountId}/${adgroupId}/${ruleIds}`, {
         method: 'PUT'
     })
+}
+
+
+/**
+ * 配置账号下告警
+ * @param param0 
+ * @returns 
+ */
+export async function configRuleAccountApi({ accountIds, ruleId }: { accountIds: string, ruleId: string }) {
+    return request(`${api}/adq/sysWarningRule/configRuleAccount/${accountIds}/${ruleId}`, {
+        method: 'PUT'
+    })
 }

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

@@ -416,4 +416,33 @@ export async function putConfigStatusApi(data: { list: string, configuredStatus:
   return request(api + `/adq/campaign/configStatus/${data.list}/${data.configuredStatus}`, {
     method: 'PUT'
   });
+}
+
+export interface AduserTagProps {
+  accountId: string,
+  adgroupId: string,
+  tagValue: number
+  tagRemark: string
+}
+/**
+ * 打标记
+ * @param data 
+ * @returns 
+ */
+export async function adUserTagApi(data: AduserTagProps) {
+  return request(api + `/tencentMonitor/adUserTag/doTag`, {
+    method: 'POST',
+    data
+  });
+}
+
+/**
+ * 删除标记
+ * @param data 
+ * @returns 
+ */
+export async function delUserTagApi(data: {accountId: string, adgroupId: string}) {
+  return request(api + `/tencentMonitor/adUserTag/removeTag/${data.accountId}/${data.adgroupId}`, {
+    method: 'DELETE'
+  });
 }