Jelajahi Sumber

渠道号预存

朱鑫波 3 tahun lalu
induk
melakukan
a4202058f6

+ 59 - 0
src/views/modules/autoLaunch/channelManage/channelManage.less

@@ -0,0 +1,59 @@
+.channelManage {
+    .middle-button {
+        margin: 0 8px;
+    }
+    .divider {
+        height: 62px;
+    }
+    .showNumBox {
+        background: white;
+        overflow: hidden;
+        margin: 15px 0;
+        padding: 30px 0;
+        text-align: center;
+        .ant-card-body {
+            padding-top: 0;
+        }
+        .title {
+            font-size: 14px;
+            font-family: PingFangSC-Regular, PingFang SC;
+            font-weight: 400;
+            color: #999999;
+            line-height: 22px;
+            display: inline-block;
+        }
+    }
+    .tabbody {
+        background: white;
+        padding: 0 24px;
+        margin-bottom: 15px;
+        .ant-tabs-bar {
+            margin: 0;
+        }
+    }
+    .chartBox {
+        background: white;
+        padding: 20px 0;
+    }
+    .tableBody {
+        background: white;
+        padding: 20px;
+    }
+}
+.channel-modal-content {
+    width: 100%;
+    height: 300px;
+    display: flex;
+    flex-direction: column;
+    .channel-modal-content-button {
+        width: 100%;
+        height: 100%;
+        margin: 10px;
+        display: flex;
+        align-items: center;
+        .introduce{
+            margin-left: 10px;
+        }
+
+    }
+}

+ 304 - 0
src/views/modules/autoLaunch/channelManage/components/treeSelectAccount.vue

@@ -0,0 +1,304 @@
+<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="value"
+            :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 true
+            }
+        },
+        appId: {
+            default() {
+                return ''
+            }
+        },
+        //判断媒体类型
+        request: {
+            type: String,
+            default() {
+                return '2,4'
+            }
+        },
+        //一级请求接口
+        reqUrl: {
+            type: String,
+            default() {
+                return '/ctop/projectMember/participateListByMediaId'
+            }
+        },
+        // 展示条数
+        limit: {
+            type: Number,
+            default() {
+                return 2
+            }
+        },
+        disabled: {
+            type: Boolean,
+            default() {
+                return false
+            }
+        }
+    },
+    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
+                }
+            },
+            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.')
+                    }
+                })
+            }
+        },
+        emitValue(value, id) {
+            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/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.'))
+                    }
+                })
+            }
+        },
+        getParticipateList() {
+            //我参与的
+            //   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)
+                        }
+                    }
+                })
+            } 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]
+                                })
+                            }
+                            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 = '暂无数据'
+                        }
+                    }
+                })
+            }
+        }
+    },
+
+    mounted() {
+        this.getParticipateList()
+    }
+}
+</script>

+ 589 - 0
src/views/modules/autoLaunch/channelManage/createChannel.vue

@@ -0,0 +1,589 @@
+<style scoped lang="scss">
+.account-item {
+    /deep/ .ant-form-item-control {
+        line-height: 1;
+    }
+}
+
+/deep/.display-none-selset {
+    display: none !important;
+}
+// .step-jump {
+//     /deep/ table tr td {
+//         border-bottom: 0px;
+//     }
+// }
+.bottom-to-one {
+    /deep/ .ant-form-item {
+        margin-bottom: 0;
+    }
+}
+.target-person-add-button {
+    margin-left: 15px;
+}
+.card-person {
+    width: 300px;
+    /deep/.ant-card-body {
+        padding: 0px;
+    }
+    /deep/.ant-card-head {
+        padding: 0px 10px;
+    }
+    .card-main-case {
+        height: 250px;
+        overflow: auto;
+        padding: 0 5px;
+    }
+}
+.card-person-drawer {
+    width: 100%;
+    height: 90%;
+    overflow: hidden;
+    padding: 10px 0px;
+    display: flex;
+    flex-wrap: wrap;
+    margin-right: -10px;
+    justify-content: space-between;
+    .card-item {
+        width: calc(33% - 10px);
+        margin-bottom: 10px;
+        float: left;
+    }
+    .card-item-else {
+        width: calc(20% - 10px);
+        margin-bottom: 10px;
+        float: left;
+    }
+}
+.showShare {
+    position: relative;
+}
+.share {
+    display: none;
+}
+.showShare:hover .share {
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.chouzhen {
+    border-style: solid;
+    border-width: 1px;
+    border-color: #e4e4e4;
+    width: calc(20% - 10px);
+    padding: 10px;
+    margin-right: 10px;
+    margin-bottom: 10px;
+    display: flex;
+    align-items: center;
+    background: #fff;
+    position: relative;
+    z-index: 99;
+    float: left;
+}
+
+li.chouzhen.first:before {
+    font-size: 12px;
+    content: '首帧';
+    position: absolute;
+    top: 7px;
+    left: 5px;
+    width: 36px;
+    height: 20px;
+    color: rgb(255, 255, 255);
+    line-height: 20px;
+    text-align: center;
+    background: rgba(0, 0, 0, 0.5);
+    border-radius: 2px;
+    z-index: 1000;
+}
+.display-none-selset {
+    display: none !important;
+}
+.logo {
+    padding-left: 24px;
+    img {
+        height: 32px !important;
+    }
+    .name {
+        font-size: 14px;
+        font-family: PingFangSC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #ced2d9;
+        // line-height: 22px;
+        margin-left: 20px;
+        padding-left: 21px;
+        position: relative;
+    }
+    .name::before {
+        content: '';
+        width: 1px;
+        height: 18px;
+        background: rgba(255, 255, 255, 0.31);
+        position: absolute;
+        left: 0;
+        top: 50%;
+        margin-top: -9px;
+    }
+}
+.chartBox {
+    .chartBody {
+        display: flex;
+        justify-content: space-around;
+        flex-wrap: wrap;
+    }
+    .search-box {
+        margin-bottom: 20px;
+    }
+}
+
+/deep/ .ant-descriptions-item-content {
+    font-weight: bold;
+}
+
+.info-detail {
+    /deep/ table tr td {
+        border: 0;
+    }
+    /deep/ .ant-descriptions-item-label {
+        color: darkgray;
+        // min-width: 30px;
+        white-space: nowrap;
+    }
+}
+.flex-main {
+    display: flex;
+    margin-bottom: 10px;
+    p {
+        color: black;
+        font-weight: 600;
+        overflow: hidden; //超出的文本隐藏
+        text-overflow: ellipsis; //溢出用省略号显示
+        white-space: nowrap; //溢出不换行
+    }
+}
+</style>
+<style lang="scss">
+.hide-checkbox .ant-table-thead .ant-table-selection {
+    display: none;
+}
+.new-batch .ant-card-head-title {
+    font-weight: 700;
+}
+// .new-batch textarea {
+//   resize: none;
+//   border: none;
+//   outline: 0;
+//   box-shadow: none;
+// }
+.create-info .ant-form-item {
+    margin-bottom: 0 !important;
+}
+.fengmian .ant-checkbox-wrapper:first-child {
+    margin-left: 8px;
+}
+@media screen and (max-width: 1200px) {
+    // 这里写对应要修改的样式如:
+    .new-batch .el-step__title {
+        font-size: 12px;
+    }
+}
+.line-height-one .ant-form-item-control {
+    line-height: inherit;
+}
+.creat-all-info .ant-form-item-control {
+    width: 60%;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+.config-new-batch {
+    .display-none-selset {
+        display: none !important;
+    }
+    .ant-btn-danger {
+        background-color: #ff4d4f !important;
+    }
+}
+</style>
+<template>
+    <div ref="questionnaireBox" class="new-batch config-new-batch">
+        <a-spin :spinning="spinning">
+            <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-form layout="horizontal" v-bind="formItemLayout" :form="formProject">
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="使用范围">
+                                            <a-radio-group
+                                                button-style="solid"
+                                                v-decorator="[
+                                                    'usageRange',
+                                                    {
+                                                        rules: [{ required: true, message: '使用范围必选' }],
+                                                        initialValue: 2
+                                                    }
+                                                ]"
+                                            >
+                                                <a-radio-button :value="2">项目</a-radio-button>
+                                                <a-radio-button :value="1">账户</a-radio-button>
+                                            </a-radio-group>
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                <a-row
+                                    :gutter="16"
+                                    v-if="getFormData('usageRange') == 2 || getFormData('usageRange') == undefined"
+                                >
+                                    <a-col :span="16">
+                                        <a-form-item label="选择项目">
+                                            <a-radio-group
+                                                button-style="solid"
+                                                v-decorator="[
+                                                    'projectId',
+                                                    {
+                                                        rules: [{ required: true, message: '使用范围必选' }],
+                                                        initialValue: 1
+                                                    }
+                                                ]"
+                                            >
+                                                <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"
+                                                v-decorator="[
+                                                    'accountId',
+                                                    {
+                                                        rules: [{ required: true, message: '使用范围必选' }],
+                                                        initialValue: 1
+                                                    }
+                                                ]"
+                                            >
+                                                <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">
+                                    <a-col :span="16">
+                                        <a-form-item label="编号位数">
+                                            <a-select
+                                                style="width:300px"
+                                                allowClear
+                                                v-decorator="[
+                                                    'numberLength',
+                                                    {
+                                                        rules: [{ required: true, message: '编号位数限制必选' }],
+                                                        initialValue: 0
+                                                    }
+                                                ]"
+                                            >
+                                                <a-select-option :value="0">不限制</a-select-option>
+                                                <a-select-option :value="3">三位数</a-select-option>
+                                                <a-select-option :value="4">四位数</a-select-option>
+                                                <a-select-option :value="5">五位数</a-select-option>
+                                            </a-select>
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                                {{getFormData('numberMin')}}
+                                {{getFormData('numberMax')}}
+                                <a-row :gutter="16">
+                                    <a-col :span="16">
+                                        <a-form-item label="编号">
+                                            <a-input-number
+                                                v-decorator="[
+                                                    'numberMin',
+                                                    {
+                                                        rules: [{ required: true, message: '编号位数限制必填' }]
+                                                    }
+                                                ]"
+                                                :precision="0"
+                                                :min="1"
+                                                :max="100"
+                                            />
+                                            ~
+                                            <a-input-number
+                                                v-decorator="[
+                                                    'numberMax',
+                                                    {
+                                                        rules: [{ required: true, message: '编号位数限制12312' }]
+                                                    }
+                                                ]"
+                                                :precision="0"
+                                                :min="1"
+                                                :max="100"
+                                            />
+                                        </a-form-item>
+                                    </a-col>
+                                </a-row>
+                            </a-form>
+                        </a-card>
+                    </a-col>
+                </a-row>
+            </div>
+        </a-spin>
+    </div>
+</template>
+
+<script>
+//   import UserMenu from '../tools/UserMenu'
+//   import SMenu from '../menu/'
+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 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 EditableCell from './editablCell'
+// import lookPreviewVue from './lookPreview.vue'
+function tqFun(qcArr1) {
+    var tempArr = []
+    function bbFun(qcArr) {
+        for (var i = 0; i < qcArr.length; i++) {
+            if (qcArr[i] instanceof Array) {
+                bbFun(qcArr[i])
+            } else {
+                tempArr.push(qcArr[i])
+            }
+        }
+        return tempArr
+    }
+    return bbFun(qcArr1)
+}
+
+let optionsAppActive = []
+let businessOptions = []
+let interestVideoOptions = []
+let retargetColumns = [
+    {
+        title: '人群包',
+        dataIndex: 'name',
+        sorter: true,
+        width: '40%',
+        scopedSlots: { customRender: 'name' }
+    },
+    {
+        title: '属性',
+        dataIndex: 'populationType',
+        scopedSlots: {
+            customRender: 'populationType'
+        },
+        width: 200
+    },
+    {
+        title: '所属账号',
+        dataIndex: 'accountId',
+        sorter: true,
+        width: '40%',
+        scopedSlots: { customRender: 'accountId' }
+    }
+]
+export default {
+    name: 'GlobalHeader',
+    components: {
+        //   UserMenu,
+        //   SMenu,
+        Logo,
+        Treeselect,
+        selectCheckAll,
+        checkBoxGroup,
+        uploadFile,
+        selectTable
+        // EditableCell
+    },
+    mixins: [mixin],
+    data() {
+        return {
+            spinning: false,
+            accountIds: [],
+            fansStarOptions: [],
+            fansStarType: 0,
+            deviceType: 0,
+            priceType: 0,
+            customCrowd: '0',
+            tabKey: '0',
+            retargetDataAll: [],
+            finallyRightTree: [],
+            retargetColumns,
+            activeKey: '',
+            loading: false,
+            formProject: this.$form.createForm(this), //选择项目表单
+            formItemLayout: {
+                labelCol: { span: 4 },
+                wrapperCol: { span: 16 }
+            },
+            tailFormItemLayout: {
+                wrapperCol: {
+                    sm: {
+                        span: 20,
+                        offset: 4
+                    }
+                }
+            }
+        }
+    },
+    computed: {},
+    watch: {},
+    mounted() {
+        this.$nextTick(function() {
+            window.addEventListener('scroll', this.onScroll)
+            const that = this
+            window.onresize = () => {
+                return (() => {
+                    window.screenWidth = document.body.clientWidth
+                    that.screenWidth = window.screenWidth
+                })()
+            }
+        })
+    },
+    filters: {},
+    methods: {
+        moment,
+
+        //获取表单的某一个属性值
+        getFormData(className) {
+            return this.formProject.getFieldValue(className)
+        },
+        onScroll() {
+            // var box = document.getElementById('box')
+            // var t = document.documentElement.scrollTop || document.body.scrollTop
+            // box.style.top = t + 'px'
+
+            var jump = document.querySelectorAll('.step-jump')
+            var distance =
+                document.documentElement.scrollTop + 180 || window.pageYOffset + 180 || document.body.scrollTop + 180
+            jump.forEach((item, index) => {
+                if (distance >= item.offsetTop) {
+                    this.activeStep = index
+                }
+            })
+        },
+        // 锚点点击
+        jump(index) {
+            this.activeStep = index
+            // 用 class=".step-jump" 添加锚点,此时的类名要放在tr上,放在td上不对,
+            // 以后做的时候要注意这点,不是表格的时候,如何放置锚点
+            let jump = document.querySelectorAll('.step-jump')
+            // 通过 offsetTop 获取对象到窗体顶部的距离,然后赋值给 scrollTop,就能实现锚点的功能
+            let total = jump[index].offsetTop
+            // scrollTop滚动条距离页面的距离
+            let distance = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop
+            // 平滑滚动,时长500ms,每10ms一跳,共50跳
+            let step = total / 50
+            if (total > distance) {
+                smoothDown()
+            } else {
+                let newTotal = distance - total
+                step = newTotal / 50
+                smoothUp()
+            }
+            function smoothDown() {
+                if (distance < total) {
+                    distance += step
+                    document.body.scrollTop = distance
+                    document.documentElement.scrollTop = distance
+                    window.pageYOffset = distance
+                    setTimeout(smoothDown, 5)
+                } else {
+                    document.body.scrollTop = total
+                    document.documentElement.scrollTop = total
+                    window.pageYOffset = total
+                }
+            }
+            function smoothUp() {
+                if (distance > total) {
+                    distance -= step
+                    document.body.scrollTop = distance
+                    document.documentElement.scrollTop = distance
+                    window.pageYOffset = distance
+                    setTimeout(smoothUp, 10)
+                } else {
+                    document.body.scrollTop = total
+                    document.documentElement.scrollTop = total
+                    window.pageYOffset = total
+                }
+            }
+        },
+
+        getData(className, formName) {
+            return this[formName].getFieldValue(className)
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+/* update_begin author:scott date:20190220 for: 缩小首页布局顶部的高度*/
+
+$height: 59px;
+.layout .header .user-wrapper .action .anticon,
+.layout .top-nav-header-index .user-wrapper .action .anticon {
+    color: #999;
+}
+.layout .header .user-wrapper .action .anticon,
+.layout .top-nav-header-index .user-wrapper .action .anticon {
+    color: #999;
+}
+.layout {
+    .top-nav-header-index {
+        .header-index-wide {
+            margin-left: 10px;
+
+            .ant-menu.ant-menu-horizontal {
+                height: $height;
+                line-height: $height;
+            }
+        }
+
+        .trigger {
+            line-height: 48px;
+            font-size: 17px;
+            &:hover {
+                background: rgba(0, 0, 0, 0.05);
+            }
+        }
+    }
+
+    .header {
+        z-index: 2;
+        color: #999;
+        height: $height;
+        background-color: #1890ff;
+        transition: background 300ms;
+
+        /* dark 样式 */
+        &.dark {
+            color: #000000;
+            box-shadow: 0 0 4px rgba(0, 0, 0, 0.2);
+            background-color: white !important;
+        }
+    }
+
+    .header,
+    .top-nav-header-index {
+        &.dark .trigger:hover {
+            background: rgba(0, 0, 0, 0.05);
+        }
+    }
+}
+
+.ant-layout-header {
+    height: $height;
+    line-height: $height;
+}
+</style>

+ 644 - 0
src/views/modules/autoLaunch/channelManage/index.vue

@@ -0,0 +1,644 @@
+<style lang="scss" scoped>
+.search-bar {
+    display: flex;
+    align-items: center;
+}
+.search-box p {
+    display: inline-block;
+    border: 1px solid #f2f2f2;
+    border-radius: 5px;
+    margin-right: 10px;
+    padding: 5px 10px;
+    cursor: pointer;
+}
+</style>
+<style scoped>
+.showNumBox {
+    margin: 10px 0;
+}
+.showNumBox .ant-card-body {
+    display: flex;
+    justify-content: center;
+}
+.showNumBox p,
+.showNumBox span {
+    text-align: center;
+    line-height: 40px;
+    font-size: 30px;
+    font-weight: 600;
+    color: red;
+    margin: 0;
+}
+.search-box .ant-card-body {
+    padding: 5px 15px;
+}
+.showNumBox .ant-card-body .styleElse {
+    line-height: 60px;
+    height: 40px;
+    font-size: 16px;
+    font-weight: 400;
+    margin-left: 10px;
+}
+.ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
+    display: none !important;
+}
+.yincang .ant-col-6 p {
+    text-align: left;
+    color: red;
+    font-size: 16px;
+    font-weight: 500;
+}
+.ant-table-thead div {
+    font-weight: 700;
+}
+.tool-tip {
+    position: absolute;
+    top: 65px;
+    right: 10px;
+}
+</style>
+<style lang="less" scoped>
+.ant-card-head .ant-tabs-bar {
+    padding: 0;
+}
+.search-box .ant-card-body {
+    padding: 5px 15px;
+}
+.search-box {
+    padding: 15px 10px;
+}
+.search-box p {
+    display: inline-block;
+    border: 1px solid #f2f2f2;
+    border-radius: 5px;
+    margin-right: 10px;
+    padding: 5px 10px;
+    cursor: pointer;
+}
+.statistics .ant-col-6 .ant-card-body .styleElse {
+    line-height: 60px;
+    height: 40px;
+    font-size: 16px;
+    font-weight: 400;
+    margin-left: 10px;
+}
+.ant-modal-wrap .yincang .ant-modal-content .ant-modal-footer {
+    display: none !important;
+}
+.yincang .ant-col-6 p {
+    text-align: left;
+    color: red;
+    font-size: 16px;
+    font-weight: 500;
+}
+.ant-table-thead div {
+    font-weight: 700;
+}
+.tool-tip {
+    position: absolute;
+    top: 65px;
+    right: 10px;
+}
+.statistics {
+    .ant-card-bordered {
+        border: none;
+    }
+    .ant-card-head .ant-tabs {
+        clear: both;
+        margin-bottom: -13px;
+        color: rgba(0, 0, 0, 0.65);
+        font-weight: normal;
+        font-size: 14px;
+    }
+    .duibi {
+        position: absolute;
+        right: 24px;
+        top: 15px;
+    }
+    p {
+        margin-bottom: 0;
+    }
+}
+</style>
+
+<style lang="less" scoped>
+@import 'channelManage';
+</style>
+<template>
+    <div class="channelManage config-project">
+        <a-card>
+            <div class="table-page-search-wrapper">
+                <a-form layout="inline" :form="form" hide-required-mark :selfUpdate="true" @submit="handleQueryList">
+                    <a-row :gutter="24">
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <!-- <a-form-item label="项目名称"> -->
+                            <selectTable :projectId.sync="productId" ref="selectTable"></selectTable>
+                        </a-col>
+
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <selectTableProject
+                                :projectId.sync="projectId"
+                                :productId="productId"
+                                ref="selectTableProject"
+                            ></selectTableProject>
+                        </a-col>
+                        <!--  -->
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <a-form-item label="账户ID">
+                                <a-input placeholder="请输入账户ID" v-decorator="['accountId']"></a-input>
+                            </a-form-item>
+                        </a-col>
+                        <a-col :md="8" :sm="8" :xxl="6">
+                            <span style="float: left; overflow: hidden" class="table-page-search-submitButtons">
+                                <a-button type="primary" icon="search" @click="handleQueryList">查询</a-button>
+                                <a-button type="primary" @click="handleResetForm" icon="reload" class="middle-button"
+                                    >重置</a-button
+                                >
+                                <a-button type="primary" icon="plus" @click="addNewChannel">新建渠道号</a-button>
+                            </span>
+                        </a-col>
+                    </a-row>
+                </a-form>
+            </div>
+        </a-card>
+
+        <a-row style="margin-bottom:15px;margin-top:12px">
+            <a-col :span="24">
+                <div class="tableBody" style="min-height:200px;padding-bottom: 50px">
+                    <a-table
+                        :columns="columns"
+                        :dataSource="dataSource"
+                        :pagination="false"
+                        :loading="dataLoading"
+                        bordered
+                        @change="tableChange"
+                        size="middle"
+                        style="word-break: break-all;font-size:16px;font-weight:600"
+                        id="outTable"
+                        ref="accountTable"
+                    >
+                        <span slot="action" slot-scope="text, records">
+                            <a>添加渠道号</a>
+                            <a-divider type="vertical" />
+                            <a>查看详情</a>
+                        </span>
+                    </a-table>
+                    <a-pagination
+                        size="small"
+                        :showTotal="ipagination.showTotal"
+                        style="float: right;margin-top:10px"
+                        v-if="dataSource.length > 0"
+                        showQuickJumper
+                        :pageSize.sync="ipagination.pageSize"
+                        :total="ipagination.total"
+                        v-model="ipagination.current"
+                        @change="getDataSource"
+                    />
+                </div>
+            </a-col>
+        </a-row>
+
+        <a-modal
+            title="选择新建方式"
+            :width="800"
+            ref="modal"
+            :visible="visibleChannel"
+            @ok="handleOk"
+            @cancel="handleCancel"
+            okText="下一步"
+        >
+            <a-radio-group v-model="channelType" button-style="solid" style="width:100%">
+                <div class="channel-modal-content">
+                    <div class="channel-modal-content-button">
+                        <a-radio-button value="a">
+                            系统生成
+                        </a-radio-button>
+                        <div class="introduce">
+                            适用于渠道号比较固定和简单的客户和产品,如渠道号为KS-001到KS-101
+                        </div>
+                    </div>
+                    <div class="channel-modal-content-button">
+                        <a-radio-button value="b">
+                            表格导入
+                        </a-radio-button>
+                        <div class="introduce">
+                            适用于渠道号相对复杂一些的客户和产品,或者无法用系统生成满足的情况
+                        </div>
+                    </div>
+                    <div class="channel-modal-content-button">
+                        <a-radio-button value="c">
+                            自定义填写
+                        </a-radio-button>
+                        <div class="introduce">
+                            适用于渠道号较少,不需要大量生成或者导入的客户和产品
+                        </div>
+                    </div>
+                </div>
+            </a-radio-group>
+        </a-modal>
+    </div>
+</template>
+
+<script>
+import { TreeSelect } from 'ant-design-vue'
+const SHOW_PARENT = TreeSelect.SHOW_PARENT
+import ARow from 'ant-design-vue/es/grid/Row'
+import ACol from 'ant-design-vue/es/grid/Col'
+import moment from 'moment'
+import { getKsAccountReport, getKsDetail, getReportList } from '@api/video.js'
+import { getAction, postAction, downFile, downFilePost } from '@/api/manage'
+import selectTable from '@/views/modules/material/comment/selectTable.vue'
+import selectTableProject from '@/views/modules/Statistics/components/selectPagination.vue'
+import qs from 'qs'
+
+let TTcolumns = [
+    {
+        title: '产品名称',
+        dataIndex: 'productName',
+        scopedSlots: { customRender: 'productName' },
+        align: 'center',
+        key: 'productName'
+    },
+    {
+        title: '项目名称',
+        dataIndex: 'projectName',
+        scopedSlots: { customRender: 'projectName' },
+        align: 'center',
+        key: 'projectName'
+    },
+
+    {
+        title: '账户ID',
+        dataIndex: 'accountId',
+        scopedSlots: { customRender: 'accountId' },
+        align: 'center',
+        key: 'accountId'
+    },
+    {
+        title: '渠道号创建人',
+        dataIndex: 'realname',
+        scopedSlots: { customRender: 'realname' },
+        align: 'center',
+        key: 'realname'
+    },
+
+    {
+        title: '创建时间(最新创建时间)',
+        dataIndex: 'stateDate',
+        scopedSlots: { customRender: 'stateDate' },
+        align: 'center',
+        key: 'stateDate'
+    },
+    {
+        title: '操作',
+        dataIndex: 'action',
+        scopedSlots: { customRender: 'action' },
+        align: 'center',
+        key: 'action'
+    }
+]
+
+export default {
+    components: {
+        ACol,
+        ARow,
+        selectTable,
+        selectTableProject
+    },
+
+    data() {
+        return {
+            productId: '',
+            projectId: '',
+            accountId: '',
+            visibleChannel: false,
+            channelType: 'a',
+            createType:1,
+            indexAll: 0,
+            spinning: false,
+            form: this.$form.createForm(this),
+            exportloading: false,
+            dateRange: [moment().subtract(1, 'weeks'), moment()],
+            noImg: require('@/assets/noImg.png'),
+            validationRules: {
+                bid: [
+                    {
+                        required: true,
+                        message: '出价信息必须填写'
+                        // validator: this.validateBid,
+                    }
+                ]
+            },
+            ipagination: {
+                current: 1,
+                pageSize: 10,
+                //   pageSizeOptions: ['10', '20', '30'],
+                showTotal: (total, range) => {
+                    return range[0] + '-' + range[1] + ' 共' + total + '条'
+                },
+                showQuickJumper: true,
+                showSizeChanger: true,
+                pageSizeOptions: ['10', '30', '50'],
+                total: 0,
+                onChange: (current, pageSize) => {
+                    // 切换分页时的回调,
+                    // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+                    this.ipagination.current = current
+                    this.ipagination.pageSize = pageSize
+                }
+            },
+            value: 'valid',
+            KSaccountList: [],
+            TTaccountList: [],
+
+            KSdesignList: [],
+            TTdesignList: [],
+
+            operateDisabled: false,
+            duration: 1000,
+            //treeselect的参数
+            treeValue: [],
+            treeData: [],
+            SHOW_PARENT,
+
+            type: 3,
+
+            operate: '',
+            designList: [],
+
+            tabKey: 1,
+
+            loading: false,
+            columns: [...TTcolumns],
+            dataSource: [],
+
+            tableTab: 1,
+
+            newPlan: 0,
+            effectPlan: 0,
+
+            openOptions: false,
+
+            target: 'createTime',
+            order: 'descend',
+            dataLoading: false,
+            url: '/channel/channelManagementHome',
+            modifyPriceVisible: false,
+            modifyPriceLoading: false,
+            modifyPriceDetail: null,
+            accountVisible: false,
+            againLoading: false,
+            accountProjectDetail: null,
+            accountProjectList: []
+        }
+    },
+    methods: {
+        moment,
+        newCreat(id) {
+            if (id) {
+                window.open('/creat-config?id=' + id, '_blank')
+            } else {
+                window.open('/creat-config', '_blank')
+            }
+        },
+
+        cpaBidValid(rule, value, callback) {
+            let z = /-/g
+            let a = /\//g
+            let d = /\./g
+            if (value === '' || value === undefined) {
+                callback('出价必须填写')
+            } else if (value.startsWith('.') || value.endsWith('.')) {
+                callback('请填写正确出价')
+            } else if (value.startsWith('-') || value.endsWith('-')) {
+                callback('请填写正确出价')
+            } else if (value.match(a) && value.match(z)) {
+                callback('不允许出现除"-"和"/"之外的所有字符,并且二者不可同时出现')
+            } else if (value.match(/[^0-9+-\/]/g)) {
+                callback('请填写正确出价')
+            } else {
+                callback()
+            }
+        },
+        handleOk() {
+            if (this.channelType == 'a') {
+                this.createType = 1
+                this.$router.push({ path: '/autoLaunch/createChannel' })
+            }
+        },
+        handleCancel() {
+            this.visibleChannel = false
+        },
+        addNewChannel() {
+            this.visibleChannel = true
+        },
+        getDataSource(current, pageSize) {
+            // 切换分页时的回调,
+            // 当在页面定义change事件时,切记要把此处的事件清除,因为这两个事件重叠了,可能到时候会导致一些莫名的bug
+            this.ipagination.current = current
+            this.ipagination.pageSize = pageSize
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        handleQueryList(event) {
+            this.ipagination.current = 1
+            event.preventDefault()
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        handleResetForm() {
+            this.ipagination.current = 1
+            this.form.resetFields()
+            this.$refs.selectTable.keyValue = ''
+            this.$refs.selectTable.getData()
+            this.$refs.selectTableProject.keyValue = ''
+            this.$refs.selectTableProject.getData()
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        handleGetTableList(data) {
+            let paramsData = {
+                productId: this.productId,
+                projectId: this.projectId,
+                accountId: data.accountId,
+                pageNo: this.ipagination.current,
+                pageSize: this.ipagination.pageSize
+            }
+            this.dataSource = []
+            this.dataLoading = true
+            this.getAction(this.url, paramsData)
+                .then(result => {
+                    this.dataLoading = false
+                    if (result.code === 200) {
+                        this.dataSource = result.result.list || []
+                        this.ipagination.total = result.pageInfo.total || 0
+                        // result.result.total
+                    } else {
+                        this.$message.error(result.message)
+                    }
+                })
+                .catch(error => {
+                    this.dataLoading = false
+                    console.log(error, 'eeee')
+                })
+        },
+        getAccountNoProject() {
+            this.projectId = undefined
+            const paramsData = this.form.getFieldsValue()
+            this.handleGetTableList(paramsData)
+        },
+        disabledDate(current) {
+            // Can not select days before today and today
+            return current && current > moment().endOf('day')
+        },
+        dateChange(date, dateString) {
+            // console.log(date,dateString)
+        },
+
+        filterOption(input, option) {
+            // console.log(input, option)
+            return option.componentOptions.children[0].text.toLowerCase().indexOf(input.toLowerCase()) >= 0
+        },
+        operateChange(value) {
+            console.log(value)
+            if (value) {
+                this.accountDisabled = true
+                this.accountId = ''
+            } else {
+                this.accountDisabled = false
+            }
+        },
+
+        tableChange(pagination, filters, sorter, { currentDataSource }) {
+            this.ipagination.current = pagination.current
+            this.ipagination.pageSize = pagination.pageSize
+            if (sorter.order) {
+                this.order = sorter.order ? sorter.order : 'descend'
+                this.target = sorter.columnKey
+                const paramsData = this.form.getFieldsValue()
+                this.handleGetTableList({
+                    ...paramsData,
+                    target: sorter.columnKey,
+                    order: sorter.order ? sorter.order : 'descend'
+                })
+            }
+        },
+
+        // 获取所有运营
+        getAllOperator(key) {
+            let url = '/sys/user/getAllUserListV1'
+            this.designList = []
+
+            getAction(url, {}).then(res => {
+                if (res.success) {
+                    this.designList = res.result
+                }
+            })
+        }
+    },
+    watch: {
+        productId: function(n, o) {
+            if (n != '') {
+                this.$refs.selectTableProject.keyValue = ''
+                this.$refs.selectTableProject.getData(n)
+            }
+        }
+    },
+    computed: {
+        newDate() {
+            var myDate = new Date()
+            myDate.getYear() //获取当前年份(2位)
+            var n = myDate.getFullYear() //获取完整的年份(4位,1970-????)
+            var m = myDate.getMonth() //获取当前月份(0-11,0代表1月)
+            var d = myDate.getDate() //获取当前日(1-31)
+            var day = myDate.getHours()
+            return day
+        }
+    },
+    mounted() {
+        const paramsData = this.form.getFieldsValue()
+        this.handleGetTableList(paramsData)
+        this.getAllOperator()
+    },
+    activated: function() {},
+
+    filters: {
+        toPercentage(val) {
+            if (typeof val != 'string') {
+                return (val * 100).toFixed(2) + '%'
+            } else {
+                return val
+            }
+        },
+        //保留两位小数并且变成货币格式
+        decimalsHandle(val) {
+            if (val && typeof val != 'string') {
+                if (val >= 0) {
+                    val = parseFloat(val).toFixed(2)
+                    let numberStr = val.toString()
+                    let str = numberStr.split('.')
+
+                    let str0 = str[0].split('').reverse()
+                    for (let i = 0; i < str0.length; i++) {
+                        if ((i + 1) % 4 === 0) {
+                            str0.splice(i, 0, ',')
+                        }
+                    }
+                    str0.reverse()
+                    let handleResult = ''
+                    for (let j = 0; j < str0.length; j++) {
+                        handleResult += str0[j]
+                    }
+
+                    return handleResult + '.' + str[1]
+                } else {
+                    val = parseFloat(val).toFixed(2)
+                    let numberStr = val.toString()
+                    let str = numberStr.split('.')
+
+                    let str0 = str[0]
+                        .substr(1)
+                        .split('')
+                        .reverse()
+                    for (let i = 0; i < str0.length; i++) {
+                        if ((i + 1) % 4 === 0) {
+                            str0.splice(i, 0, ',')
+                        }
+                    }
+                    str0.reverse()
+                    let handleResult = ''
+                    for (let j = 0; j < str0.length; j++) {
+                        handleResult += str0[j]
+                    }
+
+                    return '-' + handleResult + '.' + str[1]
+                }
+            } else if (typeof val == 'string') {
+                return val
+            } else {
+                return 0
+            }
+        },
+        //变成货币格式
+        formatCurrency(val) {
+            if (val) {
+                let numberStr = val.toString()
+                let str = numberStr.split('').reverse()
+                for (let i = 0; i < str.length; i++) {
+                    if ((i + 1) % 4 === 0) {
+                        str.splice(i, 0, ',')
+                    }
+                }
+                str.reverse()
+                let handleResult = ''
+                for (let j = 0; j < str.length; j++) {
+                    handleResult += str[j]
+                }
+                return handleResult
+            } else {
+                return '-'
+            }
+        }
+    }
+}
+</script>

+ 2 - 2
vue.config.js

@@ -105,7 +105,7 @@ module.exports = {
         // target: 'http://192.168.1.43:8088', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.1.43:8806', //请求本地 需要jeecg-boot后台项目  毕洁泉
         // target: 'http://192.168.0.252:8098', //请求本地 需要jeecg-boot后台项目  毕洁泉
-        // target: 'http://192.168.1.219:8081', //请求本地 需要jeecg-boot后台项目  赵西安
+        target: 'http://192.168.1.219:7701', //请求本地 需要jeecg-boot后台项目  赵西安
         // target: 'http://192.168.1.193:8080', //请求本地 需要jeecg-boot后台项目  李煜一
         // target: 'http://192.168.1.193:31012', //请求本地 需要jeecg-boot后台项目  李煜一
         // target: 'http://api.tjyourong.com.cn', //请求本地 需要jeecg-boot后台项目
@@ -116,7 +116,7 @@ module.exports = {
         // target:'http://118.24.244.213:8804',
         // target: 'http://192.168.1.43:9999', // 子安
         // target: 'http://192.168.1.8:8806', // 学超
-        target:'http://gateway.tjyourong.com.cn', //测试
+        // target:'http://gateway.tjyourong.com.cn', //测试
         // target:'http://apipre.tjyourong.com.cn', //预生产
         // target: 'http://192.168.1.134:8080', //请求本地 需要jeecg-boot后台项目  周泽宇