Ui
yfx
2026-03-13 4c63525525e2b1940b78b7c4a8af587e075072ae
Ui
5 files added
11087 ■■■■■ changed files
uni_modules/piaoyi-cityPicker/changelog.md 22 ●●●●● patch | view | raw | blame | history
uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/cityData.js 10661 ●●●●● patch | view | raw | blame | history
uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/piaoyi-cityPicker.vue 281 ●●●●● patch | view | raw | blame | history
uni_modules/piaoyi-cityPicker/package.json 17 ●●●●● patch | view | raw | blame | history
uni_modules/piaoyi-cityPicker/readme.md 106 ●●●●● patch | view | raw | blame | history
uni_modules/piaoyi-cityPicker/changelog.md
New file
@@ -0,0 +1,22 @@
## 1.1.7(2024-10-29)
修复底部露出部分组件bug
## 1.1.6(2024-08-20)
更新本地数据源为最新数据源
## 1.1.5(2024-06-12)
使用说明文档优化
## 1.1.4(2024-06-12)
增加问题反馈描述
## 1.1.3(2024-02-29)
更新使用文档
## 1.1.2(2024-01-16)
解决Vue3项目导入导出报错问题
## 1.1.1(2023-12-06)
defaultValue可以传入defaultValue:['河北省','唐山市','丰南区']数组类型以及defaultValue: '420103'地区编码字符串类型
## 1.1.0(2023-12-05)
即默认值传入地区编码,也支持传入中文省市区数组
## 1.0.9(2023-12-04)
优化
## 1.0.8(2023-10-24)
修复东菀市和中山市下各镇的行政编码错误问题
## 1.0.4(2023-09-15)
改为uni_modules规范
uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/cityData.js
New file
Diff too large
uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/piaoyi-cityPicker.vue
New file
@@ -0,0 +1,281 @@
<template>
    <view class="pupop">
        <view class="popup-box" :animation="animationData">
            <view class="pupop-btn">
                <view @tap="cancel">取消</view>
                <view @tap="confirm" style="color: #2979ff;">确定</view>
            </view>
            <picker-view :value="value" :indicator-style="indicatorStyle" @change="bindChange" class="picker-view">
                <picker-view-column>
                    <view class="item" v-for="(item,index) in provinceList" :key="index">{{item.name}}</view>
                </picker-view-column>
                <picker-view-column>
                    <view class="item" v-for="(item,index) in cityList" :key="index">{{item.name}}</view>
                </picker-view-column>
                <picker-view-column v-if="column == 3">
                    <view class="item" v-for="(item,index) in areaList" :key="index">{{item.name}}</view>
                </picker-view-column>
            </picker-view>
        </view>
        <view @tap="close" @touchmove.stop.prevent :class="visible ? 'pupop-model' : 'pupop-models'"></view>
    </view>
</template>
<script>
    import {
        addressList
    } from './cityData.js'
    export default {
        data() {
            return {
                value: [],
                addressList,
                provinceList: [],
                cityList: [],
                areaList: [],
                indicatorStyle: `height: 50px;`,
                provinceIndex: 0,
                cityIndex: 0,
                areaIndex: 0,
                animationData: {}
            }
        },
        props: {
            column: {
                type: Number,
                default: 3
            },
            defaultValue: {
                default: () => ''
            },
            visible: {
                type: Boolean,
                default: () => false
            },
            maskCloseAble: {
                type: Boolean,
                default: () => true
            },
        },
        watch: {
            visible (val) {
                this.changeActive()
            },
            defaultValue() {
                this.init()
            }
        },
        created() {
            this.init()
        },
        methods: {
            init () {
                var provinceList = []
                addressList.filter(item => {
                    provinceList.push({
                        code: item.code,
                        name: item.name
                    })
                })
                this.provinceList = [...provinceList]
                if (!this.defaultValue) {
                    this.cityList = addressList[0].children
                    this.areaList = addressList[0].children[0].children
                } else {
                    var city = {11:"北京",12:"天津",13:"河北",14:"山西",15:"内蒙古",21:"辽宁",22:"吉林",23:"黑龙江 ",31:"上海",32:"江苏",33:"浙江",34:"安徽",35:"福建",36:"江西",37:"山东",41:"河南",42:"湖北 ",43:"湖南",44:"广东",45:"广西",46:"海南",50:"重庆",51:"四川",52:"贵州",53:"云南",54:"西藏 ",61:"陕西",62:"甘肃",63:"青海",64:"宁夏",65:"新疆",71:"台湾",81:"香港",82:"澳门",91:"国外 "}
                    if (Array.isArray(this.defaultValue) && this.defaultValue.length >= 2) {
                        //console.log(this.defaultValue)
                        var province = this.defaultValue[0]
                        var city = this.defaultValue[1]
                        this.provinceIndex = 0
                        this.cityIndex = 0
                        this.areaIndex = 0
                        this.provinceIndex = addressList.findIndex(obj => {
                            return obj.name == province
                        })
                        this.provinceIndex = this.provinceIndex >= 0 ? this.provinceIndex : 0
                        this.cityList = addressList[this.provinceIndex].children
                        this.cityIndex = this.cityList.findIndex(obj => {
                            return obj.name == city
                        })
                        this.cityIndex = this.cityIndex >= 0 ? this.cityIndex : 0
                        this.areaList = this.cityList[this.cityIndex].children
                        if (this.defaultValue.length > 2) {
                            this.areaIndex = this.areaList.findIndex(obj => {
                                return obj.name == this.defaultValue[2]
                            })
                        }
                        this.areaIndex = this.areaIndex >= 0 ? this.areaIndex : 0
                        this.$nextTick(() => {
                            if (this.column == 3) {
                                this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex, this.areaIndex]))
                            } else if (this.column == 2) {
                                this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex]))
                            }
                        })
                    } else if (/^\d{6}$/.test(this.defaultValue)) {
                        var province = this.defaultValue.substr(0, 2)
                        var city = this.defaultValue.substr(0, 4)
                        this.provinceIndex = 0
                        this.cityIndex = 0
                        this.areaIndex = 0
                        this.provinceIndex = addressList.findIndex(obj => {
                            return obj.code == province
                        })
                        this.provinceIndex = this.provinceIndex >= 0 ? this.provinceIndex : 0
                        this.cityList = addressList[this.provinceIndex].children
                        this.cityIndex = this.cityList.findIndex(obj => {
                            return obj.code == city
                        })
                        this.cityIndex = this.cityIndex >= 0 ? this.cityIndex : 0
                        this.areaList = this.cityList[this.cityIndex].children
                        this.areaIndex = this.areaList.findIndex(obj => {
                            return obj.code == this.defaultValue
                        })
                        this.areaIndex = this.areaIndex >= 0 ? this.areaIndex : 0
                        this.$nextTick(() => {
                            if (this.column == 3) {
                                this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex, this.areaIndex]))
                            } else if (this.column == 2) {
                                this.value = JSON.parse(JSON.stringify([this.provinceIndex, this.cityIndex]))
                            }
                        })
                    } else {
                        uni.showToast({
                            title: '地区编码格式不正确',
                            icon: 'none'
                        })
                        //console.log('地区编码格式不正确')
                    }
                }
                this.changeActive()
            },
            confirm () {
                if (this.column == 3) {
                    this.$emit('confirm', {
                        code: addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].code,
                        name: addressList[this.provinceIndex].name + addressList[this.provinceIndex].children[this.cityIndex].name + addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].name,
                        provinceName: addressList[this.provinceIndex].name,
                        cityName: addressList[this.provinceIndex].children[this.cityIndex].name,
                        areaName: addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].name
                    })
                } else if (this.column == 2) {
                    this.$emit('confirm', {
                        code: addressList[this.provinceIndex].children[this.cityIndex].children[this.areaIndex].code.substring(0, 4) + '00',
                        name: addressList[this.provinceIndex].name + addressList[this.provinceIndex].children[this.cityIndex].name,
                        provinceName: addressList[this.provinceIndex].name,
                        cityName: addressList[this.provinceIndex].children[this.cityIndex].name
                    })
                } else {
                    uni.showToast({
                        title: '目前column只能传2和3',
                        icon: 'none'
                    })
                }
            },
            cancel () {
                this.$emit('cancel')
            },
            // 动画
            changeActive () {
                var active = '-415px'
                if (this.visible) {
                    active = 0
                }
                var animation = uni.createAnimation({
                    duration: 400,
                    timingFunction: 'linear'
                })
                animation.bottom(active).step()
                this.animationData = animation.export()
            },
            bindChange(e) {
                e.detail.value[0] = e.detail.value[0] || 0
                e.detail.value[1] = e.detail.value[1] || 0
                e.detail.value[2] = e.detail.value[2] || 0
                if (e.detail.value[0] != this.provinceIndex) {
                    // console.log('监听第一列')
                    this.provinceChange(e.detail.value[0])
                } else if (e.detail.value[1] != this.cityIndex) {
                    // console.log('监听第二列')
                    this.cityChange(e.detail.value[1])
                } else if (e.detail.value[2] != this.areaIndex) {
                    // console.log('监听第三列')
                    this.areaChange(e.detail.value[2])
                }
            },
            // 监听第一列变化
            provinceChange (e) {
                this.provinceIndex = e
                this.cityIndex = 0
                this.areaIndex = 0
                this.value = [...[e, 0, 0]]
                this.cityList = addressList[e].children
                this.areaList = addressList[e].children[0].children
            },
            // 监听第二列变化
            cityChange (e) {
                this.cityIndex = e
                this.areaIndex = 0
                // console.log(this.cityIndex, this.areaIndex)
                this.value = [...[this.provinceIndex, e, 0]]
                this.cityList = addressList[this.provinceIndex].children
                this.areaList = addressList[this.provinceIndex].children[e].children
            },
            // 监听第三列变化
            areaChange (e) {
                this.areaIndex = e
            },
            // 点击模态框
            close () {
                if (this.maskCloseAble) {
                    this.cancel()
                }
            }
        }
    }
</script>
<style scoped lang="scss">
    .pupop {
        .popup-box {
            position: fixed;
            left: 0;
            bottom: -315px;
            z-index: 99999;
            background: #fff;
            padding-bottom: 50px;
            .pupop-btn{
                height: 40px;
                display: flex;
                align-items: center;
                padding: 0 30upx;
                justify-content: space-between;
            }
        }
        .pupop-model {
            position: fixed;
            left: 0;
            top: 0;
            width: 100%;
            height: 100%;
            z-index: 9999;
            background: rgba(0, 0, 0, .5);
        }
        .pupop-models{
            display: none;
        }
        .picker-view {
            width: 750rpx;
            height: 225px;
            margin-top: 20rpx;
        }
        .item {
            height: 50px;
            align-items: center;
            justify-content: center;
            text-align: center;
            line-height: 50px;
        }
    }
</style>
uni_modules/piaoyi-cityPicker/package.json
New file
@@ -0,0 +1,17 @@
{
    "id": "piaoyi-cityPicker",
    "name": " data-cityPicker省市区地址选择器",
    "displayName": " data-cityPicker省市区地址选择器(兼容vue3)",
    "version": "1.1.7",
    "description": "常用省市区选择器,可反选,自定义模态框、兼容vue3",
    "keywords": [
        "省市区",
        "选择器",
        "可反选",
        "自定义模态框和弹框",
        "兼容vue3"
    ],
    "dcloudext": {
        "type": "component-vue"
    }
}
uni_modules/piaoyi-cityPicker/readme.md
New file
@@ -0,0 +1,106 @@
## 1.0.7(2023-09-15)
改为uni_modules规范
### cityPicker 省市区选择器(兼容vue3)
**使用方法:**
```
<template>
    <view>
        <button @tap="open">打开</button>
        <cityPicker :column="column" :default-value="defaultValue" :mask-close-able="maskCloseAble" @confirm="confirm" @cancel="cancel" :visible="visible"/>
        <view>{{str}}</view>
    </view>
</template>
<script>
    import cityPicker from '@/uni_modules/piaoyi-cityPicker/components/piaoyi-cityPicker/piaoyi-cityPicker'
    export default {
        data() {
            return {
                visible: false,
                maskCloseAble: true,
                str: '',
                defaultValue: '420103',
                // defaultValue: ['河北省','唐山市','丰南区'],
                column: 3
            }
        },
        components: {
            cityPicker
        },
        methods: {
            open () {
                this.visible = true
            },
            confirm (val) {
                console.log(val)
                this.str = JSON.stringify(val)
                this.visible = false
            },
            cancel () {
                this.visible = false
            }
        },
        onShareAppMessage(res) {
            if (res.from === 'button') { // 来自页面内分享按钮
                console.log(res.target)
            }
            return {
                title: 'data-cityPicker省市区地址选择器!',
                path: '/pages/cityPicker/cityPicker'
            }
        },
        onShareTimeline(res) {
            if (res.from === 'button') { // 来自页面内分享按钮
                console.log(res.target)
            }
            return {
                title: 'data-cityPicker省市区地址选择器!'
            }
        }
    }
</script>
<style lang="scss">
</style>
```
### 注:近期收到使用用户反馈,存在以下一个问题(如有好的建议,期待私信,谢谢)
1、之前只支持默认值传入地区编码,已更新可以支持传入中文省市区数组
defaultValue可以传入defaultValue:['河北省','唐山市','丰南区']数组类型以及defaultValue: '420103'地区编码字符串类型
可以使用const reg =/([\u4e00-\u9fa5]+省|自治区|[\u4e00-\u9fa5]+市|[\u4e00-\u9fa5]+区)/g;将自己的省市区数据进行处理为数组再传入
2、有些用户反馈vue3下watch监听有问题
我自己创建一个vue项目,导入插件后,按照示例原封不动进行测试,没有发现问题; 发现有问题的朋友可以提供一下可以复现的demo给我,我这边看看具体什么情况
3、有些用户返回无法关闭弹框
不要把插件放到scroll-view里面,请务必放到最外层进行使用
#### 事件说明
|   事件名    | 返回值 |      描述      |
| :---------: | :----: | :------------: |
| @confirm |   对象(code,完整地区名称)   | 点击确定的回调 |
| @cancel | 无 | 点击取消的回调 |
#### Prop
| 参数名称 | 描述                           |
| -------- | ------------------------------ |
| visible | 控制选择器显示和隐藏 |
| column | 可选值2和3,2是省市两列选择;3是省市区三列选择 |
| maskCloseAble | 点击模态框是否关闭弹框 |
| defaultValue | 初始地区编码(例:420102或者['河北省','唐山市','丰南区']) |
### 数据来源:[点击查看省市区数据来源](https://github.com/modood/Administrative-divisions-of-China/blob/master/dist/pca-code.json)
### 可接定制化组件开发
### 右侧有本人代表作小程序二维码,可以扫码体验
### 如使用过程中有问题或有一些好的建议,欢迎加QQ群互相学习交流:120594820