|
@@ -0,0 +1,315 @@
|
|
|
+<template>
|
|
|
+ <el-popover
|
|
|
+ class="select-tag-container"
|
|
|
+ ref="selectTagRef"
|
|
|
+ placement="bottom-end"
|
|
|
+ trigger="manual"
|
|
|
+ :append-to-body="false"
|
|
|
+ popper-class="select-tag-popover"
|
|
|
+ :visible-arrow="false"
|
|
|
+ :offset="0"
|
|
|
+ :width="childrenList.length > 0 ? 393 : 200"
|
|
|
+ v-model="show">
|
|
|
+ <div class="selector-container">
|
|
|
+ <div class="selector-content">
|
|
|
+ <ul class="level-box level-2-box" v-if="childrenList.length > 0">
|
|
|
+ <li class="check-item" :class="{'active': child.checked }" v-for="(child, cIndex) in childrenList" :key="child.id">
|
|
|
+ <el-checkbox v-model="child.checked" @change="onChildChange($event, child, cIndex)" :label="child.id" >{{child.name}}</el-checkbox>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ <ul class="level-box level-1-box">
|
|
|
+ <li class="check-item" :class="{'active': parent.checked }" @mouseover="onLevel1MouseOver(parent, pIndex)" @mouseout="onLevel1MouseOut($event)" v-for="(parent, pIndex) in list" :key="parent.id" >
|
|
|
+ <el-checkbox v-model="parent.checked" :indeterminate="parent.indeterminate" :label="parent.id" @change="onParentChange($event, parent, pIndex)">{{parent.name}}</el-checkbox>
|
|
|
+ <i class="el-icon-arrow-right" v-if="parent.children.length > 0"></i>
|
|
|
+ </li>
|
|
|
+ </ul>
|
|
|
+ </div>
|
|
|
+ <div class="selector-footer">
|
|
|
+ <el-button type="default" @click="cancelHandle">取消</el-button>
|
|
|
+ <el-button type="primary" @click="confirmHandle">确定</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="handle-btn" @click.stop="showPop" slot="reference">选择标签<i :class="show ? 'el-icon-caret-top' : 'el-icon-caret-bottom'"></i></div>
|
|
|
+ </el-popover>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { getProblemLabel, saveClientProblemLabel } from '@/api/modules/'
|
|
|
+import { debounce } from 'lodash'
|
|
|
+export default {
|
|
|
+ props: {
|
|
|
+ uid: {
|
|
|
+ type: String,
|
|
|
+ default: ''
|
|
|
+ },
|
|
|
+ labelIds: {
|
|
|
+ type: Array,
|
|
|
+ default: () => []
|
|
|
+ }
|
|
|
+ },
|
|
|
+ inject: ['getProblemInfo'],
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ show: false,
|
|
|
+ list: [],
|
|
|
+ childrenList: [],
|
|
|
+ pActive: 0,
|
|
|
+ pTimer: false,
|
|
|
+ timer: null
|
|
|
+ }
|
|
|
+ },
|
|
|
+ created () {
|
|
|
+ this.getList()
|
|
|
+ const _this = this
|
|
|
+ document.addEventListener('click', function () {
|
|
|
+ _this.show = false
|
|
|
+ })
|
|
|
+ },
|
|
|
+ beforeDestroy () {
|
|
|
+ if (this.timer) clearTimeout(this.timer)
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ async getList () {
|
|
|
+ const { error_code: code, data = [] } = await getProblemLabel()
|
|
|
+ if (code === 0 && data && Array.isArray(data)) {
|
|
|
+ for (const item of data) {
|
|
|
+ item.checked = false
|
|
|
+ if (item.children) {
|
|
|
+ for (const childItem of item.children) {
|
|
|
+ childItem.checked = false
|
|
|
+ }
|
|
|
+ item.indeterminate = false
|
|
|
+ } else {
|
|
|
+ item.children = []
|
|
|
+ }
|
|
|
+ item._childrenLen = item.children.length
|
|
|
+ }
|
|
|
+ this.list = data
|
|
|
+ this.childrenList = this.list[0].children
|
|
|
+ // 回选
|
|
|
+ this.setStatus(this.labelIds)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onLevel1MouseOut (e) {
|
|
|
+ clearTimeout(this.pTimer)
|
|
|
+ this.pTimer = null
|
|
|
+ },
|
|
|
+ onLevel1MouseOver (parent, pIndex) {
|
|
|
+ if (!this.pTimer) {
|
|
|
+ this.pTimer = setTimeout(() => {
|
|
|
+ this.onOpenLevel2(parent, pIndex)
|
|
|
+ const calcLeft = parent.children.length === 0
|
|
|
+ this.calcPopoverPosition('hover', calcLeft)
|
|
|
+ }, 150)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 父级选中/取消选中
|
|
|
+ onParentChange (checked, parent, pIndex) {
|
|
|
+ this.onOpenLevel2(parent, pIndex)
|
|
|
+ parent.checked = checked
|
|
|
+ parent.indeterminate = false
|
|
|
+ parent.children.forEach((second) => {
|
|
|
+ second.checked = checked
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 子级选中/取消选中
|
|
|
+ onChildChange (checked, child, cIndex) {
|
|
|
+ child.checked = checked
|
|
|
+ this.setWholeCheckedStatus(child.pid)
|
|
|
+ },
|
|
|
+ // 设置全选、半选状态
|
|
|
+ setWholeCheckedStatus (pid) {
|
|
|
+ const pList = this.list.filter(item => item.id === pid)
|
|
|
+ const pItem = pList[0] || []
|
|
|
+ const checkedList = pItem.children.filter(item => item.checked)
|
|
|
+ this.list[this.pActive].indeterminate = false
|
|
|
+ if (checkedList.length > 0) {
|
|
|
+ this.list[this.pActive].indeterminate = true
|
|
|
+ this.list[this.pActive].checked = false
|
|
|
+ }
|
|
|
+ if (pItem._childrenLen === checkedList.length) {
|
|
|
+ this.list[this.pActive].indeterminate = false
|
|
|
+ this.list[this.pActive].checked = true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ onOpenLevel2 (parent, pIndex) {
|
|
|
+ this.pActive = pIndex
|
|
|
+ this.childrenList = parent.children
|
|
|
+ },
|
|
|
+ getStatus () {
|
|
|
+ const ids = []
|
|
|
+ for (const item of this.list){
|
|
|
+ if (item.checked) {
|
|
|
+ ids.push(item.id)
|
|
|
+ } else if (item.indeterminate){
|
|
|
+ for (const cItem of item.children) {
|
|
|
+ if (cItem.checked) {
|
|
|
+ ids.push(cItem.id)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return ids.join(',')
|
|
|
+ },
|
|
|
+ setStatus (ids) {
|
|
|
+ if (ids && Array.isArray(ids)) {
|
|
|
+ const idList = ids.map(temp => Number(temp))
|
|
|
+ for (const item of this.list) {
|
|
|
+ if (idList.includes(item.id)) {
|
|
|
+ item.checked = true
|
|
|
+ }
|
|
|
+ for (const cItem of item.children) {
|
|
|
+ if (idList.includes(cItem.id)) {
|
|
|
+ item.indeterminate = true
|
|
|
+ cItem.checked = true
|
|
|
+ }
|
|
|
+ if (item.checked && !item.indeterminate) {
|
|
|
+ cItem.checked = true
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ showPop () {
|
|
|
+ this.show = !this.show
|
|
|
+ this.childrenList = this.list[0].children
|
|
|
+ this.pActive = 0
|
|
|
+ if (this.show) {
|
|
|
+ this.calcPopoverPosition()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ initPopoverPosition () {
|
|
|
+ const popover = this.$refs.selectTagRef
|
|
|
+ if (popover) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ popover.updatePopper()
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 处理问题:由于外层overflow:hidden,元素也不能插入body,但是父元素其他内容过长,所剩底部区域过小时,popover展示不全
|
|
|
+ calcPopoverPosition (isHover, calcLeft) {
|
|
|
+ const parent = document.querySelector('#customer-info')
|
|
|
+ const parentRect = parent.getBoundingClientRect()
|
|
|
+ const elementRect = this.$el.getBoundingClientRect()
|
|
|
+ const left = elementRect.left
|
|
|
+ const bottom = parentRect.bottom - elementRect.bottom
|
|
|
+ if (bottom < 260 && this.$refs.selectTagRef) {
|
|
|
+ const popover = this.$refs.selectTagRef
|
|
|
+ if (popover) {
|
|
|
+ if (isHover) {
|
|
|
+ popover.popperElm.style.top = (elementRect.bottom - 350) + 'px'
|
|
|
+ popover.popperElm.style.left = calcLeft ? (left - 123) + 'px' : (left - 323) + 'px'
|
|
|
+ } else {
|
|
|
+ if (this.timer) clearTimeout(this.timer)
|
|
|
+ this.timer = setTimeout(() => {
|
|
|
+ popover.popperElm.style.top = (elementRect.bottom - 350) + 'px'
|
|
|
+ popover.popperElm.style.left = (left - 323) + 'px'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ this.initPopoverPosition()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ cancelHandle () {
|
|
|
+ this.show = false
|
|
|
+ },
|
|
|
+ confirmHandle: debounce(async function () {
|
|
|
+ const ids = this.getStatus()
|
|
|
+ if (!ids) {
|
|
|
+ this.$toast('请选择标签!')
|
|
|
+ return
|
|
|
+ }
|
|
|
+ const params = {
|
|
|
+ label_ids: ids,
|
|
|
+ uid: this.uid
|
|
|
+ }
|
|
|
+ const { error_code: code } = await saveClientProblemLabel(params)
|
|
|
+ if (code === 0) {
|
|
|
+ this.show = false
|
|
|
+ this.getProblemInfo()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .select-tag-container {
|
|
|
+ .handle-btn{
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #2ABED1;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+ .selector-content {
|
|
|
+ display: flex;
|
|
|
+ height: 250px;
|
|
|
+ .level-box{
|
|
|
+ height:100%;
|
|
|
+ overflow-y: auto;
|
|
|
+ background: #fff;
|
|
|
+ padding-top: 16px;
|
|
|
+ }
|
|
|
+ .level-1-box {
|
|
|
+ width:200px;
|
|
|
+ border-radius: 8px 8px 0 0;
|
|
|
+ }
|
|
|
+ .level-2-box {
|
|
|
+ box-sizing: border-box;
|
|
|
+ width:193px;
|
|
|
+ border-right: 1px solid #eee;
|
|
|
+ border-top-left-radius: 8px;
|
|
|
+ }
|
|
|
+ .check-item{
|
|
|
+ padding: 5px 8px;
|
|
|
+ display: flex;
|
|
|
+ width: 100% !important;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ &:hover{
|
|
|
+ background: rgba(234, 248, 250, 1);
|
|
|
+ }
|
|
|
+ &.active {
|
|
|
+ background: rgba(234, 248, 250, 1);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .selector-footer{
|
|
|
+ padding: 12px 18px 12px 0;
|
|
|
+ text-align: right;
|
|
|
+ border-top:1px solid #eee;
|
|
|
+ .el-button{
|
|
|
+ padding: 4px 23px;
|
|
|
+ font-size:14px;
|
|
|
+ line-height: 22px;
|
|
|
+ }
|
|
|
+ .el-button--primary {
|
|
|
+ margin-left:16px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ ::v-deep {
|
|
|
+ .el-popover.select-tag-popover {
|
|
|
+ max-width: 393px;
|
|
|
+ min-width: 200px;
|
|
|
+ padding: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+ border-radius: 8px;
|
|
|
+ border: 1px solid #2ABED1;
|
|
|
+ box-shadow: 0 0 28px 0 rgba(0, 0, 0, 0.08);
|
|
|
+ margin-top:4px;
|
|
|
+ }
|
|
|
+ .el-checkbox{
|
|
|
+ .el-checkbox__label{
|
|
|
+ color: #1d1d1d;
|
|
|
+ }
|
|
|
+ .el-checkbox__inner{
|
|
|
+ border-color: #e0e0e0;
|
|
|
+ }
|
|
|
+ .el-checkbox__input.is-checked .el-checkbox__inner {
|
|
|
+ border-color: #2CB7CA;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|