朱鑫波 před 4 roky
rodič
revize
eca19702c7

+ 440 - 0
src/views/modules/autoLaunch/channelManage/components/creatApplication.vue

@@ -0,0 +1,440 @@
+<style lang="less" scoped>
+.require-class {
+    /deep/ .ant-form-item-label {
+        label::before {
+            display: inline-block;
+            margin-right: 4px;
+            color: #f5222d;
+            font-size: 14px;
+            font-family: SimSun, sans-serif;
+            line-height: 1;
+            content: '*';
+        }
+    }
+}
+</style>
+<template>
+    <div>
+        <a-modal
+            title="添加应用"
+            :visible="application"
+            @ok="handleSubmit"
+            :confirmLoading="confirmLoading"
+            @cancel="handleCancel"
+            width="800px"
+        >
+            <a-card :body-style="{ padding: '24px 32px' }" :bordered="false">
+                <a-form :form="form">
+                    <a-form-item
+                        label="下载链接"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            placeholder="请填写应用下载链接"
+                            v-decorator="[
+                                'url',
+                                {
+                                    rules: [{ required: true, validator: handleConfirmValue }]
+                                }
+                            ]"
+                        />
+                    </a-form-item>
+
+                    <a-form-item
+                        label="应用包名"
+                        v-if="uploadType == '2' && appType == 'android'"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'packageName',
+                                {
+                                    rules: [{ required: true, message: '请填写正确的应用包名称' }]
+                                }
+                            ]"
+                            placeholder="请填写包名称,如com.smile.gifmaker"
+                        />
+                    </a-form-item>
+
+                    <a-form-item
+                        label="应用名称"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'appName',
+                                {
+                                    rules: [{ required: true, message: '请填写应用名称' }]
+                                }
+                            ]"
+                            placeholder="请填写应用名称"
+                        />
+                    </a-form-item>
+
+                    <a-form-item
+                        label="上传图标"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 19 } }"
+                        v-if="application"
+                        class="require-class"
+                    >
+                        <uploadFile
+                            v-if="application"
+                            :value.sync="fileUrl"
+                            :multiple="false"
+                            :fileCount="1"
+                            uploadType="image"
+                            @overUpload="overUpload"
+                            :size="100"
+                        ></uploadFile>
+                        <p class="upload-txt-rules">文件格式:支持上传png/jpg/jpeg图片,尺寸450*450,小于100kb</p>
+                    </a-form-item>
+                    <a-form-item
+                        label="应用标记"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'appVersion',
+                                {
+                                    rules: [{ required: true, message: '应用标记必填' }]
+                                }
+                            ]"
+                            placeholder="请填写应用标记,必填且不可重复,如快手-5.6.1.66"
+                        />
+                    </a-form-item>
+                    <a-form-item
+                        label="隐私政策链接"
+                        :labelCol="{ xs: { span: 24 }, sm: { span: 5 } }"
+                        :wrapperCol="{ xs: { span: 24 }, sm: { span: 16 } }"
+                    >
+                        <a-input
+                            v-decorator="[
+                                'appPrivacyUrl',
+                                {
+                                    rules: [
+                                        { required: true, message: '请填写隐私政策链接' },
+                                        { validator: handleConfirmValue }
+                                    ]
+                                }
+                            ]"
+                            placeholder="请填写隐私政策链接"
+                        />
+                    </a-form-item>
+                </a-form>
+            </a-card>
+        </a-modal>
+    </div>
+</template>
+
+<script>
+import Vue from 'vue'
+import { ACCESS_TOKEN } from '@/store/mutation-types'
+import { deleteAction, postAction, getAction, downFilePost, downFile } from '@/api/manage'
+import uploadFile from './uploadFile.vue'
+import { mapActions, mapGetters } from 'vuex'
+import BMF from 'browser-md5-file'
+import selectTable from '@/views/modules/Statistics/components/selectPagination.vue'
+import $ from 'jquery'
+const fileSuffix = ['xlsx', 'xls', 'zip']
+export default {
+    name: 'BaseForm',
+    components: {
+        uploadFile,
+        selectTable
+    },
+    data() {
+        return {
+            useSdk: [],
+            loadDisabled: false,
+            projectId: '',
+            accountId: '',
+            fileList: [],
+            fileUrl: '',
+            accountList: {},
+            appType: 'android', //设备类型
+            platform: '1', //应用类型   : 1 Android 应用下载,2: Android 网页游戏,3: iOS 应用下载, 4:iOS 网页游戏
+            uploadType: '2', //上传类型 1 本地上传 2 填写链接
+            appVersion: '', //应用标记
+            appName: '', // 应用名称
+            packageName: '', //应用包名
+            file: '', // 上传文件
+            imageUrl: '', // 上传图标链接链接
+            downloadUrl: '', //下载链接
+            showUploadFile: true,
+            showDownLoad: false,
+            showUpload: true,
+            showAndroid: true,
+            showIOS: false,
+            customDomain: '',
+            acceptVideo: '/*.apk,/*.png,/*.jpg,/*.jpeg,/*.mp4',
+            accessKeyId: 'LTAIbNbqWzSOklQV',
+            accessKeySecret: '1rkPz7JNoXk8sJevPaeYHWqfkQXBGh',
+            region: 'oss-cn-beijing',
+            bucket: 'ctop-media',
+            form: this.$form.createForm(this),
+            url: {
+                insertTemplateUrl: '/kuaishouAppPackage/fillInLink',
+                userAllocationList: '/ctop/userAllocation/list'
+            },
+            application: false,
+            confirmLoading: false,
+            imageToken: '',
+            // uploadAction: '/kuaishouAppPackage/importAppExcel',
+            tokenHeader: { 'X-Access-Token': Vue.ls.get(ACCESS_TOKEN) },
+            okCreated: false,
+            dataFile: null
+        }
+    },
+    methods: {
+        overUpload(file) {},
+        downLoadFile() {
+            downFile('/kuaishouAppPackage/exportAppTemplate').then(res => {
+                let blob = new Blob([res], {
+                    type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
+                })
+                let downloadElement = document.createElement('a')
+                let href = window.URL.createObjectURL(blob) //创建下载的链接
+                downloadElement.href = href
+                downloadElement.download = '应用模板' //下载后文件名
+                document.body.appendChild(downloadElement)
+                downloadElement.click() //点击下载
+                document.body.removeChild(downloadElement) //下载完成移除元素
+                window.URL.revokeObjectURL(href) //释放掉blob对象
+            })
+        },
+        handleChange(info) {
+            this.loadDisabled = false
+            this.$message.success('文件导入成功')
+        },
+        beforeUpload(file) {
+            this.dataFile = $('.fileUpload')
+                .eq(0)
+                .find('input')[0].files[0]
+            this.loadDisabled = true
+            const size = (Number(file.size) / (1024 * 1024)).toFixed(2)
+            const fileName = file.name
+            const fileStrArr = fileName.split('.')
+            const suffix = fileStrArr[fileStrArr.length - 1]
+
+            let result = fileSuffix.some(item => {
+                return item === suffix
+            })
+
+            if (!result) {
+                this.$message.error('不支持该文件类型')
+                this.loadDisabled = false
+                return false
+            }
+        },
+        cosUpload(file) {
+            let that = this
+            let date = new Date()
+            let y = date.getFullYear()
+            let MM = date.getMonth() + 1
+            MM = MM < 10 ? '0' + MM : MM
+            let d = date.getDate()
+            d = d < 10 ? '0' + d : d
+            let timeElse = new Date().getTime()
+            let arr = file.name.split('.')
+            let str = ''
+            for (let i = 0; i < arr.length; i++) {
+                if (i === arr.length - 1) {
+                } else {
+                    if (i === arr.length - 2) {
+                        str += arr[i]
+                    } else {
+                        str += arr[i] + '.'
+                    }
+                }
+            }
+            cos.putObject(
+                {
+                    Bucket: 'media-1301855440',
+                    Region: 'ap-chongqing',
+                    // 存储桶所在地域,必须字段
+                    Key:
+                        that.appType +
+                        '/' +
+                        y +
+                        '-' +
+                        MM +
+                        '-' +
+                        d +
+                        '/' +
+                        str +
+                        '-' +
+                        timeElse +
+                        '.' +
+                        arr[arr.length - 1],
+                    StorageClass: 'STANDARD',
+                    Body: file // 上传文件对象
+                },
+                function(err, data) {
+                    if (err) {
+                        that.$message.error('上传失败!!!' + err)
+                        return
+                    }
+                    that.loadingElse = false
+                    that.fileList.push({
+                        uid: file.name,
+                        name: file.name,
+                        status: 'done',
+                        url: '//' + data.Location
+                    })
+                    if (that.fileList.length > 1) {
+                        that.fileList = that.fileList.slice(-1)
+                    }
+                    const isZip = file.type.includes('zip') || file.type.includes('text')
+                    const fileOvesize = file.size > 1024 * 1024 * 1024
+                    if (!isZip) {
+                        that.$message.error('只能上传zip格式的文件或者txt文件')
+                        return
+                    }
+                    if (fileOvesize) {
+                        that.$message.error('文件大小不能超过1G')
+                        return
+                    }
+                    that.handleMd5(file)
+                }
+            )
+        },
+        handleMd5(file) {
+            let bmf = new BMF()
+            let that = this
+            return new Promise(function(resolve, reject) {
+                bmf.md5(file, (err, md5) => {
+                    // getAction('kuaishouPopulationPackage/checkPopulationPackage', { signature: md5 })
+                    //   .then((result) => {
+                    //     if (result.code === 200) {
+                    that.personNameDisabled = false
+                    that.personResourceDisabled = false
+                    resolve()
+                    //   } else if (result.code === 201) {
+                    //     that.$message.error(result.message)
+                    //     that.personForm.name = result.result.orientationName
+                    //     that.personForm.resource = result.result.type
+                    //     that.personNameDisabled = true
+                    //     that.personResourceDisabled = true
+                    //     reject()
+                    //   }
+                    // })
+                    // .catch((error) => {
+                    //   console.log(error, 'eeee')
+                    //   reject()
+                    // })
+                })
+            })
+        },
+        handleOk() {
+            this.handleSubmit()
+        },
+        handleCancel() {
+            this.dataFile = null
+            this.appType = 'android'
+            this.okCreated = false
+            this.form.resetFields()
+            this.fileUrl = ''
+            this.file = ''
+            this.platform = '1'
+            this.application = false
+        },
+        showApplication() {
+            this.application = true
+        },
+        handleConfirmValue(rule, value, callback) {
+            if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '') {
+                callback()
+            } else {
+                callback('链接不能为空且开头为http://或https://')
+            }
+        },
+        ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        changePlatform() {
+            this.form.resetFields()
+            if (this.appType == 'android') {
+                this.showAndroid = true
+                this.showIOS = false
+                this.platform = '1'
+            } else {
+                this.showAndroid = false
+                this.showIOS = true
+                this.showDownLoad = true
+                this.platform = '1'
+            }
+        },
+        changeShowUpload() {
+            this.form.resetFields()
+            this.fileUrl = ''
+        },
+        changeShowUploadType() {
+            this.form.resetFields()
+            if (this.platform == '2') {
+                this.showUpload = false
+                this.showUploadFile = false
+                this.showDownLoad = true
+                this.uploadType = '1'
+            } else {
+                this.showUpload = true
+                this.showUploadFile = true
+                this.showDownLoad = false
+            }
+        },
+
+        handleSubmit() {
+            //   console.log('设备类型:' + this.appType)
+            //   console.log('应用类型:' + this.platform)
+            //   console.log('上传类型:' + this.uploadType)
+            //   console.log('应用标记:' + this.appVersion)
+            //   console.log('应用名称:' + this.appName)
+            //   console.log('包名称:' + this.packageName)
+            //   console.log('文件地址:' + this.file)
+            //   console.log('图片地址:' + this.imageUrl)
+            //   e.preventDefault()
+
+            this.form.validateFields((err, values) => {
+                if (!err) {
+                    if (this.fileUrl) {
+                        this.confirmLoading = true
+                        let params = {}
+
+                        this.url.insertTemplateUrl = '/kuaishouAppPackage/fillInLink'
+                        params = { ...values }
+                        params.appIconUrl = this.fileUrl
+                        this.$emit('getDataList', params)
+                        // postAction(this.url.insertTemplateUrl, params).then(res => {
+                        //     this.confirmLoading = false
+                        //     if (res.success) {
+                        //         this.$message.success('创建成功')
+                        //         this.handleCancel()
+                        //         this.$emit('getDataList')
+                        //     } else {
+                        //         this.$message.error(res.message)
+                        //     }
+                        // })
+                    } else {
+                        this.$message.error('请填写必填项')
+                    }
+                }
+            })
+        },
+
+        onChange(value) {}
+    },
+    created: function() {
+        let params = {}
+        params.pageSize = '1000'
+        params.mediaId = '2'
+        params.userId = this.userInfo().id
+        getAction(this.url.userAllocationList, params).then(res => {
+            if (res.success) {
+                this.accountList = res.result.records
+            }
+        })
+    }
+}
+</script>

+ 111 - 171
src/views/modules/autoLaunch/channelManage/components/treeSelectAccount.vue

@@ -12,7 +12,7 @@
             :options="options"
             :load-options="loadOptions"
             placeholder="请选择项目以及账户"
-            v-model="value"
+            v-model="selectedVal"
             :value-consists-of="valueConsistsOf"
             :auto-load-root-options="false"
             @select="update"
@@ -62,7 +62,7 @@ export default {
         multiple: {
             type: Boolean,
             default() {
-                return true
+                return false
             }
         },
         appId: {
@@ -81,7 +81,7 @@ export default {
         reqUrl: {
             type: String,
             default() {
-                return '/ctop/projectMember/participateListByMediaId'
+                return '/ctop/projectMember/getProductProjectAndAccountList'
             }
         },
         // 展示条数
@@ -101,61 +101,61 @@ export default {
     components: {
         Treeselect
     },
-    watch: {
-        $route(n, o) {},
-        appId: {
-            handler(n, o) {
-                console.log(n)
-                if (n.length == 0) {
-                    if (this.multiple) {
-                        this.value = []
-                    } else {
-                        this.value = undefined
-                    }
-                } else {
-                    this.value = this.appId
-                }
+    computed: {
+        selectedVal: {
+            get: function() {
+                return this.value
             },
-            deep: true,
-            immediate: true
+            set: function(val) {
+                console.log(val)
+                this.$emit('input', val)
+                this.$emit('change', val)
+            }
         }
     },
+    watch: {
+        $route(n, o) {}
+        // appId: {
+        //     handler(n, o) {
+        //         console.log(n)
+        //         if (n.length == 0) {
+        //             if (this.multiple) {
+        //                 this.value = []
+        //             } else {
+        //                 this.value = undefined
+        //             }
+        //         } else {
+        //             this.value = this.appId
+        //         }
+        //     },
+        //     deep: true,
+        //     immediate: true
+        // }
+    },
     methods: {
         ...mapGetters(['nickname', 'avatar', 'userInfo']),
         update(node, id) {
             this.$emit('select-value', node)
-            console.log(node)
-            if (typeof node.id == 'string' && node.id.indexOf('p') != -1) {
-                getAction('/ctop/userAllocation/getByProjectId', {
-                    projectId: node.id.split('p')[0]
-                }).then(res => {
-                    // console.log(res)
-                    if (res.code == 0) {
-                        if (res.result.length > 0) {
-                            node.children = res.result.map(item => {
-                                return {
-                                    id: item.userId ? item.userId : '',
-                                    label: item.userId ? item.userId : '',
-                                    children: item.accounts.map(c => {
-                                        return {
-                                            id: c.accountId,
-                                            label:
-                                                c.userName +
-                                                '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
-                                                c.authName
-                                        }
-                                    })
-                                }
-                            })
-                        } else {
-                        }
-                    } else {
-                        new Error('Failed to load options: network error.')
-                    }
-                })
-            }
+            // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+            //   projectId: node.id,
+            // }).then((res) => {
+            //   // console.log(res)
+            //   if (res.code == 0) {
+            //     if (res.result.length > 0) {
+            //       node.children = res.result.map((item) => {
+            //         return {
+            //           id: item.accountId,
+            //           label: item.userName + '         ' + item.authName,
+            //         }
+            //       })
+            //     } else {
+            //     }
+            //   } else {
+            //     new Error('Failed to load options: network error.')
+            //   }
+            // })
         },
-        emitValue(value, id) {
+        emitValue() {
             this.$emit('update:appId', this.value)
         },
         loadOptions({ action, parentNode, callback }) {
@@ -163,35 +163,26 @@ export default {
             // Once the server has responded,
             // assign children options to the parent node & call the callback.
             if (action === LOAD_CHILDREN_OPTIONS) {
-                getAction('/ctop/userAllocation/getByProjectId', {
-                    projectId: parentNode.id.split('p')[0]
-                }).then(res => {
-                    if (res.code == 0) {
-                        if (res.result.length > 0) {
-                            parentNode.children = res.result.map(item => {
-                                return {
-                                    id: item.userId ? item.userId : '',
-                                    label: item.userId ? item.userId : '',
-                                    children: item.accounts.map(c => {
-                                        return {
-                                            id: c.accountId,
-                                            label:
-                                                c.userName +
-                                                '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
-                                                c.authName
-                                        }
-                                    })
-                                }
-                            })
-                            callback()
-                        } else {
-                            parentNode.children = []
-                            callback()
-                        }
-                    } else {
-                        callback(new Error('Failed to load options: network error.'))
-                    }
-                })
+                // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+                //   projectId: parentNode.id,
+                // }).then((res) => {
+                //   if (res.code == 0) {
+                //     if (res.result.length > 0) {
+                //       parentNode.children = res.result.map((item) => {
+                //         return {
+                //           id: item.accountId,
+                //           label: item.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' + item.authName,
+                //         }
+                //       })
+                //       callback()
+                //     } else {
+                //       parentNode.children = []
+                //       callback()
+                //     }
+                //   } else {
+                //     callback(new Error('Failed to load options: network error.'))
+                //   }
+                // })
             }
         },
         getParticipateList() {
@@ -199,101 +190,50 @@ export default {
             //   toutiaoParticipateList
             var params = {}
             params.userId = this.userInfo().id
-
-            if (this.request == '1,3') {
-                params.type = 'bytedance'
-            } else if (this.request == '2,4') {
-                params.type = 'kuaishou'
-            }
-
-            if (this.reqUrl == '/ctop/projectMember/participateListByMediaId') {
-                if (this.options.length > 0) {
-                    return
-                }
-                getAction('/ctop/projectMember/projectList').then(res => {
-                    if (res.success) {
-                        this.options = res.data.map(item => {
-                            return {
-                                id: item.id + 'projectId',
-                                label: item.projectName,
-                                children: null
-                            }
-                        })
-                        if (this.oneData && !this.multiple) {
-                            var data = this.options.filter(item => {
-                                if (item.children && item.children.length > 0) {
-                                    return { ...item }
-                                }
-                            })
-                            this.$emit('update:appId', data[0].children[0].id)
+            postAction(this.reqUrl, params).then(res => {
+                if (res.success) {
+                    console.log(res)
+                    this.options = res.result.map(item => {
+                        return {
+                            id: item.productId + 'productId',
+                            label: item.productName,
+                            children: item.projectList
+                                ? item.projectList.map(i => {
+                                      return {
+                                          id: i.projectId,
+                                          label: i.projectName,
+                                          children: i.accountList
+                                              ? i.accountList.map(c => {
+                                                    return {
+                                                        id: c.accountId,
+                                                        label:
+                                                            (c.userName && c.userName.length == 2
+                                                                ? c.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0'
+                                                                : c.userName && c.userName.length == 3
+                                                                ? c.userName + '\xa0\xa0\xa0\xa0'
+                                                                : c.userName) +
+                                                            '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                            c.accountId +
+                                                            '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
+                                                            c.authName
+                                                    }
+                                                })
+                                              : []
+                                      }
+                                  })
+                                : []
                         }
-                    }
-                })
-            } else if (this.reqUrl == '/ctop/projectMember/getProjectAccountByUserId') {
-                getAction(this.reqUrl, {
-                    mediaType: this.request
-                }).then(res => {
-                    if (res.code == 0) {
-                        if (res.result.length > 0) {
-                            res.result.forEach((element, index) => {
-                                if (element) {
-                                    this.options.push({})
-                                    this.options[index].label =
-                                        element.project.projectName + '_(' + element.project.advertiserName + ')'
-                                    this.options[index].id = 'project' + element.project.projectId
-                                    this.options[index].key = element.project.projectId
-                                    this.options[index].mediaId = element.project.mediaId
-                                    this.options[index].children = []
-
-                                    if (element.account.length) {
-                                        element.account.forEach((ele, i) => {
-                                            this.options[index].children.push({})
-                                            this.options[index].children[i].label =
-                                                ele.userName + '_' + ele.authName + '_' + element.project.projectName
-                                            this.options[index].children[i].id = ele.accountId
-                                            this.options[index].children[i].key = ele.accountId
-                                        })
-                                    }
-                                }
-                            })
-                        } else {
-                            this.showLoading = '暂无数据'
-                        }
-                    }
-                })
-            } else {
-                getAction(this.reqUrl, {
-                    userId: this.userInfo().id
-                }).then(res => {
-                    if (res.code == 0) {
-                        if (res.result.length > 0) {
-                            var arr = this.request.split(',')
-                            var dataTwo = []
-                            var data = res.result.filter(item => {
-                                return item.mediaId == arr[0]
-                            })
-                            if (arr.length > 1) {
-                                dataTwo = res.result.filter(item => {
-                                    return item.mediaId == arr[1]
-                                })
+                    })
+                    if (this.oneData && !this.multiple) {
+                        var data = this.options.filter(item => {
+                            if (item.children && item.children.length > 0) {
+                                return { ...item }
                             }
-                            var allData = data.concat(dataTwo)
-                            this.options = allData.map(item => {
-                                return {
-                                    id: item.projectId,
-                                    label:
-                                        item.projectName +
-                                        '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' +
-                                        item.advertiserName,
-                                    children: null
-                                }
-                            })
-                        } else {
-                            this.showLoading = '暂无数据'
-                        }
+                        })
+                        this.$emit('update:appId', data[0].children[0].id)
                     }
-                })
-            }
+                }
+            })
         }
     },
 

+ 228 - 0
src/views/modules/autoLaunch/channelManage/components/treeSelectProject.vue

@@ -0,0 +1,228 @@
+<style lang="scss" scoped>
+.select-project {
+    width: 50%;
+}
+</style>
+<template>
+    <div class="select-project">
+        <treeselect
+            :multiple="multiple"
+            :disable-branch-nodes="!multiple"
+            :disable-fuzzy-matching="true"
+            :options="options"
+            :load-options="loadOptions"
+            placeholder="请选择项目以及账户"
+            v-model="selectedVal"
+            :value-consists-of="valueConsistsOf"
+            :auto-load-root-options="false"
+            @select="update"
+            @input="emitValue"
+            :limit="limit"
+            :default-options="true"
+            :disabled="disabled"
+            :limitText="
+                count => {
+                    return '隐藏' + count + '条'
+                }
+            "
+            noChildrenText="该项目下暂无账号"
+            :noOptionsText="showLoading"
+        />
+    </div>
+</template>
+
+<script>
+//   @open="getParticipateList"
+// import the component
+import Treeselect from '@riophae/vue-treeselect'
+// import the styles
+import '@riophae/vue-treeselect/dist/vue-treeselect.css'
+import { LOAD_CHILDREN_OPTIONS } from '@riophae/vue-treeselect'
+
+import { getAction, postAction } from '@/api/manage'
+import { mapGetters } from 'vuex'
+// We just use `setTimeout()` here to simulate an async operation
+// instead of requesting a real API server for demo purpose.
+let called = false
+export default {
+    data: () => ({
+        value: null,
+        valueConsistsOf: 'LEAF_PRIORITY',
+        options: [],
+        showLoading: 'loading...'
+    }),
+    props: {
+        oneData: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        //是否多选
+        multiple: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        },
+        appId: {
+            type: [Number, Array, String],
+            default() {
+                return ""
+            }
+        },
+        //判断媒体类型
+        request: {
+            type: String,
+            default() {
+                return '2,4'
+            }
+        },
+        //一级请求接口
+        reqUrl: {
+            type: String,
+            default() {
+                return '/ctop/projectMember/getProductProjectList'
+            }
+        },
+        // 展示条数
+        limit: {
+            type: Number,
+            default() {
+                return 2
+            }
+        },
+        disabled: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        }
+    },
+    components: {
+        Treeselect
+    },
+    computed: {
+        selectedVal: {
+            get: function() {
+                return this.value
+            },
+            set: function(val) {
+                console.log(val)
+                this.$emit('input', val)
+                this.$emit('change', val)
+            }
+        }
+    },
+    watch: {
+        $route(n, o) {},
+        // appId: {
+        //     handler(n, o) {
+        //         console.log(n)
+        //         if (n.length == 0) {
+        //             if (this.multiple) {
+        //                 this.value = []
+        //             } else {
+        //                 this.value = undefined
+        //             }
+        //         } else {
+        //             this.value = this.appId
+        //         }
+        //     },
+        //     deep: true,
+        //     immediate: true
+        // }
+    },
+    methods: {
+        ...mapGetters(['nickname', 'avatar', 'userInfo']),
+        update(node, id) {
+            this.$emit('select-value', node)
+            // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+            //   projectId: node.id,
+            // }).then((res) => {
+            //   // console.log(res)
+            //   if (res.code == 0) {
+            //     if (res.result.length > 0) {
+            //       node.children = res.result.map((item) => {
+            //         return {
+            //           id: item.accountId,
+            //           label: item.userName + '         ' + item.authName,
+            //         }
+            //       })
+            //     } else {
+            //     }
+            //   } else {
+            //     new Error('Failed to load options: network error.')
+            //   }
+            // })
+        },
+        emitValue() {
+            // this.$emit('update:appId', this.value)
+        },
+        loadOptions({ action, parentNode, callback }) {
+            // Typically, do the AJAX stuff here.
+            // Once the server has responded,
+            // assign children options to the parent node & call the callback.
+            if (action === LOAD_CHILDREN_OPTIONS) {
+                // getAction('/ctop/userAllocation/getAccountListByProjectId', {
+                //   projectId: parentNode.id,
+                // }).then((res) => {
+                //   if (res.code == 0) {
+                //     if (res.result.length > 0) {
+                //       parentNode.children = res.result.map((item) => {
+                //         return {
+                //           id: item.accountId,
+                //           label: item.userName + '\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0\xa0' + item.authName,
+                //         }
+                //       })
+                //       callback()
+                //     } else {
+                //       parentNode.children = []
+                //       callback()
+                //     }
+                //   } else {
+                //     callback(new Error('Failed to load options: network error.'))
+                //   }
+                // })
+            }
+        },
+        getParticipateList() {
+            //我参与的
+            //   toutiaoParticipateList
+            var params = {}
+            params.userId = this.userInfo().id
+            postAction(this.reqUrl, params).then(res => {
+                if (res.success) {
+                    console.log(res)
+                    this.options = res.result.map(item => {
+                        return {
+                            id: item.productId + 'productId',
+                            label: item.productName,
+                            children: item.projectList
+                                ? item.projectList.map(i => {
+                                      return {
+                                          id: i.projectId,
+                                          label: i.projectName
+                                      }
+                                  })
+                                : []
+                        }
+                    })
+                    if (this.oneData && !this.multiple) {
+                        var data = this.options.filter(item => {
+                            if (item.children && item.children.length > 0) {
+                                return { ...item }
+                            }
+                        })
+                        this.$emit('update:appId', data[0].children[0].id)
+                    }
+                }
+            })
+        }
+    },
+
+    mounted() {
+        this.getParticipateList()
+    }
+}
+</script>

+ 365 - 0
src/views/modules/autoLaunch/channelManage/components/uploadFile.vue

@@ -0,0 +1,365 @@
+<style>
+</style>
+<style lang="scss" scoped>
+</style>
+<template>
+  <div class="upload-file">
+    <a-upload
+      name="file"
+      :multiple="multiple"
+      list-type="picture-card"
+      class="avatar-uploader"
+      action="https://media-1301855440.cos.ap-chongqing.myqcloud.com/"
+      :before-upload="beforeUpload"
+      @change="handleChange"
+      :accept="uploadType + '/' + (uploadType == 'image' ? 'jpeg,image/*' : 'mp4')"
+      :file-list="fileList"
+      :remove="removeFile"
+      @preview="handlePreview"
+      :disabled="loadingElse || disabled"
+    >
+      <div v-if="fileList.length < fileCount || fileList.length < 1">
+        <a-progress v-if="loadingElse" :percent="percent" :show-info="false" />
+        <div class="ant-upload-text">点击上传</div>
+      </div>
+    </a-upload>
+    <!-- <div style="color: red" v-if="sizeCheck">
+      {{ uploadType == 'image' ? '请上传jpg格式的图片,并且大小在2m之内' : '请上传mp4格式,大小在'+(size/1024)+'m之内' }}
+    </div> -->
+    <a-modal :visible="previewVisible" :footer="null" @cancel="handleCancel">
+      <img alt="example" style="width: 100%" :src="previewImage" v-if="uploadType == 'image'" />
+      <video :src="previewImage" v-else style="width: 100%" controls="controls">您的浏览器不支持 video 标签。</video>
+    </a-modal>
+  </div>
+</template>
+
+<script>
+import { stopOtherVideo, closeAllVideoFun } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
+import { mapGetters } from 'vuex'
+import moment from 'moment'
+
+import BMF from 'browser-md5-file'
+
+import qs from 'qs'
+var COS = require('cos-js-sdk-v5')
+var cos = new COS({
+  SecretId: 'AKIDE6IpMi8fJQRCg1iuWzFajjRs43kbbets',
+  SecretKey: 'tXzuwMfplTTK3c9GFUyETilasvQfePu9',
+})
+var i = 0
+const oneKB = 1024
+
+function getBase64(file) {
+  return new Promise((resolve, reject) => {
+    const reader = new FileReader()
+    reader.readAsDataURL(file)
+    reader.onload = () => resolve(reader.result)
+    reader.onerror = (error) => reject(error)
+  })
+}
+export default {
+  name: 'upload-file',
+  components: {},
+  props: {
+    uploadType: {
+      //上传类型  值为  image/video,同时目录名称也是这样
+      type: String,
+      default() {
+        return 'image'
+      },
+    },
+    multiple: {
+      // true 可以批量上传  false 不可以
+      type: Boolean,
+      default() {
+        return true
+      },
+    },
+    fileCount: {
+      //最大上传数量
+      type: Number,
+      default() {
+        return 10
+      },
+    },
+    checkFile: {
+      //返回promise方法,判读文件是否上传过,进行上传拦截
+      type: Function,
+      default() {
+        return Promise.resolve()
+      },
+    },
+    disabled: {
+      type: Boolean,
+      default() {
+        return false
+      },
+    },
+    value: {
+      required: true,
+      default() {
+        return ''
+      },
+    },
+    size: {
+      type: Number,
+      default() {
+        if (this.sizeCheck) {
+          if (this.uploadType == 'image') {
+            return 2048
+          } else {
+            return 102400
+          }
+        }
+      },
+    },
+    sizeCheck: {
+      type: Boolean,
+      default() {
+        return true
+      },
+    },
+    onOversize: {
+      type: Function,
+      default() {
+        alert(`请选择${this.size}KB内的文件!`)
+      },
+    },
+  },
+  data() {
+    return {
+      fileList: [],
+      loadingElse: false,
+      imageUrl: '',
+      percent: 0,
+      previewVisible: false,
+      previewImage: '',
+    }
+  },
+  filters: {},
+  computed: {},
+  mounted() {},
+  watch: {
+    //    fileListAll
+    value: {
+      immediate: true,
+      handler(n, o) {
+        this.$nextTick(() => {
+          if (this.fileList && this.fileList.length == 0) {
+            if (typeof n == 'object') {
+              this.fileList = n.map((item, index) => {
+                return {
+                  uid: index + 1,
+                  name: index + 1,
+                  status: 'done',
+                  url: item,
+                }
+              })
+            } else {
+              if (n === '') {
+                this.fileList = []
+              } else {
+                this.fileList = []
+                var data = {
+                  uid: 1,
+                  name: '回显',
+                  status: 'done',
+                  url: n,
+                }
+                this.fileList.push(data)
+              }
+            }
+          } else {
+            if (n.length == 0 || n == '') {
+              this.clearAll()
+            }
+          }
+        })
+      },
+      deep: true,
+    },
+  },
+  methods: {
+    handleCancel() {
+      closeAllVideoFun()
+      this.previewVisible = false
+    },
+    handleChange(info) {
+      if (info.file.status === 'uploading') {
+        this.loading = true
+        return
+      }
+      if (info.file.status === 'done') {
+        // Get this url from response in real world.
+        getBase64(info.file.originFileObj, (imageUrl) => {
+          this.imageUrl = imageUrl
+          this.loading = false
+        })
+      }
+    },
+    removeFile(file) {
+      // console.log(file)
+      var index = this.fileList.findIndex((v) => v.uid === file.uid)
+      this.fileList.splice(index, 1)
+      this.$emit('removeUpload', file)
+    },
+    async handlePreview(file) {
+      if (!file.url && !file.preview) {
+        file.preview = await getBase64(file.originFileObj)
+      }
+      this.previewImage = file.url || file.preview
+      this.previewVisible = true
+    },
+    beforeUpload(file) {
+      this.percent = 0
+      this.loadingElse = true
+      const fileOvesize = file.size > this.size * oneKB
+      console.log(file)
+      var image = new Image()
+      var reader = new FileReader()
+      var height = 0
+      var width = 0
+      reader.readAsDataURL(file)
+      //文件读取结束时间
+      reader.onload = function (e) {
+        image.src = reader.result
+      }
+      var that = this
+      //图片读取事件
+      image.onload = function () {
+        height = image.naturalHeight
+        width = image.naturalWidth
+      }
+      if (image.complete) {
+        height = image.naturalHeight
+        width = image.naturalWidth
+      }
+
+      setTimeout(() => {
+        if (height != 450 || width != 450) {
+          that.$message.error('请上传450*450大小的图片')
+          this.loadingElse = false
+          return
+        }
+        // console.log(fileOvesize)
+        if (fileOvesize && this.sizeCheck) {
+          this.onOversize()
+          this.loadingElse = false
+          return
+        } else {
+          if (file.type.includes('jpg') || file.type.includes('png') || file.type.includes('jpeg')) {
+            this.checkFile(file)
+              .then((res) => {
+                this.cosUpload(file)
+              })
+              .catch(() => {
+                this.loadingElse = false
+              })
+          } else {
+            this.$message.error('请上传正确格式')
+            this.loadingElse = false
+          }
+
+          return new Promise(function (resolve, reject) {
+            reject()
+          })
+        }
+      }, 200)
+    },
+    clearAll() {
+      this.fileList = []
+    },
+    cosUpload(file) {
+      var that = this
+      let date = new Date()
+      let y = date.getFullYear()
+      let MM = date.getMonth() + 1
+      MM = MM < 10 ? '0' + MM : MM
+      let d = date.getDate()
+      d = d < 10 ? '0' + d : d
+      var timeElse = new Date().getTime()
+      var arr = file.name.split('.')
+
+      var str = ''
+      for (let i = 0; i < arr.length; i++) {
+        if (i == arr.length - 1) {
+        } else {
+          if (i == arr.length - 2) {
+            str += arr[i]
+          } else {
+            str += arr[i] + '.'
+          }
+        }
+      }
+      // console.log(str + '-' + timeElse + '.' + arr[arr.length - 1])
+      cos.putObject(
+        {
+          Bucket: 'media-1301855440',
+          /* 必须 */
+          Region: 'ap-chongqing',
+          /* 存储桶所在地域,必须字段 */
+          Key: that.uploadType + '/' + y + '-' + MM + '-' + d + '/' + str + '-' + timeElse + '.' + arr[arr.length - 1],
+          /* 必须 */
+          StorageClass: 'STANDARD',
+          Body: file, // 上传文件对象
+          onProgress: function (progressData) {
+            //进度条方法
+
+            that.percent = progressData.percent * 100
+          },
+          onTaskReady: function (tid) {
+            // console.log('onTaskReady', tid);
+          },
+          onTaskStart: function (info) {
+            //开始上传
+            // console.log('onTaskStart', info);
+          },
+        },
+        function (err, data) {
+          if (err) {
+            that.loadingElse = false
+            that.$message.error('上传失败!!!' + err)
+            return
+          }
+          // alert('成功')
+          that.loadingElse = false
+          if (that.fileList.length < that.fileCount) {
+            that.fileList.push({
+              uid: file.name,
+              name: file.name,
+              status: 'done',
+              url: '//' + data.Location,
+            })
+
+            // that.$emit('overUpload', that.fileList.map(item => {
+            //                 return item.url
+            //               }))
+            that.$emit('overUpload', that.fileList)
+
+            if (that.multiple) {
+              that.$emit(
+                'update:value',
+                that.fileList.map((item) => {
+                  return item.url
+                })
+              )
+            } else {
+              that.$emit(
+                'update:value',
+                that.fileList.map((item) => {
+                  return item.url
+                })[0]
+              )
+            }
+          } else {
+            that.$message.error('上传已达上限' + that.fileCount + '张')
+          }
+        }
+      )
+    },
+  },
+}
+</script>
+<style scoped>
+@import '~@assets/less/common.less';
+</style>

+ 351 - 27
src/views/modules/autoLaunch/channelManage/createChannel.vue

@@ -1,4 +1,7 @@
 <style scoped lang="scss">
+/deep/.vue-treeselect__control {
+    line-height: 36px !important;
+}
 .account-item {
     /deep/ .ant-form-item-control {
         line-height: 1;
@@ -212,7 +215,7 @@ li.chouzhen.first:before {
             <div class="chartBox">
                 <a-row :gutter="20">
                     <a-col :sm="24" style="margin-bottom: 20px; z-index: 10" id="container">
-                        <a-card class="search-box step-jump" title="选择账户">
+                        <a-card class="search-box step-jump">
                             <a-form layout="horizontal" v-bind="formItemLayout" :form="formProject">
                                 <a-row :gutter="16">
                                     <a-col :span="16">
@@ -239,38 +242,30 @@ li.chouzhen.first:before {
                                 >
                                     <a-col :span="16">
                                         <a-form-item label="选择项目">
-                                            <a-radio-group
-                                                button-style="solid"
+                                            <Treeselect
+                                                style="width:600px"
                                                 v-decorator="[
                                                     'projectId',
                                                     {
-                                                        rules: [{ required: true, message: '使用范围必选' }],
-                                                        initialValue: 1
+                                                        rules: [{ required: true, message: '项目必选' }]
                                                     }
                                                 ]"
-                                            >
-                                                <a-radio-button :value="1">账户</a-radio-button>
-                                                <a-radio-button :value="2">项目</a-radio-button>
-                                            </a-radio-group>
+                                            />
                                         </a-form-item>
                                     </a-col>
                                 </a-row>
                                 <a-row :gutter="16" v-else>
                                     <a-col :span="16">
                                         <a-form-item label="选择账户">
-                                            <a-radio-group
-                                                button-style="solid"
+                                            <treeSelectAccount
+                                                style="width:600px"
                                                 v-decorator="[
                                                     'accountId',
                                                     {
-                                                        rules: [{ required: true, message: '使用范围必选' }],
-                                                        initialValue: 1
+                                                        rules: [{ required: true, message: '账户必选' }]
                                                     }
                                                 ]"
-                                            >
-                                                <a-radio-button :value="1">账户</a-radio-button>
-                                                <a-radio-button :value="2">项目</a-radio-button>
-                                            </a-radio-group>
+                                            />
                                         </a-form-item>
                                     </a-col>
                                 </a-row>
@@ -296,8 +291,6 @@ li.chouzhen.first:before {
                                         </a-form-item>
                                     </a-col>
                                 </a-row>
-                                {{getFormData('numberMin')}}
-                                {{getFormData('numberMax')}}
                                 <a-row :gutter="16">
                                     <a-col :span="16">
                                         <a-form-item label="编号">
@@ -305,7 +298,13 @@ li.chouzhen.first:before {
                                                 v-decorator="[
                                                     'numberMin',
                                                     {
-                                                        rules: [{ required: true, message: '编号位数限制必填' }]
+                                                        rules: [
+                                                            {
+                                                                required: true,
+                                                                message: '请输入正确的编号',
+                                                                validator: numberMinCheck
+                                                            }
+                                                        ]
                                                     }
                                                 ]"
                                                 :precision="0"
@@ -317,9 +316,15 @@ li.chouzhen.first:before {
                                                 v-decorator="[
                                                     'numberMax',
                                                     {
-                                                        rules: [{ required: true, message: '编号位数限制12312' }]
+                                                        rules: [
+                                                            {
+                                                                required: true,
+                                                                message: '编号位数限制12312'
+                                                            }
+                                                        ]
                                                     }
                                                 ]"
+                                                @change="numberMaxCheck"
                                                 :precision="0"
                                                 :min="1"
                                                 :max="100"
@@ -327,12 +332,226 @@ li.chouzhen.first:before {
                                         </a-form-item>
                                     </a-col>
                                 </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="渠道号">
+                                            <a-input
+                                                v-decorator="[
+                                                    'channelCode',
+                                                    { rules: [{ required: true, message: '请填写渠道号' }] }
+                                                ]"
+                                                allow-clear
+                                                id="channelCode"
+                                            />
+                                        </a-form-item>
+                                        <a-form-item v-bind="tailFormItemLayout">
+                                            <a-tag
+                                                color="#2db7f5"
+                                                @click="getChangeAll('渠道号', 'formProject', 'channelCode')"
+                                                >+渠道号</a-tag
+                                            >
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="渠道号名称">
+                                            <a-input
+                                                v-decorator="[
+                                                    'channelName',
+                                                    { rules: [{ required: true, message: '请填写渠道号' }] }
+                                                ]"
+                                                allow-clear
+                                                id="channelName"
+                                            />
+                                        </a-form-item>
+                                        <a-form-item v-bind="tailFormItemLayout">
+                                            <a-tag
+                                                color="#2db7f5"
+                                                @click="getChangeAll('渠道号', 'formProject', 'channelName')"
+                                                >+渠道号</a-tag
+                                            >
+                                            <a-tag
+                                                color="#2db7f5"
+                                                @click="getChangeAll('编号', 'formProject', 'channelName')"
+                                                >+编号</a-tag
+                                            >
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="下载链接">
+                                            <a-button type="primary" @click="addNewApp">添加应用</a-button>
+                                        </a-form-item>
+                                        <a-form-item v-bind="tailFormItemLayout">
+                                            <span style="color:red">由于快手API限制,每天最多新建300个应用包</span>
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="调起链接">
+                                            <a-input
+                                                v-decorator="[
+                                                    'url',
+                                                    {
+                                                        rules: [{ validator: handleConfirmValueOkUndefind }]
+                                                    }
+                                                ]"
+                                                allow-clear
+                                                id="url"
+                                            />
+                                        </a-form-item>
+                                        <a-form-item v-bind="tailFormItemLayout">
+                                            <a-tag color="#2db7f5" @click="getChangeAll('渠道号', 'formProject', 'url')"
+                                                >+渠道号</a-tag
+                                            >
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="第三方点击监测链接">
+                                            <a-input
+                                                v-decorator="[
+                                                    'clickTrackUrl',
+                                                    {
+                                                        rules: [
+                                                            { required: true, message: '请填写第三方点击监测链接' },
+                                                            { validator: handleConfirmValue }
+                                                        ]
+                                                    }
+                                                ]"
+                                                allow-clear
+                                                id="clickTrackUrl"
+                                            />
+                                        </a-form-item>
+                                        <a-form-item v-bind="tailFormItemLayout">
+                                            <a-tag
+                                                color="#2db7f5"
+                                                @click="getChangeAll('渠道号', 'formProject', 'clickTrackUrl')"
+                                                >+渠道号</a-tag
+                                            >
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="第三方actionBar监测链接">
+                                            <a-input
+                                                v-decorator="[
+                                                    'actionbarClickUrl',
+                                                    {
+                                                        rules: [
+                                                            {
+                                                                required: true,
+                                                                message: '请填写第三方actionBar监测链接'
+                                                            },
+                                                            { validator: handleConfirmValue }
+                                                        ]
+                                                    }
+                                                ]"
+                                                allow-clear
+                                                id="actionbarClickUrl"
+                                            />
+                                        </a-form-item>
+                                        <a-form-item v-bind="tailFormItemLayout">
+                                            <a-tag
+                                                color="#2db7f5"
+                                                @click="getChangeAll('渠道号', 'formProject', 'actionbarClickUrl')"
+                                                >+渠道号</a-tag
+                                            >
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="是否关联单品">
+                                            <a-radio-group
+                                                button-style="solid"
+                                                v-decorator="[
+                                                    'isHaveItem',
+                                                    {
+                                                        rules: [{ required: true, message: '是否关联单品必选' }],
+                                                        initialValue: 1
+                                                    }
+                                                ]"
+                                            >
+                                                <a-radio-button :value="1">是</a-radio-button>
+                                                <a-radio-button :value="0">否</a-radio-button>
+                                            </a-radio-group>
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="使用层级">
+                                            <a-radio-group
+                                                button-style="solid"
+                                                v-decorator="[
+                                                    'usageLevel',
+                                                    {
+                                                        rules: [{ required: true, message: '使用层级必选' }],
+                                                        initialValue: 'account'
+                                                    }
+                                                ]"
+                                            >
+                                                <a-radio-button value="account">账户</a-radio-button>
+                                                <a-radio-button value="plan">计划</a-radio-button>
+                                                <a-radio-button value="group">组</a-radio-button>
+                                            </a-radio-group>
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="是否循环使用">
+                                            <a-radio-group
+                                                button-style="solid"
+                                                v-decorator="[
+                                                    'isCycle',
+                                                    {
+                                                        rules: [{ required: true, message: '使用层级必选' }],
+                                                        initialValue: 1
+                                                    }
+                                                ]"
+                                            >
+                                                <a-radio-button :value="1">是</a-radio-button>
+                                                <a-radio-button :value="0">否</a-radio-button>
+                                            </a-radio-group>
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="循环使用次数">
+                                            <a-input-number
+                                                v-decorator="[
+                                                    'cycleTimes',
+                                                    {
+                                                        rules: [
+                                                            {
+                                                                required: getFormData('isCycle') == 0 ? false : true,
+                                                                message: '请输入循环使用次数'
+                                                            }
+                                                        ]
+                                                    }
+                                                ]"
+                                                :precision="0"
+                                                :min="1"
+                                                :max="999"
+                                            />
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
                             </a-form>
                         </a-card>
                     </a-col>
                 </a-row>
             </div>
         </a-spin>
+        <creatApplication ref="application" @getDataList="getDataAll" />
     </div>
 </template>
 
@@ -342,13 +561,16 @@ li.chouzhen.first:before {
 import Logo from '@/components/tools/Logo.vue'
 import pick from 'lodash.pick'
 import { mixin } from '@/utils/mixin.js'
-import Treeselect from './components/treeSelectAccount.vue'
+import Treeselect from './components/treeSelectProject.vue'
+import treeSelectAccount from './components/treeSelectAccount.vue'
+
 import moment from 'moment'
 import selectCheckAll from '@/components/formComponents/toutiaoTime'
 import checkBoxGroup from '@/components/formComponents/checkBoxGroup'
 import uploadFile from '@/components/uploadFileMd5Push.vue'
 import { stopOtherVideo, closeAllVideoFun } from '@/utils/videoControl' // 停止除当前外的其他视频播放,及停止所有视频播放的方法
 import selectTable from '@/views/modules/Statistics/components/selectPagination.vue'
+import creatApplication from './components/creatApplication.vue'
 // import EditableCell from './editablCell'
 // import lookPreviewVue from './lookPreview.vue'
 function tqFun(qcArr1) {
@@ -403,12 +625,15 @@ export default {
         selectCheckAll,
         checkBoxGroup,
         uploadFile,
-        selectTable
+        selectTable,
+        treeSelectAccount,
+        creatApplication
         // EditableCell
     },
     mixins: [mixin],
     data() {
         return {
+            projectId: null,
             spinning: false,
             accountIds: [],
             fansStarOptions: [],
@@ -424,14 +649,14 @@ export default {
             loading: false,
             formProject: this.$form.createForm(this), //选择项目表单
             formItemLayout: {
-                labelCol: { span: 4 },
+                labelCol: { span: 6 },
                 wrapperCol: { span: 16 }
             },
             tailFormItemLayout: {
                 wrapperCol: {
                     sm: {
-                        span: 20,
-                        offset: 4
+                        span: 18,
+                        offset: 6
                     }
                 }
             }
@@ -454,7 +679,106 @@ export default {
     filters: {},
     methods: {
         moment,
-
+        getDataAll(form) {},
+        addNewApp() {
+            this.$refs.application.showApplication()
+        },
+        getChangeAll(type, form, field) {
+            var node = document.getElementById(field)
+            var v = '-{{' + type + '}}-'
+            if (document.selection) {
+                //IE
+                node.focus()
+                var sel = document.selection.createRange()
+                sel.text = v
+                sel.select()
+                if (field == 'channelName') {
+                    this[form].setFieldsValue({ channelName: sel.text })
+                } else if (field == 'channelCode') {
+                    this[form].setFieldsValue({ channelCode: sel.text })
+                } else if (field == 'url') {
+                    this[form].setFieldsValue({ url: sel.text })
+                } else if (field == 'clickTrackUrl') {
+                    this[form].setFieldsValue({ clickTrackUrl: sel.text })
+                } else if (field == 'actionbarClickUrl') {
+                    this[form].setFieldsValue({ actionbarClickUrl: sel.text })
+                }
+            } else if (node.selectionStart || node.selectionStart == '0') {
+                //MOZILLA/GOOGLE
+                var startPos = node.selectionStart
+                var endPos = node.selectionEnd
+                var restoreTop = node.scrollTop
+                node.value = node.value.substring(0, startPos) + v + node.value.substring(endPos, node.value.length)
+                if (restoreTop > 0) {
+                    node.scrollTop = restoreTop
+                }
+                if (field == 'channelName') {
+                    this[form].setFieldsValue({ channelName: node.value })
+                } else if (field == 'channelCode') {
+                    this[form].setFieldsValue({ channelCode: node.value })
+                } else if (field == 'url') {
+                    this[form].setFieldsValue({ url: sel.text })
+                } else if (field == 'clickTrackUrl') {
+                    this[form].setFieldsValue({ clickTrackUrl: sel.text })
+                } else if (field == 'actionbarClickUrl') {
+                    this[form].setFieldsValue({ actionbarClickUrl: sel.text })
+                }
+                node.focus()
+                node.selectionStart = startPos + v.length
+                node.selectionEnd = startPos + v.length
+                // this.channelName = node.value
+            } else {
+                //OTHER
+                node.value += v
+                // console.log(node.value)
+                if (field == 'channelName') {
+                    this[form].setFieldsValue({ channelName: node.value })
+                } else if (field == 'channelCode') {
+                    this[form].setFieldsValue({ channelCode: node.value })
+                } else if (field == 'url') {
+                    this[form].setFieldsValue({ url: sel.text })
+                } else if (field == 'clickTrackUrl') {
+                    this[form].setFieldsValue({ clickTrackUrl: sel.text })
+                } else if (field == 'actionbarClickUrl') {
+                    this[form].setFieldsValue({ actionbarClickUrl: sel.text })
+                }
+                node.focus()
+                // this.channelName = node.value
+            }
+        },
+        handleConfirmValue(rule, value, callback) {
+            if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) && value != '') {
+                callback()
+            } else {
+                callback('链接不能为空且开头为http://或https://')
+            }
+        },
+        handleConfirmValueOkUndefind(rule, value, callback) {
+            if (/(http|https):\/\/([\w.]+\/?)\S*/.test(value) || value == '') {
+                callback()
+            } else {
+                callback('链接开头为http://或https://')
+            }
+        },
+        numberMinCheck(rule, value, callback) {
+            if (value == '' || value == null) {
+                callback('请输入正确的编号')
+            } else if (this.getFormData('numberMax') && value > this.getFormData('numberMax')) {
+                callback('请输入正确的编号')
+            } else {
+                callback()
+            }
+        },
+        numberMaxCheck() {
+            // if (value == '' || value == null) {
+            //     callback('请输入最高出价')
+            // } else if (this.getFormData('numberMin') && value < this.getFormData('numberMin')) {
+            //     callback('该编号不能比前面小')
+            // } else {
+            //     callback()
+            // }
+            this.formProject.validateFields(['numberMin'])
+        },
         //获取表单的某一个属性值
         getFormData(className) {
             return this.formProject.getFieldValue(className)