|
@@ -0,0 +1,408 @@
|
|
|
+<template>
|
|
|
+ <div class="selector-content" v-if="selectorType === 'card'" key="selector-content">
|
|
|
+ <div class="search-container">
|
|
|
+ <el-input v-model.trim="searchContent" placeholder="搜索" prefix-icon="el-icon-search"></el-input>
|
|
|
+ </div>
|
|
|
+ <div class="select-list scrollbar" ref="selectList">
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in industryListMap"
|
|
|
+ :key="index"
|
|
|
+ class="list-item-container"
|
|
|
+ >
|
|
|
+ <div class="list-item-header">
|
|
|
+ <button
|
|
|
+ class="j-button-item button-level-1"
|
|
|
+ :class="{
|
|
|
+ active: item.selected,
|
|
|
+ [item.id]: true
|
|
|
+ }"
|
|
|
+ @click="changeIndustryState(item)"
|
|
|
+ >{{ item.name }}</button>
|
|
|
+ </div>
|
|
|
+ <div class="list-item-main">
|
|
|
+ <button
|
|
|
+ v-for="(iitem, iindex) in item.children" :key="999-iindex"
|
|
|
+ class="j-button-item button-level-2"
|
|
|
+ :class="{
|
|
|
+ active: iitem.selected,
|
|
|
+ [iitem.id]: true
|
|
|
+ }"
|
|
|
+ @click="changeIndustryState(iitem)"
|
|
|
+ >{{ iitem.name }}</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="selector-content" :class="{ 'no-more': !showMore }" key="selector-content" v-else-if="selectorType === 'line'">
|
|
|
+ <span class="action-button show-more" @click="showMore = !showMore">
|
|
|
+ <span class="action-text">{{ showMore ? '收起' : '更多' }}</span>
|
|
|
+ <span class="el-icon-arrow-down" :class="showMore ? 'rotate180' : ''"></span>
|
|
|
+ </span>
|
|
|
+ <div
|
|
|
+ v-for="(item, index) in industryListMap"
|
|
|
+ :key="index"
|
|
|
+ class="list-item-container"
|
|
|
+ >
|
|
|
+ <div class="list-item-header">
|
|
|
+ <button
|
|
|
+ class="j-button-item"
|
|
|
+ :class="{
|
|
|
+ active: item.selected,
|
|
|
+ [item.id]: true,
|
|
|
+ 'button-level-0': item.level === 0,
|
|
|
+ 'button-level-1': item.level === 1,
|
|
|
+ }"
|
|
|
+ @click="changeIndustryState(item)"
|
|
|
+ >{{ item.name }}</button>
|
|
|
+ </div>
|
|
|
+ <div class="list-item-main">
|
|
|
+ <button
|
|
|
+ v-for="(iitem, iindex) in item.children" :key="999-iindex"
|
|
|
+ class="j-button-item button-level-2"
|
|
|
+ :class="{
|
|
|
+ active: iitem.selected,
|
|
|
+ [iitem.id]: true
|
|
|
+ }"
|
|
|
+ @click="changeIndustryState(iitem)"
|
|
|
+ >{{ iitem.name }}</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import { Input, Icon } from 'element-ui'
|
|
|
+import { industryListMapExp } from '@/assets/js/selector.js'
|
|
|
+import { debounce, getRandomString } from '@/utils/'
|
|
|
+export default {
|
|
|
+ name: 'industry-selector-content',
|
|
|
+ components: {
|
|
|
+ [Input.name]: Input,
|
|
|
+ [Icon.name]: Icon
|
|
|
+ },
|
|
|
+ props: {
|
|
|
+ selectorType: {
|
|
|
+ type: String,
|
|
|
+ default: 'card'
|
|
|
+ },
|
|
|
+ initIndustry: {
|
|
|
+ type: Object,
|
|
|
+ default () {
|
|
|
+ return {
|
|
|
+ // '建筑工程': [
|
|
|
+ // '勘察设计',
|
|
|
+ // '工程施工',
|
|
|
+ // '监理咨询',
|
|
|
+ // '材料设备',
|
|
|
+ // ],
|
|
|
+ // '水利水电': [
|
|
|
+ // '水利工程',
|
|
|
+ // '发电工程',
|
|
|
+ // '航运工程',
|
|
|
+ // '其他工程',
|
|
|
+ // ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+ data () {
|
|
|
+ return {
|
|
|
+ searchContent: '',
|
|
|
+ // 原始数据
|
|
|
+ industryListMapExp,
|
|
|
+ // 页面中循环的数据
|
|
|
+ industryListMap: [],
|
|
|
+ industryExp: {
|
|
|
+ name: '全部行业',
|
|
|
+ selected: false,
|
|
|
+ level: 0,
|
|
|
+ children: [],
|
|
|
+ id: ''
|
|
|
+ },
|
|
|
+ showMore: true
|
|
|
+ }
|
|
|
+ },
|
|
|
+ watch: {
|
|
|
+ initIndustry (newVal, oldVal) {
|
|
|
+ this.setIndustryState(newVal)
|
|
|
+ },
|
|
|
+ searchContent: debounce(function (newVal, oldVal) {
|
|
|
+ const search = newVal
|
|
|
+ const id = this.getIndexWithString(search)
|
|
|
+ if (id) {
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const wrapper = document.querySelector('.industry-selector.card')
|
|
|
+ this.$refs.selectList.scrollTop = wrapper.querySelector(`.${id}`).offsetTop
|
|
|
+ })
|
|
|
+ }
|
|
|
+ }, 300)
|
|
|
+ },
|
|
|
+ created () {
|
|
|
+ this.initIndustryMap()
|
|
|
+ this.setIndustryState(this.initIndustry)
|
|
|
+ window.data = this
|
|
|
+ },
|
|
|
+ methods: {
|
|
|
+ // 整理数据列表
|
|
|
+ initIndustryMap () {
|
|
|
+ const industryListMap = []
|
|
|
+
|
|
|
+ // 全部
|
|
|
+ const all = JSON.parse(JSON.stringify(this.industryExp))
|
|
|
+ all.selected = true
|
|
|
+ all.id = `lv0-${getRandomString(8).toLowerCase()}`
|
|
|
+ industryListMap.push(all)
|
|
|
+
|
|
|
+ for (const key in this.industryListMapExp) {
|
|
|
+ const level1 = JSON.parse(JSON.stringify(this.industryExp))
|
|
|
+ level1.name = key
|
|
|
+ level1.level = 1
|
|
|
+ level1.id = `lv1-${getRandomString(8).toLowerCase()}`
|
|
|
+
|
|
|
+ const level2Arr = []
|
|
|
+ this.industryListMapExp[key].forEach(item => {
|
|
|
+ const level2 = JSON.parse(JSON.stringify(this.industryExp))
|
|
|
+ level2.name = item
|
|
|
+ level2.level = 2
|
|
|
+ level2.id = `lv2-${getRandomString(8).toLowerCase()}`
|
|
|
+ level2Arr.push(level2)
|
|
|
+ })
|
|
|
+
|
|
|
+ level1.children = level2Arr
|
|
|
+ industryListMap.push(level1)
|
|
|
+ }
|
|
|
+
|
|
|
+ this.industryListMap = industryListMap
|
|
|
+ },
|
|
|
+ // 按钮点击事件
|
|
|
+ changeIndustryState (item) {
|
|
|
+ // 循环所有数据,判断并改变状态
|
|
|
+ switch (item.level) {
|
|
|
+ case 0: {
|
|
|
+ this.setIndustryState()
|
|
|
+ break
|
|
|
+ }
|
|
|
+ case 1: {
|
|
|
+ item.selected = !item.selected
|
|
|
+
|
|
|
+ this.industryListMap[0].selected = false
|
|
|
+ // 二级子按钮状态跟随一级按钮
|
|
|
+ item.children.forEach(level2 => {
|
|
|
+ level2.selected = item.selected
|
|
|
+ })
|
|
|
+ break
|
|
|
+ }
|
|
|
+ case 2: {
|
|
|
+ item.selected = !item.selected
|
|
|
+
|
|
|
+ // 找到当前点击的父级元素
|
|
|
+ this.industryListMap.forEach(level1 => {
|
|
|
+ const selectedStateArr = []
|
|
|
+ if (item.level !== 0) {
|
|
|
+ level1.children.forEach(level2 => {
|
|
|
+ selectedStateArr.push(level2.selected)
|
|
|
+ })
|
|
|
+ if (selectedStateArr.indexOf(false) === -1) {
|
|
|
+ level1.selected = true
|
|
|
+ } else {
|
|
|
+ level1.selected = false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.industryListMap[0].selected = false
|
|
|
+ break
|
|
|
+ }
|
|
|
+ default: {
|
|
|
+ console.log('未知level')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (item.level !== 0) {
|
|
|
+ const allSelected = this.checkAllSelectedState()
|
|
|
+ if (allSelected.allSelected || allSelected.allNotSelected) {
|
|
|
+ this.setIndustryState()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ this.onChange()
|
|
|
+ },
|
|
|
+ // 检查是否全部选中了/全部不选中
|
|
|
+ checkAllSelectedState () {
|
|
|
+ // 一级标签选中状态(如果一级标签全部被选中,则说明,全部按钮被选中)
|
|
|
+ const level1StateArr = []
|
|
|
+ // 所有标签选中状态
|
|
|
+ const allSelectedArr = []
|
|
|
+
|
|
|
+ this.industryListMap.forEach(level1 => {
|
|
|
+ if (level1.level !== 0) {
|
|
|
+ level1StateArr.push(level1.selected)
|
|
|
+ allSelectedArr.push(level1.selected)
|
|
|
+ level1.children.forEach(level2 => {
|
|
|
+ allSelectedArr.push(level2.selected)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ // 找不到false,就说明全部被选中
|
|
|
+ allSelected: level1StateArr.indexOf(false) === -1,
|
|
|
+ // 找不到true,就说明没有一个被选中
|
|
|
+ allNotSelected: allSelectedArr.indexOf(true) === -1
|
|
|
+ }
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 初始化页面选中状态
|
|
|
+ * @param { Array | undefined } data 要恢复的数据
|
|
|
+ */
|
|
|
+ setIndustryState (data) {
|
|
|
+ // 设置全部按钮
|
|
|
+ if (!data || Object.keys(data).length === 0) {
|
|
|
+ // 其他全部设置不选中,全部按钮设置选中
|
|
|
+ this.industryListMap.forEach(item => {
|
|
|
+ item.selected = false
|
|
|
+ item.children.forEach(iitem => {
|
|
|
+ iitem.selected = false
|
|
|
+ })
|
|
|
+ })
|
|
|
+
|
|
|
+ this.industryListMap[0].selected = true
|
|
|
+ } else {
|
|
|
+ this.setIndustryState()
|
|
|
+ this.industryListMap[0].selected = false
|
|
|
+
|
|
|
+ this.industryListMap.forEach(item => {
|
|
|
+ if (data[item.name]) {
|
|
|
+ // 如果恢复数组长度等于页面二级标签长度,则一级标签点亮
|
|
|
+ if (data[item.name].length === item.children.length) {
|
|
|
+ item.selected = true
|
|
|
+ }
|
|
|
+ item.children.forEach(function (iitem) {
|
|
|
+ if (data[item.name].indexOf(iitem.name) !== -1) {
|
|
|
+ iitem.selected = true
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 获取选中的数据
|
|
|
+ getSelected () {
|
|
|
+ const map = {}
|
|
|
+
|
|
|
+ this.industryListMap.forEach(item => {
|
|
|
+ const mapArr = []
|
|
|
+
|
|
|
+ if (item.level !== 0) {
|
|
|
+ item.children.forEach(iitem => {
|
|
|
+ if (iitem.selected) {
|
|
|
+ mapArr.push(iitem.name)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mapArr.length !== 0) {
|
|
|
+ map[item.name] = mapArr
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ return map
|
|
|
+ },
|
|
|
+ // 搜索找到其level1级id
|
|
|
+ getIndexWithString (s = '') {
|
|
|
+ if (!s) return
|
|
|
+ let giveId = ''
|
|
|
+ this.industryListMap.find(level1 => {
|
|
|
+ if (level1.name.includes(s)) {
|
|
|
+ giveId = level1.id
|
|
|
+ return level1.id
|
|
|
+ } else {
|
|
|
+ return level1.children.find(level2 => {
|
|
|
+ if (level2.name.includes(s)) {
|
|
|
+ giveId = level1.id
|
|
|
+ return level2
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ return giveId
|
|
|
+ },
|
|
|
+ onChange () {
|
|
|
+ const selected = this.getSelected()
|
|
|
+ this.$emit('onChange', selected)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+</script>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+ .s-card {
|
|
|
+ .button-level-1 {
|
|
|
+ color: inherit;
|
|
|
+ font-weight: bold;
|
|
|
+ }
|
|
|
+ .button-level-2 {
|
|
|
+ margin: 5px;
|
|
|
+ }
|
|
|
+ .list-item-container {
|
|
|
+ padding: 6px 20px;
|
|
|
+ &:not(:last-of-type) {
|
|
|
+ border-bottom: 1px solid rgba(0,0,0,.05);
|
|
|
+ }
|
|
|
+ .list-item-main {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .s-line {
|
|
|
+ .selector-content {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ &.no-more {
|
|
|
+ height: 38px;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+ .j-button-item {
|
|
|
+ border-color: transparent;
|
|
|
+ }
|
|
|
+ .button-level-0 {
|
|
|
+ font-weight: 700;
|
|
|
+ border-color: transparent;
|
|
|
+ }
|
|
|
+ .button-level-1 {
|
|
|
+ color: $color-text--highlight;
|
|
|
+ &.active {
|
|
|
+ color: #fff;
|
|
|
+ background-color: $color-text--highlight;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .button-level-2 {
|
|
|
+ &.active {
|
|
|
+ background: rgba(44,183,202,0.10);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ .list-item-container {
|
|
|
+ position: relative;
|
|
|
+ margin: 0 4px;
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ &:not(:last-of-type)::after {
|
|
|
+ content: '';
|
|
|
+ position: absolute;
|
|
|
+ right: -6px;
|
|
|
+ top: 50%;
|
|
|
+ width: 1px;
|
|
|
+ height: 16px;
|
|
|
+ background-color: #E3E4E6;
|
|
|
+ margin-top: -8px;
|
|
|
+ }
|
|
|
+ .list-item-main {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+</style>
|