Эх сурвалжийг харах

feat:标讯收藏相关组件新增、拓展

yangfeng 1 жил өмнө
parent
commit
b161016b3e

+ 2 - 1
apps/bigmember_pc/src/components/drawer/Drawer.vue

@@ -16,7 +16,7 @@
       <div class="el-container">
         <div class="el-header">
           <div slot="title">
-            <span>{{ title }}</span>
+            <span v-html="title"></span>
             <el-icon
               v-if="showClose && !withHeader"
               class="el-icon-close self-close"
@@ -166,6 +166,7 @@ export default {
       border-radius: 6px;
       border: 1px solid #2cb7ca;
       color: #2cb7ca;
+      font-size: 16px;
       &.el-cancel {
         margin-left: 40px;
         color: #686868;

+ 80 - 0
apps/bigmember_pc/src/components/filter-items/CollectSearchInput.vue

@@ -0,0 +1,80 @@
+<template>
+  <div class="collect-search-input">
+    <div class="search-input-container">
+      <el-input
+        clearable
+        v-model="value"
+        :placeholder="placeholder"
+        @input="onInput"
+      >
+      </el-input>
+      <el-button type="text" @click="onButtonClick">{{ buttonText }}</el-button>
+    </div>
+  </div>
+</template>
+
+<script>
+import { Input, Button } from 'element-ui'
+export default {
+  name: 'CollectSearchInput',
+  components: {
+    [Input.name]: Input,
+    [Button.name]: Button
+  },
+  props: {
+    placeholder: {
+      type: String,
+      default: '请输入要搜索的关键词'
+    },
+    maxlength: {
+      type: Number,
+      default: 100
+    },
+    buttonText: {
+      type: String,
+      default: '搜索'
+    }
+  },
+  data() {
+    return {
+      value: ''
+    }
+  },
+  methods: {
+    onInput(val) {
+      this.value = val
+    },
+    onButtonClick() {
+      this.$emit('change', this.value)
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.collect-search-input{
+  flex: 1;
+  .search-input-container{
+    display: flex;
+    align-items: center;
+    .el-input{
+      width: 280px;
+      height: 30px;
+    }
+    .el-button--text{
+      padding: 0;
+      margin-left: 8px;
+      font-size: 14px;
+    }
+  }
+  ::v-deep{
+    .el-input__inner{
+      height: 30px;
+      line-height: 30px;
+    }
+    .el-input__icon{
+      line-height: 30px;
+    }
+  }
+}
+</style>

+ 353 - 0
apps/bigmember_pc/src/components/filter-items/CollectTagSelector.vue

@@ -0,0 +1,353 @@
+<template>
+  <div class="collect-tag-selector">
+    <div class="select-group-container">
+      <div
+        v-for="(item, index) in tagsList"
+        :key="index"
+        class="j-button-item"
+        :class="{
+          active: item.selected,
+          all: item.name === '全部'
+        }"
+        @click="buttonClick(item)"
+      >
+        {{ item.name }}
+      </div>
+    </div>
+    <span class="manage-button" @click="onManageClick">标签管理</span>
+    <DrawerCard
+      customClass="drawer-class"
+      percent="600px"
+      :title="calcTitle"
+      :with-header="false"
+      confirmText="确定"
+      v-model="showDrawer"
+      @close="onCloseDrawer"
+      @saveData="onSaveDrawer"
+    >
+      <div class="tag-header flex">
+        <el-input
+          placeholder="输入标签"
+          v-model.trim="addTagInput"
+          maxlength="10"
+          clearable
+          @keyup.enter.native="addTagConfirmed">
+        </el-input>
+        <div class="add-tag-confirm-button flex no-select" @click="addTagConfirmed">确认添加</div>
+      </div>
+      <div class="tag-main">
+        <el-tag
+          :key="tag.value"
+          v-for="tag in drawerTags"
+          closable
+          type="info"
+          :disable-transitions="false"
+          @close="delThisTag(tag)">
+          {{ tag.name }} ( {{ tag.count }} )
+        </el-tag>
+      </div>
+    </DrawerCard>
+    <vDialog
+      customClass="custom-dialog"
+      width="380px"
+      top="30vh"
+      center
+      title="删除标签"
+      :show-close="false"
+      :visible.sync="dialog.delete"
+      @cancel="onDialogCancel"
+      @confirm="onDialogConfirm"
+    >
+      <div class="dialog-content">
+        <span v-if="currentItem.count === 0">确定删除{{currentItem.name ? ('“' + currentItem.name + '”') : '该'}}标签?</span>
+        <span v-else>警告:当前有{{currentItem.count}}条标讯使用了该标签,如果删除标签,那么对应的标讯也将删除该关联标签。</span>
+      </div>
+    </vDialog>
+  </div>
+</template>
+
+<script>
+import { Input, Tag, Dialog } from 'element-ui'
+import DrawerCard from '@/components/drawer/Drawer'
+import vDialog from '@/components/dialog/Dialog'
+export default {
+  name: 'CollectTags',
+  components: {
+    [Input.name]: Input,
+    [Tag.name]: Tag,
+    [Dialog.name]: Dialog,
+    DrawerCard,
+    vDialog
+  },
+  props: {
+    sourceList: {
+      type: Array,
+      default() {
+        return []
+      }
+    },
+    singleChoice: {
+      // 是是否单选
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      tagsList: [],
+      defaultItemExp: {
+        name: '全部',
+        value: '',
+        selected: true
+      },
+      showDrawer: false,
+      addTagInput: '',
+      dialog: {
+        delete: false,
+        already: false
+      },
+      currentItem: {
+        name: '',
+        value: '',
+        count: 0
+      }
+    }
+  },
+  model: {
+    prop: 'value',
+    event: 'change'
+  },
+  computed: {
+    calcTitle() {
+      return `标签管理 <em class="highlight-text">${this.tagsList.length}</em>`
+    },
+    drawerTags() {
+      return this.tagsList.filter(item => item.name !== '全部')
+    }
+  },
+  watch: {
+    value(val) {
+      this.setState(val)
+    },
+    sourceList() {
+      this.init()
+    }
+  },
+  mounted() {
+    this.init()
+  },
+  methods: {
+    init() {
+      const list = [JSON.parse(JSON.stringify(this.defaultItemExp))]
+      this.sourceList.forEach((item) => {
+        list.push({
+          name: item.name,
+          value: item.value,
+          count: item.count,
+          selected: false
+        })
+      })
+      this.tagsList = list
+    },
+    buttonClick(item) {
+      if (item.name === this.defaultItemExp.name) {
+        this.setState()
+      } else {
+        if (this.singleChoice) {
+          this.setState()
+          this.tagsList[0].selected = false
+          item.selected = !item.selected
+        } else {
+          this.tagsList[0].selected = false
+          item.selected = !item.selected
+
+          // 子项全部选中则全部按钮选中,子项如果一个没有被选中,则全部按钮被选中
+          const { allNotSelected } = this.checkAllSelectedState()
+          if (allNotSelected) {
+            this.setState()
+          }
+        }
+      }
+      this.onChange()
+    },
+    // 除了全部按钮之外的按钮的状态
+    checkAllSelectedState() {
+      const stateArr = []
+
+      this.tagsList.forEach((item) => {
+        if (item.value !== this.defaultItemExp.value) {
+          stateArr.push(item.selected)
+        }
+      })
+      return {
+        // 找不到false,就说明全部被选中
+        allSelected: stateArr.indexOf(false) === -1,
+        // 找不到true,就说明没有一个被选中
+        allNotSelected: stateArr.indexOf(true) === -1
+      }
+    },
+    onChange() {
+      const state = this.getState()
+      this.$emit('change', state)
+    },
+    setState(data = []) {
+      if (!Array.isArray) return
+      if (data.length === 0) {
+        this.tagsList.forEach((item) => (item.selected = false))
+        this.tagsList[0].selected = true
+      } else {
+        this.tagsList[0].selected = false
+        this.tagsList.forEach((item) => {
+          if (data.includes(item.value)) {
+            item.selected = true
+          }
+        })
+      }
+    },
+    getState() {
+      const arr = []
+      if (this.tagsList[0].selected) {
+        return arr
+      }
+      return this.tagsList
+        .filter((item) => item.selected)
+        .map((item) => item.value)
+    },
+    onManageClick() {
+      this.$emit('manage')
+      this.showDrawer = true
+    },
+    onCloseDrawer() {
+      this.$emit('close')
+      this.showDrawer = false
+    },
+    onSaveDrawer() {
+      this.$emit('save')
+      this.showDrawer = false
+    },
+    addTagConfirmed() {
+      this.$emit('addTag', this.addTagInput)
+      this.addTagInput = ''
+    },
+    delThisTag(tag) {
+      this.dialog.delete = true
+      this.currentItem = tag
+    },
+    onDialogCancel() {
+      this.dialog.delete = false
+      this.$emit('cancel')
+    },
+    onDialogConfirm() {
+      this.dialog.delete = false
+      this.$emit('delTag', this.currentItem)
+    }
+  }
+}
+</script>
+
+<style scoped lang="scss">
+.collect-tag-selector{
+  display: flex;
+  justify-content: space-between;
+  .select-group-container{
+    flex: 1;
+    display: flex;
+    align-items: center;
+    flex-wrap: wrap;
+    .j-button-item{
+      display: flex;
+      align-items: center;
+      margin: 0 5px;
+      padding: 1px 8px;
+      line-height: 20px;
+      border-radius: 4px;
+      font-size: 14px;
+      text-align: center;
+      background-color: #F5F6F7;
+      border: 1px solid #ECECEC;
+      color: #1D1D1D;
+      cursor: pointer;
+      &.active,
+      &.hover{
+        background-color: #2abed1;
+        color: #fff;
+        border-color: #2abed1;
+      }
+    }
+  }
+  .manage-button{
+    display: flex;
+    align-items: center;
+    padding: 4px 17px;
+    line-height: 22px;
+    border-radius: 4px;
+    font-size: 14px;
+    text-align: center;
+    background-color: #2abed1;
+    color: #fff;
+    cursor: pointer;
+  }
+  ::v-deep{
+    .drawer-class{
+      .el-header{
+        padding: 20px;
+        font-size: 20px;
+        line-height: 32px;
+        border-bottom: 1px solid #ebebeb;
+      }
+      .tag-header{
+        display: flex;
+        align-items: center;
+        padding: 28px 28px 20px;
+        justify-content: space-between;
+      }
+      .add-tag-confirm-button{
+        margin-left: 16px;
+        height: 100%;
+        color: #2CB7CA;
+        white-space: nowrap;
+        cursor: pointer;
+      }
+      .tag-main{
+        padding: 0 20px;
+        flex: 1;
+        overflow-y: scroll;
+        .el-tag {
+          margin: 6px;
+          padding: 1px 8px;
+          height: auto;
+          color: #1d1d1d;
+          background-color: #f5f6f7;
+          border: 1px solid #ececec;
+          border-radius: 5px;
+          line-height: 22px;
+          cursor: pointer;
+          &:hover {
+            color: #2CB7CA;
+            border-color: #2CB7CA;
+            .el-icon-close {
+              color: #2CB7CA;
+              background: transparent;
+            }
+          }
+        }
+      }
+    }
+    .custom-dialog{
+      .dialog-content{
+        text-align: center;
+      }
+      .el-dialog__footer{
+        padding-bottom: 40px;
+        .dialog-footer{
+          flex-direction: row-reverse;
+        }
+        .action-button:not(:last-of-type){
+          margin-right: 0;
+          margin-left: 48px;
+        }
+      }
+    }
+  }
+}
+</style>

+ 10 - 0
apps/bigmember_pc/src/components/selector/SearchTimeScopeSelector.vue

@@ -9,6 +9,8 @@
       :defaultSelectedKey="value"
       :exactCanHalf="exactCanHalf"
       :showConfirmButton="showConfirmButton"
+      :startPlaceholder="startPlaceholder"
+      :endPlaceholder="endPlaceholder"
       @onChange="onChange"
     />
   </div>
@@ -55,6 +57,14 @@ export default {
     showConfirmButton: {
       type: Boolean,
       default: false
+    },
+    startPlaceholder: {
+      type: String,
+      default: ''
+    },
+    endPlaceholder: {
+      type: String,
+      default: ''
     }
   },
   data() {

+ 10 - 0
apps/bigmember_pc/src/components/selector/TimeSelector.vue

@@ -14,6 +14,8 @@
       :selectorType="selectorType"
       :defaultSelectedKey="defaultSelectedKey"
       :showExact="showExact"
+      :startPlaceholder="startPlaceholder"
+      :endPlaceholder="endPlaceholder"
       @onChange="onChange"
     />
   </selector-card>
@@ -42,6 +44,14 @@ export default {
       type: Boolean,
       default: true
     },
+    startPlaceholder: {
+      type: String,
+      default: ''
+    },
+    endPlaceholder: {
+      type: String,
+      default: ''
+    },
     value: {
       type: [Object, String],
       default: () => {

+ 69 - 2
apps/bigmember_pc/src/components/selector/TimeSelectorContent.vue

@@ -242,6 +242,65 @@ const timeSelectMap = {
       value: '12',
       selected: false
     }
+  ],
+  bidPushTime: [
+    {
+      name: '全部',
+      value: 'all',
+      selected: true
+    },
+    {
+      name: '最近7天',
+      value: 'lately7',
+      selected: false
+    },
+    {
+      name: '最近30天',
+      value: 'lately30',
+      selected: false
+    },
+    {
+      name: '最近1年',
+      value: 'sinceLastYear',
+      selected: false
+    },
+    {
+      name: '最近3年',
+      value: 'sinceLastThreeYear',
+      selected: false
+    },
+    {
+      name: '最近5年',
+      value: 'sinceLastFiveYear',
+      selected: false
+    }
+  ],
+  collectTime: [
+    {
+      name: '全部',
+      value: 'all',
+      selected: true
+    },
+    {
+      name: '今天',
+      value: 'today',
+      selected: false
+    },
+    {
+      name: '昨天',
+      value: 'yesterday',
+      selected: false
+    },
+    {
+      name: '最近7天',
+      value: 'lately7',
+      selected: false
+    },
+    {
+      name: '最近30天',
+      value: 'lately30',
+      selected: false
+    }
   ]
 }
 
@@ -298,6 +357,14 @@ export default {
     showConfirmButton: {
       type: Boolean,
       default: false
+    },
+    startPlaceholder: {
+      type: String,
+      default: ''
+    },
+    endPlaceholder: {
+      type: String,
+      default: ''
     }
   },
   data() {
@@ -314,8 +381,8 @@ export default {
       dateTimePickerState: {
         start: '',
         end: '',
-        startPlaceHolder: '', // 开始日期
-        endPlaceHolder: '' // 结束日期
+        startPlaceHolder: this.startPlaceholder, // 开始日期
+        endPlaceHolder: this.endPlaceholder // 结束日期
       },
       startPickerOptions: {
         disabledDate: (time) => {