123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- <template>
- <u-picker
- ref="areaPicker"
- keyName="label"
- valueName="value"
- :show="show"
- :columns="columns"
- :showToolbar="showToolbar"
- :title="title"
- :loading="loading"
- :itemHeight="itemHeight"
- :cancelText="cancelText"
- :confirmText="confirmText"
- :cancelColor="cancelColor"
- :confirmColor="confirmColor"
- :visibleItemCount="visibleItemCount"
- :closeOnClickOverlay="closeOnClickOverlay"
- :defaultIndex="innerDefaultIndex"
- :immediateChange="immediateChange"
- :round="round"
- @close="close"
- @cancel="cancel"
- @confirm="confirm"
- @change="change"
- >
- <template v-slot:trigger>
- <slot name="trigger">
- <u-input
- v-if="showInput"
- :value="inputValue"
- :clearable="inputProps.clearable"
- :placeholder="inputProps.placeholder"
- :disabled="inputProps.disabled"
- :border="inputProps.border"
- :round="inputProps.round"
- :backgroundColor="inputProps.disabled ? '' : inputProps.backgroundColor"
- :disabledColor="inputProps.disabled ? inputProps.backgroundColor : ''"
- :placeholderClass="inputProps.placeholderClass"
- :placeholderStyle="inputProps.placeholderStyle"
- :confirmType="inputProps.confirmType"
- :focus="inputProps.focus"
- :inputAlign="inputProps.inputAlign"
- :fontSize="inputProps.fontSize"
- :color="inputProps.color"
- :borderColor="inputProps.borderColor"
- :prefixIcon="inputProps.prefixIcon"
- :suffixIcon="inputProps.suffixIcon"
- :suffixIconStyle="inputProps.suffixIconStyle"
- :prefixIconStyle="inputProps.prefixIconStyle"
- :shape="inputProps.shape"
- :customStyle="inputProps.customStyle"
- />
- </slot>
- </template>
- </u-picker>
- </template>
- <script>
- import area from '../../libs/util/area.js'
- import props from './props.js'
- import mixin from '../../libs/mixin/mixin'
- import mpMixin from '../../libs/mixin/mpMixin'
- export default {
- name: 'u-region-picker',
- mixins: [mpMixin, mixin, props],
- data() {
- return {
- inputValue: '',
- columns: [],
- innerDefaultIndex: [],
- selectedValue:[]
- }
- },
- watch: {
- // #ifdef VUE2
- value(newValue) {
- if(newValue){
- this.init()
- }
- },
- // #endif
- // #ifdef VUE3
- modelValue(newValue) {
- if(newValue){
- this.init()
- }
- },
- // #endif
- },
- mounted() {
- this.init();
- },
- // #ifdef VUE3
- emits: ['update:modelValue','init', 'confirm', 'change', 'close', 'cancel'],
- // #endif
- methods: {
- // 初始化数据
- init() {
- const columns = [];
- const innerDefaultIndex = [];
- const innerDefaultLabel = []
-
- // 获取当前值
- const currentValue = this.getCurrentValue();
-
- // 处理省份列
- let selectedProvince;
- if (this.province) {
- const province = this.getProvinceList();
- columns.push(province);
-
- selectedProvince = this.getSelectedValue(0, province);
- let provinceIndex = province.findIndex(item => item.value == selectedProvince);
- innerDefaultIndex.push(provinceIndex >= 0 ? provinceIndex : 0);
- innerDefaultLabel.push(province[provinceIndex].label)
- }
- // 处理城市列
- let selectedCity;
- if (this.city) {
- const city = this.getCityList(selectedProvince);
- columns.push(city);
-
- const cityIndex = this.province ? 1 : 0;
- selectedCity = this.getSelectedValue(cityIndex, city);
- let cityIndexValue = city.findIndex(item => item.value == selectedCity);
- innerDefaultIndex.push(cityIndexValue >= 0 ? cityIndexValue : 0);
- innerDefaultLabel.push(city[cityIndexValue].label)
- }
-
- // 处理县区列
- if (this.county && selectedCity) {
- const county = this.getCountyList(selectedCity);
- columns.push(county);
-
- const countyIndex = (this.province ? 1 : 0) + (this.city ? 1 : 0);
- const selectedCounty = this.getSelectedValue(countyIndex, county);
- let countyIndexValue = county.findIndex(item => item.value == selectedCounty);
- innerDefaultIndex.push(countyIndexValue >= 0 ? countyIndexValue : 0);
- innerDefaultLabel.push(county[countyIndexValue].label)
- }
-
- // 设置列数据
- this.columns = columns;
- this.innerDefaultIndex = innerDefaultIndex;
- if(this.showInput && currentValue.length > 0){
- this.inputValue = innerDefaultLabel.join(this.inputProps.separator)
- }
-
- },
-
- // 获取选中值
- getSelectedValue(index, list) {
- const currentValue = this.getCurrentValue();
- // 如果有默认值且列表不为空,则使用默认值,否则使用第一个值
- return (currentValue && currentValue[index] && list.length > 0)
- ? Number(currentValue[index])
- : Number(list[0].value);
- },
-
- // 获取当前值,兼容 Vue2 和 Vue3
- getCurrentValue() {
- // #ifdef VUE2
- return this.value;
- // #endif
- // #ifdef VUE3
- return this.modelValue;
- // #endif
- },
- // 获取省份数据
- getProvinceList() {
- let list = [];
- Object.entries(area.province_list).forEach(([value, label],idx) => {
- list.push({ value, label });
- });
- return list;
- },
-
- // 获取城市数据
- getCityList(cityCode) {
- let list = [];
- Object.entries(area.city_list).forEach(([value, label],idx) => {
- if(cityCode){
- if (value.startsWith(String(cityCode).substring(0, 2))) {
- list.push({ value, label });
- }
- }else{
- list.push({ value, label });
- }
- });
- return list;
- },
-
- // 获取区县数据
- getCountyList(countyCode) {
- let list = [];
- Object.entries(area.county_list).forEach(([value, label],idx) => {
- if(countyCode){
- if (value.startsWith(String(countyCode).substring(0, 4))) {
- list.push({ value, label });
- }
- }else{
- list.push({ value, label });
- }
- });
- return list;
- },
-
- // 选择器变化事件
- change(e) {
- const { columnIndex, value } = e;
-
- // 计算实际的列索引(考虑可能跳过的列)
- let actualColumnIndex = columnIndex;
- let valueIndex = columnIndex;
-
- // 省份列变化
- if ((this.province && actualColumnIndex === 0) && this.city) {
- // 选择省份时更新城市列表
- const cityList = this.getCityList(value[valueIndex].value);
- const cityColumnIndex = this.province ? 1 : 0;
- this.$refs.areaPicker.setColumnValues(cityColumnIndex, cityList);
- // 如果显示区县列,同时更新区县列表
- if (this.county && cityList.length > 0) {
- const countyList = this.getCountyList(cityList[0].value);
- const countyColumnIndex = (this.province ? 1 : 0) + (this.city ? 1 : 0);
- this.$refs.areaPicker.setColumnValues(countyColumnIndex, countyList);
- }
- }
- // 城市列变化
- else if (this.city &&
- ((this.province && actualColumnIndex === 1) ||
- (!this.province && actualColumnIndex === 0)) &&
- this.county) {
- // 选择城市时更新区县列表
- const cityValueIndex = this.province ? 1 : 0;
- let countyList = this.getCountyList(value[cityValueIndex].value);
- const countyColumnIndex = (this.province ? 1 : 0) + (this.city ? 1 : 0) - 1;
- this.$refs.areaPicker.setColumnValues(countyColumnIndex + 1, countyList);
- }
- this.$emit('change', e);
- },
- // 关闭选择器
- close() {
- if (this.closeOnClickOverlay) {
- this.$emit('close')
- }
- },
- // 确认选择
- confirm(e) {
- this.$emit('confirm', e);
- let value = e.value.map(item => item.value)
- if(this.showInput){
- let label = e.value.map(item => item.label)
- this.inputValue = label.join(this.inputProps.separator)
- }
-
- // #ifdef VUE2
- this.$emit('input', value)
- // #endif
- // #ifdef VUE3
- this.$emit('update:modelValue', value)
- // #endif
- },
- // 取消选择
- cancel() {
- this.$emit('cancel');
- }
- },
- }
- </script>
- <style lang="scss" scoped>
- @import "../../libs/css/components.scss";
- </style>
|