Quellcode durchsuchen

RING:新增计划part3框架

ringcode vor 3 Jahren
Ursprung
Commit
e639ed1234

+ 194 - 0
src/views/put/component/check-box.vue

@@ -0,0 +1,194 @@
+<template>
+  <div class="check-box">
+    <div class="common-box list-box">
+      <div class="title-box">
+        <h3>{{ typeList[type - 1] }}</h3>
+      </div>
+      <div class="list">
+        <a-checkbox
+          v-model:checked="checkAll"
+          :indeterminate="indeterminate"
+          @change="onCheckAllChange"
+        >
+          全选
+        </a-checkbox>
+        <a-checkbox-group style="display: block" v-model:value="checkedList">
+          <a-checkbox v-for="item in list" :key="item.value" :value="item">{{
+            item.label
+          }}</a-checkbox>
+        </a-checkbox-group>
+      </div>
+    </div>
+    <div class="common-box selected-box">
+      <div class="title-box">
+        <span
+          style="
+            display: block;
+            font-weight: bold;
+            line-height: 30px;
+            float: left;
+            font-size: 13px;
+          "
+          >已选</span
+        >
+        <h3 class="clear-all" @click="clearAll">全部清空</h3>
+      </div>
+      <div class="selected">
+        <p v-for="item in checkedList" :key="item.value">
+          <span>{{ item.label }}</span>
+          <i class="iconfont icon-guanbi" @click="deleteItem(item)"></i>
+        </p>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, toRefs, ref, watch } from "vue";
+import {} from "@/api";
+import { message } from "ant-design-vue";
+
+const CheckBox = defineComponent({
+  props: ["compType"],
+  setup() {
+    const state = reactive({
+      list: ref<any[]>([]),
+      indeterminate: false,
+      checkAll: false,
+      checkedList: ref<any[]>([]),
+      typeList: ["文章分类", "手机品牌", "职业状态", "可开放定向"],
+      type: 1,
+    });
+    const onCheckAllChange = (e: any) => {
+      state.checkedList = e.target.checked ? state.list : [];
+      state.checkAll = e.target.checked;
+      state.indeterminate = false;
+    };
+    watch(
+      () => state.checkedList,
+      (val) => {
+        state.indeterminate = !!val.length && val.length < state.list.length;
+        state.checkAll = val.length === state.list.length;
+      }
+    );
+
+    return { ...toRefs(state), onCheckAllChange };
+  },
+  mounted() {
+    this.type = this.$props.compType ?? 1;
+    this.list = [
+      { label: "测试1", value: 1 },
+      { label: "测试2", value: 2 },
+      { label: "测试3", value: 3 },
+      { label: "测试4", value: 4 },
+      { label: "测试5", value: 5 },
+      { label: "测试6", value: 6 },
+      { label: "测试7", value: 7 },
+      { label: "测试8", value: 8 },
+      { label: "测试9", value: 9 },
+      { label: "测试10", value: 10 },
+    ];
+  },
+  methods: {
+    // 全部清空
+    clearAll() {
+      this.checkedList = [];
+    },
+    // 删除单个
+    deleteItem(val: any) {
+      this.checkedList.splice(this.checkedList.indexOf(val), 1);
+      this.indeterminate =
+        this.checkedList.length === 0 ||
+        this.checkedList.length === this.list.length
+          ? false
+          : true;
+      this.checkAll = this.checkedList.length === this.list.length;
+    },
+    // 全选操作
+  },
+});
+
+export default CheckBox;
+</script>
+<style lang="scss" scoped>
+.check-box {
+  margin-top: 10px;
+  width: 550px;
+  .common-box {
+    height: 210px;
+    float: left;
+    border: 1px solid rgb(210, 210, 210);
+    border-radius: 2px;
+    .title-box {
+      padding: 0 10px;
+      height: 30px;
+      border-bottom: 1px solid rgb(210, 210, 210);
+      h3 {
+        font-size: 13px;
+        font-weight: bold;
+        height: 30px;
+        line-height: 30px;
+        float: left;
+        margin-bottom: 0;
+      }
+      .clear-all {
+        font-size: 13px;
+        font-weight: normal;
+        color: gray;
+        float: right;
+        cursor: pointer;
+      }
+    }
+  }
+  .list-box {
+    width: 320px;
+    .list {
+      height: 176px;
+      overflow: auto;
+      padding: 0 10px;
+      .ant-checkbox-wrapper {
+        display: block;
+        margin: 0;
+        line-height: 32px;
+        height: 32px;
+      }
+    }
+  }
+  .selected-box {
+    width: 200px;
+    margin-left: 20px;
+
+    .selected {
+      height: 176px;
+      overflow: auto;
+      padding: 0 10px;
+      p {
+        background: rgb(240, 240, 240);
+        height: 26px;
+        line-height: 26px;
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        margin-top: 6px;
+        font-size: 13px;
+        span {
+          display: inline-block;
+          width: 130px;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          overflow: hidden;
+          word-break: break-all;
+          border-radius: 2px;
+        }
+        i {
+          cursor: pointer;
+          font-size: 13px;
+          &:hover {
+            color: skyblue;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 351 - 0
src/views/put/component/direction-exclusion.vue

@@ -0,0 +1,351 @@
+<template>
+  <div class="direction-exclusion">
+    <a-input-search
+      v-model:value="search"
+      :placeholder="
+        type === 'crowd' ? '请输入人群包名称或ID' : '请输入媒体包名称或ID'
+      "
+      style="width: 200px"
+      @input="onSearch"
+    />
+    <br />
+    <div class="common-box list-box">
+      <div class="title-box">
+        <!-- 人群定向 -->
+        <h3 style="width: 120px" v-if="type === 'crowd'">人群包</h3>
+        <h3 style="width: 184px" v-else>定向包</h3>
+        <h3 style="width: 100px" v-if="type === 'crowd'">创建时间</h3>
+        <h3 :style="type === 'crowd' ? 'width: 70px' : 'width: 90px'">操作</h3>
+      </div>
+      <div class="list">
+        <!-- 人群定向循环列表 -->
+        <p v-for="item in list" :key="item.id">
+          <span
+            v-if="type === 'crowd'"
+            :title="item.name"
+            style="width: 110px"
+            class="item-name"
+            >{{ item.name }}</span
+          >
+          <span
+            v-else
+            :title="item.name"
+            style="width: 180px"
+            class="item-name"
+            >{{ item.name }}</span
+          >
+          <span
+            style="width: 100px; margin: 0 20px 0 10px"
+            v-if="type === 'crowd'"
+            >{{ item.time }}</span
+          >
+          <span :style="'width:' + type === 'crowd' ? '70px' : '90px'">
+            <a-button
+              style="padding: 4px"
+              type="link"
+              @click="addDirection(item)"
+              :disabled="directionList.idList.includes(item.id)"
+              >定向</a-button
+            >
+            <a-button
+              style="padding: 0"
+              type="link"
+              @click="addExclusion(item)"
+              :disabled="exclusionList.idList.includes(item.id)"
+              >排除</a-button
+            >
+          </span>
+        </p>
+      </div>
+    </div>
+    <div class="common-box selected-box">
+      <div class="title-box">
+        <span
+          style="
+            display: block;
+            font-weight: bold;
+            line-height: 30px;
+            float: left;
+            font-size: 13px;
+          "
+          >已选</span
+        >
+        <h3 class="clear-all" @click="clearAll">全部清空</h3>
+      </div>
+      <div class="tabs">
+        <span
+          :class="selectedKey === 'direction' ? 'tabs-active' : ''"
+          @click="selectedKey = 'direction'"
+          >定向({{ directionList.itemList.length }})</span
+        >
+        <span
+          :class="selectedKey === 'exclusion' ? 'tabs-active' : ''"
+          @click="selectedKey = 'exclusion'"
+          >排除({{ exclusionList.itemList.length }})</span
+        >
+      </div>
+      <div class="selected-item">
+        <div v-show="selectedKey === 'direction'">
+          <p v-for="item in directionList.itemList" :key="item.id">
+            <span>{{ item.name }}</span>
+            <i
+              class="iconfont icon-guanbi"
+              @click="deleteDirectionItem(item.id)"
+            ></i>
+          </p>
+        </div>
+        <div v-show="selectedKey === 'exclusion'">
+          <p v-for="item in exclusionList.itemList" :key="item.id">
+            <span>{{ item.name }}</span>
+            <i
+              class="iconfont icon-guanbi"
+              @click="deleteExclusionItem(item.id)"
+            ></i>
+          </p>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts">
+import { defineComponent, reactive, toRefs, ref } from "vue";
+import {} from "@/api";
+import { message } from "ant-design-vue";
+
+const DirectionExclusion = defineComponent({
+  props: ["compType"],
+  setup() {
+    const state = reactive({
+      search: "", // 过滤
+      selectedKey: "direction",
+      type: "crowd", // 人群组件/媒体组件
+      list: ref<any[]>([]),
+      originList: [
+        {
+          name: "测试人群包A测试人群包A测试人群包A",
+          time: "2020-01-10",
+          id: "1",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "2",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "3",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "4",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "5",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "6",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "7",
+        },
+        {
+          name: "测试人群包B",
+          time: "2020-01-10",
+          id: "8",
+        },
+      ],
+      directionList: {
+        itemList: ref<any[]>([]), // 渲染数组
+        idList: ref<any[]>([]), // 传参数组
+      },
+      exclusionList: {
+        itemList: ref<any[]>([]), // 渲染数组
+        idList: ref<any[]>([]), // 传参数组
+      },
+    });
+    return { ...toRefs(state) };
+  },
+  mounted() {
+    this.type = this.$props.compType === "media" ? "media" : "crowd";
+    this.list = JSON.parse(JSON.stringify(this.originList));
+  },
+  methods: {
+    // 添加定向
+    addDirection(val: any) {
+      this.directionList.itemList.push(val);
+      this.directionList.idList.push(val.id);
+      if (this.exclusionList.idList.includes(val.id)) {
+        this.deleteExclusionItem(val.id);
+      }
+      this.selectedKey = "direction";
+    },
+    // 添加排除
+    addExclusion(val: any) {
+      this.exclusionList.itemList.push(val);
+      this.exclusionList.idList.push(val.id);
+      if (this.directionList.idList.includes(val.id)) {
+        this.deleteDirectionItem(val.id);
+      }
+      this.selectedKey = "exclusion";
+    },
+    // 全部删除
+    clearAll() {
+      this.directionList.itemList = [];
+      this.directionList.idList = [];
+      this.exclusionList.itemList = [];
+      this.exclusionList.idList = [];
+    },
+    // 根据id删除定向项
+    deleteDirectionItem(id: any) {
+      this.directionList.idList.splice(
+        this.directionList.idList.indexOf(id),
+        1
+      );
+      this.directionList.itemList.forEach((item: any) => {
+        if (item.id === id) {
+          this.directionList.itemList.splice(
+            this.directionList.itemList.indexOf(item),
+            1
+          );
+        }
+      });
+    },
+    // 根据id删除排除项
+    deleteExclusionItem(id: any) {
+      this.exclusionList.idList.splice(
+        this.exclusionList.idList.indexOf(id),
+        1
+      );
+      this.exclusionList.itemList.forEach((item: any) => {
+        if (item.id === id) {
+          this.exclusionList.itemList.splice(
+            this.exclusionList.itemList.indexOf(item),
+            1
+          );
+        }
+      });
+    },
+    // 返回过滤结果
+    onSearch() {
+      this.list = this.originList.filter((item: any) => {
+        return (
+          item.name.indexOf(this.search) > -1 ||
+          item.id.indexOf(this.search) > -1
+        );
+      });
+    },
+  },
+});
+
+export default DirectionExclusion;
+</script>
+<style lang="scss" scoped>
+.direction-exclusion {
+  width: 560px;
+  overflow: hidden;
+  .common-box {
+    height: 210px;
+    float: left;
+    border: 1px solid rgb(210, 210, 210);
+    border-radius: 2px;
+    .title-box {
+      padding: 0 10px;
+      height: 30px;
+      border-bottom: 1px solid rgb(210, 210, 210);
+      h3 {
+        font-size: 13px;
+        font-weight: bold;
+        height: 30px;
+        line-height: 30px;
+        float: left;
+        margin-bottom: 0;
+      }
+      .clear-all {
+        font-size: 13px;
+        font-weight: normal;
+        color: gray;
+        float: right;
+        cursor: pointer;
+      }
+    }
+    .list {
+      height: 180px;
+      padding: 4px 10px;
+      overflow: auto;
+      p {
+        height: 28px;
+        line-height: 28px;
+        .item-name {
+          display: block;
+          float: left;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          overflow: hidden;
+          word-break: break-all;
+        }
+      }
+    }
+  }
+  .list-box {
+    width: 320px;
+  }
+  .selected-box {
+    width: 200px;
+    margin-left: 20px;
+    .tabs {
+      width: 100%;
+      display: flex;
+      justify-content: space-around;
+      span {
+        cursor: pointer;
+        display: inline-block;
+        line-height: 30px;
+      }
+      .tabs-active {
+        color: rgb(80, 138, 245);
+        border-bottom: 3px solid rgb(80, 138, 245);
+      }
+    }
+    .selected-item {
+      height: 140px;
+      padding: 0px 10px;
+      overflow: auto;
+      p {
+        background: rgb(240, 240, 240);
+        height: 26px;
+        line-height: 26px;
+        display: flex;
+        align-items: center;
+        justify-content: space-around;
+        margin-top: 6px;
+        font-size: 13px;
+        span {
+          display: inline-block;
+          width: 130px;
+          white-space: nowrap;
+          text-overflow: ellipsis;
+          overflow: hidden;
+          word-break: break-all;
+          border-radius: 2px;
+        }
+        i {
+          cursor: pointer;
+          font-size: 13px;
+          &:hover {
+            color: skyblue;
+          }
+        }
+      }
+    }
+  }
+}
+</style>

+ 7 - 10
src/views/put/component/location-auto-release.vue

@@ -268,12 +268,6 @@
               style="margin-top: 3px"
             ></i>
           </p>
-          <!-- <img
-                            src="./../../assets/image/empty.png"
-                            alt="empty"
-                            v-if="checkedCounties.length===0"
-                            style="display:block;margin:50px auto 0"
-                        > -->
           <span v-if="checkedCounties.length === 0">暂无数据</span>
         </div>
       </div>
@@ -925,6 +919,8 @@ export default {
 
     // 省份列表change事件 根据省份查找城市  按县区选择00000
     getCityListInCounty(province) {
+      console.log(province);
+      console.log(cityData.rtnData);
       this.provinceToCity = []; // 置空
       this.countyFlag = "countyHidden";
       if (
@@ -936,7 +932,7 @@ export default {
         this.clickProvince = "changeProvinceWidth";
         this.cityFlag = "";
         cityData.rtnData.forEach((item) => {
-          if (item === province) {
+          if (item.value === province.value) {
             item.children.forEach((itm) => {
               this.provinceToCity.push(itm);
             });
@@ -959,6 +955,7 @@ export default {
     },
     // 按区县查找 点击城市获取当前区县
     getCountyList(city) {
+      console.log("生成区县");
       // this.$refs.countyScroll.scrollLeft=205
       this.$refs.countyScroll.scrollLeft = this.$refs.countyScroll.scrollWidth;
       this.cityToCounty = []; // 置空
@@ -975,7 +972,7 @@ export default {
         ) {
           if (item.children) {
             item.children.forEach((cityItm) => {
-              if (cityItm === city) {
+              if (cityItm.value === city.value) {
                 cityItm.children.forEach((countyItm) => {
                   this.cityToCounty.push(countyItm);
                 });
@@ -987,7 +984,7 @@ export default {
             let arr = [];
             arr.push(item);
             arr.forEach((itm) => {
-              if (itm === city) {
+              if (itm.value === city.value) {
                 itm.children.forEach((countyItm) => {
                   this.cityToCounty.push(countyItm);
                 });
@@ -1027,7 +1024,7 @@ export default {
 };
 </script>
 <style lang="scss" scope>
-@import "@/assets/common-style/scroll-bar.scss";
+// @import "@/assets/common-style/scroll-bar.scss";
 ::-webkit-scrollbar {
   width: 8px;
 }

+ 24 - 0
src/views/put/component/plan-data.ts

@@ -0,0 +1,24 @@
+// 手机价格slider
+export const PriceSlider = {
+  0: "0",
+  500: "",
+  1000: "",
+  1500: "",
+  2000: "2000元",
+  2500: "",
+  3000: "",
+  3500: "",
+  4000: "",
+  5000: "5000元",
+  6000: "",
+  7000: "",
+  8000: "",
+  9000: "",
+  10000: "1万元",
+  11000: {
+    style: {
+      color: "skyblue",
+    },
+    label: "不限",
+  },
+}

+ 5 - 3
src/views/put/component/time-schedule.vue

@@ -220,6 +220,7 @@ export default {
 </script>
 <style lang="scss" scoped>
 .choose-schedule-time {
+  width: 600px;
   position: relative;
   .select-box-dashed {
     position: absolute;
@@ -284,7 +285,7 @@ export default {
       .week-list {
         min-width: 50px;
         width: calc(100% - 720px);
-        padding-top: 30px;
+        padding-top: 20px;
         .week-name {
           height: 24px;
           line-height: 24px;
@@ -294,16 +295,17 @@ export default {
       }
 
       .mainbox {
-        width: 710px;
+        width: 720px;
         padding-left: 10px;
         background-color: #eeeeee;
 
         .time-list {
+          width: 710px;
           display: flex;
           flex-wrap: wrap;
           .list-item {
             height: 16px;
-            width: 10px;
+            width: 12px;
             border: 1px solid #999;
             border-radius: 2px;
             margin: 0 1px 7px;

+ 1 - 1
src/views/put/plan-create/account-select.vue

@@ -157,7 +157,7 @@ const AccountSelect = defineComponent({
 export default AccountSelect;
 </script>
 <style lang="scss" scoped>
-@import "@/assets/common-style/scroll-bar.scss";
+// @import "@/assets/common-style/scroll-bar.scss";
 .account-select {
   overflow: hidden;
   .common-box {

+ 1 - 1
src/views/put/plan-create/group-select.vue

@@ -382,7 +382,7 @@ const GroupSelect = defineComponent({
 export default GroupSelect;
 </script>
 <style lang="scss" scoped>
-@import "@/assets/common-style/scroll-bar.scss";
+// @import "@/assets/common-style/scroll-bar.scss";
 .group-select {
   .ad-group-box {
     width: 600px;

+ 56 - 4
src/views/put/plan-create/plan-edit.vue

@@ -3,7 +3,6 @@
     <!-- part1------优化目标 -->
     <div class="part-box">
       <h1>优化目标</h1>
-      <!-- <time-schedule></time-schedule> -->
       <a-form :label-col="labelCol" :wrapper-col="wrapperCol">
         <a-form-item label="转化跟踪方式">
           <a-select placeholder="请选择">
@@ -75,6 +74,13 @@
           </a-checkbox-group>
         </a-form-item>
         <!-- 自定义人群 -->
+        <a-form-item label="自定义人群">
+          <a-radio-group>
+            <a-radio-button value="0">不限</a-radio-button>
+            <a-radio-button value="1">自定义人群</a-radio-button>
+          </a-radio-group>
+          <direction-exclusion :compType="'crowd'"></direction-exclusion>
+        </a-form-item>
         <a-form-item label="行为兴趣">
           <a-radio-group>
             <a-radio-button value="0">不限</a-radio-button>
@@ -82,6 +88,14 @@
           </a-radio-group>
         </a-form-item>
         <!-- 媒体定向 -->
+        <a-form-item label="媒体定向">
+          <a-radio-group>
+            <a-radio-button value="0">不限</a-radio-button>
+            <a-radio-button value="1">游戏优质媒体</a-radio-button>
+            <a-radio-button value="2">自定义</a-radio-button>
+          </a-radio-group>
+          <direction-exclusion :compType="'media'"></direction-exclusion>
+        </a-form-item>
         <a-form-item label="平台">
           <a-checkbox-group>
             <a-checkbox value="0">不限</a-checkbox>
@@ -133,6 +147,13 @@
           </a-radio-group>
         </a-form-item>
         <!-- 文章分类 -->
+        <a-form-item label="文章分类">
+          <a-radio-group>
+            <a-radio-button value="0">不限</a-radio-button>
+            <a-radio-button value="1">文章分类</a-radio-button>
+          </a-radio-group>
+          <check-box :compType="1"></check-box>
+        </a-form-item>
         <a-form-item label="运营商">
           <a-checkbox-group>
             <a-checkbox value="0">不限</a-checkbox>
@@ -150,14 +171,39 @@
           </a-checkbox-group>
         </a-form-item>
         <!-- 手机品牌 -->
+        <a-form-item label="手机品牌">
+          <a-radio-group>
+            <a-radio-button value="0">不限</a-radio-button>
+            <a-radio-button value="1">手机品牌</a-radio-button>
+          </a-radio-group>
+          <check-box :compType="2"></check-box>
+        </a-form-item>
         <a-form-item label="手机价格">
           <a-radio-group>
             <a-radio-button value="0">不限</a-radio-button>
-            <a-radio-button value="1">自定义</a-radio-button> </a-radio-group
-          >滑动条
+            <a-radio-button value="1">自定义</a-radio-button>
+          </a-radio-group>
+          <a-slider
+            range
+            :marks="phonePriceMarks"
+            :max="11000"
+            :min="0"
+            :step="null"
+          />
         </a-form-item>
         <!-- 职业状态 -->
+        <a-form-item label="职业状态">
+          <a-radio-group>
+            <a-radio-button value="0">不限</a-radio-button>
+            <a-radio-button value="1">职业状态</a-radio-button>
+          </a-radio-group>
+          <check-box :compType="3"></check-box>
+        </a-form-item>
         <!-- 智能放量 -->
+        <a-form-item label="智能放量">
+          <a-switch />
+          <check-box :compType="4"></check-box>
+        </a-form-item>
       </a-form>
     </div>
 
@@ -186,8 +232,8 @@
           <a-radio-group>
             <a-radio-button value="0">从今天起长期投放</a-radio-button>
             <a-radio-button value="1">设置开始和结束时间</a-radio-button>
-            时间选择器
           </a-radio-group>
+          <time-schedule style="width: 800px; margin-top: 10px"></time-schedule>
         </a-form-item>
         <!-- 投放时段 -->
         <a-form-item label="付费方式">
@@ -245,16 +291,22 @@ import {} from "@/api";
 import Bus from "@/utils/bus";
 import TimeSchedule from "../component/time-schedule.vue";
 import Location from "../component/location-auto-release.vue";
+import DirectionExclusion from "../component/direction-exclusion.vue";
+import CheckBox from "../component/check-box.vue";
 import { message } from "ant-design-vue";
+import { PriceSlider } from "../component/plan-data";
 
 const PlanEdit = defineComponent({
   components: {
     TimeSchedule,
     Location,
+    DirectionExclusion,
+    CheckBox,
   },
   setup() {
     const state = reactive({
       plan: {},
+      phonePriceMarks: PriceSlider, //手机价格区间
     });
     return {
       ...toRefs(state),