朱鑫波 4 éve
szülő
commit
2c5a3e5be4

+ 5 - 1
src/config/router.config.js

@@ -77,7 +77,11 @@ export const constantRouterMap = [
       }
     ]
   },
-
+  {
+    path: '/creat-config',
+    name: 'creatConfig',
+    component: () => import(/* webpackChunkName: "fail" */ '@/views/modules/autoLaunch/configProject/creatConfig')
+  },
 
   {
     path: '/test',

+ 1 - 1
src/permission.js

@@ -10,7 +10,7 @@ import { generateIndexRouter } from "@/utils/util"
 NProgress.configure({ showSpinner: false }) // NProgress Configuration
 
 
-const whiteList = ['/user/login', '/user/register', '/user/register-result', '/user/alteration', '/user/transfer-local', '/errorPage', '/user/new-batch', '/user/lookPreview', 'http://192.168.0.111:8088/jeecg-boot/sys/feishu/url', '/user/FStransfer'] // no redirect whitelist
+const whiteList = ['/user/login', '/user/register', '/user/register-result', '/user/alteration', '/user/transfer-local', '/errorPage', '/user/new-batch', '/user/lookPreview', 'http://192.168.0.111:8088/jeecg-boot/sys/feishu/url', '/user/FStransfer','/creat-config'] // no redirect whitelist
 
 router.beforeEach((to, from, next) => {
   NProgress.start() // start progress bar

+ 1 - 1
src/views/modules/autoLaunch/configLaunchInfo.vue

@@ -1182,7 +1182,7 @@
                                 </a-input>
                                 <span style="margin-left:5px">元</span>
                                 <br>
-                                <span style="color:red">单出价请输入单数字,阶梯出价请用/隔开</span>
+                                <span style="color:red">单出价请输入单数字,阶梯出价请用/隔开 例如10/12,区间出价请用-链接 例如20-25</span>
                             </a-form-item>
                                 <span
                                 class="tip"

+ 4 - 203
src/views/modules/autoLaunch/configProject/configProject-service.js

@@ -1,212 +1,13 @@
 /**
- * @file 人群包管理基础服务
- * @author jiayufei(jiayufei@c-top.com.cn)
+ * @file 项目配置列表
+ * @author zhuxinbo(zhuxinbo@c-top.com.cn)
  */
 
- class AppMarketService {
-    constructor() {}
+class AppMarketService {
+    constructor() { }
 
-    // 相关账户的table列表
-    setAcountColumns() {
-        return [
-            {
-                title: '账户名称',
-                dataIndex: 'authName',
-                width: '50%',
-                align: 'center'
-            },
-            {
-                title: '编辑',
-                dataIndex: 'action',
-                scopedSlots: {customRender: 'action'},
-                width: '50%',
-                align: 'center'
-            }
-        ]
-    }
 
-    // 原因的table列表
-    setCauseColumns() {
-        return [
-            {
-                title: '账户名称',
-                dataIndex: 'authName',
-                width: '25%',
-                align: 'center'
-            },
-            {
-                title: '推送结果',
-                dataIndex: 'result',
-                width: '25%',
-                align: 'center'
-            },
-            {
-                title: '失败原因',
-                dataIndex: 'message',
-                width: '25%',
-                align: 'center',
-                customRender(t) {
-                    if(t === 'OK') {
-                        return '-';
-                    }
-                    else {
-                        return t;
-                    }
-                }
-            },
-            {
-                title: '操作',
-                dataIndex: 'action',
-                scopedSlots: {customRender: 'action'},
-                width: '25%',
-                align: 'center'
-            }
-        ]
-    }
 
-    // 相关项目的table列表
-    setDepColumns() {
-        return [
-            {
-                title: '广告组名称',
-                dataIndex: 'unitName',
-                width: '50%',
-                align: 'center'
-            },
-            {
-                title: '所属账户',
-                dataIndex: 'authName',
-                width: '50%',
-                align: 'center'
-            }
-        ]
-    }
-
-    // 状态枚举
-    setPlatform() {
-        return [
-            {
-                label: 0,
-                value: '不限'
-            },
-            {
-                label: 1,
-                value: 'Android'
-            },
-            {
-                label: 2,
-                value: 'IOS'
-            }
-        ]
-    }
-
-    // 上传人去报的校验规则
-    setPersonRules() {
-        return {
-            name: [
-                {required: true, message: '人群包名称不能为空', trigger: 'blur'},
-                {min: 1, max: 20, message: '人群包名称不能超过20个字符', trigger: 'blur'}
-            ],
-            resource: [
-                {required: true, message: '请选择匹配类型', trigger: 'change'}
-            ]
-        }
-    }
-
-    // 人群包类型枚举值
-    setPopulationTypeTasks() {
-        return [
-            {
-                label: 1,
-                value: '上传人群'
-            }, {
-                label: 2,
-                value: '广告人群'
-            }, {
-                label: 3,
-                value: '主题专区'
-            }, {
-                label: 4,
-                value: '逻辑规则'
-            }, {
-                label: 5,
-                value: '人群扩展'
-            }, {
-                label: 6,
-                value: '平台制定'
-            }, {
-                label: 7,
-                value: '定制付费'
-            }, {
-                label: 8,
-                value: '网红粉丝类别'
-            }, {
-                label: 9,
-                value: '内容付费行为'
-            }, {
-                label: 10,
-                value: '移动应用安装'
-            }, {
-                label: 11,
-                value: '快手使用活跃度'
-            }, {
-                label: 12,
-                value: '行业分类'
-            }, {
-                label: 13,
-                value: '商业兴趣'
-            }, {
-                label: 14,
-                value: '固话标签'
-            }, {
-                label: 15,
-                value: '行业偏好'
-            }, {
-                label: 16,
-                value: '第三方标签'
-            }, {
-                label: 17,
-                value: '产品关键词'
-            }, {
-                label: 19,
-                value: '应用渗透率'
-            }, {
-                label: 22,
-                value: '指定网红'
-            }, {
-                label: 23,
-                value: '行业分类'
-            }
-        ]
-    }
-
-    // 匹配类型枚举值
-    setMateTypeTasks() {
-        return [
-            {
-                label: 1,
-                value: 'IMEI'
-            }, {
-                label: 2,
-                value: 'IDFA'
-            }, {
-                label: 3,
-                value: 'IMEI_MD5'
-            }, {
-                label: 4,
-                value: 'IDFA_MD5'
-            }, {
-                label: 5,
-                value: '手机号-MD5'
-            }, {
-                label: 7,
-                value: 'OAID'
-            }, {
-                label: 8,
-                value: 'OAID_MD5'
-            }
-        ]
-    }
 
 }
 

A különbségek nem kerülnek megjelenítésre, a fájl túl nagy
+ 1069 - 0
src/views/modules/autoLaunch/configProject/creatConfig.vue


+ 305 - 13
src/views/modules/autoLaunch/configProject/index.vue

@@ -171,6 +171,9 @@
             <a-tabs v-model="tabKey" @change="tabChange">
                 <a-tab-pane :key="1" tab="项目"> </a-tab-pane>
                 <a-tab-pane :key="2" tab="账户"> </a-tab-pane>
+                <a-button slot="tabBarExtraContent" type="primary" @click="newCreat(null)">
+                    创建投放策略
+                </a-button>
             </a-tabs>
         </div>
         <a-card>
@@ -212,7 +215,10 @@
                                 <a-range-picker
                                     :disabled-date="disabledDate"
                                     format="YYYY-MM-DD"
-                                    v-decorator="['timeRange', { initialValue: [moment(), moment()] }]"
+                                    v-decorator="[
+                                        'timeRange',
+                                        { initialValue: [moment().subtract(6, 'months'), moment()] }
+                                    ]"
                                 />
                             </a-form-item>
                         </a-col>
@@ -246,7 +252,10 @@
                                 <a-range-picker
                                     :disabled-date="disabledDate"
                                     format="YYYY-MM-DD"
-                                    v-decorator="['timeRange', { initialValue: [moment(), moment()] }]"
+                                    v-decorator="[
+                                        'timeRange',
+                                        { initialValue: [moment().subtract(6, 'months'), moment()] }
+                                    ]"
                                 />
                             </a-form-item>
                         </a-col>
@@ -265,7 +274,7 @@
 
         <a-row style="margin-bottom:15px;margin-top:12px">
             <a-col :span="24">
-                <div class="tableBody" style="min-height:200px">
+                <div class="tableBody" style="min-height:200px;padding-bottom: 50px">
                     <a-table
                         :columns="columns"
                         :dataSource="dataSource"
@@ -284,22 +293,26 @@
                                 :checked="text == 0"
                                 @change="onChangeStatus(text, record)"
                                 :loading="spinning"
-                                v-if="record.projectName !== ''"
+                                v-if="record.projectName !== '-'"
                             />
                         </span>
+                        <span slot="statDate" slot-scope="text, record">
+                            {{ record.projectName !== '-' ? text : '-' }}
+                        </span>
                         <span slot="projectName" slot-scope="text, record">
-                            <a @click="toAccountDetail(record)">{{ text }}</a>
+                            <a @click="toAccountDetail(record)" v-if="tabKey === 1 && text !== '-'">{{ text }}</a>
+                            <span v-else> {{ text }} </span>
                         </span>
                         <span slot="allAccountCount" slot-scope="text, record">
-                            {{ record.projectName !== '' ? record.successCount + '/' + text : '-' }}
+                            {{ record.successCount + '/' + text }}
                         </span>
                         <span slot="action" slot-scope="text, record">
-                            <div v-if="record.projectName !== ''">
-                                <a>出价</a>
+                            <div v-if="record.projectName !== '-'">
+                                <a @click="editPrice(record)">出价</a>
                                 <a-divider type="vertical" />
                                 <a>编辑</a>
                                 <a-divider type="vertical" />
-                                <a>配</a>
+                                <a @click="matchingAccount(record)">配</a>
                             </div>
                             <div v-else>
                                 -
@@ -335,6 +348,72 @@
                 </div>
             </a-col>
         </a-row>
+        <!-- 修改出价 -->
+        <a-modal
+            title="修改出价"
+            v-if="modifyPriceVisible"
+            :visible="modifyPriceVisible"
+            :confirm-loading="modifyPriceLoading"
+            dialog-class="push-modal"
+            @ok="handleOkPrice"
+            @cancel="handleCancelPrice"
+        >
+            <a-form
+                :form="priceForm"
+                :labelCol="{ lg: { span: 7 }, sm: { span: 7 } }"
+                :wrapperCol="{ lg: { span: 17 }, sm: { span: 17 } }"
+                v-if="modifyPriceDetail"
+            >
+                <a-form-item label="目标项目"> {{ modifyPriceDetail.projectName }} </a-form-item>
+                <a-form-item label="优化目标">
+                    <a-button type="primary">{{ modifyPriceDetail.bidType | bidType }}</a-button></a-form-item
+                >
+                <a-form-item label="转化目标"> {{ modifyPriceDetail.ocpxActionType | ocpxActionType }}</a-form-item>
+                <a-form-item label="计费方式">
+                    <a-button type="primary">{{
+                        modifyPriceDetail.bidType === 2 ? '点击计费(CPC)' : '按展示付费(oCPM)'
+                    }}</a-button>
+                </a-form-item>
+                <a-form-item label="转化目标出价">
+                    <a-input
+                        style="width:200px;ime-mode:disabled"
+                        v-decorator="['cpaBid', { rules: [{ required: true, validator: cpaBidValid }] }]"
+                    >
+                    </a-input>
+                </a-form-item>
+                <a-form-item label="深度转化出价" v-if="modifyPriceDetail.deepConversionType"
+                    ><a-input
+                        style="width:200px;ime-mode:disabled"
+                        v-decorator="['deepConversionBid', { rules: [{ required: true, validator: cpaBidValid }] }]"
+                    >
+                    </a-input>
+                </a-form-item>
+            </a-form>
+        </a-modal>
+
+        <a-modal
+            title="账户匹配情况"
+            :width="800"
+            v-if="accountVisible"
+            :visible="accountVisible"
+            @cancel="accountVisible = false"
+            dialog-class="push-modal"
+            :footer="null"
+        >
+            <div v-if="accountProjectDetail" style="font-size:16px;font-weight:700;margin-bottom:15px">
+                <span>项目:</span>
+                <span>{{ accountProjectDetail.projectName }}</span>
+            </div>
+            <a-table
+                :columns="accountProjectColumns"
+                :dataSource="accountProjectList"
+                :pagination="false"
+                bordered
+                size="middle"
+                style="word-break: break-all;font-size:16px;font-weight:600"
+            >
+            </a-table>
+        </a-modal>
     </div>
 </template>
 
@@ -599,12 +678,22 @@ export default {
         return {
             spinning: false,
             form: this.$form.createForm(this),
+            priceForm: this.$form.createForm(this),
             exportloading: false,
             planId: '',
             shotId: '',
             clipId: '',
             dateRange: [moment().subtract(1, 'weeks'), moment()],
             noImg: require('@/assets/noImg.png'),
+            validationRules: {
+                bid: [
+                    {
+                        required: true,
+                        message: '出价信息必须填写'
+                        // validator: this.validateBid,
+                    }
+                ]
+            },
             ipagination: {
                 current: 1,
                 pageSize: 10,
@@ -662,11 +751,211 @@ export default {
             order: 'descend',
             projectId: undefined,
             dataLoading: false,
-            url: '/kuaishouProjectStrategy/queryProjectList'
+            url: '/kuaishouProjectStrategy/queryProjectList',
+            modifyPriceVisible: false,
+            modifyPriceLoading: false,
+            modifyPriceDetail: null,
+            accountVisible: false,
+            accountProjectDetail: null,
+            accountProjectList: [],
+            accountProjectColumns: [
+                {
+                    title: '账户名称',
+                    dataIndex: 'authName',
+                    scopedSlots: { customRender: 'authName' },
+                    align: 'center',
+                    key: 'authName'
+                },
+                {
+                    title: '账户状态',
+                    dataIndex: 'authStatus',
+                    scopedSlots: { customRender: 'authStatus' },
+                    align: 'center',
+                    key: 'authStatus'
+                },
+                {
+                    title: '失败原因',
+                    dataIndex: 'dataStatus',
+                    scopedSlots: { customRender: 'dataStatus' },
+                    align: 'center',
+                    key: 'dataStatus'
+                }
+            ]
         }
     },
     methods: {
         moment,
+        newCreat(id) {
+            if (id) {
+                window.open('/creat-config?id=' + id, '_blank')
+            } else {
+                window.open('/creat-config', '_blank')
+            }
+        },
+        editPrice(item) {
+            getAction('/kuaishouProjectStrategy/queryBidInfo', { id: item.id }).then(res => {
+                if (res.success) {
+                    this.modifyPriceVisible = true
+                    this.modifyPriceDetail = { ...res.result, projectName: item.projectName, id: item.id }
+                    this.$nextTick(() => {
+                        let cpaBid = ''
+                        let changeBid = res.result.bidType === 2 ? res.result.bid : res.result.cpaBid
+                        if ((changeBid + '').includes('/')) {
+                            let bidArr = changeBid.split('/')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] / 1000
+                            }
+                            cpaBid = bidArr.join('/')
+                        } else if ((changeBid + '').includes('-')) {
+                            let bidArr = changeBid.split('-')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] / 1000
+                            }
+                            cpaBid = bidArr.join('-')
+                        } else {
+                            cpaBid = changeBid / 1000
+                        }
+                        let deepConversionBid = ''
+                        if ((res.result.deepConversionBid + '').includes('/')) {
+                            let bidArr = res.result.deepConversionBid.split('/')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] / 1000
+                            }
+                            deepConversionBid = bidArr.join('/')
+                        } else if ((res.result.deepConversionBid + '').includes('-')) {
+                            let bidArr = res.result.deepConversionBid.split('-')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] / 1000
+                            }
+                            deepConversionBid = bidArr.join('-')
+                        } else {
+                            deepConversionBid = res.result.deepConversionBid / 1000
+                        }
+                        this.priceForm.setFieldsValue({
+                            cpaBid: cpaBid,
+                            deepConversionBid: deepConversionBid
+                        })
+                    })
+                }
+            })
+        },
+        handleOkPrice() {
+            this.priceForm.validateFields((err, values) => {
+                //console.log(values)
+                if (!err) {
+                    this.modifyPriceLoading = true
+                    if (values.cpaBid) {
+                        if ((values.cpaBid + '').includes('/')) {
+                            let bidArr = values.cpaBid.split('/')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] * 1000
+                            }
+                            values.cpaBid = bidArr.join('/')
+                        } else if ((values.cpaBid + '').includes('-')) {
+                            let bidArr = values.cpaBid.split('-')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] * 1000
+                            }
+                            values.cpaBid = bidArr.join('-')
+                        } else {
+                            values.cpaBid = values.cpaBid * 1000
+                        }
+                    } else {
+                        values.cpaBid = 0
+                    }
+                    if (values.deepConversionBid) {
+                        if ((values.deepConversionBid + '').includes('/')) {
+                            let bidArr = values.deepConversionBid.split('/')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] * 1000
+                            }
+                            values.deepConversionBid = bidArr.join('/')
+                        } else if ((values.deepConversionBid + '').includes('-')) {
+                            let bidArr = values.deepConversionBid.split('-')
+                            for (let index = 0; index < bidArr.length; index++) {
+                                bidArr[index] = bidArr[index] * 1000
+                            }
+                            values.deepConversionBid = bidArr.join('-')
+                        } else {
+                            values.deepConversionBid = values.deepConversionBid * 1000
+                        }
+                    } else {
+                        values.deepConversionBid = 0
+                    }
+                    // this.modifyPriceDetail
+                    let params = {}
+                    if (this.modifyPriceDetail.bidType === 2) {
+                        params.bid = values.cpaBid
+                        if (values.deepConversionBid) {
+                            params.deepConversionBid = values.deepConversionBid
+                        }
+                    } else {
+                        params = { ...values }
+                    }
+                    postAction('/kuaishouProjectStrategy/updateProjectStrategy', {
+                        ...params,
+                        id: this.modifyPriceDetail.id
+                    }).then(res => {
+                        this.modifyPriceLoading = false
+                        if (res.success) {
+                            this.handleCancelPrice()
+                        } else {
+                            this.$message.error(res.message)
+                        }
+                    })
+                } else {
+                    this.$message.error('请正确填写必填项目')
+                }
+            })
+        },
+        handleCancelPrice() {
+            this.priceForm.resetFields()
+            this.modifyPriceVisible = false
+        },
+        cpaBidValid(rule, value, callback) {
+            let z = /-/g
+            let a = /\//g
+            let d = /\./g
+            if (value.match(a) && value.match(z)) {
+                callback('不允许出现除"-"和"/"之外的所有字符,并且二者不可同时出现')
+                return
+            } else if (value.startsWith('.') || value.endsWith('.')) {
+                callback('请填写正确出价')
+                return
+            } else if (value.startsWith('-') || value.endsWith('-')) {
+                callback('请填写正确出价')
+                return
+            } else if (value === '') {
+                callback('出价必须填写')
+            } else if (value.match(/[^0-9+-\/]/g)) {
+                callback('请填写正确出价')
+            } else {
+                callback()
+            }
+        },
+        btKeyUp(e) {
+            //没有显示‘破折号’和 '.' 需要的可以手动加上
+            // this.priceForm.setFieldsValue({
+            //     cpaBid: e.target.value.replace(/[^0-9+-\/]/g, '')
+            // })
+            // (
+            //         /[\u4e00-\u9fa5/\s+/]|[`~!@#$%^&*() \+ =<>?"{}|, \/ ;' \\ [ \] ·~!@#¥%……&*()—— \+ ={}|《》?:“”【】、;‘’,。、]/g,
+            //         ''
+            //     )
+        },
+        getData(className) {
+            return this.priceForm.getFieldValue(className)
+        },
+
+        matchingAccount(item) {
+            this.accountVisible = true
+            this.accountProjectDetail = { id: item.id, projectName: item.projectName }
+            getAction('/kuaishouProjectStrategy/queryMatchResult', { id: item.id }).then(res => {
+                if (res.success) {
+                    this.accountProjectList = res.result
+                }
+            })
+        },
         getDataSource(current, pageSize) {
             // 切换分页时的回调,
             // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
@@ -756,8 +1045,11 @@ export default {
                 this.tabKey == 1
                     ? '/kuaishouProjectStrategy/queryProjectList'
                     : '/kuaishouProjectStrategy/queryAccountList'
-            const paramsData = this.form.getFieldsValue()
-            this.handleGetTableList(paramsData)
+            this.$nextTick(() => {
+                this.columns = this.tabKey == 1 ? [...TTcolumns] : [...KScolumns]
+                const paramsData = this.form.getFieldsValue()
+                this.handleGetTableList(paramsData)
+            })
         },
         disabledDate(current) {
             // Can not select days before today and today
@@ -815,7 +1107,7 @@ export default {
                 this.columns = this.tabKey == 1 ? [...TTcolumns] : [...KScolumns]
                 this.target = 'new'
             } else {
-                this.columns = this.tabKey == 1 ? [...TTcolumnsVaild] : [...KScolumnsVaild]
+                this.columns = this.tabKey == 1 ? [...TTcolumns] : [...KScolumns]
                 this.target = 'valid'
             }
             // this.getNewPlan()