省市级联组件

This commit is contained in:
fengachen
2021-09-01 19:02:12 +08:00
parent d92c946254
commit c59f959373
12 changed files with 3803 additions and 2448 deletions
+78
View File
@@ -0,0 +1,78 @@
import { pcaa } from 'area-data'
/**
* 省市区
*/
export default class Area {
/**
* 构造器
* @param express
*/
constructor() {
const arr = []
const province = pcaa['86']
Object.keys(province).map(key => {
arr.push({ id: key, text: province[key], pid: '86' })
const city = pcaa[key]
Object.keys(city).map(key2 => {
arr.push({ id: key2, text: city[key2], pid: key })
const qu = pcaa[key2]
Object.keys(qu).map(key3 => {
arr.push({ id: key3, text: qu[key3], pid: key2 })
})
})
})
this.all = arr
}
get pca() {
return this.all
}
getCode(text) {
if (!text || text.length === 0) {
return ''
}
for (const item of this.all) {
if (item.text === text) {
return item.id
}
}
}
getText(code) {
if (!code || code.length === 0) {
return ''
}
const arr = []
this.getAreaBycode(code, arr)
return arr.join('/')
}
getRealCode(code) {
const arr = []
this.getPcode(code, arr)
return arr
}
getPcode(id, arr) {
for (const item of this.all) {
if (item.id === id) {
arr.unshift(id)
if (item.pid !== '86') {
this.getPcode(item.pid, arr)
}
}
}
}
getAreaBycode(code, arr) {
// console.log("this.all.length",this.all)
for (const item of this.all) {
if (item.id === code) {
arr.unshift(item.text)
this.getAreaBycode(item.pid, arr)
}
}
}
}
+74
View File
@@ -0,0 +1,74 @@
import pca from '../../../public/map/areaPca'
/**
* 省市区
*/
export default class Area {
/**
* 构造器
* @param express
*/
constructor() {
const arr = []
const province = pca['86']
Object.keys(province).map(key => {
arr.push({ id: key, text: province[key], pid: '86' })
const city = pca[key]
Object.keys(city).map(key2 => {
arr.push({ id: key2, text: city[key2], pid: key })
})
})
this.all = arr
}
get pca() {
return this.all
}
getCode(text) {
if (!text || text.length === 0) {
return ''
}
for (const item of this.all) {
if (item.text === text) {
return item.id
}
}
}
getText(code) {
if (!code || code.length === 0) {
return ''
}
const arr = []
this.getAreaBycode(code, arr)
return arr.join('/')
}
getRealCode(code) {
const arr = []
this.getPcode(code, arr)
return arr
}
getPcode(id, arr) {
for (const item of this.all) {
if (item.id === id) {
arr.unshift(id)
if (item.pid !== '86') {
this.getPcode(item.pid, arr)
}
}
}
}
getAreaBycode(code, arr) {
// console.log("this.all.length",this.all)
for (const item of this.all) {
if (item.id === code) {
arr.unshift(item.text)
this.getAreaBycode(item.pid, arr)
}
}
}
}
+35
View File
@@ -0,0 +1,35 @@
/**
* 获取字符串的长度ascii长度为1 中文长度为2
* @param str
* @returns {number}
*/
export const getStrFullLength = (str = '') =>
str.split('').reduce((pre, cur) => {
const charCode = cur.charCodeAt(0)
if (charCode >= 0 && charCode <= 128) {
return pre + 1
}
return pre + 2
}, 0)
/**
* 给定一个字符串和一个长度,将此字符串按指定长度截取
* @param str
* @param maxLength
* @returns {string}
*/
export const cutStrByFullLength = (str = '', maxLength) => {
let showLength = 0
return str.split('').reduce((pre, cur) => {
const charCode = cur.charCodeAt(0)
if (charCode >= 0 && charCode <= 128) {
showLength += 1
} else {
showLength += 2
}
if (showLength <= maxLength) {
return pre + cur
}
return pre
}, '')
}
+12
View File
@@ -0,0 +1,12 @@
/**
* components util
*/
/**
* 清理空值,对象
* @param children
* @returns {*[]}
*/
export function filterEmpty(children = []) {
return children.filter(c => c.tag || (c.text && c.text.trim() !== ''))
}
+169
View File
@@ -0,0 +1,169 @@
<template>
<div v-if="!reloading" class="j-area-linkage">
<!--area-cascader level-0二级联动 1-三级联动-->
<area-cascader
v-if="_type === enums.type[0]"
:value="innerValue"
:data="pca"
:style="{width}"
v-bind="$attrs"
v-on="_listeners"
@change="handleChange"
:class="isActive ? 'placeholderBlack' : 'placeholderGray'"
/>
<!--area-select level-1二级联动 2-三级联动-->
<area-select
v-else-if="_type === enums.type[1]"
:value="innerValue"
:data="pca"
v-bind="$attrs"
v-on="_listeners"
@change="handleChange"
:class="isActive ? 'placeholderBlack' : 'placeholderGray'"
/>
<div v-else>
<span style="color:red;"> Bad type value: {{_type}}</span>
</div>
</div>
</template>
<script>
import pca from '../../../public/map/areaPca'
import Area from '@comp/_util/AreaPca'
export default {
name: 'JAreaLinkagePca',
props: {
value: {
type: String,
required: false
},
// 组件的类型,可选值:
// select 下拉样式
// cascader 级联样式(默认)
type: {
type: String,
default: 'cascader'
},
width: {
type: String,
default: '100%'
}
},
data() {
return {
pca,
isActive: false, // false placeholder为灰色。 true placeholder 为黑色
innerValue: [],
usedListeners: ['change'],
enums: {
type: ['cascader', 'select']
},
reloading: false,
areaData: ''
}
},
computed: {
_listeners() {
const listeners = { ...this.$listeners }
// 去掉已使用的事件,防止冲突
this.usedListeners.forEach(key => {
delete listeners[key]
})
return listeners
},
_type() {
if (this.enums.type.includes(this.type)) {
return this.type
} else {
console.error(`JAreaLinkage的type属性只能接收指定的值(${this.enums.type.join('|')}`)
return this.enums.type[0]
}
}
},
watch: {
value: {
immediate: true,
handler() {
this.loadDataByValue(this.value)
if (this.value) {
this.isActive = true // 此时value有值
}
}
}
},
created() {
this.initAreaData()
},
methods: {
/** 通过 value 反推 options */
loadDataByValue(value) {
if (!value || value.length === 0) {
this.innerValue = []
this.reloading = true
setTimeout(() => {
this.reloading = false
}, 100)
} else {
this.initAreaData()
const arr = this.areaData.getRealCode(value)
this.innerValue = arr
}
},
/** 通过地区code获取子级 */
loadDataByCode(value) {
const options = []
const data = pca[value]
if (data) {
for (const key in data) {
if (data.hasOwnProperty(key)) {
options.push({ value: key, label: data[key] })
}
}
return options
} else {
return []
}
},
/** 判断是否有子节点 */
hasChildren(options) {
options.forEach(option => {
const data = this.loadDataByCode(option.value)
option.isLeaf = data.length === 0
})
},
handleChange(values) {
const value = values[values.length - 1]
this.$emit('change', value)
},
initAreaData() {
if (!this.areaData) {
this.areaData = new Area()
}
}
},
model: { prop: 'value', event: 'change' }
}
</script>
<style lang="less" scoped>
.j-area-linkage {
height:40px;
/deep/ .area-cascader-wrap .area-select {
width: 100%;
}
/deep/ .area-select .area-selected-trigger {
line-height: 1.15;
}
}
///deep/.placeholderBlack .area-cascader-wrap .area-select.active {
// color: #333 !important;
//}
///deep/.placeholderGray .area-cascader-wrap .area-select {
// color: rgb(191,191,191) !important;
//}
</style>
+101
View File
@@ -0,0 +1,101 @@
<template>
<a-date-picker
:disabledDate="disabledDate"
:disabled="disabled || readOnly"
:placeholder="placeholder"
@change="handleDateChange"
:value="momVal"
:showTime="showTime"
:format="dateFormat"
:mode="mode"
:getCalendarContainer="getCalendarContainer"
/>
</template>
<script>
import moment from 'moment'
export default {
name: 'JDate',
props: {
placeholder: {
type: String,
default: '',
required: false
},
value: {
type: String,
required: false
},
disabledDate: {
type: Function
},
dateFormat: {
type: String,
default: 'YYYY-MM-DD',
required: false
},
// 此属性可以被废弃了
triggerChange: {
type: Boolean,
required: false,
default: false
},
readOnly: {
type: Boolean,
required: false,
default: false
},
disabled: {
type: Boolean,
required: false,
default: false
},
showTime: {
type: Boolean,
required: false,
default: false
},
getCalendarContainer: {
type: Function,
default: (node) => node.parentNode
},
mode: {
type: String,
required: false,
default: 'date'
}
},
data() {
const dateStr = this.value
return {
decorator: '',
momVal: !dateStr ? null : moment(dateStr, this.dateFormat)
}
},
watch: {
value(val) {
if (!val) {
this.momVal = null
} else {
this.momVal = moment(val, this.dateFormat)
}
}
},
methods: {
moment,
handleDateChange(mom, dateStr) {
console.log('handleDateChange----', dateStr)
this.$emit('change', dateStr)
}
},
// 2.2新增 在组件内定义 指定父组件调用时候的传值属性和事件类型 这个牛逼
model: {
prop: 'value',
event: 'change'
}
}
</script>
<style lang="less" scoped>
/deep/ .ant-input {
padding: 4px 6px;
}
</style>