123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651 |
- // 传入你要获取的参数的名字
- function getParam (name) {
- var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i');
- var r = window.location.search.substr(1).match(reg); //获取url中'?'符后的字符串并正则匹配
- var context = '';
- if (r != null) context = r[2];
- // 释放变量
- reg = null;
- r = null;
- return context == null || context == '' || context == 'undefined' ? '' : context;
- }
- // 需要结合area-three-sidebar-template.js使用
- function getRandomString (len) {
- let randomString = ''
- if (len) {
- var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'
- var maxPos = $chars.length
- for (let i = 0; i < len; i++) {
- randomString += $chars.charAt(Math.floor(Math.random() * maxPos))
- }
- } else {
- randomString = Math.random().toString(36).substring(2)
- }
- return randomString
- }
- var AreaThreeSidebarTemplate = `
- <sidebar-selector-ui
- ref="firstSidebar"
- class="area-city-sidebar-selector first-sidebar"
- :height="height"
- :class="{
- 'disabled-city': disabledCitySelect,
- 'province-city-split': useProvinceCitySplit
- }"
- :whenParentLevel0Selected="whenParentLevel0Selected"
- :sourceList="provinceList"
- :childrenAddText="childrenAddText"
- @onChange="onChangeFirst"
- :beforeChildChange="beforeChildChange"
- :showParentWhenChildrenEmpty="false"
- :lazyRender="false">
- <template #tab-tag="{ parent }">
- <slot name="tab-tag" :parent="parent">
- <van-tag
- round
- type="primary"
- v-if="parent.value && sourceFirstCount[parent.value] && sourceFirstCount[parent.value]._children_selectedCount"
- :class="{ visible: sourceFirstCount[parent.value]._children_selectedCount === 0 }">
- {{sourceFirstCount[parent.value]._children_selectedCount }}
- </van-tag>
- </slot>
- </template>
- <template #tab-content="{ parent }">
- <!-- 嵌套的 side-bar 组件 -->
- <Sidebar-selector-ui
- :ref="'secondSidebar_' + parent.id || ''"
- class="area-city-sidebar-selector second-sidebar"
- :class="{
- 'disabled-city': disabledCitySelect,
- 'province-city-split': useProvinceCitySplit
- }"
- :height="height"
- :childrenAddText="childrenAddText"
- :source-list="parent.children"
- @onChange="onChange($event, parent.value)"
- :beforeChildChange="beforeChildChange"
- :showParentWhenChildrenEmpty="false">
- <template #tab-item="{ parent }">
- <div class="title-name" v-show="!isGAT(parent.name)">{{ parent.name }}</div>
- <div class="title-text" v-show="!isGAT(parent.name)">
- <slot name="tab-tag" :parent="parent">
- <van-tag
- round
- type="primary"
- v-if="tagTextOnlySelectedCount && parent._children_selectedCount">
- {{ parent._children_selectedCount }}
- </van-tag>
- </slot>
- </div>
- </template>
- <template #default="{ parent, child }">
- <slot name="default" v-bind="{ parent, child }">
- <template v-if="parent.level !== 0 && child.level === 0 && useProvinceCitySplit">
- <van-cell is-link :border="false">
- {{child.name}}
- <template #right-icon>
- <span class="j-icon checkbox" :class="{ checked: child._selected }"></span>
- </template>
- </van-cell>
- <div class="children-title border-line-b" @click.stop>
- <div class="c-title-text">市级</div>
- <van-tag v-if="disabledCitySelect" round plain type="danger" @click="disabledCityClick">开通</van-tag>
- </div>
- </template>
- </slot>
- </template>
- </Sidebar-selector-ui>
- </template>
- </sidebar-selector-ui>`
- var areaThreeSidebarComponent = {
- name: 'area-three-sidebar-template',
- template: AreaThreeSidebarTemplate,
- components: {
- SidebarSelectorUi: SidebarSelectorUi
- },
- props: {
- height: {
- type: String,
- default: ''
- },
- value: {
- type: Object,
- default () {
- return {}
- }
- },
- /**
- * 省份城市布局分割
- */
- useProvinceCitySplit: {
- type: Boolean,
- default: false
- },
- /**
- * 城市选择禁用
- */
- disabledCitySelect: {
- type: Boolean,
- default: false
- },
- /**
- * 数据统计tag显示
- */
- tagTextOnlySelectedCount: {
- type: Boolean,
- default: false
- },
- /**
- * 二级子项 "全部" 文字的替换
- */
- childrenAddText: String,
- /**
- * 更改确认函数
- *
- * 如果传入该函数,点击二级子项会触发,返回true会确认成功,返回false则会阻止更改
- */
- beforeChange: Function,
- /**
- * 是否可全不选中
- */
- canEmptySelected: {
- type: Boolean,
- default: false
- }
- },
- model: {
- prop: 'value',
- event: 'modelChange'
- },
- watch: {
- value: {
- handler(newVal) {
- this.setState(newVal)
- },
- deep: true
- }
- },
- data () {
- return {
- // 原始数组
- provinceListMapExp: {
- '#': ['全国'],
- A: ['安徽', '澳门'],
- B: ['北京'],
- C: ['重庆'],
- F: ['福建'],
- G: ['广东', '广西', '贵州', '甘肃'],
- H: ['河北', '湖北', '黑龙江', '海南', '河南', '湖南'],
- J: ['吉林', '江苏', '江西'],
- L: ['辽宁'],
- N: ['内蒙古', '宁夏'],
- Q: ['青海'],
- S: ['山西', '陕西', '上海', '山东', '四川'],
- T: ['天津', '台湾'],
- X: ['西藏', '新疆', '香港'],
- Y: ['云南'],
- Z: ['浙江']
- },
- whenParentLevel0Selected: false,
- // 原始城市数据
- // chinaMapJSON,
- provinceListMap: {
- // A: [
- // {
- // name: '安徽',
- // expanded: false,
- // canExpanded: true,
- // selectedState: '',
- // children: []
- // }
- // ]
- },
- provinceList: [],
- // indexBar数据
- indexList: [],
- provinceExp: {
- name: '安徽',
- value: '',
- // 展开状态
- expanded: false,
- // 是否可以展开
- canExpanded: false,
- children: []
- },
- sourceFirstCount: {},
- // 全国二级菜单名
- allCountryRefName: null,
- // 二级菜单ref名
- secondRefNameObj: {}
- }
- },
- created () {
- this.init(this.provinceListMapExp)
- },
- mounted () {
- var defaultVal = this.canEmptySelected ? -1 : {}
- this.setState(defaultVal)
- this.setActiveTab(1)
- },
- methods: {
- setActiveTab (num) {
- var { firstSidebar } = this.$refs
- firstSidebar.setActiveTab(num)
- },
- // 整理城市数据列表(并初始化indexBar数据)
- init (provinceListMapExp) {
- // 整理数据得到List,同时获得indexList
- var provinceListMap = {}
- var indexList = []
- this.secondRefNameObj = {}
- this.allCountryRefName = null
- for (var key in provinceListMapExp) {
- var areaArr = []
- indexList.push(key)
- provinceListMapExp[key].forEach(pName => {
- var provinceExp = JSON.parse(JSON.stringify(this.provinceExp))
- provinceExp.name = pName
- provinceExp.id = `ap-${getRandomString(8).toLowerCase()}`
- // 记录下二级ref
- this.$set(this.secondRefNameObj, pName, 'secondSidebar_' + provinceExp.id)
- if(pName === '全国') {
- this.allCountryRefName = 'secondSidebar_' + provinceExp.id
- }
- if (pName !== '全国') {
- var cities = this.getCitiesFromJSONMap(pName)
- // 筛选掉直辖市和特别行政区(台湾省也不不需要展开)
- if (cities.ProRemark === '省份' || cities.ProRemark === '自治区') {
- if (cities.ProID === 32) {
- provinceExp.children = []
- provinceExp.canExpanded = false
- } else {
- cities.city.forEach(c => {
- // 将区县数据取出,处理成新数组,放入城市
- let districtChildren = []
- if(c.area && c.area.length > 0) {
- districtChildren = c.area.map(dItem => {
- return {
- district: dItem,
- selected: false,
- canSelected: true,
- id: `adi-${getRandomString(8).toLowerCase()}`
- }
- })
- }
- // 将市区重组成一个新的对象
- provinceExp.children.push({
- city: c.name,
- selected: false,
- canSelected: true,
- id: `ac-${getRandomString(8).toLowerCase()}`,
- children: districtChildren// 区县
- })
- })
- }
- } else if (cities.ProRemark === '直辖市') {
- // 直辖市,将区县放置到第二级
- if(cities.city && Array.isArray(cities?.city)) {
- var orgDistrict = cities?.city[0].area || []
- // 将区县数据取出,处理成新数组,放入城市
- let districtChildren = orgDistrict.map(dItem => {
- return {
- district: dItem,
- selected: false,
- canSelected: true,
- id: `adi-${getRandomString(8).toLowerCase()}`
- }
- })
- provinceExp.children.push({
- city: provinceExp.name?.indexOf('市') > -1 ? provinceExp.name : provinceExp.name + '市',
- selected: false,
- canSelected: true,
- id: `ac-${getRandomString(8).toLowerCase()}`,
- children: districtChildren
- })
- }
- } else {
- provinceExp.children = []
- provinceExp.canExpanded = false
- }
- }
- provinceExp.canExpanded = provinceExp.children.length !== 0
- areaArr.push(provinceExp)
- })
- provinceListMap[key] = areaArr
- }
- this.provinceListMap = provinceListMap
- this.indexList = indexList.filter(i => i !== '#')
- // 给provinceListMap赋值
- for (var k in provinceListMap) {
- this.$set(this.provinceListMap, k, provinceListMap[k])
- }
- this.initProvinceList(provinceListMap)
- },
- // 循环chinaMapJSON,找到对应省下面对应的市
- getCitiesFromJSONMap (provinceName) {
- let temp = null
- for (let i = 0; i < chinaMapJSON.length; i++) {
- var findThis = chinaMapJSON[i].name.indexOf(provinceName) !== -1
- // 如果找到了,就不再循环后面的了
- if (findThis) {
- temp = chinaMapJSON[i]
- break
- }
- }
- return temp
- },
- initProvinceList (provinceListMap) {
- var provinceList = []
- for (var key in provinceListMap) {
- var provinces = provinceListMap[key]
- provinces.forEach(province => {
- if (province.name === '全国') {
- province.level = 0
- } else {
- province.level = 1
- }
- var cities = []
- if (Array.isArray(province.children)) {
- province.children.forEach(city => {
- // 将区县数据取出,处理成新数组,放入城市
- let districtChildren = []
- if(Array.isArray(city.children)) {
- districtChildren = city.children.map(dItem => {
- return {
- topName: province.name,
- parentName: city.city,
- name: dItem.district,
- value: dItem.district,
- id: dItem.id,
- level: 3
- }
- })
- }
- cities.push({
- id: city.id,
- name: city.city,
- value: city.city,
- level: 2,
- parentName: province.name,
- sourceChildrenCount: districtChildren.length, // 子集真实数量
- children: districtChildren // 区县
- })
- })
- }
- provinceList.push({
- id: province.id,
- name: province.name,
- value: province.name,
- level: province.level,
- sourceChildrenCount: cities.length, // 子集真实数量
- children: cities,
- hasThree: true
- })
- })
- }
- this.provinceList = provinceList
- },
- disabledCityClick () {
- this.$emit('on-disabled-city-click')
- },
- beforeChildChange (parent, child) {
- if (this.beforeChange) {
- return this.beforeChange(parent, child)
- }
- // 已选的省份列表
- const selectedProvinceList = []
- for(var key in this.sourceFirstCount) {
- selectedProvinceList.push(key)
- }
- if (this.disabledCitySelect) {
- if(parent.parentName && selectedProvinceList.indexOf(parent.parentName) > -1) {
- return true
- } else {
- this.disabledCityClick()
- return false
- }
- } else {
- return true
- }
- },
- getState () {
- var { state } = this.getStateMore()
- return state
- },
- /**
- * 最后输出数据结构
- * 参数area示例
- * {
- * 澳门: {}
- * 北京: {
- * 北京: ['朝阳区']
- * },
- * 河南: {
- * 南阳市: [],
- * 郑州: ['金水区'],
- * 洛阳市: ['栾川县','老城区']
- * }
- * }
- */
- getStateMore () {
- // 选中状态
- var state = {}
- // 选中数量统计
- var stateCounter = {}
- // 是否选了全国
- var isSelectedCountry = false
- // 所有二级市区遍历
- for(let refKey in this.secondRefNameObj) {
- var refName = this.secondRefNameObj[refKey]
- var renderList = this.$refs[refName]?.renderList || []
- for (let i = 0; i < renderList.length; i++) {
- var parent = renderList[i]
- var children = parent.children
- var provinceName = parent.parentName
- // 全国选中
- if (parent.level === 0 && provinceName === '全国') {
- if (children && children[0]._selected) {
- isSelectedCountry = true
- break
- }
- continue
- }
- // 当前省份下,全部选中(保存当前省份)
- if(parent.level === 0 && provinceName !== '全国') {
- // 市区【全部】和区县【全部】都选中
- if (parent._selected) {
- state[provinceName] = {}
- break
- }
- continue
- }
- // 当前市全选中(【市区】和【全部】选中)
- if(parent.level === 2 && parent._selected) {
- if(!state[provinceName]) {
- state[provinceName] = {}
- }
- this.$set(state[provinceName], parent.name, [])
- continue
- }
- // 区县选择
- if (Array.isArray(children)) {
- var childSelected = []
- for (let j = 0; j < children.length; j++) {
- var child = children[j]
- if (child.level === 0) {
- continue
- } else {
- if (child._selected) {
- childSelected.push(child.value)
- }
- }
- }
- if (childSelected.length > 0) {
- if(!state[provinceName]) {
- state[provinceName] = {}
- }
- if(!state[provinceName][parent.name]) {
- this.$set(state[provinceName], parent.name, [])
- }
- state[provinceName][parent.name] = childSelected
- }
- }
- }
- }
- var resultState = state
- if(Object.keys(state).length === 0 && !isSelectedCountry && this.canEmptySelected) {
- resultState = -1
- }
- return {
- state: resultState,
- stateCounter
- }
- },
- /**
- * 设置组件状态
- * getState中获取的数据能够直接传入进行状态恢复
- * 全部不选中传入-1
- */
- setState (state) {
- // 所有都不选中
- if (state === -1) {
- this.resetSelect(false)
- this.$emit('modelChange', -1)
- return
- }
- var firstSidebar = this.$refs.firstSidebar
- firstSidebar.setAllState(false)
- firstSidebar.refreshAllChildrenState(false)
- // 重置第二级,并且选中全国
- this.resetSelect()
- if (typeof state === 'object' && Object.keys(state).length > 0) {
- this.setSidebarState(state)
- this.$refs[this.allCountryRefName]?.setParentLevel0State(false)
- }
- // 重新计算parent数据统计
- firstSidebar.refreshAllChildrenState()
- this.$emit('modelChange', state || {})
- },
- setSidebarState (state) {
- for(var proName in state) {
- var refName = this.secondRefNameObj[proName]
- var refItem = this.$refs[refName]
- if(!refItem) {
- return
- }
- // 选择了全省
- var stateProvince = state[proName]
- // 第一级省份下选中的市区数量
- let _children_selectedCount = 0
- refItem.setState(renderList => {
- // 选择了全省
- if(stateProvince && Object.keys(stateProvince).length === 0) {
- refItem.setAllState(true)
- refItem.refreshAllChildrenState(true)
- // 更新第一级 side-bar 的状态
- _children_selectedCount = renderList.length - 1
- } else {
- renderList.forEach(parent => {
- // 当前市下选择的区域数组
- var stateDistrict = stateProvince[parent.name]
- if(stateDistrict) {
- if (Array.isArray(stateDistrict)) {
- _children_selectedCount += 1
- // 选择了全市
- if (stateDistrict.length === 0) {
- refItem.setChildrenState(parent.children, true)
- } else {
- // 选择了部分区域
- parent.children.forEach(child => {
- if (stateDistrict.includes(child.value)) {
- child._selected = true
- }
- })
- }
- }
- refItem.checkChildrenAllChecked(parent, parent.children)
- }
- })
- }
- // 更新第一级 side-bar 的状态
- this.$set(this.sourceFirstCount, proName, {
- _children_selectedCount: _children_selectedCount,
- _children_count: renderList.length - 1
- })
- })
- refItem.refreshAllChildrenState()
- }
- },
- // 重置所有选择
- resetSelect(selectedAll = true) {
- var { firstSidebar } = this.$refs
- firstSidebar.setAllState(false)
- firstSidebar.refreshAllChildrenState(false)
- firstSidebar.setParentLevel0State(selectedAll)
- var firstRenderList = firstSidebar.renderList
- for(let item of firstRenderList) {
- var secondRef = this.$refs['secondSidebar_' + item.id]
- secondRef.setAllState(false)
- secondRef.refreshAllChildrenState(false)
- if(item.name === '全国'){
- secondRef.setParentLevel0State(selectedAll)
- }
- }
- this.sourceFirstCount = {}
- },
- // 处理第一级 side-bar 组件的变化事件
- onChangeFirst({ parent, child, renderList }) {
- if (parent.level === 0 && parent.name === '全国') {
- this.resetSelect()
- } else {
- this.$set(this.sourceFirstCount, parent.value, {
- _children_selectedCount: parent._children_selectedCount,
- _children_count: parent._children_count
- })
- this.$refs.firstSidebar.setParentLevel0State(false)
- }
- },
- // 处理第二级 side-bar 组件的变化事件
- onChange ({ parent, child, renderList }, value) {
- this.disposeSecondCount({ parent, child, renderList }, value)
- var stateValue = this.getState()
- var payload = { parent, child, value: stateValue }
- this.$emit('modelChange', payload.value)
- this.$emit('change', payload)
- },
- // 处理二级菜单选择
- disposeSecondCount ({ parent, child, renderList }, value) {
- if(parent.level === 0 && parent.parentName ==='全国'){
- this.resetSelect()
- return
- }
- // 将全国选择重置掉
- if(this.allCountryRefName) {
- this.$refs[this.allCountryRefName]?.setParentLevel0State(false)
- }
- var selectedNum = renderList?.filter(temp => temp._children_selectedCount > 0)?.length || 0
- var result = {
- _children_selectedCount: selectedNum,
- _children_count: renderList.length - 1
- }
- // 更新第一级 side-bar 的状态
- this.$set(this.sourceFirstCount, value, result)
- this.$refs.firstSidebar.setParentLevel0State(false)
- },
- // 是否是港澳台地区
- isGAT(val) {
- var GATList = ['香港', '澳门', '台湾']
- return val && GATList.indexOf(val) > -1
- }
- }
- }
|