|
|
@@ -0,0 +1,378 @@
|
|
|
+var hierarchy_tpl = `
|
|
|
+ <div class="hierarchy_filter">
|
|
|
+ <div class="hierarchy_filter_trigger" @click="showPopup = true">
|
|
|
+ <div class="top_data_title_branch2">{{ label }}:{{ displayText || placeholder }}</div>
|
|
|
+ <div class="triangle"></div>
|
|
|
+ </div>
|
|
|
+ <van-popup v-model="showPopup" duration="0.2" round position="bottom" :close-on-click-overlay="false" :style="{ width: '100%' }">
|
|
|
+ <div class="hierarchy_title">
|
|
|
+ <div class="close_icon"></div>
|
|
|
+ <div>层级筛选</div>
|
|
|
+ <img class="close_icon" src="./img/qw/close_icon.png" alt="" @click="showPopup = false">
|
|
|
+ </div>
|
|
|
+ <div class="hierarchy_panel">
|
|
|
+ <!-- 城市 -->
|
|
|
+ <div class="hierarchy_column">
|
|
|
+ <div
|
|
|
+ v-for="city in cityOptionsData"
|
|
|
+ :key="city.value"
|
|
|
+ :class="['hierarchy_item', { 'hierarchy_item--active': city.value === activeCityValue }]"
|
|
|
+ @click="selectCity(city)"
|
|
|
+ >
|
|
|
+ {{ city.label }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 门店 -->
|
|
|
+ <div class="hierarchy_column" v-if="currentOutlets.length">
|
|
|
+ <div
|
|
|
+ v-for="outlet in currentOutlets"
|
|
|
+ :key="outlet.value"
|
|
|
+ :class="['hierarchy_item', { 'hierarchy_item--active': outlet.value === activeOutletValue }]"
|
|
|
+ @click="selectOutlet(outlet)"
|
|
|
+ >
|
|
|
+ {{ outlet.label }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 部门 -->
|
|
|
+ <div class="hierarchy_column" v-if="currentDepartments.length">
|
|
|
+ <div
|
|
|
+ v-for="dept in currentDepartments"
|
|
|
+ :key="dept.value"
|
|
|
+ :class="['hierarchy_item', { 'hierarchy_item--active': dept.value === activeDeptValue }]"
|
|
|
+ @click="selectDepartment(dept)"
|
|
|
+ >
|
|
|
+ {{ dept.label }}
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="hierarchy_actions">
|
|
|
+ <van-button size="small" @click="handleClear">重置</van-button>
|
|
|
+ <van-button size="small" type="primary" @click="handleConfirm">确定</van-button>
|
|
|
+ </div>
|
|
|
+ </van-popup>
|
|
|
+ </div>
|
|
|
+`
|
|
|
+
|
|
|
+var hierarchyComponent = Vue.extend({
|
|
|
+ template: hierarchy_tpl,
|
|
|
+
|
|
|
+ props: {
|
|
|
+ tenancyId: {
|
|
|
+ type: [Number, String],
|
|
|
+ default: () => ''
|
|
|
+ },
|
|
|
+ token: {
|
|
|
+ type: String,
|
|
|
+ default: () => ''
|
|
|
+ },
|
|
|
+ // 绑定值(选中路径的 value 数组)
|
|
|
+ value: {
|
|
|
+ type: Array,
|
|
|
+ default: function () {
|
|
|
+ return []
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // 外部可直接传入完整的层级数据(结构与原 aa.vue 一致)
|
|
|
+ options: {
|
|
|
+ type: Array,
|
|
|
+ default: function () {
|
|
|
+ return []
|
|
|
+ },
|
|
|
+ },
|
|
|
+ // 标签文本
|
|
|
+ label: {
|
|
|
+ type: String,
|
|
|
+ default: '筛选',
|
|
|
+ },
|
|
|
+ // 占位符
|
|
|
+ placeholder: {
|
|
|
+ type: String,
|
|
|
+ default: '全部',
|
|
|
+ },
|
|
|
+ // 是否显示连接符
|
|
|
+ showConnector: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
+ // 连接符
|
|
|
+ connector: {
|
|
|
+ type: String,
|
|
|
+ default: '-',
|
|
|
+ },
|
|
|
+ // 是否展示城市层级(与原组件保持一致,预留)
|
|
|
+ showCityOptions: {
|
|
|
+ type: Boolean,
|
|
|
+ default: true,
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ data: function () {
|
|
|
+ return {
|
|
|
+ httpUrl: '',
|
|
|
+ env: '',
|
|
|
+ showPopup: false,
|
|
|
+ internalValue: [],
|
|
|
+ cityOptionsData: [],
|
|
|
+ activeCityValue: null,
|
|
|
+ activeOutletValue: null,
|
|
|
+ activeDeptValue: null,
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ computed: {
|
|
|
+ // 当前门店列表
|
|
|
+ currentOutlets: function () {
|
|
|
+ var city = this.cityOptionsData.find(function (item) {
|
|
|
+ return String(item.value) === String(this.activeCityValue)
|
|
|
+ }.bind(this))
|
|
|
+ return city && city.children ? city.children : []
|
|
|
+ },
|
|
|
+ // 当前部门列表
|
|
|
+ currentDepartments: function () {
|
|
|
+ var outlets = this.currentOutlets
|
|
|
+ var outlet = outlets.find(function (item) {
|
|
|
+ return String(item.value) === String(this.activeOutletValue)
|
|
|
+ }.bind(this))
|
|
|
+ return outlet && outlet.children ? outlet.children : []
|
|
|
+ },
|
|
|
+ // 展示文本
|
|
|
+ displayText: function () {
|
|
|
+ if (!this.internalValue.length) return ''
|
|
|
+ var labels = this.getLabelsByValues(this.internalValue)
|
|
|
+ if (!labels.length) return ''
|
|
|
+ if (labels[0] === '全部') return '全部'
|
|
|
+ var lastTwo = labels.slice(-2).map(function (l) {
|
|
|
+ return String(l).replace(/-/g, '')
|
|
|
+ })
|
|
|
+ return this.showConnector ? lastTwo.join(this.connector) : lastTwo.join('')
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ watch: {
|
|
|
+ value: {
|
|
|
+ immediate: true,
|
|
|
+ handler: function (val) {
|
|
|
+ this.internalValue = (val || []).slice()
|
|
|
+ this.syncActiveFromValue()
|
|
|
+ },
|
|
|
+ },
|
|
|
+ options: {
|
|
|
+ immediate: true,
|
|
|
+ handler: function (list) {
|
|
|
+ if (Array.isArray(list) && list.length) {
|
|
|
+ this.cityOptionsData = list
|
|
|
+ }
|
|
|
+ },
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+ created: function () {
|
|
|
+ this.env = this.getQueryParam('env')
|
|
|
+
|
|
|
+ if (!this.env || this.env === 'prod') {
|
|
|
+ this.httpUrl = 'https://wlapi.wefanbot.com'
|
|
|
+ } else {
|
|
|
+ this.httpUrl = 'http://test.wefanbot.com:18993'
|
|
|
+ }
|
|
|
+ // 如果外部没有传 options,则可以在这里按需请求
|
|
|
+ // 由于 lottery 项目中未必有 $http,这里只保留占位逻辑,避免直接报错
|
|
|
+ if ((!this.options || !this.options.length) && typeof this.getCityOptions === 'function') {
|
|
|
+ this.getCityOptions()
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ methods: {
|
|
|
+ // 获取城市-门店-部门层级数据(与 aa.vue 保持同结构)
|
|
|
+ getCityOptions() {
|
|
|
+ var headers = new Headers()
|
|
|
+ headers.append('tenancyId', this.tenancyId)
|
|
|
+ headers.append('token', this.token)
|
|
|
+ fetch(this.httpUrl + '/scrm/v1/tenancy-city/city-outlet-depart-options', {
|
|
|
+ method: 'GET',
|
|
|
+ headers: headers,
|
|
|
+ })
|
|
|
+ .then(function (res) {
|
|
|
+ return res.json()
|
|
|
+ })
|
|
|
+ .then(function (result) {
|
|
|
+ var data = result.data
|
|
|
+ var code = result.code
|
|
|
+ var msg = result.msg
|
|
|
+ if (code === 1) {
|
|
|
+ var list = Array.isArray(data) ? data : (data && (data.records || data.list)) || []
|
|
|
+ this.cityOptionsData =
|
|
|
+ list && list.length
|
|
|
+ ? [
|
|
|
+ {
|
|
|
+ value: 'allCity',
|
|
|
+ label: '全部城市',
|
|
|
+ },
|
|
|
+ ].concat(
|
|
|
+ list.map(function (j) {
|
|
|
+ return {
|
|
|
+ value: j.cityAreaNo,
|
|
|
+ label: j.cityName,
|
|
|
+ children:
|
|
|
+ j.outlets && j.outlets.length
|
|
|
+ ? [
|
|
|
+ {
|
|
|
+ value: 'outlet_' + j.cityAreaNo,
|
|
|
+ label: '全部门店',
|
|
|
+ },
|
|
|
+ ].concat(
|
|
|
+ j.outlets.map(function (k) {
|
|
|
+ return {
|
|
|
+ value: k.outletId,
|
|
|
+ label: k.outletName,
|
|
|
+ outletId: k.outletId,
|
|
|
+ children:
|
|
|
+ k.departments && k.departments.length
|
|
|
+ ? [
|
|
|
+ {
|
|
|
+ value: 'department_' + k.outletId,
|
|
|
+ label: '全部部门',
|
|
|
+ },
|
|
|
+ ].concat(
|
|
|
+ k.departments.map(function (p) {
|
|
|
+ return {
|
|
|
+ value: p.departmentId,
|
|
|
+ label: p.departmentName,
|
|
|
+ }
|
|
|
+ })
|
|
|
+ )
|
|
|
+ : [],
|
|
|
+ }
|
|
|
+ })
|
|
|
+ )
|
|
|
+ : [],
|
|
|
+ }
|
|
|
+ })
|
|
|
+ )
|
|
|
+ : []
|
|
|
+ } else {
|
|
|
+ vant.Toast.fail(msg || '获取城市选项失败')
|
|
|
+ }
|
|
|
+ }.bind(this))
|
|
|
+ .catch(function () {
|
|
|
+ vant.Toast.fail('获取城市选项失败')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ // 根据当前 internalValue 还原活动节点
|
|
|
+ syncActiveFromValue: function () {
|
|
|
+ var vals = this.internalValue
|
|
|
+ if (!vals || !vals.length) {
|
|
|
+ this.activeCityValue = null
|
|
|
+ this.activeOutletValue = null
|
|
|
+ this.activeDeptValue = null
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.activeCityValue = vals[0] != null ? vals[0] : null
|
|
|
+ this.activeOutletValue = vals[1] != null ? vals[1] : null
|
|
|
+ this.activeDeptValue = vals[2] != null ? vals[2] : null
|
|
|
+ },
|
|
|
+
|
|
|
+ // 根据 value 路径拿到 label 数组
|
|
|
+ getLabelsByValues: function (values) {
|
|
|
+ var labels = []
|
|
|
+ var level = this.cityOptionsData
|
|
|
+ for (var i = 0; i < values.length; i++) {
|
|
|
+ if (!level || !level.length) break
|
|
|
+ var val = values[i]
|
|
|
+ var node = null
|
|
|
+ for (var j = 0; j < level.length; j++) {
|
|
|
+ if (String(level[j].value) === String(val)) {
|
|
|
+ node = level[j]
|
|
|
+ break
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!node) break
|
|
|
+ labels.push(node.label)
|
|
|
+ level = node.children || []
|
|
|
+ }
|
|
|
+ return labels
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择城市
|
|
|
+ selectCity: function (city) {
|
|
|
+ this.activeCityValue = city.value
|
|
|
+ this.activeOutletValue = null
|
|
|
+ this.activeDeptValue = null
|
|
|
+ this.internalValue = [city.value]
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择门店
|
|
|
+ selectOutlet: function (outlet) {
|
|
|
+ this.activeOutletValue = outlet.value
|
|
|
+ this.activeDeptValue = null
|
|
|
+ this.internalValue = [this.activeCityValue, outlet.value]
|
|
|
+ },
|
|
|
+
|
|
|
+ // 选择部门
|
|
|
+ selectDepartment: function (dept) {
|
|
|
+ this.activeDeptValue = dept.value
|
|
|
+ this.internalValue = [this.activeCityValue, this.activeOutletValue, dept.value]
|
|
|
+ },
|
|
|
+
|
|
|
+ // 清空选择
|
|
|
+ handleClear: function () {
|
|
|
+ this.activeCityValue = null
|
|
|
+ this.activeOutletValue = null
|
|
|
+ this.activeDeptValue = null
|
|
|
+ this.internalValue = []
|
|
|
+ this.$emit('input', [])
|
|
|
+ this.$emit('on-change', [], [], [])
|
|
|
+ },
|
|
|
+
|
|
|
+ // 确认选择,复用原 aa.vue 的 on-change 事件签名
|
|
|
+ handleConfirm: function () {
|
|
|
+ var values = this.internalValue.slice()
|
|
|
+ var departmentIds = []
|
|
|
+ var outletIds = []
|
|
|
+ var tenancyIds = []
|
|
|
+ if (values && values.length) {
|
|
|
+ var value = String(values[values.length - 1])
|
|
|
+ if (value !== 'allRegion' && value !== 'allCity' && value.indexOf('_') === -1) {
|
|
|
+ if (this.showCityOptions) {
|
|
|
+ departmentIds.push(Number(value))
|
|
|
+ } else {
|
|
|
+ tenancyIds.push(Number(value))
|
|
|
+ }
|
|
|
+ } else if (value.indexOf('department_') > -1) {
|
|
|
+ outletIds.push(Number(value.split('_')[1]))
|
|
|
+ } else if (value.indexOf('outlet_') > -1) {
|
|
|
+ var city = this.cityOptionsData.filter(function (item) {
|
|
|
+ return Number(item.value) === Number(value.split('_')[1])
|
|
|
+ })
|
|
|
+ if (city[0] && city[0].children) {
|
|
|
+ outletIds = city[0].children
|
|
|
+ .filter(function (item) {
|
|
|
+ return item.outletId
|
|
|
+ })
|
|
|
+ .map(function (item) {
|
|
|
+ return item.outletId
|
|
|
+ })
|
|
|
+ }
|
|
|
+ } else if (value.indexOf('city_') > -1) {
|
|
|
+ tenancyIds.push(Number(value.split('_')[1]))
|
|
|
+ } else if (value === 'allRegion' || value === 'allCity') {
|
|
|
+ departmentIds = []
|
|
|
+ outletIds = []
|
|
|
+ tenancyIds = []
|
|
|
+ }
|
|
|
+ }
|
|
|
+ this.$emit('input', values)
|
|
|
+ this.$emit('on-change', departmentIds, outletIds, tenancyIds)
|
|
|
+ this.showPopup = false
|
|
|
+ },
|
|
|
+ // 截取 url 中的 env(与 select-tag.js 保持一致)
|
|
|
+ getQueryParam: function (paramName) {
|
|
|
+ var queryString = window.location.search
|
|
|
+ var urlParams = new URLSearchParams(queryString)
|
|
|
+ return urlParams.get(paramName)
|
|
|
+ },
|
|
|
+ },
|
|
|
+})
|
|
|
+
|
|
|
+// 全局注册组件:<hierarchy-filter></hierarchy-filter>
|
|
|
+Vue.component('hierarchy-filter', hierarchyComponent)
|
|
|
+
|